summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose Fonseca <jfonseca@vmware.com>2016-02-10 21:44:36 +0000
committerJose Fonseca <jfonseca@vmware.com>2016-02-10 21:46:30 +0000
commit80f0f0532dabf2d4c4bb3dd17aea16a574d1db44 (patch)
tree5a4eaee09f086a82e129e1a37af91cef4819ad2a
parent2257503ff3fc87d76309bd58b3206ee4cac33c37 (diff)
parentf6305d3d105376de5306f6d0e70ff666df38d2e0 (diff)
Merge branch 'master' into virtual-memory-regionsvirtual-memory-regions
-rw-r--r--.editorconfig19
-rw-r--r--.gitignore5
-rw-r--r--.lvimrc1
-rw-r--r--.travis.yml79
-rw-r--r--Android.mk9
-rw-r--r--CMakeLists.txt474
-rw-r--r--DEVELOPMENT.markdown169
-rw-r--r--INSTALL.markdown142
-rw-r--r--NEWS.markdown72
-rw-r--r--README.markdown524
-rw-r--r--appveyor.yml42
-rw-r--r--cli/CMakeLists.txt27
-rw-r--r--cli/cli.hpp6
-rw-r--r--cli/cli_diff.cpp10
-rw-r--r--cli/cli_diff_images.cpp10
-rw-r--r--cli/cli_diff_state.cpp71
-rw-r--r--cli/cli_leaks.cpp85
-rw-r--r--cli/cli_main.cpp2
-rw-r--r--cli/cli_pager.cpp47
-rw-r--r--cli/cli_pager.hpp4
-rw-r--r--cli/cli_pickle.cpp30
-rw-r--r--cli/cli_repack.cpp30
-rw-r--r--cli/cli_resources.cpp7
-rw-r--r--cli/cli_resources.hpp4
-rw-r--r--cli/cli_retrace.hpp4
-rw-r--r--cli/cli_sed.cpp59
-rw-r--r--cli/cli_trace.cpp99
-rw-r--r--cli/cli_trim.cpp284
-rw-r--r--cli/cli_trim_auto.cpp432
-rw-r--r--cli/cli_trim_auto_analyzer.cpp (renamed from cli/trace_analyzer.cpp)2
-rw-r--r--cli/cli_trim_auto_analyzer.hpp (renamed from cli/trace_analyzer.hpp)0
-rw-r--r--cli/pickle.hpp62
-rw-r--r--cmake/ConvenienceLibrary.cmake15
-rw-r--r--cmake/FindDirectX.cmake508
-rw-r--r--cmake/FindSNAPPY.cmake13
-rw-r--r--cmake/FindWaffle.cmake38
-rw-r--r--cmake/Findprocps.cmake16
-rw-r--r--cmake/InstallPDB.cmake17
-rw-r--r--cmake/Windows10SDK.cmake53
-rw-r--r--cmake/toolchain/android.toolchain.cmake1776
-rw-r--r--common/CMakeLists.txt52
-rw-r--r--common/highlight.cpp17
-rw-r--r--common/highlight.hpp4
-rw-r--r--common/os.hpp27
-rw-r--r--common/os_backtrace.hpp5
-rw-r--r--common/os_binary.hpp4
-rw-r--r--common/os_crtdbg.cpp92
-rw-r--r--common/os_crtdbg.hpp57
-rw-r--r--common/os_dl.hpp4
-rw-r--r--common/os_memory.hpp23
-rw-r--r--common/os_posix.cpp115
-rw-r--r--common/os_process.hpp4
-rw-r--r--common/os_string.hpp6
-rw-r--r--common/os_thread.hpp180
-rw-r--r--common/os_time.hpp4
-rw-r--r--common/os_version.hpp61
-rw-r--r--common/os_win32.cpp103
-rw-r--r--common/trace_api.hpp5
-rw-r--r--common/trace_callset.cpp25
-rw-r--r--common/trace_callset.hpp4
-rw-r--r--common/trace_dump.cpp66
-rw-r--r--common/trace_dump.hpp5
-rw-r--r--common/trace_fast_callset.hpp4
-rw-r--r--common/trace_file.cpp8
-rw-r--r--common/trace_file.hpp60
-rw-r--r--common/trace_file_read.cpp3
-rw-r--r--common/trace_file_snappy.cpp113
-rw-r--r--common/trace_file_zlib.cpp60
-rw-r--r--common/trace_format.hpp5
-rw-r--r--common/trace_loader.cpp137
-rw-r--r--common/trace_loader.hpp65
-rw-r--r--common/trace_lookup.hpp4
-rw-r--r--common/trace_model.cpp73
-rw-r--r--common/trace_model.hpp18
-rw-r--r--common/trace_option.cpp9
-rw-r--r--common/trace_option.hpp7
-rw-r--r--common/trace_ostream.hpp52
-rw-r--r--common/trace_ostream_snappy.cpp206
-rw-r--r--common/trace_ostream_zlib.cpp99
-rw-r--r--common/trace_parser.cpp28
-rw-r--r--common/trace_parser.hpp35
-rw-r--r--common/trace_parser_flags.cpp4705
-rw-r--r--common/trace_parser_flags.cpp.re565
-rw-r--r--common/trace_parser_flags_test.cpp652
-rw-r--r--common/trace_parser_loop.cpp111
-rw-r--r--common/trace_profiler.cpp1
-rw-r--r--common/trace_profiler.hpp4
-rw-r--r--common/trace_snappy.hpp61
-rw-r--r--common/trace_writer.cpp46
-rw-r--r--common/trace_writer.hpp9
-rw-r--r--common/trace_writer_local.cpp71
-rw-r--r--common/trace_writer_local.hpp6
-rw-r--r--common/trace_writer_model.cpp4
-rw-r--r--common/ubjson.hpp111
-rw-r--r--dispatch/.gitignore1
-rw-r--r--dispatch/CMakeLists.txt36
-rw-r--r--dispatch/compat.h24
-rw-r--r--dispatch/d2dimports.hpp12
-rw-r--r--dispatch/d3d10imports.hpp9
-rw-r--r--dispatch/d3d11imports.hpp6
-rw-r--r--dispatch/d3d8imports.hpp4
-rw-r--r--dispatch/d3d9imports.hpp4
-rw-r--r--dispatch/d3derr.hpp46
-rw-r--r--dispatch/d3dimports.hpp (renamed from dispatch/d3d10_1imports.hpp)29
-rw-r--r--dispatch/dispatch.py73
-rw-r--r--dispatch/dlopen.hpp4
-rw-r--r--dispatch/dxgiint.h30
-rw-r--r--dispatch/dxva2imports.hpp49
-rw-r--r--dispatch/dxvaint.h179
-rw-r--r--dispatch/eglimports.hpp9
-rw-r--r--dispatch/glimports.hpp59
-rw-r--r--dispatch/glproc.py176
-rw-r--r--dispatch/glproc_egl.cpp72
-rw-r--r--dispatch/glproc_gl.cpp1
-rw-r--r--docs/Android.markdown (renamed from Dalvik.markdown)36
-rw-r--r--docs/BUGS.markdown (renamed from BUGS.markdown)66
-rw-r--r--docs/FORMAT.markdown (renamed from FORMAT.markdown)3
-rw-r--r--docs/HACKING.markdown245
-rw-r--r--docs/INSTALL.markdown204
-rw-r--r--docs/NEWS.markdown102
-rw-r--r--docs/TODO.markdown (renamed from TODO.markdown)0
-rw-r--r--docs/USAGE.markdown566
-rw-r--r--docs/VMWX_map_buffer_debug.txt116
-rw-r--r--gui/.gitignore3
-rw-r--r--gui/CMakeLists.txt88
-rw-r--r--gui/androiddevicedialog.cpp556
-rw-r--r--gui/androiddevicedialog.h65
-rw-r--r--gui/androidfiledialog.cpp279
-rw-r--r--gui/androidfiledialog.h45
-rw-r--r--gui/androidretracer.cpp326
-rw-r--r--gui/androidretracer.h33
-rw-r--r--gui/androidutils.cpp185
-rw-r--r--gui/androidutils.h71
-rw-r--r--gui/apicalldelegate.cpp18
-rw-r--r--gui/apicalldelegate.h5
-rw-r--r--gui/apisurface.cpp17
-rw-r--r--gui/apisurface.h13
-rw-r--r--gui/apitrace.cpp117
-rw-r--r--gui/apitrace.h25
-rw-r--r--gui/apitracecall.cpp205
-rw-r--r--gui/apitracecall.h46
-rw-r--r--gui/apitracefilter.h5
-rw-r--r--gui/apitracemodel.cpp1
-rw-r--r--gui/apitracemodel.h5
-rw-r--r--gui/argumentseditor.h5
-rw-r--r--gui/calldurationgraph.h4
-rw-r--r--gui/glsledit.cpp2
-rw-r--r--gui/graphing/frameaxiswidget.h5
-rw-r--r--gui/graphing/graphaxiswidget.h5
-rw-r--r--gui/graphing/graphing.h5
-rw-r--r--gui/graphing/graphlabelwidget.h5
-rw-r--r--gui/graphing/graphview.h5
-rw-r--r--gui/graphing/graphwidget.h5
-rw-r--r--gui/graphing/heatmapverticalaxiswidget.h5
-rw-r--r--gui/graphing/heatmapview.h5
-rw-r--r--gui/graphing/histogramview.h5
-rw-r--r--gui/graphing/timeaxiswidget.h5
-rw-r--r--gui/imageviewer.cpp8
-rw-r--r--gui/imageviewer.h8
-rw-r--r--gui/jumpwidget.h5
-rw-r--r--gui/leaktracethread.cpp82
-rw-r--r--gui/leaktracethread.h35
-rw-r--r--gui/main.cpp5
-rw-r--r--gui/mainwindow.cpp476
-rw-r--r--gui/mainwindow.h31
-rw-r--r--gui/pixelwidget.h5
-rw-r--r--gui/profiledialog.cpp2
-rw-r--r--gui/profiledialog.h5
-rw-r--r--gui/profileheatmap.h13
-rw-r--r--gui/profiletablemodel.h4
-rw-r--r--gui/profiling.h5
-rw-r--r--gui/qapitrace.qrc46
-rw-r--r--gui/qubjson.cpp298
-rw-r--r--gui/qubjson.h34
-rw-r--r--gui/qubjson_test.cpp161
-rw-r--r--gui/resources/android-setup.pngbin0 -> 4289 bytes
-rw-r--r--gui/resources/android.pngbin0 -> 5237 bytes
-rwxr-xr-xgui/resources/glreference-man.sh10
-rwxr-xr-xgui/resources/glreference-registry.sh6
-rw-r--r--gui/resources/glreference.tsv6498
-rw-r--r--gui/retracer.cpp181
-rw-r--r--gui/retracer.h22
-rw-r--r--gui/saverthread.cpp11
-rw-r--r--gui/saverthread.h6
-rw-r--r--gui/searchwidget.h5
-rw-r--r--gui/settingsdialog.cpp60
-rw-r--r--gui/settingsdialog.h11
-rw-r--r--gui/shaderssourcewidget.h5
-rw-r--r--gui/thumbnail.h5
-rw-r--r--gui/tracedialog.h5
-rw-r--r--gui/traceloader.cpp228
-rw-r--r--gui/traceloader.h11
-rw-r--r--gui/traceprocess.h5
-rw-r--r--gui/trimprocess.cpp2
-rw-r--r--gui/trimprocess.h5
-rw-r--r--gui/ui/androiddevicedialog.ui132
-rw-r--r--gui/ui/androidfiledialog.ui149
-rw-r--r--gui/ui/imageviewer.ui18
-rw-r--r--gui/ui/jumpwidget.ui2
-rw-r--r--gui/ui/mainwindow.ui142
-rw-r--r--gui/ui/profilereplaydialog.ui12
-rw-r--r--gui/ui/settings.ui136
-rw-r--r--gui/vertexdatainterpreter.h5
-rw-r--r--guids/CMakeLists.txt6
-rw-r--r--guids/guids.cpp132
-rw-r--r--guids/guids.hpp51
-rw-r--r--guids/guids_defs.hpp38
-rw-r--r--guids/guids_entries.h721
-rw-r--r--guids/guids_test.cpp56
-rw-r--r--helpers/CMakeLists.txt18
-rw-r--r--helpers/com_ptr.hpp112
-rw-r--r--helpers/d3d10size.hpp44
-rw-r--r--helpers/d3d11size.hpp100
-rw-r--r--helpers/d3d7size.hpp118
-rw-r--r--helpers/d3d8size.hpp102
-rw-r--r--helpers/d3d9size.hpp154
-rw-r--r--helpers/d3dcommonsize.hpp89
-rw-r--r--helpers/d3dshader.cpp4
-rw-r--r--helpers/d3dshader.hpp4
-rw-r--r--helpers/dxgisize.hpp47
-rw-r--r--helpers/eglsize.hpp5
-rw-r--r--helpers/glprofile.cpp325
-rw-r--r--helpers/glprofile.hpp143
-rw-r--r--helpers/glsize.hpp361
-rw-r--r--image/image.hpp13
-rw-r--r--image/image_md5.cpp4
-rw-r--r--image/image_png.cpp75
-rw-r--r--image/image_pnm.cpp11
-rw-r--r--inject/CMakeLists.txt19
-rw-r--r--inject/inject.h144
-rw-r--r--inject/injectee.cpp1159
-rw-r--r--inject/injector.cpp652
-rw-r--r--retrace/.gitignore2
-rw-r--r--retrace/CMakeLists.txt286
-rw-r--r--retrace/android/AndroidManifest.xml23
-rw-r--r--retrace/android/build.gradle46
-rw-r--r--retrace/android/java/apitrace/github/io/eglretrace/AbstractServer.java31
-rw-r--r--retrace/android/java/apitrace/github/io/eglretrace/QtCreatorDebugger.java242
-rw-r--r--retrace/android/java/apitrace/github/io/eglretrace/RetraceActivity.java114
-rw-r--r--retrace/android/java/apitrace/github/io/eglretrace/Servers.java54
-rw-r--r--retrace/android/local.properties.in7
-rw-r--r--retrace/android/res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--retrace/android/res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--retrace/android/res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--retrace/android/res/drawable-xxhdpi/ic_launcher.pngbin0 -> 19388 bytes
-rw-r--r--retrace/android/res/values/strings.xml4
-rw-r--r--retrace/d3d10state.cpp150
-rw-r--r--retrace/d3d10state.hpp92
-rw-r--r--retrace/d3d10state_images.cpp412
-rw-r--r--retrace/d3d11state.cpp177
-rw-r--r--retrace/d3d11state.hpp (renamed from common/trace_file_write.cpp)33
-rw-r--r--retrace/d3d11state_images.cpp435
-rw-r--r--retrace/d3d7state.cpp62
-rw-r--r--retrace/d3d7state_images.cpp216
-rw-r--r--retrace/d3d8state.cpp53
-rw-r--r--retrace/d3d8state_images.cpp231
-rw-r--r--retrace/d3d9retrace.py87
-rw-r--r--retrace/d3d9state.cpp62
-rw-r--r--retrace/d3d9state.hpp57
-rw-r--r--retrace/d3d9state_formats.cpp259
-rw-r--r--retrace/d3d9state_images.cpp209
-rw-r--r--retrace/d3dretrace.hpp21
-rw-r--r--retrace/d3dretrace_dxgi.hpp215
-rw-r--r--retrace/d3dretrace_dxgi_misc.cpp113
-rw-r--r--retrace/d3dretrace_dxgi_priv.cpp283
-rw-r--r--retrace/d3dretrace_main.cpp3
-rw-r--r--retrace/d3dretrace_ws.cpp135
-rw-r--r--retrace/d3dstate.hpp82
-rw-r--r--retrace/ddrawretrace.py149
-rw-r--r--retrace/dllretrace.py1
-rwxr-xr-xretrace/dxgiretrace.py307
-rw-r--r--retrace/dxgistate.cpp421
-rw-r--r--retrace/dxgistate.hpp11
-rw-r--r--retrace/dxgistate_so.hpp116
-rw-r--r--retrace/dxgistate_so.py275
-rw-r--r--retrace/glretrace.hpp92
-rw-r--r--retrace/glretrace.py462
-rw-r--r--retrace/glretrace_cgl.cpp107
-rw-r--r--retrace/glretrace_egl.cpp102
-rw-r--r--retrace/glretrace_glx.cpp6
-rwxr-xr-xretrace/glretrace_main.cpp494
-rw-r--r--retrace/glretrace_wgl.cpp212
-rw-r--r--retrace/glretrace_wgl.hpp42
-rwxr-xr-xretrace/glretrace_wgl_font.cpp4896
-rw-r--r--retrace/glretrace_ws.cpp120
-rw-r--r--retrace/glstate.cpp358
-rw-r--r--retrace/glstate.hpp12
-rw-r--r--retrace/glstate_formats.cpp679
-rw-r--r--retrace/glstate_images.cpp839
-rw-r--r--retrace/glstate_internal.hpp153
-rwxr-xr-xretrace/glstate_params.py312
-rw-r--r--retrace/glstate_shaders.cpp955
-rw-r--r--retrace/glws.cpp74
-rw-r--r--retrace/glws.hpp106
-rw-r--r--retrace/glws_cocoa.mm87
-rw-r--r--retrace/glws_egl_android.cpp745
-rw-r--r--retrace/glws_egl_xlib.cpp321
-rw-r--r--retrace/glws_glx.cpp461
-rw-r--r--retrace/glws_waffle.cpp212
-rw-r--r--retrace/glws_wgl.cpp648
-rw-r--r--retrace/glws_xlib.cpp24
-rw-r--r--retrace/glws_xlib.hpp4
-rw-r--r--retrace/json.cpp49
-rw-r--r--retrace/json.hpp49
-rw-r--r--retrace/metric_backend.hpp285
-rw-r--r--retrace/metric_backend_amd_perfmon.cpp449
-rw-r--r--retrace/metric_backend_amd_perfmon.hpp178
-rw-r--r--retrace/metric_backend_intel_perfquery.cpp361
-rw-r--r--retrace/metric_backend_intel_perfquery.hpp170
-rw-r--r--retrace/metric_backend_opengl.cpp481
-rw-r--r--retrace/metric_backend_opengl.hpp198
-rw-r--r--retrace/metric_helper.cpp217
-rw-r--r--retrace/metric_writer.cpp224
-rw-r--r--retrace/metric_writer.hpp124
-rw-r--r--retrace/mmap_allocator.hpp171
-rw-r--r--retrace/retrace.cpp39
-rw-r--r--retrace/retrace.hpp73
-rw-r--r--retrace/retrace.py118
-rw-r--r--retrace/retrace_main.cpp279
-rw-r--r--retrace/retrace_stdc.cpp30
-rw-r--r--retrace/retrace_swizzle.cpp87
-rw-r--r--retrace/retrace_swizzle.hpp20
-rw-r--r--retrace/scoped_allocator.hpp9
-rw-r--r--retrace/state_writer.cpp81
-rw-r--r--retrace/state_writer.hpp182
-rw-r--r--retrace/state_writer_json.cpp126
-rw-r--r--retrace/state_writer_ubjson.cpp220
-rw-r--r--retrace/ws.cpp38
-rw-r--r--retrace/ws.hpp37
-rw-r--r--retrace/ws_win32.cpp234
-rw-r--r--retrace/ws_win32.hpp49
-rw-r--r--scripts/CMakeLists.txt10
-rwxr-xr-xscripts/convert.py161
-rwxr-xr-xscripts/jsondiff.py49
-rwxr-xr-xscripts/jsonextractimages.py21
-rwxr-xr-xscripts/leaks.py162
-rwxr-xr-xscripts/retracediff.py1
-rwxr-xr-xscripts/tracediff.py93
-rwxr-xr-xscripts/unpickle.py68
-rw-r--r--specs/cglapi.py49
-rw-r--r--specs/d2d1.py769
-rw-r--r--specs/d2dbasetypes.py80
-rw-r--r--specs/d2derr.py62
-rw-r--r--specs/d3d.py116
-rw-r--r--specs/d3d10.py203
-rw-r--r--specs/d3d10_1.py119
-rw-r--r--specs/d3d10misc.py55
-rw-r--r--specs/d3d10sdklayers.py11
-rw-r--r--specs/d3d11.py1465
-rw-r--r--specs/d3d11_1.py177
-rw-r--r--specs/d3d11sdklayers.py8
-rw-r--r--specs/d3d11shader.py186
-rw-r--r--specs/d3d8.py16
-rw-r--r--specs/d3d8types.py2
-rw-r--r--specs/d3d9.py33
-rw-r--r--specs/d3d9dxva2.py382
-rw-r--r--specs/d3d9types.py2
-rw-r--r--specs/d3dcommon.py701
-rw-r--r--specs/d3dtypes.py4
-rw-r--r--specs/ddraw.py592
-rw-r--r--specs/dwrite.py631
-rw-r--r--specs/dxgi.py643
-rw-r--r--specs/dxgi1_2.py52
-rw-r--r--specs/dxgiformat.py132
-rw-r--r--specs/dxgitype.py115
-rw-r--r--specs/dxva2.py458
-rw-r--r--specs/eglapi.py23
-rw-r--r--specs/glapi.py1252
-rw-r--r--specs/glesapi.py261
-rw-r--r--specs/glparams.py523
-rw-r--r--specs/gltypes.py8
-rw-r--r--specs/glxapi.py104
-rw-r--r--specs/scripts/.gitignore1
-rw-r--r--specs/scripts/Makefile10
-rwxr-xr-xspecs/scripts/xml2api.py108
-rwxr-xr-xspecs/scripts/xml2glparams.py38
-rw-r--r--specs/stdapi.py28
-rw-r--r--specs/wglapi.py86
-rw-r--r--specs/wglenum.py2
-rw-r--r--specs/winapi.py61
-rw-r--r--thirdparty/devcon/CMakeLists.txt12
-rw-r--r--thirdparty/devcon/devcon.cpp946
-rw-r--r--thirdparty/devcon/devcon.hpp70
-rw-r--r--thirdparty/devcon/license.rtf25
-rw-r--r--thirdparty/directxtex/CMakeLists.txt26
-rw-r--r--thirdparty/directxtex/DirectXTex/BC.cpp62
-rw-r--r--thirdparty/directxtex/DirectXTex/BC.h183
-rw-r--r--thirdparty/directxtex/DirectXTex/BC4BC5.cpp58
-rw-r--r--thirdparty/directxtex/DirectXTex/BC6HBC7.cpp440
-rw-r--r--thirdparty/directxtex/DirectXTex/BCDirectCompute.cpp616
-rw-r--r--thirdparty/directxtex/DirectXTex/BCDirectCompute.h67
-rw-r--r--thirdparty/directxtex/DirectXTex/DDS.h47
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTex.h440
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTex.inl205
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexCompress.cpp413
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexCompressGPU.cpp402
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexConvert.cpp3597
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexD3D11.cpp232
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexDDS.cpp610
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp16
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexImage.cpp242
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexMipmaps.cpp2439
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexMisc.cpp109
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexNormalMaps.cpp24
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexP.h129
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexPMAlpha.cpp229
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexResize.cpp772
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexTGA.cpp70
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexUtil.cpp370
-rw-r--r--thirdparty/directxtex/DirectXTex/DirectXTexWIC.cpp466
-rw-r--r--thirdparty/directxtex/DirectXTex/filters.h426
-rw-r--r--thirdparty/directxtex/DirectXTex/scoped.h40
-rw-r--r--thirdparty/directxtex/MIT.txt21
-rw-r--r--thirdparty/directxtex/Microsoft Public License.rtf234
-rw-r--r--thirdparty/directxtex/ReadMe.txt176
-rw-r--r--thirdparty/directxtex/mingw/tweaks.h10
-rw-r--r--thirdparty/dxerr/CMakeLists.txt29
-rw-r--r--thirdparty/dxerr/dxerr.cpp3984
-rw-r--r--thirdparty/dxerr/dxerr.h45
-rw-r--r--thirdparty/dxerr/license.txt61
-rw-r--r--thirdparty/gradlew/gradle/wrapper/gradle-wrapper.jarbin0 -> 49896 bytes
-rw-r--r--thirdparty/gradlew/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xthirdparty/gradlew/gradlew164
-rw-r--r--thirdparty/gradlew/gradlew.bat90
-rw-r--r--thirdparty/gtest/CHANGES157
-rw-r--r--thirdparty/gtest/CMakeLists.txt252
-rw-r--r--thirdparty/gtest/CONTRIBUTORS37
-rw-r--r--thirdparty/gtest/LICENSE28
-rw-r--r--thirdparty/gtest/README435
-rw-r--r--thirdparty/gtest/cmake/.gitignore1
-rw-r--r--thirdparty/gtest/cmake/internal_utils.cmake227
-rw-r--r--thirdparty/gtest/include/gtest/gtest-death-test.h294
-rw-r--r--thirdparty/gtest/include/gtest/gtest-message.h250
-rw-r--r--thirdparty/gtest/include/gtest/gtest-param-test.h1421
-rw-r--r--thirdparty/gtest/include/gtest/gtest-param-test.h.pump487
-rw-r--r--thirdparty/gtest/include/gtest/gtest-printers.h855
-rw-r--r--thirdparty/gtest/include/gtest/gtest-spi.h232
-rw-r--r--thirdparty/gtest/include/gtest/gtest-test-part.h179
-rw-r--r--thirdparty/gtest/include/gtest/gtest-typed-test.h259
-rw-r--r--thirdparty/gtest/include/gtest/gtest.h2291
-rw-r--r--thirdparty/gtest/include/gtest/gtest_pred_impl.h358
-rw-r--r--thirdparty/gtest/include/gtest/gtest_prod.h58
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-death-test-internal.h319
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-filepath.h206
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-internal.h1158
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-linked_ptr.h233
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-param-util-generated.h5143
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-param-util-generated.h.pump301
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-param-util.h619
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-port.h1947
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-string.h167
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-tuple.h1012
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-tuple.h.pump339
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-type-util.h3331
-rw-r--r--thirdparty/gtest/include/gtest/internal/gtest-type-util.h.pump297
-rw-r--r--thirdparty/gtest/src/gtest-all.cc48
-rw-r--r--thirdparty/gtest/src/gtest-death-test.cc1344
-rw-r--r--thirdparty/gtest/src/gtest-filepath.cc382
-rw-r--r--thirdparty/gtest/src/gtest-internal-inl.h1218
-rw-r--r--thirdparty/gtest/src/gtest-port.cc805
-rw-r--r--thirdparty/gtest/src/gtest-printers.cc363
-rw-r--r--thirdparty/gtest/src/gtest-test-part.cc110
-rw-r--r--thirdparty/gtest/src/gtest-typed-test.cc110
-rw-r--r--thirdparty/gtest/src/gtest.cc5015
-rw-r--r--thirdparty/gtest/src/gtest_main.cc38
-rw-r--r--thirdparty/khronos/EGL/egl.h11
-rw-r--r--thirdparty/khronos/EGL/eglext.h281
-rw-r--r--thirdparty/khronos/EGL/eglplatform.h6
-rw-r--r--thirdparty/khronos/EGL/eglplatform.patch14
-rw-r--r--thirdparty/khronos/GL/glext.h986
-rw-r--r--thirdparty/khronos/GL/glxext.h49
-rw-r--r--thirdparty/khronos/GL/wglext.h13
-rw-r--r--thirdparty/khronos/GLES2/gl2.h154
-rw-r--r--thirdparty/khronos/GLES2/gl2ext.h1071
-rw-r--r--thirdparty/khronos/Makefile18
-rw-r--r--thirdparty/libbacktrace/CMakeLists.txt46
-rw-r--r--thirdparty/libbacktrace/ChangeLog278
-rw-r--r--thirdparty/libbacktrace/alloc.c30
-rw-r--r--thirdparty/libbacktrace/atomic.c113
-rw-r--r--thirdparty/libbacktrace/backtrace-supported.h.in7
-rw-r--r--thirdparty/libbacktrace/backtrace.c27
-rw-r--r--thirdparty/libbacktrace/backtrace.h36
-rw-r--r--thirdparty/libbacktrace/btest.c99
-rw-r--r--thirdparty/libbacktrace/config.h.in.cmake3
-rw-r--r--thirdparty/libbacktrace/dwarf.c439
-rw-r--r--thirdparty/libbacktrace/elf.c155
-rw-r--r--thirdparty/libbacktrace/fileline.c42
-rw-r--r--thirdparty/libbacktrace/internal.h70
-rw-r--r--thirdparty/libbacktrace/mmap.c53
-rw-r--r--thirdparty/libbacktrace/mmapio.c2
-rw-r--r--thirdparty/libbacktrace/nounwind.c2
-rw-r--r--thirdparty/libbacktrace/pecoff.c937
-rw-r--r--thirdparty/libbacktrace/posix.c4
-rw-r--r--thirdparty/libbacktrace/print.c2
-rw-r--r--thirdparty/libbacktrace/read.c2
-rw-r--r--thirdparty/libbacktrace/simple.c2
-rw-r--r--thirdparty/libbacktrace/sort.c108
-rw-r--r--thirdparty/libbacktrace/state.c2
-rw-r--r--thirdparty/libbacktrace/stest.c137
-rw-r--r--thirdparty/libbacktrace/unknown.c2
-rw-r--r--thirdparty/libpng/ANNOUNCE56
-rw-r--r--thirdparty/libpng/CHANGES1776
-rw-r--r--thirdparty/libpng/CMakeLists.txt10
-rw-r--r--thirdparty/libpng/LICENSE55
-rw-r--r--thirdparty/libpng/README63
-rw-r--r--thirdparty/libpng/TODO2
-rw-r--r--thirdparty/libpng/png.c2735
-rw-r--r--thirdparty/libpng/png.h2212
-rw-r--r--thirdparty/libpng/pngconf.h484
-rw-r--r--thirdparty/libpng/pngdebug.h22
-rw-r--r--thirdparty/libpng/pngerror.c434
-rw-r--r--thirdparty/libpng/pngget.c563
-rw-r--r--thirdparty/libpng/pnginfo.h76
-rw-r--r--thirdparty/libpng/pnglibconf.h189
-rw-r--r--thirdparty/libpng/pngmem.c675
-rw-r--r--thirdparty/libpng/pngpread.c1056
-rw-r--r--thirdparty/libpng/pngpriv.h1645
-rw-r--r--thirdparty/libpng/pngread.c3714
-rw-r--r--thirdparty/libpng/pngrio.c74
-rw-r--r--thirdparty/libpng/pngrtran.c1518
-rw-r--r--thirdparty/libpng/pngrutil.c3369
-rw-r--r--thirdparty/libpng/pngset.c1227
-rw-r--r--thirdparty/libpng/pngstruct.h249
-rw-r--r--thirdparty/libpng/pngtrans.c279
-rw-r--r--thirdparty/libpng/pngwio.c116
-rw-r--r--thirdparty/libpng/pngwrite.c2101
-rw-r--r--thirdparty/libpng/pngwtran.c267
-rw-r--r--thirdparty/libpng/pngwutil.c2615
-rw-r--r--thirdparty/md5/md5.h10
-rw-r--r--thirdparty/mingw/sal/sal.h27
-rw-r--r--thirdparty/mingw/wrl/wrl/client.h112
-rw-r--r--thirdparty/msinttypes/.gitignore1
-rw-r--r--thirdparty/msinttypes/LICENSE26
-rw-r--r--thirdparty/msinttypes/Makefile10
-rw-r--r--thirdparty/msinttypes/inttypes.h306
-rw-r--r--thirdparty/msinttypes/stdint.h259
-rw-r--r--thirdparty/qjson/.gitignore1
-rw-r--r--thirdparty/qjson/CMakeLists.txt39
-rw-r--r--thirdparty/qjson/COPYING.lib504
-rw-r--r--thirdparty/qjson/README27
-rw-r--r--thirdparty/qjson/json_parser.cc1116
-rw-r--r--thirdparty/qjson/json_parser.hh325
-rw-r--r--thirdparty/qjson/json_parser.yy219
-rw-r--r--thirdparty/qjson/json_scanner.cpp377
-rw-r--r--thirdparty/qjson/json_scanner.h54
-rw-r--r--thirdparty/qjson/location.hh145
-rw-r--r--thirdparty/qjson/parser.cpp125
-rw-r--r--thirdparty/qjson/parser.h94
-rw-r--r--thirdparty/qjson/parser_p.h56
-rw-r--r--thirdparty/qjson/parserrunnable.cpp68
-rw-r--r--thirdparty/qjson/parserrunnable.h67
-rw-r--r--thirdparty/qjson/position.hh142
-rw-r--r--thirdparty/qjson/qjson_debug.h33
-rw-r--r--thirdparty/qjson/qjson_export.h35
-rw-r--r--thirdparty/qjson/qobjecthelper.cpp85
-rw-r--r--thirdparty/qjson/qobjecthelper.h144
-rw-r--r--thirdparty/qjson/serializer.cpp322
-rw-r--r--thirdparty/qjson/serializer.h134
-rw-r--r--thirdparty/qjson/serializerrunnable.cpp60
-rw-r--r--thirdparty/qjson/serializerrunnable.h74
-rw-r--r--thirdparty/qjson/stack.hh129
-rw-r--r--thirdparty/snappy/CMakeLists.txt11
-rw-r--r--thirdparty/snappy/COPYING26
-rw-r--r--thirdparty/snappy/ChangeLog699
-rw-r--r--thirdparty/snappy/NEWS39
-rw-r--r--thirdparty/snappy/config.h68
-rw-r--r--thirdparty/snappy/framing_format.txt35
-rw-r--r--thirdparty/snappy/snappy-c.h2
-rw-r--r--thirdparty/snappy/snappy-internal.h4
-rw-r--r--thirdparty/snappy/snappy-stubs-internal.h84
-rw-r--r--thirdparty/snappy/snappy-stubs-public.h17
-rw-r--r--thirdparty/snappy/snappy-stubs-public.h.in13
-rw-r--r--thirdparty/snappy/snappy-test.cc50
-rw-r--r--thirdparty/snappy/snappy-test.h99
-rw-r--r--thirdparty/snappy/snappy.cc347
-rw-r--r--thirdparty/snappy/snappy.h47
-rw-r--r--thirdparty/snappy/snappy_unittest.cc270
-rw-r--r--thirdparty/zlib/CMakeLists.txt6
-rw-r--r--wrappers/.gitignore1
-rw-r--r--wrappers/CMakeLists.txt277
-rw-r--r--wrappers/assert.cpp65
-rw-r--r--wrappers/cgltrace.py24
-rw-r--r--wrappers/config.cpp449
-rw-r--r--wrappers/config.hpp74
-rw-r--r--wrappers/d2d1trace.def (renamed from wrappers/d2d1.def)2
-rw-r--r--wrappers/d2d1trace.py2
-rw-r--r--wrappers/d3d10.def31
-rw-r--r--wrappers/d3d10_1.def32
-rw-r--r--wrappers/d3d10stubs.cpp522
-rw-r--r--wrappers/d3d11.def44
-rw-r--r--wrappers/d3d11stubs.cpp121
-rw-r--r--wrappers/d3d8trace.py2
-rw-r--r--wrappers/d3d9.def2
-rw-r--r--wrappers/d3d9shader.hpp4
-rw-r--r--wrappers/d3d9trace.py60
-rw-r--r--wrappers/d3dcommonshader.hpp4
-rw-r--r--wrappers/d3dkmtstubs.cpp713
-rw-r--r--wrappers/ddraw.def2
-rw-r--r--wrappers/ddrawtrace.py34
-rw-r--r--wrappers/dlltrace.py3
-rw-r--r--wrappers/dwrite.def4
-rw-r--r--wrappers/dwritetrace.cpp6
-rw-r--r--wrappers/dxgi.def47
-rw-r--r--wrappers/dxgistubs.cpp114
-rw-r--r--wrappers/dxgitrace.def16
-rw-r--r--wrappers/dxgitrace.py78
-rw-r--r--wrappers/egltrace.py59
-rw-r--r--wrappers/egltrace.version10
-rw-r--r--wrappers/glcaps.cpp119
-rw-r--r--wrappers/gltrace.hpp23
-rw-r--r--wrappers/gltrace.py502
-rw-r--r--wrappers/gltrace_state.cpp9
-rw-r--r--wrappers/glxtrace.py2
-rw-r--r--wrappers/glxtrace.version9
-rw-r--r--wrappers/trace.py291
-rw-r--r--wrappers/wgltrace.py145
616 files changed, 121441 insertions, 37200 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..bcb9c924
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,19 @@
+# http://editorconfig.org
+
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+
+[*.{markdown,md}]
+trim_trailing_whitespace = false
+
+[*.yml]
+indent_style = space
+indent_size = 2
+
+[{Makefile,*.mk}]
+indent_style = tab
+indent_size = 8
+tab_width = 8
diff --git a/.gitignore b/.gitignore
index cd840f6c..6e689285 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,6 +27,7 @@
*.so
*.trace
*.zip
+*.ubj
_CPack_Packages
CMakeCache.txt
CMakeFiles
@@ -37,6 +38,10 @@ build
dxsdk
eglretrace
glretrace
+guids_test
install_manifest.txt
qapitrace
+qubjson_test
+trace_parser_flags_test
traces
+Testing
diff --git a/.lvimrc b/.lvimrc
deleted file mode 100644
index 2bb16b4f..00000000
--- a/.lvimrc
+++ /dev/null
@@ -1 +0,0 @@
-set sw=4 ts=8 et
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..8f20e2a2
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,79 @@
+branches:
+ except:
+ - /^appveyor.*$/
+
+sudo: required
+dist: trusty
+
+language: generic
+
+env:
+ global:
+ - MAKEFLAGS=-j2
+
+matrix:
+ include:
+ - os: linux
+ env:
+ - APT_REPOS="ppa:ubuntu-toolchain-r/test"
+ - APT_PACKAGES="gcc-4.9 g++-4.9 libdwarf-dev libprocps3-dev qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev"
+ - CMAKE_OPTIONS="-DCMAKE_C_COMPILER=gcc-4.9 -DCMAKE_CXX_COMPILER=g++-4.9 -DENABLE_GUI=1"
+ - os: linux
+ env:
+ - APT_REPOS="ppa:ubuntu-toolchain-r/test"
+ - APT_PACKAGES="gcc-4.9-multilib g++-4.9-multilib"
+ - CMAKE_OPTIONS="-DCMAKE_C_COMPILER=gcc-4.9 -DCMAKE_CXX_COMPILER=g++-4.9 -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 -DCMAKE_SYSTEM_LIBRARY_PATH=/usr/lib32 -DENABLE_GUI=0"
+ - os: linux
+ env:
+ - APT_PACKAGES="clang-3.6 libc++-dev libc++abi-dev libdwarf-dev libprocps3-dev qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev"
+ - CMAKE_OPTIONS="-DCMAKE_C_COMPILER=clang-3.6 -DCMAKE_CXX_COMPILER=clang++-3.6 -DCMAKE_CXX_FLAGS=-stdlib=libc++ -DENABLE_GUI=1"
+ - os: linux
+ env:
+ - APT_REPOS="ppa:tobydox/mingw-x-trusty"
+ - APT_PACKAGES="mingw32-x-gcc"
+ - MINGW_ROOT=/opt/mingw32
+ - MINGW_PREFIX=i686-w64-mingw32
+ - CMAKE_OPTIONS="-DCMAKE_TOOLCHAIN_FILE=Toolchain.cmake -Cdxsdk-master/Cache-mingw32.cmake -DENABLE_GUI=0"
+ - os: osx
+ env:
+ - CMAKE_OPTIONS="-DENABLE_GUI=1"
+
+before_install:
+- |
+ if [ "$APT_PACKAGES" ]
+ then for APT_REPO in $APT_REPOS
+ do
+ sudo add-apt-repository -y $APT_REPO
+ done
+ if [ "$CXX" == "clang++" ]
+ then
+ wget -nv -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
+ sudo apt-add-repository -y 'deb http://llvm.org/apt/trusty llvm-toolchain-trusty-3.6 main'
+ fi
+ sudo apt-get update -qq
+ sudo apt-get install -qq -y $APT_PACKAGES
+ fi
+- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew install qt5; export CMAKE_PREFIX_PATH=$(brew --prefix qt5); fi
+- if [ "$MINGW_ROOT" ]; then export PATH=$MINGW_ROOT/bin:$PATH; fi
+- cmake --version
+
+script:
+- |
+ if [ "$MINGW_PREFIX" ]
+ then
+ echo "set (CMAKE_SYSTEM_NAME Windows)" >> Toolchain.cmake
+ echo "set (CMAKE_C_COMPILER $MINGW_PREFIX-gcc)" >> Toolchain.cmake
+ echo "set (CMAKE_CXX_COMPILER $MINGW_PREFIX-g++)" >> Toolchain.cmake
+ echo "set (CMAKE_RC_COMPILER $MINGW_PREFIX-windres)" >> Toolchain.cmake
+ echo "set (CMAKE_FIND_ROOT_PATH $MINGW_ROOT)" >> Toolchain.cmake
+ echo "set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)" >> Toolchain.cmake
+ echo "set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)" >> Toolchain.cmake
+ echo "set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)" >> Toolchain.cmake
+ wget -q -O - https://github.com/apitrace/dxsdk/archive/master.tar.gz | tar -xz
+ fi
+- cmake -H. -Bbuild $CMAKE_OPTIONS
+- cmake --build build --use-stderr -- -k
+- cmake --build build --use-stderr --target check -- -k
+- cmake --build build --use-stderr --target package -- -k
+
+# vim: set sw=2 et :
diff --git a/Android.mk b/Android.mk
index 481898e6..89e1c944 100644
--- a/Android.mk
+++ b/Android.mk
@@ -49,7 +49,12 @@ MY_APITRACE_ROOT := $(TOPDIR)external/apitrace
MY_APITRACE_BUILD_ROOT_HOST := out/host/apitrace
MY_APITRACE_BUILD_ROOT_TARGET := out/target/apitrace
-apitrace_private_target:
+MY_ANDROID_CMAKE_COMMIT := 556cc14296c226f753a3778d99d8b60778b7df4f
+
+android.toolchain.cmake:
+ curl -s -O https://raw.githubusercontent.com/taka-no-me/android-cmake/$(MY_ANDROID_CMAKE_COMMIT)/android.toolchain.cmake
+
+apitrace_private_target: android.toolchain.cmake
$(hide) # apitrace: run cmake for the host if it has not been run
$(hide) if [ ! -e $(MY_APITRACE_BUILD_ROOT_HOST)/Makefile ] ; then \
cd $(MY_APITRACE_ROOT) && \
@@ -61,7 +66,7 @@ apitrace_private_target:
$(hide) if [ ! -e $(MY_APITRACE_BUILD_ROOT_TARGET)/Makefile ] ; then \
cd $(MY_APITRACE_ROOT) && \
cmake \
- -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/android.toolchain.cmake \
+ -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake \
-DANDROID_NDK=../../$(NDK) \
-DANDROID_NDK_LAYOUT=LINARO \
-DANDROID_TOOLCHAIN_NAME=$(TOOLCHAIN) \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4031eb3..200cc24f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,14 +1,15 @@
-cmake_minimum_required (VERSION 2.8)
+cmake_minimum_required (VERSION 2.8.11)
-# Use clang on MacOSX. gcc doesn't support __thread key, and Apple has
-# abandoned it for clang. This must be done before the project is defined.
-# But DONT force clang if we are cross-compiling to Android.
-if (APPLE AND NOT ANDROID_NDK)
- set (CMAKE_C_COMPILER "clang")
- set (CMAKE_CXX_COMPILER "clang++")
+if (CMAKE_GENERATOR STREQUAL "Xcode")
+ message (FATAL_ERROR "Xcode generator is not supported. Please build with \"Unix Makefiles\" or \"Ninja\" generators.")
endif ()
+# http://www.cmake.org/cmake/help/v3.0/policy/CMP0042.html
+if (POLICY CMP0042)
+ cmake_policy (SET CMP0042 NEW)
+endif()
+
project (apitrace)
@@ -27,11 +28,40 @@ endif ()
# prescribed in http://www.gentoo.org/proj/en/qa/automagic.xml
set (ENABLE_GUI "AUTO" CACHE STRING "Enable Qt GUI.")
-set (ENABLE_CLI true CACHE BOOL "Enable command Line interface.")
-
-set (ENABLE_EGL true CACHE BOOL "Enable EGL support.")
-
-set (ENABLE_WAFFLE false CACHE BOOL "Enable WAFFLE support.")
+option (ENABLE_CLI "Enable command Line interface." ON)
+
+option (ENABLE_EGL "Enable EGL support." ON)
+
+option (ENABLE_WAFFLE "Enable WAFFLE support." OFF)
+
+option (ENABLE_FRAME_POINTER "Disable frame pointer omission" ON)
+
+# Proprietary Linux games often ship their own libraries (zlib, libstdc++,
+# etc.) in order to ship a single set of binaries across multiple
+# distributions. Given that apitrace wrapper modules will be loaded into those
+# processes, they must not depend on any shared object that could also be
+# provided by such applications. See also
+# http://lists.freedesktop.org/archives/mesa-dev/2015-March/079121.html
+if (NOT ANDROID)
+ option (ENABLE_STATIC_SNAPPY "Statically link against snappy" ON)
+ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ option (ENABLE_STATIC_LIBGCC "Statically link LD_PRELOAD wrappers against libgcc" ON)
+ option (ENABLE_STATIC_LIBSTDCXX "Statically link LD_PRELOAD wrappers against libstdc++" ON)
+ if (NOT (ENABLE_STATIC_LIBGCC AND
+ ENABLE_STATIC_LIBSTDCXX AND
+ ENABLE_STATIC_SNAPPY))
+ # XXX: Should probably throw a run-time too.
+ message (WARNING
+ "LD_PRELOAD wrappers not statically linked against all "
+ "dependencies, therefore will fail to work with many "
+ "third-party applications built on different Linux "
+ "distributions and that ship their own shared-object "
+ "dependencies."
+ )
+ endif ()
+ option (ENABLE_STATIC_EXE "Statically link executables" OFF)
+ endif ()
+endif ()
##############################################################################
@@ -42,15 +72,15 @@ set (ENABLE_WAFFLE false CACHE BOOL "Enable WAFFLE support.")
# DLLs.
if (NOT WIN32)
include (CheckCXXSourceCompiles)
- check_cxx_source_compiles("__thread int i; int main() { return 0; }" HAVE_COMPILER_TLS)
- if (HAVE_COMPILER_TLS)
- add_definitions (-DHAVE_COMPILER_TLS=__thread)
- else ()
- message (WARNING "C++ compiler does not support __thread keyword.")
+ check_cxx_source_compiles ("__thread int i; int main() { return 0; }" HAVE_COMPILER_TLS)
+ if (NOT HAVE_COMPILER_TLS)
+ message (FATAL_ERROR "C++ compiler does not support __thread keyword.")
endif ()
endif ()
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
+include (ConvenienceLibrary)
+include (InstallPDB)
if (ANDROID)
set (ENABLE_GUI false)
@@ -60,27 +90,45 @@ else ()
endmacro()
endif ()
-find_host_package (PythonInterp 2.6 REQUIRED)
+find_host_package (PythonInterp 2.7 REQUIRED)
if (NOT PYTHON_VERSION_MAJOR EQUAL 2)
message (FATAL_ERROR "Python 2.x required and requested, but Python ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} found.")
endif ()
find_package (Threads)
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT ENABLE_STATIC_EXE)
+ find_package (procps)
+ if (PROCPS_FOUND)
+ add_definitions (-DHAVE_READPROC_H)
+ endif ()
+endif ()
+
if (ENABLE_GUI)
if (NOT (ENABLE_GUI STREQUAL "AUTO"))
set (REQUIRE_GUI REQUIRED)
endif ()
- find_package (Qt4 4.7 COMPONENTS QtCore QtGui QtWebKit ${REQUIRE_GUI})
+ if (POLICY CMP0020)
+ cmake_policy (SET CMP0020 NEW)
+ endif()
+ find_package (Qt5Widgets ${REQUIRE_GUI})
+ find_package (Qt5WebKitWidgets ${REQUIRE_GUI})
+endif ()
+
+if (MSVC)
+ if (${MSVC_VERSION} LESS 1800)
+ message (FATAL_ERROR "Visual Studio 2013 or later required")
+ endif ()
+
+ include (Windows10SDK)
endif ()
if (WIN32)
find_package (DirectX)
- foreach (api in D3D D3D8 D3D9 D3D10 D3D10_1 D3D11 D3D11_1 D2D1)
- if (EXISTS "${DirectX_${api}_INCLUDE_DIR}")
- find_package_message (${api} "Found ${api}" "${DirectX_${api}_INCLUDE_DIR}")
- endif ()
- endforeach ()
+
+ if (DEFINED MSVC_VERSION AND NOT DirectX_D3D11_3_INCLUDE_FOUND AND NOT CMAKE_GENERATOR_TOOLSET MATCHES "_xp$")
+ message (WARNING "Windows 10 SDK (https://dev.windows.com/en-us/downloads/windows-10-sdk) is required for D3D11.3 support")
+ endif ()
set (ENABLE_EGL false)
elseif (APPLE)
@@ -98,9 +146,9 @@ else ()
endif ()
endif ()
-if (ENABLE_EGL AND (ANDROID OR ENABLE_WAFFLE))
- # if waffle is found eglretrace will be built for Android.
- find_package (Waffle)
+if (ENABLE_EGL AND ENABLE_WAFFLE)
+ # Use Waffle for eglretrace
+ find_package (Waffle REQUIRED)
endif ()
@@ -110,27 +158,50 @@ endif ()
include (CheckCXXCompilerFlag)
include (CheckIncludeFileCXX)
+macro (add_compiler_flags)
+ string (REPLACE ";" " " _FLAGS "${ARGV}")
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FLAGS}")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_FLAGS}")
+endmacro ()
+
+macro (add_linker_flags)
+ string (REPLACE ";" " " _FLAGS "${ARGV}")
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_FLAGS}")
+ set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${_FLAGS}")
+ set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${_FLAGS}")
+endmacro ()
+
+add_definitions (
+ -D__STDC_LIMIT_MACROS
+ -D__STDC_FORMAT_MACROS
+)
+
if (WIN32)
# http://msdn.microsoft.com/en-us/library/aa383745.aspx
- add_definitions (-D_WIN32_WINNT=0x0601 -DWINVER=0x0601)
+ if (MINGW OR CMAKE_GENERATOR_TOOLSET MATCHES "_xp$")
+ # Windows XP
+ add_definitions (-D_WIN32_WINNT=0x0501 -DWINVER=0x0501)
+ else ()
+ # Windows 7
+ add_definitions (-D_WIN32_WINNT=0x0601 -DWINVER=0x0601)
+ endif ()
else (WIN32)
CHECK_CXX_COMPILER_FLAG("-fvisibility=hidden" CXX_COMPILER_FLAG_VISIBILITY)
if (CXX_COMPILER_FLAG_VISIBILITY)
- add_definitions ("-fvisibility=hidden")
+ add_compiler_flags (-fvisibility=hidden)
endif ()
endif ()
if (MSVC)
- # Use bundled stdint.h for older MSVC versions
- check_include_file_cxx (stdint.h HAVE_STDINT_H)
- if (NOT HAVE_STDINT_H)
- include_directories (${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/msinttypes)
- endif ()
-
# No RTTI required
string (REGEX REPLACE "/GR *" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
+ # Disable C++ exceptions
+ add_definitions (-D_HAS_EXCEPTIONS=0)
+ string (REGEX REPLACE "/EHsc *" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
+
# Enable math constants defines
add_definitions (-D_USE_MATH_DEFINES)
@@ -140,16 +211,17 @@ if (MSVC)
# Adjust warnings
add_definitions (-D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
add_definitions (-D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
- add_definitions (-W3)
+ add_compiler_flags (-W3)
# XXX: it's safer to use ssize_t everywhere instead of disabling warning
- add_definitions (-wd4018) # signed/unsigned mismatch
- add_definitions (-wd4063) # not a valid value for switch of enum
- add_definitions (-wd4100) # unreferenced formal parameter
- add_definitions (-wd4127) # conditional expression is constant
- add_definitions (-wd4244) # conversion from 'type1' to 'type2', possible loss of data
- add_definitions (-wd4505) # unreferenced local function has been removed
- add_definitions (-wd4512) # assignment operator could not be generated
- add_definitions (-wd4800) # forcing value to bool 'true' or 'false' (performance warning)
+ add_compiler_flags (-wd4018) # signed/unsigned mismatch
+ add_compiler_flags (-wd4063) # not a valid value for switch of enum
+ add_compiler_flags (-wd4100) # unreferenced formal parameter
+ add_compiler_flags (-wd4127) # conditional expression is constant
+ add_compiler_flags (-wd4244) # conversion from 'type1' to 'type2', possible loss of data
+ add_compiler_flags (-wd4267) # conversion from 'type1' to 'type2', possible loss of data
+ add_compiler_flags (-wd4505) # unreferenced local function has been removed
+ add_compiler_flags (-wd4512) # assignment operator could not be generated
+ add_compiler_flags (-wd4800) # forcing value to bool 'true' or 'false' (performance warning)
# Use static runtime
# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
@@ -162,74 +234,147 @@ if (MSVC)
endif ()
endforeach (flag_var)
else ()
+ # Enable and require C++11
+ #
+ # We must use `-std=gnu++11` instead `-std=c++11` as the latter defines
+ # __STRICT_ANSI__ which prevents _isnan from being declared with MinGW.
+ #
+ # See also:
+ # - https://gcc.gnu.org/projects/cxx0x.html
+ # - http://clang.llvm.org/cxx_status.html
+ check_cxx_compiler_flag ("-std=gnu++11" CXX_COMPILER_FLAG_STD_GNUXX11)
+ if (CXX_COMPILER_FLAG_STD_GNUXX11)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
+ else ()
+ message (FATAL_ERROR "${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} compiler does not support C++11")
+ endif ()
+
+ # We require at least GCC 4.9 for decent C++11 support
+ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND
+ CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9")
+ message (WARNING "GCC 4.9 or later recommended -- https://github.com/apitrace/apitrace/wiki/GCC")
+ endif ()
+
# Adjust warnings
- add_definitions (-Wall)
+ add_compiler_flags (-Wall)
# XXX: it's safer to use ssize_t everywhere instead of disabling warning
- add_definitions (-Wno-sign-compare) # comparison between signed and unsigned integer expressions
+ add_compiler_flags (-Wno-sign-compare) # comparison between signed and unsigned integer expressions
+
+ # Disable strict aliasing assumptions. We generate a lot of C++ code, and
+ # it's not always easy to guarantee or spot when strict aliasing
+ # assumptions are violated. Above all, the benefit is not worth the risk.
+ add_compiler_flags (-fno-strict-aliasing)
# No RTTI required
- #set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+ # XXX: there's a dynamic_cast in Android
+ if (NOT ANDROID)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+ endif ()
- # Use GDB extensions if available
- if (CMAKE_COMPILER_IS_GNUC)
- set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -O0")
- set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -ggdb")
+ # Disable C++ exceptions
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
+
+ # Enable stack protection
+ if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_COMPILER_IS_GNUCXX)
+ set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fstack-protector-all")
+ set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstack-protector-all")
+ if (MINGW)
+ # MinGW doesn't link against libssp automatically, and furthermore
+ # we want static linking.
+ set (SSP_LIBRARY "-Wl,-Bstatic -lssp -Wl,-Bdynamic")
+ set (CMAKE_C_STANDARD_LIBRARIES "${SSP_LIBRARY} ${CMAKE_C_STANDARD_LIBRARIES}")
+ set (CMAKE_CXX_STANDARD_LIBRARIES "${SSP_LIBRARY} ${CMAKE_CXX_STANDARD_LIBRARIES}")
+ endif ()
endif ()
- if (CMAKE_COMPILER_IS_GNUCXX)
- set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O0")
- set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -ggdb")
+
+ # Enable SSE2 intrinsics on x86
+ if (MINGW AND CMAKE_SIZEOF_VOID_P EQUAL 4)
+ add_compiler_flags (-msse2 -mfpmath=sse)
+
+ # And tell GCC to assume 4 bytes alignment, many Linux/Windows
+ # applications only guarantee that, but not on systems where ABI
+ # clearly states otherwise.
+ #
+ # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38496
+ add_compiler_flags (-mincoming-stack-boundary=2)
endif ()
# Be nice to Eclipse
- add_definitions (-fmessage-length=0)
+ add_compiler_flags (-fmessage-length=0)
+endif ()
+
+if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_BUILD_TYPE MATCHES Rel)
+ message (WARNING
+ "\n"
+ " WARNING: NON-DEBUG BUILDS ON CLANG CAN TAKE UP TO 45MIN!\n"
+ " See https://github.com/apitrace/apitrace/issues/346\n"
+ ""
+ )
+ execute_process (COMMAND ${CMAKE_COMMAND} -E sleep 5)
endif ()
if (MINGW)
# Avoid depending on MinGW runtime DLLs
- check_cxx_compiler_flag (-static-libgcc HAVE_STATIC_LIBGCC_FLAG)
- if (HAVE_STATIC_LIBGCC_FLAG)
- set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc")
- set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc")
- set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -static-libgcc")
+ add_linker_flags (-static-libgcc -static-libstdc++)
+elseif (ENABLE_STATIC_EXE)
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
+endif ()
+
+if (ENABLE_FRAME_POINTER)
+ # disable frame pointer omission
+ if (MSVC)
+ add_compiler_flags (/Oy-)
+ else ()
+ add_compiler_flags (-fno-omit-frame-pointer)
endif ()
- check_cxx_compiler_flag (-static-libstdc++ HAVE_STATIC_LIBSTDCXX_FLAG)
- if (HAVE_STATIC_LIBSTDCXX_FLAG)
- set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++")
- set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++")
- set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -static-libstdc++")
+endif ()
+
+# Enable Data Execution Prevention and Address Space Layout Randomization
+if (WIN32)
+ if (MSVC)
+ add_linker_flags (/NXCOMPAT /DYNAMICBASE)
+ else ()
+ add_linker_flags (-Wl,--nxcompat -Wl,--dynamicbase)
endif ()
endif ()
-if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
# For RTLD_DEFAULT and RTLD_NEXT
add_definitions (-D_GNU_SOURCE)
endif ()
-check_include_file_cxx (tr1/memory HAVE_TR1_MEMORY)
-if (HAVE_TR1_MEMORY)
- add_definitions (-DHAVE_TR1_MEMORY)
+include (TestBigEndian)
+test_big_endian (HAVE_BIGENDIAN)
+if (HAVE_BIGENDIAN)
+ add_definitions (-DHAVE_BIGENDIAN)
endif ()
# Put all executables into the same top level build directory, regardless of
# which subdirectory they are declared
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+enable_testing ()
+if (CMAKE_CROSSCOMPILING)
+ add_custom_target (check)
+elseif (DEFINED CMAKE_BUILD_TYPE)
+ # Single configuration
+ add_custom_target (check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure)
+else ()
+ # Multiple configuration
+ add_custom_target (check COMMAND ${CMAKE_CTEST_COMMAND} -C "$<CONFIG>" --output-on-failure)
+endif ()
+
##############################################################################
# Installation directories
-if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
# Debian multiarch support
execute_process(COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
OUTPUT_VARIABLE ARCH_SUBDIR
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
- CHECK_INCLUDE_FILES(proc/readproc.h READPROC_H_FOUND)
- if (READPROC_H_FOUND)
- add_definitions (-DHAVE_READPROC_H)
- find_library (proc_LIBRARY NAMES proc procps)
- endif ()
endif()
if (WIN32 OR APPLE)
@@ -255,28 +400,49 @@ set (WRAPPER_INSTALL_DIR ${LIB_ARCH_INSTALL_DIR}/wrappers)
##############################################################################
# Bundled dependencies
#
-# We always use the bundled zlib, libpng, and snappy sources:
+# We prefer to bundle and statically link against many dependencies:
# - on Windows to make it easy to deploy the wrappers DLLs
# - on unices to prevent symbol collisions when tracing applications that link
# against other versions of these libraries
-set (ZLIB_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/zlib)
-set (ZLIB_LIBRARIES z_bundled)
-add_subdirectory (thirdparty/zlib)
-
-include_directories (${ZLIB_INCLUDE_DIRS})
-
-set (SNAPPY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/snappy)
-set (SNAPPY_LIBRARIES snappy_bundled)
-add_subdirectory (thirdparty/snappy)
-
+if (NOT ENABLE_STATIC_SNAPPY)
+ find_package (SNAPPY)
+endif ()
+if (ENABLE_STATIC_SNAPPY OR NOT SNAPPY_FOUND)
+ message (STATUS "Using bundled SNAPPY")
+ set (SNAPPY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/snappy)
+ set (SNAPPY_LIBRARIES snappy_bundled)
+ add_subdirectory (thirdparty/snappy)
+endif ()
include_directories (${SNAPPY_INCLUDE_DIRS})
-set (PNG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libpng)
-set (PNG_DEFINITIONS "")
-set (PNG_LIBRARIES png_bundled)
+if (NOT WIN32 AND NOT ENABLE_STATIC_EXE)
+ # zlib 1.2.4-1.2.5 made it impossible to read the last block of incomplete
+ # gzip traces (e.g., apitrace-tests/traces/zlib-no-eof.trace).
+ find_package (ZLIB 1.2.6)
+endif ()
+if (NOT ZLIB_FOUND)
+ message (STATUS "Using bundled ZLIB")
+ set (ZLIB_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/zlib)
+ set (ZLIB_LIBRARIES z_bundled)
+ add_subdirectory (thirdparty/zlib)
+endif ()
+include_directories (${ZLIB_INCLUDE_DIRS})
-add_subdirectory (thirdparty/libpng)
+# FindPNG.cmake will search ZLIB internally (without requiring any particular
+# version), adding its include dirs and libraries, and overwriting ZLIB_FOUND.
+# So if the system's ZLIB was did not meet the our requirements, then there's
+# no safe way to use the system's PNG library.
+if (NOT WIN32 AND NOT ENABLE_STATIC_EXE AND ZLIB_FOUND)
+ find_package (PNG)
+endif ()
+if (NOT PNG_FOUND)
+ message (STATUS "Using bundled PNG")
+ set (PNG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libpng)
+ set (PNG_DEFINITIONS "")
+ set (PNG_LIBRARIES png_bundled)
+ add_subdirectory (thirdparty/libpng)
+endif ()
if (MSVC)
add_subdirectory (thirdparty/getopt)
@@ -285,13 +451,15 @@ if (MSVC)
endif ()
if (WIN32)
+ add_subdirectory (thirdparty/dxerr)
add_subdirectory (thirdparty/directxtex)
+ add_subdirectory (thirdparty/devcon)
endif ()
if (CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
add_subdirectory (thirdparty/libbacktrace)
include_directories (${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libbacktrace)
- set (LIBBACKTRACE_LIBRARIES dl backtrace)
+ set (LIBBACKTRACE_LIBRARIES ${CMAKE_DL_LIBS} backtrace)
add_definitions (-DHAVE_BACKTRACE=1)
endif ()
@@ -299,82 +467,36 @@ add_subdirectory (thirdparty/md5)
set (MD5_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/md5)
set (MD5_LIBRARIES md5_bundled)
-# Always use bundled QJSon.
-# - The packaged versions QJson are very old, and do not support NaN/Infinity.
-# - To make it easier to build the GUI on Windows and MacOSX, as there are no
-# binaries at all.
-if (QT4_FOUND)
- add_definitions (-DQJSON_EXPORT=)
- add_subdirectory (thirdparty/qjson)
- set (QJSON_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty)
- set (QJSON_LIBRARY_DIRS)
- set (QJSON_LIBRARIES qjson_bundled)
- set (QJSON_FOUND TRUE)
-endif ()
-
# We use bundled headers for all Khronos APIs, to guarantee support for both
# OpenGL and OpenGL ES at build time, because the OpenGL and OpenGL ES 1 APIs
# are so intertwined that conditional compilation extremely difficult. This
# also avoids missing/inconsistent declarations in system headers.
include_directories (BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/khronos)
+# We use non-standard C++ flags, so we can't just use GTest's CMakeLists.txt
+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/gtest/include)
+add_library (gtest ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/gtest/src/gtest-all.cc)
+set_property (TARGET gtest APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/gtest)
+target_link_libraries (gtest ${CMAKE_THREAD_LIBS_INIT})
+
+# Convenience macro for adding unit tests
+macro (add_gtest)
+ add_executable (${ARGV})
+ target_link_libraries (${ARGV0} gtest)
+ add_dependencies (check ${ARGV0})
+ add_test (NAME ${ARGV0} COMMAND $<TARGET_FILE:${ARGV0}>)
+endmacro ()
+
##############################################################################
# Common libraries / utilities
include_directories (
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/common
)
-if (WIN32)
- set (os os_win32.cpp)
-else ()
- set (os os_posix.cpp)
-endif ()
-
-add_library (common STATIC
- common/trace_callset.cpp
- common/trace_dump.cpp
- common/trace_fast_callset.cpp
- common/trace_file.cpp
- common/trace_file_read.cpp
- common/trace_file_write.cpp
- common/trace_file_zlib.cpp
- common/trace_file_snappy.cpp
- common/trace_model.cpp
- common/trace_parser.cpp
- common/trace_parser_flags.cpp
- common/trace_writer.cpp
- common/trace_writer_local.cpp
- common/trace_writer_model.cpp
- common/trace_loader.cpp
- common/trace_profiler.cpp
- common/trace_option.cpp
- common/${os}
- common/os_backtrace.cpp
- common/highlight.cpp
-)
-
-set_target_properties (common PROPERTIES
- # Ensure it can be statically linked in shared libraries
- COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}"
-)
-
-target_link_libraries (common
- ${LIBBACKTRACE_LIBRARIES}
-)
-if (ANDROID)
- target_link_libraries (common
- log
- )
-endif ()
-
-
-##############################################################################
-# Sub-directories
-
+add_subdirectory (guids)
+add_subdirectory (common)
add_subdirectory (dispatch)
add_subdirectory (helpers)
add_subdirectory (wrappers)
@@ -390,35 +512,15 @@ if (ENABLE_CLI)
add_subdirectory (inject)
endif ()
add_subdirectory (cli)
+ add_subdirectory (scripts)
endif ()
-##############################################################################
-# Scripts (to support the CLI)
-
-install (
- PROGRAMS
- scripts/highlight.py
- scripts/jsondiff.py
- scripts/profileshader.py
- scripts/retracediff.py
- scripts/snapdiff.py
- scripts/tracecheck.py
- scripts/tracediff.py
- scripts/unpickle.py
- DESTINATION ${SCRIPTS_INSTALL_DIR}
-)
-if (WIN32)
- install (
- PROGRAMS scripts/convert.py
- DESTINATION ${SCRIPTS_INSTALL_DIR}
- )
-endif ()
##############################################################################
# GUI
-if (ENABLE_GUI AND QT4_FOUND AND QJSON_FOUND)
- add_subdirectory(gui)
+if (ENABLE_GUI AND Qt5Widgets_FOUND AND Qt5WebKitWidgets_FOUND)
+ add_subdirectory(gui)
endif ()
@@ -427,9 +529,10 @@ endif ()
install (
FILES
- BUGS.markdown
- NEWS.markdown
README.markdown
+ docs/BUGS.markdown
+ docs/NEWS.markdown
+ docs/USAGE.markdown
DESTINATION ${DOC_INSTALL_DIR}
)
install (
@@ -437,15 +540,8 @@ install (
DESTINATION ${DOC_INSTALL_DIR}
RENAME LICENSE.txt
)
-if (MSVC)
- install (
- FILES thirdparty/msinttypes/LICENSE
- DESTINATION ${DOC_INSTALL_DIR}
- RENAME LICENSE-msinttypes.txt
- )
-endif ()
-set (CPACK_PACKAGE_VERSION_MAJOR "5")
+set (CPACK_PACKAGE_VERSION_MAJOR "7")
set (CPACK_PACKAGE_VERSION_MINOR "0")
# Use current date in YYYYMMDD format as patch number
@@ -463,7 +559,11 @@ endif ()
# See http://www.vtk.org/Wiki/CMake:CPackPackageGenerators
if (WIN32)
- set (CPACK_GENERATOR "ZIP")
+ if (CMAKE_VERSION VERSION_LESS 3.1)
+ set (CPACK_GENERATOR "ZIP")
+ else ()
+ set (CPACK_GENERATOR "7Z")
+ endif ()
elseif (APPLE)
set (CPACK_GENERATOR "DragNDrop")
else ()
diff --git a/DEVELOPMENT.markdown b/DEVELOPMENT.markdown
deleted file mode 100644
index 154b3695..00000000
--- a/DEVELOPMENT.markdown
+++ /dev/null
@@ -1,169 +0,0 @@
-Overview
-=========
-
-Although focus was and still is on graphical APIs, apitrace has a
-generic infrastructure to trace any kind of API:
-
- * the APIs types and calls are specified in Python files in specs
- sub-directory;
-
- * there is a type hierarchy in specs/stdapi.py, capable of representing
- most types in C language, and additional semantic metadata
-
- * Python scripts generate C++ code to trace and serialize calls parameters to
- a file, and vice-versa.
-
- * Visitor software design pattern is used to navigate over the types.
-
- * Template design pattern is use so that any step of code generation can be
- overriden by derived classes, allowing to easily handle cases that need
- special treatment without sacrifycing code reuse.
-
-apitrace's architecture is composed of several layers. Too many to show in a
-single graph, so only those relevant for OpenGL API are shown below:
-
- specs
- ^
- |
- dispatch <-------------- glws
- ^ ^
- | /
- helpers <--- glstate /
- ^ ^ ^ /
- / \ | /
- / \ | /
- trace retrace | /
- ^ ^ | /
- / \ | /
- gltrace glretrace
- / | \
- / | \
- / | \
- / | \
- / | \
- glxtrace wgltrace cgltrace
-
-Here is a quick synopsis of what the layers do:
-
- * specs -- specification of the API, expressed in a Python class hierarchy
-
- * dispatch -- runtime dispatch of calls to DLLs (open the DLL, get the symbol
- address, and call it passing all arguments as-is)
-
- * helpers -- helper functions to determine sizes of arrays, blobs, etc. It
- often needs to dispatch calls to give the answers.
-
- * trace -- generate C++ code for tracing an API based on its spec
-
- * gltrace -- specialization of the tracing generation for GL API, with extra
- code to generate
-
- * glxtrace, wgltrace, cgltrace -- specialization of the tracing code for the
- GLX, WGL, and CGL APIs.
-
- * retrace -- generate C++ code to interpret calls from trace, based on the
- API's spec
-
- * glretrace -- specialization of the retrace code for the GL API
-
- * glstate -- code to dump OpenGL state to a JSON file
-
- * glws -- abstraction of the window system specific APIs (GXL, WGL, CGL), to
- enable cross-platform portability of glretrace
-
-
-Coding Style
-============
-
-These are guidelines for new code. Admittedly some of the existing code hasn't
-been updated to follow these conventions yet.
-
-Whitespace (all languages):
-
- * indentation is 4 spaces
-
- * never use tabs as indents
-
- * otherwise tab equals to 8 spaces
-
- * separate classes with two empty lines
-
-Naming convention:
-
- * camelCase for functions/methods
-
- * UpperCase for structures/classes
-
- * lowercase for namespaces/modules
-
- * `UPPER_CASE` for #defines
-
- * single underscore prefix for variables/functions in automatically generated
- code
-
-C++:
-
- * enclose single statement `if` clauses in { }, specially for automatically
- generated code
-
- * } else {
-
- * use inlines for functions/methods which are called with high-frequency
-
-CMake:
-
- * `lower_case` commands
-
- * space between ( and precedent name
-
-
-When in doubt, be consistent with the existing code.
-
-
-Commit policy
-=============
-
-Feature development:
-
-* Existing features in master branch should not degrade at any time, for any
- platform. (Unless they are seldom used or redundant and there is agreement.)
-
- * In particular, new features / changes must not introduce any sort of
- instability when tracing.
-
- While application developers and driver developers may be able to
- workaround quirks in apitrace, we want to be able to obtain traces from
- non-technical end-users with minimal intervention.
-
- This implies that tracing should not make any non-standard assumptions, and
- care must be taken to ensure the tracing code is robust against invalid
- parameters, multiple threads, etc.
-
-* It's fine to add new features for only some platforms or APIs.
-
-* Non-trivial changes should be staged in a branch, to allow review and
- regression testing. Feature branches should be deleted once they have been
- merged.
-
-* Releases are tagged commits from master. There are no stable branches.
-
-
-Backwards compatibility:
-
-* Backwards binary compatibility with old traces must be always maintained: all
- tools, including glretrace, must handle old traces without regressions.
-
-* No backwards compatibility guarantees for derived data (ASCII dumps, state,
- images, etc).
-
-* There should be no gratuitous changes to command line tool interfaces, but no
- guarantees are given.
-
-
-
-Regression testing
-==================
-
-There is a regression test suite under development in
-https://github.com/apitrace/apitrace-tests .
-
diff --git a/INSTALL.markdown b/INSTALL.markdown
deleted file mode 100644
index 32bd367b..00000000
--- a/INSTALL.markdown
+++ /dev/null
@@ -1,142 +0,0 @@
-Building from source
-====================
-
-
-Requirements
-------------
-
-Requirements common for all platforms:
-
-* Python version 2.7
-
- * Python Image Library
-
-* CMake version 2.8 or higher (tested with version 2.8)
-
-
-The GUI also dependends on:
-
-* Qt version 4.7 or higher (tested with version 4.8)
-
-* QJSON version 0.5 or higher (tested with version 0.7.1, which is bundled)
-
-Qt and QJSON will be required if `-DENABLE_GUI=TRUE` is passed to CMake, and
-never used if `-DENABLE_GUI=FALSE` is passed instead. The implicit default is
-`-DENABLE_GUI=AUTO`, which will build the GUI if Qt is available, using the
-bundled QJSON if it is not found on the system.
-
-
-The code also depends on zlib, libpng, and snappy libraries, but the bundled
-sources are always used regardless of system availability, to make the wrapper
-shared-objects/DLL self contained, and to prevent symbol collisions when
-tracing.
-
-
-Linux / Mac OS X
-----------------
-
-Additional optional dependencies for Linux:
-
-* libprocps (procps development libraries)
-
-* libdwarf
-
-Build as:
-
- cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo
- make -C build
-
-Other possible values for `CMAKE_BUILD_TYPE` `Debug`, `Release`,
-`RelWithDebInfo`, and `MinSizeRel`.
-
-You can also build the 32-bits GL wrapper on a 64-bits distribution, provided
-you have a multilib gcc and 32-bits X11 libraries, by doing:
-
- cmake \
- -DCMAKE_C_FLAGS=-m32 \
- -DCMAKE_CXX_FLAGS=-m32 \
- -DCMAKE_EXE_LINKER_FLAGS=-m32 \
- -DCMAKE_SYSTEM_LIBRARY_PATH=/usr/lib32 \
- -DENABLE_GUI=FALSE \
- -H. -Bbuild32
- make -C build32 glxtrace
-
-The `/usr/lib32` refers to the path where the 32-bits shared objects are may
-differ depending on the actual Linux distribution.
-
-
-Android
--------
-
-Additional requirements:
-
-* [Android NDK](http://developer.android.com/sdk/ndk/index.html)
-
-Build as:
-
- export ANDROID_NDK=/path/to/your/ndk
- cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/android.toolchain.cmake -DANDROID_API_LEVEL=9 -H. -Bbuild
- make -C build
-
-You can also choose a particular ABI by passing `ANDROID_ABI` variable to
-cmake, e.g., `-DANDROID_ABI=x86`.
-
-FirefoxOS
----------
-
-Put Apitrace source tree into `B2GROOT/external/apitrace/` and the `Android.mk`
-file (`B2GROOT/external/apitrace/Android.mk`) will do the needful to compile
-and install apitrace appropriately into the system image as part of FirefoxOS
-build process. It expects a linaro-type of Android NDK to be present in
-`../../prebuilt/ndk/android-ndk-r7` (ie `B2GROOT/prebuilt/ndk/android-ndk-r7`).
-
-
-Windows
--------
-
-Additional requirements:
-
-* For Direct3D 11.1 support:
-
- * [Microsoft Visual Studio 11 Ultimate Beta](http://www.microsoft.com/download/en/details.aspx?id=27543)
-
-* Other:
-
- * Microsoft Visual Studio (tested with 2010 version) or MinGW (tested with
- mingw-w64's gcc version 4.6.2)
-
- * [Microsoft DirectX SDK](http://msdn.microsoft.com/en-us/directx/aa937781):
-
- * for D3D 10, 10.1, and 11 support the [June 2010 release](http://www.microsoft.com/en-us/download/details.aspx?id=6812) is
- recommended.
-
- * for D3D7, D3D8 support the [August 2007 release](http://www.microsoft.com/downloads/details.aspx?familyid=529F03BE-1339-48C4-BD5A-8506E5ACF571)
- or earlier is required, as later releases do not include the necessary
- headers.
-
-To build with Visual Studio first invoke CMake GUI as:
-
- cmake-gui -H%cd% -B%cd%\build
-
-and press the _Configure_ button.
-
-It will try to detect most required/optional dependencies automatically. When
-not found automatically, you can manually specify the location of the
-dependencies from the CMake GUI.
-
-Qt on Windows doesn't ship with 64-bit binaries, you may want to add
-`-DENABLE_GUI=FALSE` to the above cmake command line for Windows 64-bits
-builds.
-
-After you've successfully configured, you can start the build by opening the
-generated `build\apitrace.sln` solution file, or invoking CMake as:
-
- cmake --build build --config MinSizeRel
-
-The steps to build 64bit version are similar, but choosing _Visual Studio 10
-Win64_ instead of _Visual Studio 10_.
-
-It's also possible to instruct CMake build Windows binaries on Linux with
-[MinGW cross compilers](http://www.cmake.org/Wiki/CmakeMingw).
-
-
diff --git a/NEWS.markdown b/NEWS.markdown
deleted file mode 100644
index 4bdc8f13..00000000
--- a/NEWS.markdown
+++ /dev/null
@@ -1,72 +0,0 @@
-This file lists the major user visible improvements. For a full list of changes
-and their authors see the git history.
-
-
-Version 4.0
-===========
-
-* Support tracing in Android, both native and Dalvik applications.
-
-* Show frame thumbnails in the GUI.
-
-* Basic D3D 10.1, 11, and 11.1 trace support.
-
-* Multi-threaded trace/retrace support.
-
-* Several OpenGL ES state dump fixes.
-
-* GPU profiling.
-
-* Thumbnails in GUI
-
-* Trim improvements.
-
-* Loads of bugfixes
-
-
-Version 3.0
-===========
-
-* Top-level `apitrace` command.
-
-* Trace and replay support for EGL, GLES1, and GLES2 APIs on Linux.
-
-* Ability to trim traces.
-
-* Basic CPU profiling when retracing.
-
-* Basic D3D10 trace support.
-
-* Many bugfixes.
-
-
-Version 2.0
-===========
-
-* Flush/sync trace file only when there is an uncaught signal/exception,
- yielding a 5x speed up while tracing.
-
-* Employ [snappy compression library](http://code.google.com/p/snappy/) instead
- of zlib, yielding a 2x speed up while tracing.
-
-* Implement and advertise `GL_GREMEDY_string_marker` and
- `GL_GREMEDY_frame_terminator` extensions.
-
-* Mac OS X support.
-
-* Support up-to OpenGL 4.2 calls.
-
-* Better GUI performance with very large traces, by loading frames from disk on
- demand.
-
-
-Version 1.0
-===========
-
-* Qt GUI, capable of visualizing the calls, the state, and editing the state.
-
-
-Pre-history
-===========
-
-* OpenGL replay support.
diff --git a/README.markdown b/README.markdown
index bc9e51bf..31bb4ca1 100644
--- a/README.markdown
+++ b/README.markdown
@@ -18,525 +18,15 @@ Obtaining **apitrace**
======================
To obtain apitrace either [download the latest
-binaries](http://apitrace.github.io/#download) for your platform if
-available, or follow the instructions in INSTALL.markdown to build it yourself.
+binaries](http://apitrace.github.io/#download) for your platform if available,
+or follow [these instructions](docs/INSTALL.markdown) to build and install it
+yourself.
+
On 64bits Linux and Windows platforms you'll need apitrace binaries that match
the architecture (32bits or 64bits) of the application being traced.
-Basic usage
-===========
-
-Run the application you want to trace as
-
- apitrace trace --api API /path/to/application [args...]
-
-and it will generate a trace named `application.trace` in the current
-directory. You can specify the written trace filename by passing the
-`--output` command line option.
-
-Problems while tracing (e.g, if the application uses calls/parameters
-unsupported by apitrace) will be reported via stderr output on Unices. On
-Windows you'll need to run
-[DebugView](http://technet.microsoft.com/en-us/sysinternals/bb896647) to view
-these messages.
-
-Follow the "Tracing manually" instructions below if you cannot obtain a trace.
-
-View the trace with
-
- apitrace dump application.trace
-
-Replay an OpenGL trace with
-
- apitrace replay application.trace
-
-Pass the `--sb` option to use a single buffered visual. Pass `--help` to
-`apitrace replay` for more options.
-
-
-Basic GUI usage
-===============
-
-Start the GUI as
-
- qapitrace application.trace
-
-You can also tell the GUI to go directly to a specific call
-
- qapitrace application.trace 12345
-
-
-Backtrace Capturing
-===================
-
-apitrace now has the ability to capture the call stack to an OpenGL call.
-This can be helpful in determing which piece of code made that glDrawArrays call.
-
-*NOTE* this feature is currently only available on Android and Linux at the moment.
-
-On linux you need to have libunwind, and libdwarf installed to compile in the feature.
-
-To use the feature you need to set an environment variable with the list of GL
-call prefixes you wish to capture stack traces to.
-
- export APITRACE_BACKTRACE="glDraw* glUniform*"
-
-The backtrace data will show up in qapitrace in the bottom section as a new tab.
-
-
-Advanced command line usage
-===========================
-
-
-Call sets
----------
-
-Several tools take `CALLSET` arguments, e.g:
-
- apitrace dump --calls=CALLSET foo.trace
- apitrace dump-images --calls=CALLSET foo.trace
- apitrace trim --calls=CALLSET1 --calls=CALLSET2 foo.trace
-
-The call syntax is very flexible. Here are a few examples:
-
- * `4` one call
-
- * `0,2,4,5` set of calls
-
- * `"0 2 4 5"` set of calls (commas are optional and can be replaced with whitespace)
-
- * `0-100/2` calls 1, 3, 5, ..., 99
-
- * `0-1000/draw` all draw calls between 0 and 1000
-
- * `0-1000/fbo` all fbo changes between calls 0 and 1000
-
- * `frame` all calls at end of frames
-
- * `@foo.txt` read call numbers from `foo.txt`, using the same syntax as above
-
-
-
-Tracing manually
-----------------
-
-### Linux ###
-
-On 64 bits systems, you'll need to determine whether the application is 64 bits
-or 32 bits. This can be done by doing
-
- file /path/to/application
-
-But beware of wrapper shell scripts -- what matters is the architecture of the
-main process.
-
-Run the GLX application you want to trace as
-
- LD_PRELOAD=/path/to/apitrace/wrappers/glxtrace.so /path/to/application
-
-and it will generate a trace named `application.trace` in the current
-directory. You can specify the written trace filename by setting the
-`TRACE_FILE` environment variable before running.
-
-For EGL applications you will need to use `egltrace.so` instead of
-`glxtrace.so`.
-
-The `LD_PRELOAD` mechanism should work with the majority of applications. There
-are some applications (e.g., Unigine Heaven, Android GPU emulator, etc.), that
-have global function pointers with the same name as OpenGL entrypoints, living in a
-shared object that wasn't linked with `-Bsymbolic` flag, so relocations to
-those global function pointers get overwritten with the address to our wrapper
-library, and the application will segfault when trying to write to them. For
-these applications it is possible to trace by using `glxtrace.so` as an
-ordinary `libGL.so` and injecting it via `LD_LIBRARY_PATH`:
-
- ln -s glxtrace.so wrappers/libGL.so
- ln -s glxtrace.so wrappers/libGL.so.1
- ln -s glxtrace.so wrappers/libGL.so.1.2
- export LD_LIBRARY_PATH=/path/to/apitrace/wrappers:$LD_LIBRARY_PATH
- export TRACE_LIBGL=/path/to/real/libGL.so.1
- /path/to/application
-
-If you are an application developer, you can avoid this either by linking with
-`-Bsymbolic` flag, or by using some unique prefix for your function pointers.
-
-See the `ld.so` man page for more information about `LD_PRELOAD` and
-`LD_LIBRARY_PATH` environment flags.
-
-### Android ###
-
-To trace standalone native OpenGL ES applications, use
-`LD_PRELOAD=/path/to/egltrace.so /path/to/application` as described in the
-previous section. To trace Java applications, refer to Dalvik.markdown.
-
-### Mac OS X ###
-
-Run the application you want to trace as
-
- DYLD_FRAMEWORK_PATH=/path/to/apitrace/wrappers /path/to/application
-
-Note that although Mac OS X has an `LD_PRELOAD` equivalent,
-`DYLD_INSERT_LIBRARIES`, it is mostly useless because it only works with
-`DYLD_FORCE_FLAT_NAMESPACE=1` which breaks most applications. See the `dyld` man
-page for more details about these environment flags.
-
-### Windows ###
-
-When tracing third-party applications, you can identify the target
-application's main executable, either by:
-
-* right clicking on the application's icon in the _Start Menu_, choose
- _Properties_, and see the _Target_ field;
-
-* or by starting the application, run Windows Task Manager (taskmgr.exe), right
- click on the application name in the _Applications_ tab, choose _Go To Process_,
- note the highlighted _Image Name_, and search it on `C:\Program Files` or
- `C:\Program Files (x86)`.
-
-On 64 bits Windows, you'll need to determine ether the application is a 64 bits
-or 32 bits. 32 bits applications will have a `*32` suffix in the _Image Name_
-column of the _Processes_ tab of _Windows Task Manager_ window.
-
-You also need to know which graphics API is being used. If you are unsure, the
-simplest way to determine what API an application uses is to:
-
-* download and run [Process Explorer](http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx)
-
-* search and select the application's process in _Process Explorer_
-
-* list the DLLs by pressing `Ctrl + D`
-
-* sort DLLs alphabetically, and look for the DLLs such as `opengl32.dll`,
- `d3d9.dll`, `d3d10.dll`, etc.
-
-Copy the appropriate `opengl32.dll`, `d3d8.dll`, or `d3d9.dll` from the
-wrappers directory to the directory with the application you want to trace.
-Then run the application as usual.
-
-You can specify the written trace filename by setting the `TRACE_FILE`
-environment variable before running.
-
-For D3D10 and higher you really must use `apitrace trace -a DXGI ...`. This is
-because D3D10-11 API span many DLLs which depend on each other, and once a DLL
-with a given name is loaded Windows will reuse it for LoadLibrary calls of the
-same name, causing internal calls to be traced erroneously. `apitrace trace`
-solves this issue by injecting a DLL `dxgitrace.dll` and patching all modules
-to hook only the APIs of interest.
-
-
-Emitting annotations to the trace
----------------------------------
-
-From within OpenGL applications you can embed annotations in the trace file
-through the following extensions:
-
-* [`GL_KHR_debug`](http://www.opengl.org/registry/specs/KHR/debug.txt)
-
-* [`GL_ARB_debug_output`](http://www.opengl.org/registry/specs/ARB/debug_output.txt)
-
-* [`GL_EXT_debug_marker`](http://www.khronos.org/registry/gles/extensions/EXT/EXT_debug_marker.txt)
-
-* [`GL_EXT_debug_label`](http://www.opengl.org/registry/specs/EXT/EXT_debug_label.txt)
-
-* [`GL_AMD_debug_output`](http://www.opengl.org/registry/specs/AMD/debug_output.txt)
-
-* [`GL_GREMEDY_string_marker`](http://www.opengl.org/registry/specs/GREMEDY/string_marker.txt)
-
-* [`GL_GREMEDY_frame_terminator`](http://www.opengl.org/registry/specs/GREMEDY/frame_terminator.txt)
-
-**apitrace** will advertise and intercept these OpenGL extensions regardless
-of whether the OpenGL implementation supports them or not. So all you have
-to do is to use these extensions when available, and you can be sure they
-will be available when tracing inside **apitrace**.
-
-For example, if you use [GLEW](http://glew.sourceforge.net/) to dynamically
-detect and use OpenGL extensions, you could easily accomplish this by doing:
-
- void foo() {
-
- if (GLEW_KHR_debug) {
- glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, __FUNCTION__);
- }
-
- ...
-
- if (GLEW_KHR_debug) {
- glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER,
- 0, GL_DEBUG_SEVERITY_MEDIUM, -1, "bla bla");
- }
-
- ...
-
- if (GLEW_KHR_debug) {
- glPopDebugGroup();
- }
-
- }
-
-This has the added advantage of working equally well with other OpenGL debugging tools.
-
-Also, provided that the OpenGL implementation supports `GL_KHR_debug`, labels
-defined via glObjectLabel() , and the labels of several objects (textures,
-framebuffers, samplers, etc. ) will appear in the GUI state dumps, in the
-parameters tab.
-
-
-For OpenGL ES applications you can embed annotations in the trace file through the
-[`GL_KHR_debug`](http://www.khronos.org/registry/gles/extensions/KHR/debug.txt) or
-[`GL_EXT_debug_marker`](http://www.khronos.org/registry/gles/extensions/EXT/EXT_debug_marker.txt)
-extensions.
-
-
-For Direct3D applications you can follow the standard procedure for
-[adding user defined events to Visual Studio Graphics Debugger / PIX](http://msdn.microsoft.com/en-us/library/vstudio/hh873200.aspx):
-
-- `D3DPERF_BeginEvent`, `D3DPERF_EndEvent`, and `D3DPERF_SetMarker` for D3D9 applications.
-
-- `ID3DUserDefinedAnnotation::BeginEvent`,
- `ID3DUserDefinedAnnotation::EndEvent`, and
- `ID3DUserDefinedAnnotation::SetMarker` for D3D11.1 applications.
-
-
-Dump OpenGL state at a particular call
-----------------------------------
-
-You can get a dump of the bound OpenGL state at call 12345 by doing:
-
- apitrace replay -D 12345 application.trace > 12345.json
-
-This is precisely the mechanism the GUI uses to obtain its own state.
-
-You can compare two state dumps by doing:
-
- apitrace diff-state 12345.json 67890.json
-
-
-Comparing two traces side by side
----------------------------------
-
- apitrace diff trace1.trace trace2.trace
-
-This works only on Unices, and it will truncate the traces due to performance
-limitations.
-
-
-Recording a video with FFmpeg/Libav
------------------------------------
-
-You can make a video of the output with FFmpeg by doing
-
- apitrace dump-images -o - application.trace \
- | ffmpeg -r 30 -f image2pipe -vcodec ppm -i pipe: -vcodec mpeg4 -y output.mp4
-
-or Libav (which replaces FFmpeg on recent Debian/Ubuntu distros) doing
-
- apitrace dump-images -o - application.trace \
- | avconv -r 30 -f image2pipe -vcodec ppm -i - -vcodec mpeg4 -y output.mp4
-
-Recording a video with gstreamer
---------------------------------------
-
-You can make a video of the output with gstreamer by doing
-
- glretrace --snapshot-format=RGB -s - smokinguns.trace | gst-launch-0.10 fdsrc blocksize=409600 ! queue \
- ! videoparse format=rgb width=1920 height=1080 ! queue ! ffmpegcolorspace ! queue \
- ! vaapiupload direct-rendering=0 ! queue ! vaapiencodeh264 ! filesink location=xxx.264
-
-Trimming a trace
-----------------
-
-You can truncate a trace by doing:
-
- apitrace trim --exact --calls 0-12345 -o trimed.trace application.trace
-
-If you need precise control over which calls to trim you can specify the
-individual call numbers in a plain text file, as described in the 'Call sets'
-section above.
-
-There is also experimental support for automatically trimming the calls
-necessary for a given frame or call:
-
- apitrace trim --auto --calls=12345 -o trimed.trace application.trace
- apitrace trim --auto --frames=12345 -o trimed.trace application.trace
-
-
-Profiling a trace
------------------
-
-You can perform gpu and cpu profiling with the command line options:
-
- * `--pgpu` record gpu times for frames and draw calls.
-
- * `--pcpu` record cpu times for frames and draw calls.
-
- * `--ppd` record pixels drawn for each draw call.
-
-The results from these can then be read by hand or analyzed with a script.
-
-`scripts/profileshader.py` will read the profile results and format them into a
-table which displays profiling results per shader.
-
-For example, to record all profiling data and utilise the per shader script:
-
- apitrace replay --pgpu --pcpu --ppd foo.trace | ./scripts/profileshader.py
-
-
-Advanced usage for OpenGL implementors
-======================================
-
-There are several advanced usage examples meant for OpenGL implementors.
-
-
-Regression testing
-------------------
-
-These are the steps to create a regression test-suite around **apitrace**:
-
-* obtain a trace
-
-* obtain reference snapshots, by doing on a reference system:
-
- mkdir /path/to/reference/snapshots/
- apitrace dump-images -o /path/to/reference/snapshots/ application.trace
-
-* prune the snapshots which are not interesting
-
-* to do a regression test, use `apitrace diff-images`:
-
- apitrace dump-images -o /path/to/test/snapshots/ application.trace
- apitrace diff-images --output summary.html /path/to/reference/snapshots/ /path/to/test/snapshots/
-
-
-Automated git-bisection
------------------------
-
-With tracecheck.py it is possible to automate git bisect and pinpoint the
-commit responsible for a regression.
-
-Below is an example of using tracecheck.py to bisect a regression in the
-Mesa-based Intel 965 driver. But the procedure could be applied to any OpenGL
-driver hosted on a git repository.
-
-First, create a build script, named build-script.sh, containing:
-
- #!/bin/sh
- set -e
- export PATH=/usr/lib/ccache:$PATH
- export CFLAGS='-g'
- export CXXFLAGS='-g'
- ./autogen.sh --disable-egl --disable-gallium --disable-glut --disable-glu --disable-glw --with-dri-drivers=i965
- make clean
- make "$@"
-
-It is important that builds are both robust, and efficient. Due to broken
-dependency discovery in Mesa's makefile system, it was necessary to invoke `make
-clean` in every iteration step. `ccache` should be installed to avoid
-recompiling unchanged source files.
-
-Then do:
-
- cd /path/to/mesa
- export LIBGL_DEBUG=verbose
- export LD_LIBRARY_PATH=$PWD/lib
- export LIBGL_DRIVERS_DIR=$PWD/lib
- git bisect start \
- 6491e9593d5cbc5644eb02593a2f562447efdcbb 71acbb54f49089b03d3498b6f88c1681d3f649ac \
- -- src/mesa/drivers/dri/intel src/mesa/drivers/dri/i965/
- git bisect run /path/to/tracecheck.py \
- --precision-threshold 8.0 \
- --build /path/to/build-script.sh \
- --gl-renderer '.*Mesa.*Intel.*' \
- --retrace=/path/to/glretrace \
- -c /path/to/reference/snapshots/ \
- topogun-1.06-orc-84k.trace
-
-The trace-check.py script will skip automatically when there are build
-failures.
-
-The `--gl-renderer` option will also cause a commit to be skipped if the
-`GL_RENDERER` is unexpected (e.g., when a software renderer or another OpenGL
-driver is unintentionally loaded due to a missing symbol in the DRI driver, or
-another runtime fault).
-
-
-Side by side retracing
-----------------------
-
-In order to determine which draw call a regression first manifests one could
-generate snapshots for every draw call, using the `-S` option. That is, however,
-very inefficient for big traces with many draw calls.
-
-A faster approach is to run both the bad and a good OpenGL driver side-by-side.
-The latter can be either a previously known good build of the OpenGL driver, or a
-reference software renderer.
-
-This can be achieved with retracediff.py script, which invokes glretrace with
-different environments, allowing to choose the desired OpenGL driver by
-manipulating variables such as `LD_LIBRARY_PATH`, `LIBGL_DRIVERS_DIR`, or
-`TRACE_LIBGL`.
-
-For example, on Linux:
-
- ./scripts/retracediff.py \
- --ref-env LD_LIBRARY_PATH=/path/to/reference/OpenGL/implementation \
- --retrace /path/to/glretrace \
- --diff-prefix=/path/to/output/diffs \
- application.trace
-
-Or on Windows:
-
- python scripts\retracediff.py --retrace \path\to\glretrace.exe --ref-env TRACE_LIBGL=\path\to\reference\opengl32.dll application.trace
-
-
-Advanced GUI usage
-==================
-
-qapitrace has rudimentary support for replaying traces on a remote
-target device. This can be useful, for example, when developing for an
-embedded system. The primary GUI will run on the local host, while any
-replays will be performed on the target device.
-
-In order to target a remote device, use the command-line:
-
- qapitrace --remote-target <HOST> <trace-file>
-
-In order for this to work, the following must be available in the
-system configuration:
-
-1. It must be possible for the current user to initiate an ssh session
- that has access to the target's window system. The command to be
- exectuted by qapitrace will be:
-
- ssh <HOST> glretrace
-
- For example, if the target device is using the X window system, one
- can test whether an ssh session has access to the target X server
- with:
-
- ssh <HOST> xdpyinfo
-
- If this command fails with something like "cannot open display"
- then the user will have to configure the target to set the DISPLAY
- environment variable, (for example, setting DISPLAY=:0 in the
- .bashrc file on the target or similar).
-
- Also, note that if the ssh session requires a custom username, then
- this must be configured on the host side so that ssh can be
- initiated without a username.
-
- For example, if you normally connect with `ssh user@192.168.0.2`
- you could configure ~/.ssh/config on the host with a block such as:
-
- Host target
- HostName 192.168.0.2
- User user
-
- And after this you should be able to connect with `ssh target` so
- that you can also use `qapitrace --remote-target target`.
-
-2. The target host must have a functional glretrace binary available
+Usage
+=====
-3. The target host must have access to <trace-file> at the same path
- in the filesystem as the <trace-file> path on the host system being
- passed to the qapitrace command line.
+Detailed usage instructions are available [here](docs/USAGE.markdown).
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 00000000..6f82b631
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,42 @@
+# See http://www.appveyor.com/docs/appveyor-yml
+
+version: '{build}'
+
+branches:
+ except:
+ - /^travis.*$/
+
+init:
+- git config --global core.autocrlf input
+
+shallow_clone: true
+
+environment:
+ MSBUILD_FLAGS: /verbosity:minimal /maxcpucount
+ matrix:
+ - CMAKE_GENERATOR: "Visual Studio 12"
+ QT5: C:\Qt\5.5\msvc2013
+ - CMAKE_GENERATOR: "Visual Studio 12 Win64"
+ QT5: C:\Qt\5.5\msvc2013_64
+
+matrix:
+ fast_finish: true
+
+configuration: Debug
+
+before_build:
+- set Path=%QT5%\bin;%Path%
+- cmake -H. -Bbuild -G "%CMAKE_GENERATOR%" "-DCMAKE_PREFIX_PATH=%QT5%" -DENABLE_GUI=ON
+
+build:
+ project: build\apitrace.sln
+ verbosity: minimal
+
+after_build:
+- cmake --build build --config "%CONFIGURATION%" -- %MSBUILD_FLAGS%
+- cmake --build build --config "%CONFIGURATION%" --target check -- %MSBUILD_FLAGS%
+- cmake --build build --config "%CONFIGURATION%" --target package -- %MSBUILD_FLAGS%
+
+#artifacts:
+#- path: build/apitrace-*.7z
+# name: apitrace
diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt
index 727cd7f8..31d7fdf2 100644
--- a/cli/CMakeLists.txt
+++ b/cli/CMakeLists.txt
@@ -8,12 +8,18 @@ add_definitions(
-DAPITRACE_SCRIPTS_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}/${SCRIPTS_INSTALL_DIR}"
-DAPITRACE_WRAPPERS_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}/${WRAPPER_INSTALL_DIR}"
)
+if (WIN32)
+ add_definitions (-DAPITRACE_PYTHON_EXECUTABLE="python")
+else ()
+ add_definitions (-DAPITRACE_PYTHON_EXECUTABLE="${PYTHON_EXECUTABLE}")
+endif ()
add_executable (apitrace
cli_main.cpp
cli_diff.cpp
cli_diff_state.cpp
cli_diff_images.cpp
+ cli_leaks.cpp
cli_dump.cpp
cli_dump_images.cpp
cli_pager.cpp
@@ -23,8 +29,9 @@ add_executable (apitrace
cli_sed.cpp
cli_trace.cpp
cli_trim.cpp
+ cli_trim_auto.cpp
+ cli_trim_auto_analyzer.cpp
cli_resources.cpp
- trace_analyzer.cpp
)
target_link_libraries (apitrace
@@ -36,22 +43,12 @@ target_link_libraries (apitrace
)
if (NOT CMAKE_CROSSCOMPILING)
+ # On debug builds tell where the source is so that scripts can be found
+ # http://www.cmake.org/cmake/help/v3.0/policy/CMP0043.html
set_target_properties (apitrace PROPERTIES
- # On debug builds tell where the source is so that scripts can be found
- COMPILE_DEFINITIONS_DEBUG APITRACE_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
- )
-endif ()
-
-if (MSVC AND NOT CMAKE_GENERATOR STREQUAL "Ninja")
- # On MSVC builds tell which subdirectory the binaries with be (for each
- # configuration)
- set_target_properties (apitrace PROPERTIES
- COMPILE_DEFINITIONS_DEBUG APITRACE_CONFIGURATION_SUBDIR="Debug"
- COMPILE_DEFINITIONS_RELEASE APITRACE_CONFIGURATION_SUBDIR="Release"
- COMPILE_DEFINITIONS_MINSIZEREL APITRACE_CONFIGURATION_SUBDIR="MinSizeRel"
- COMPILE_DEFINITIONS_RELWITHDEBINFO APITRACE_CONFIGURATION_SUBDIR="RelWithDebInfo"
+ COMPILE_DEFINITIONS $<$<CONFIG:Debug>:APITRACE_SOURCE_DIR="${CMAKE_SOURCE_DIR}">
)
endif ()
-
install (TARGETS apitrace RUNTIME DESTINATION bin)
+install_pdb (apitrace RUNTIME DESTINATION bin)
diff --git a/cli/cli.hpp b/cli/cli.hpp
index 088f0e8c..f777122c 100644
--- a/cli/cli.hpp
+++ b/cli/cli.hpp
@@ -25,8 +25,7 @@
*
*********************************************************************/
-#ifndef _APITRACE_CLI_HPP_
-#define _APITRACE_CLI_HPP_
+#pragma once
struct Command {
@@ -45,11 +44,12 @@ extern const Command diff_state_command;
extern const Command diff_images_command;
extern const Command dump_command;
extern const Command dump_images_command;
+extern const Command leaks_command;
extern const Command pickle_command;
extern const Command repack_command;
extern const Command retrace_command;
extern const Command sed_command;
extern const Command trace_command;
extern const Command trim_command;
+extern const Command trim_auto_command;
-#endif /* _APITRACE_CLI_HPP_ */
diff --git a/cli/cli_diff.cpp b/cli/cli_diff.cpp
index 76cdce1d..daeccd3e 100644
--- a/cli/cli_diff.cpp
+++ b/cli/cli_diff.cpp
@@ -45,12 +45,9 @@ static void
usage(void)
{
os::String command = find_command();
- if (!command.length()) {
- exit(1);
- }
char *args[4];
- args[0] = (char *) "python";
+ args[0] = (char *) APITRACE_PYTHON_EXECUTABLE;
args[1] = (char *) command.str();
args[2] = (char *) "--help";
args[3] = NULL;
@@ -64,14 +61,11 @@ command(int argc, char *argv[])
int i;
os::String command = find_command();
- if (!command.length()) {
- return 1;
- }
os::String apitracePath = os::getProcessName();
std::vector<const char *> args;
- args.push_back("python");
+ args.push_back(APITRACE_PYTHON_EXECUTABLE);
args.push_back(command.str());
args.push_back("--apitrace");
args.push_back(apitracePath.str());
diff --git a/cli/cli_diff_images.cpp b/cli/cli_diff_images.cpp
index ba8df3e9..54523cd3 100644
--- a/cli/cli_diff_images.cpp
+++ b/cli/cli_diff_images.cpp
@@ -45,12 +45,9 @@ static void
usage(void)
{
os::String command = find_command();
- if (!command.length()) {
- exit(1);
- }
char *args[4];
- args[0] = (char *) "python";
+ args[0] = (char *) APITRACE_PYTHON_EXECUTABLE;
args[1] = (char *) command.str();
args[2] = (char *) "--help";
args[3] = NULL;
@@ -64,12 +61,9 @@ command(int argc, char *argv[])
int i;
os::String command = find_command();
- if (!command.length()) {
- return 1;
- }
std::vector<const char *> args;
- args.push_back("python");
+ args.push_back(APITRACE_PYTHON_EXECUTABLE);
args.push_back(command.str());
for (i = 1; i < argc; i++) {
args.push_back(argv[i]);
diff --git a/cli/cli_diff_state.cpp b/cli/cli_diff_state.cpp
index a802b12a..0488e77f 100644
--- a/cli/cli_diff_state.cpp
+++ b/cli/cli_diff_state.cpp
@@ -26,8 +26,6 @@
*********************************************************************/
#include <string.h>
-#include <getopt.h>
-
#include <iostream>
#include "cli.hpp"
@@ -37,63 +35,42 @@
static const char *synopsis = "Identify differences between two state dumps.";
+static os::String
+find_command(void)
+{
+ return findScript("jsondiff.py");
+}
+
static void
usage(void)
{
- std::cout
- << "usage: apitrace diff-state <state-1> <state-2>\n"
- << synopsis << "\n"
- "\n"
- " Both input files should be the result of running 'glretrace -D XYZ <trace>'.\n";
-}
+ os::String command = find_command();
-const static char *
-shortOptions = "h";
+ char *args[4];
+ args[0] = (char *) APITRACE_PYTHON_EXECUTABLE;
+ args[1] = (char *) command.str();
+ args[2] = (char *) "--help";
+ args[3] = NULL;
-const static struct option
-longOptions[] = {
- {"help", no_argument, 0, 'h'},
- {0, 0, 0, 0}
-};
+ os::execute(args);
+}
static int
command(int argc, char *argv[])
{
- int opt;
- while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
- switch (opt) {
- case 'h':
- usage();
- return 0;
- default:
- std::cerr << "error: unexpected option `" << (char)opt << "`\n";
- usage();
- return 1;
- }
- }
-
- if (argc != optind + 2) {
- std::cerr << "Error: diff-state requires exactly two state-dump files as arguments.\n";
- usage();
- return 1;
- }
-
- char *file1, *file2;
+ int i;
- file1 = argv[optind];
- file2 = argv[optind + 1];
+ os::String command = find_command();
- os::String command = findScript("jsondiff.py");
-
- char *args[5];
-
- args[0] = const_cast<char *>("python");
- args[1] = const_cast<char *>(command.str());
- args[2] = file1;
- args[3] = file2;
- args[4] = NULL;
+ std::vector<const char *> args;
+ args.push_back(APITRACE_PYTHON_EXECUTABLE);
+ args.push_back(command.str());
+ for (i = 1; i < argc; i++) {
+ args.push_back(argv[i]);
+ }
+ args.push_back(NULL);
- return os::execute(args);
+ return os::execute((char * const *)&args[0]);
}
const Command diff_state_command = {
diff --git a/cli/cli_leaks.cpp b/cli/cli_leaks.cpp
new file mode 100644
index 00000000..1d28ec58
--- /dev/null
+++ b/cli/cli_leaks.cpp
@@ -0,0 +1,85 @@
+/*********************************************************************
+ *
+ * Copyright 2016 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************************/
+
+#include <string.h>
+#include <iostream>
+
+#include "cli.hpp"
+#include "os_string.hpp"
+#include "os_process.hpp"
+#include "cli_resources.hpp"
+
+static const char *synopsis = "Check trace for object leaks.";
+
+static os::String
+find_command(void)
+{
+ return findScript("leaks.py");
+}
+
+static void
+usage(void)
+{
+ os::String command = find_command();
+
+ char *args[4];
+ args[0] = (char *) APITRACE_PYTHON_EXECUTABLE;
+ args[1] = (char *) command.str();
+ args[2] = (char *) "--help";
+ args[3] = NULL;
+
+ os::execute(args);
+}
+
+static int
+command(int argc, char *argv[])
+{
+ int i;
+
+ os::String command = find_command();
+
+ os::String apitracePath = os::getProcessName();
+
+ std::vector<const char *> args;
+ args.push_back("python");
+ args.push_back(command.str());
+ args.push_back("--apitrace");
+ args.push_back(apitracePath.str());
+ for (i = 1; i < argc; i++) {
+ args.push_back(argv[i]);
+ }
+ args.push_back(NULL);
+
+ return os::execute((char * const *)&args[0]);
+}
+
+const Command leaks_command = {
+ "leaks",
+ synopsis,
+ usage,
+ command
+};
diff --git a/cli/cli_main.cpp b/cli/cli_main.cpp
index 1e278e41..b475bd3b 100644
--- a/cli/cli_main.cpp
+++ b/cli/cli_main.cpp
@@ -71,12 +71,14 @@ static const Command * commands[] = {
&diff_images_command,
&dump_command,
&dump_images_command,
+ &leaks_command,
&pickle_command,
&sed_command,
&repack_command,
&retrace_command,
&trace_command,
&trim_command,
+ &trim_auto_command,
&help_command
};
diff --git a/cli/cli_pager.cpp b/cli/cli_pager.cpp
index 579b19f3..4a3b451b 100644
--- a/cli/cli_pager.cpp
+++ b/cli/cli_pager.cpp
@@ -64,8 +64,8 @@ static pid_t pid = -1;
static void
on_exit(void)
{
- fflush(stdout);
- fflush(stderr);
+ fflush(stdout);
+ fflush(stderr);
close(STDOUT_FILENO);
close(STDERR_FILENO);
waitpid(pid, NULL, 0);
@@ -78,6 +78,7 @@ on_exit(void)
static void
on_signal(int sig)
{
+ fprintf(stderr, "on_signal\n");
on_exit();
signal(sig, SIG_DFL);
raise(sig);
@@ -93,37 +94,45 @@ pipepager(void) {
return;
}
- enum {
- READ_FD = 0,
- WRITE_FD = 1
- };
+ union {
+ int pipe[2];
+ struct {
+ int read;
+ int write;
+ };
+ } fd;
- int parentToChild[2];
int ret;
const char *pager;
- ret = pipe(parentToChild);
+ ret = pipe(fd.pipe);
assert(ret == 0);
+ if (ret != 0) {
+ return;
+ }
pid = fork();
switch (pid) {
case -1:
// failed to fork
+ close(fd.read);
+ close(fd.write);
return;
case 0:
// child
- ret = dup2(parentToChild[READ_FD], STDIN_FILENO);
- assert(ret != -1);
- ret = close(parentToChild[WRITE_FD]);
- assert(ret == 0);
+ close(fd.write);
+
+ dup2(fd.read, STDIN_FILENO);
pager = getenv("PAGER");
if (!pager) {
pager = "less";
}
- setenv("LESS", "FRXn", 0);
+ if (!getenv("PAGER")) {
+ putenv((char *)"LESS=FRXn");
+ }
execlp(pager, pager, NULL);
@@ -132,13 +141,13 @@ pipepager(void) {
default:
// parent
- ret = close(parentToChild[READ_FD]);
- assert(ret == 0);
+ close(fd.read);
- dup2(parentToChild[WRITE_FD], STDOUT_FILENO);
- if (isatty(STDERR_FILENO))
- dup2(parentToChild[WRITE_FD], STDERR_FILENO);
- close(parentToChild[WRITE_FD]);
+ dup2(fd.write, STDOUT_FILENO);
+ if (isatty(STDERR_FILENO)) {
+ dup2(fd.write, STDERR_FILENO);
+ }
+ close(fd.write);
// Ensure we wait for the pager before terminating
signal(SIGINT, on_signal);
diff --git a/cli/cli_pager.hpp b/cli/cli_pager.hpp
index 95d98781..197d712f 100644
--- a/cli/cli_pager.hpp
+++ b/cli/cli_pager.hpp
@@ -24,12 +24,10 @@
**************************************************************************/
-#ifndef _CLI_PAGER_HPP_
-#define _CLI_PAGER_HPP_
+#pragma once
void
pipepager(void);
-#endif /* _CLI_PAGER_HPP_ */
diff --git a/cli/cli_pickle.cpp b/cli/cli_pickle.cpp
index 5c267e0e..286716be 100644
--- a/cli/cli_pickle.cpp
+++ b/cli/cli_pickle.cpp
@@ -83,6 +83,10 @@ public:
writer.writeString(node->value);
}
+ void visit(WString *node) {
+ writer.writeWString(node->value);
+ }
+
void visit(Enum *node) {
if (symbolic) {
const EnumValue *it = node->lookup();
@@ -98,7 +102,7 @@ public:
if (symbolic) {
unsigned long long value = node->value;
const BitmaskSig *sig = node->sig;
- writer.beginList();
+ writer.beginTuple();
for (const BitmaskFlag *it = sig->flags; it != sig->flags + sig->num_flags; ++it) {
if ((it->value && (value & it->value) == it->value) ||
(!it->value && value == 0)) {
@@ -112,14 +116,15 @@ public:
if (value) {
writer.writeInt(value);
}
- writer.endList();
+ writer.endTuple();
} else {
writer.writeInt(node->value);
}
}
void visit(Struct *node) {
- if (false) {
+ if (true) {
+ // Structures as dictionaries
writer.beginDict();
for (unsigned i = 0; i < node->sig->num_members; ++i) {
writer.beginItem(node->sig->member_names[i]);
@@ -128,11 +133,13 @@ public:
}
writer.endDict();
} else {
- writer.beginTuple();
- for (unsigned i = 0; i < node->sig->num_members; ++i) {
+ // Structures as tuples
+ unsigned num_members = node->sig->num_members;
+ writer.beginTuple(num_members);
+ for (unsigned i = 0; i < num_members; ++i) {
_visit(node->members[i]);
}
- writer.endTuple();
+ writer.endTuple(num_members);
}
}
@@ -149,7 +156,7 @@ public:
}
void visit(Pointer *node) {
- writer.writeInt(node->value);
+ writer.writePointer(node->value);
}
void visit(Repr *r) {
@@ -169,11 +176,18 @@ public:
writer.beginList();
for (unsigned i = 0; i < call->args.size(); ++i) {
+ writer.beginTuple(2);
+ if (i < call->sig->num_args) {
+ writer.writeString(call->sig->arg_names[i]);
+ } else {
+ writer.writeNone();
+ }
if (call->args[i].value) {
_visit(call->args[i].value);
} else {
writer.writeNone();
}
+ writer.endTuple(2);
}
writer.endList();
@@ -183,6 +197,8 @@ public:
writer.writeNone();
}
+ writer.writeInt(call->flags);
+
writer.endTuple();
}
};
diff --git a/cli/cli_repack.cpp b/cli/cli_repack.cpp
index 5d122fa6..291f0d96 100644
--- a/cli/cli_repack.cpp
+++ b/cli/cli_repack.cpp
@@ -32,40 +32,54 @@
#include "cli.hpp"
#include "trace_file.hpp"
+#include "trace_ostream.hpp"
-static const char *synopsis = "Repack a trace file with Snappy compression.";
+static const char *synopsis = "Repack a trace file with different compression.";
static void
usage(void)
{
std::cout
- << "usage: apitrace repack <in-trace-file> <out-trace-file>\n"
+ << "usage: apitrace repack [options] <in-trace-file> <out-trace-file>\n"
<< synopsis << "\n"
<< "\n"
<< "Snappy compression allows for faster replay and smaller memory footprint,\n"
<< "at the expense of a slightly smaller compression ratio than zlib\n"
+ << "\n"
+ << " -z,--zlib Use ZLib compression instead\n"
<< "\n";
}
const static char *
-shortOptions = "h";
+shortOptions = "hz";
const static struct option
longOptions[] = {
{"help", no_argument, 0, 'h'},
+ {"zlib", no_argument, 0, 'z'},
{0, 0, 0, 0}
};
+enum Format {
+ FORMAT_SNAPPY = 0,
+ FORMAT_ZLIB,
+};
+
static int
-repack(const char *inFileName, const char *outFileName)
+repack(const char *inFileName, const char *outFileName, Format format)
{
trace::File *inFile = trace::File::createForRead(inFileName);
if (!inFile) {
return 1;
}
- trace::File *outFile = trace::File::createForWrite(outFileName);
+ trace::OutStream *outFile;
+ if (format == FORMAT_SNAPPY) {
+ outFile = trace::createSnappyStream(outFileName);
+ } else {
+ outFile = trace::createZLibStream(outFileName);
+ }
if (!outFile) {
delete inFile;
return 1;
@@ -89,12 +103,16 @@ repack(const char *inFileName, const char *outFileName)
static int
command(int argc, char *argv[])
{
+ Format format = FORMAT_SNAPPY;
int opt;
while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
switch (opt) {
case 'h':
usage();
return 0;
+ case 'z':
+ format = FORMAT_ZLIB;
+ break;
default:
std::cerr << "error: unexpected option `" << (char)opt << "`\n";
usage();
@@ -108,7 +126,7 @@ command(int argc, char *argv[])
return 1;
}
- return repack(argv[optind], argv[optind + 1]);
+ return repack(argv[optind], argv[optind + 1], format);
}
const Command repack_command = {
diff --git a/cli/cli_resources.cpp b/cli/cli_resources.cpp
index d6d0a55d..4186bd60 100644
--- a/cli/cli_resources.cpp
+++ b/cli/cli_resources.cpp
@@ -101,11 +101,11 @@ findWrapper(const char *wrapperFilename, bool verbose)
// Try relative build directory
// XXX: Just make build and install directory layout match
wrapperPath = processDir;
-#if defined(APITRACE_CONFIGURATION_SUBDIR)
+#if defined(CMAKE_INTDIR)
// Go from `Debug\apitrace.exe` to `wrappers\Debug\foo.dll` on MSVC builds.
wrapperPath.join("..");
wrapperPath.join("wrappers");
- wrapperPath.join(APITRACE_CONFIGURATION_SUBDIR);
+ wrapperPath.join(CMAKE_INTDIR);
#else
wrapperPath.join("wrappers");
#endif
@@ -194,6 +194,5 @@ findScript(const char *scriptFilename, bool verbose)
#endif
std::cerr << "error: cannot find " << scriptFilename << " script\n";
-
- return "";
+ exit(1);
}
diff --git a/cli/cli_resources.hpp b/cli/cli_resources.hpp
index ee3882be..27b883c3 100644
--- a/cli/cli_resources.hpp
+++ b/cli/cli_resources.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _CLI_RESOURCES_HPP_
-#define _CLI_RESOURCES_HPP_
+#pragma once
#include <stdlib.h>
@@ -43,4 +42,3 @@ os::String
findWrapper(const char *wrapperFilename, bool verbose = false);
-#endif /* _CLI_RESOURCES_HPP_ */
diff --git a/cli/cli_retrace.hpp b/cli/cli_retrace.hpp
index 0dfa823e..6df0fbe6 100644
--- a/cli/cli_retrace.hpp
+++ b/cli/cli_retrace.hpp
@@ -25,8 +25,7 @@
*
*********************************************************************/
-#ifndef _CLI_RETRACE_HPP_
-#define _CLI_RETRACE_HPP_
+#pragma once
#include <vector>
@@ -43,4 +42,3 @@ executeRetrace(const std::vector<const char *> & opts,
const char *traceName);
-#endif /* _CLI_RETRACE_HPP_ */
diff --git a/cli/cli_sed.cpp b/cli/cli_sed.cpp
index afec1257..401b7a63 100644
--- a/cli/cli_sed.cpp
+++ b/cli/cli_sed.cpp
@@ -46,8 +46,11 @@ usage(void)
<< synopsis << "\n"
"\n"
" -h, --help Show detailed help for sed options and exit\n"
- " -e s/SEARCH/REPLACE/ Search and replace a symbol.\n"
- " XXX: Only works for enums.\n"
+ " -e s/SEARCH/REPLACE/ Search and replace a symbol. Use @file(<path>)\n"
+ " to read SEARCH or REPLACE from a file.\n"
+ " Any character (not just /) can be used as \n"
+ " separator.\n"
+ " XXX: Only works for enums and strings.\n"
" -o, --output=TRACE_FILE Output trace file\n"
;
}
@@ -104,6 +107,16 @@ public:
}
void visit(String *node) {
+ if (!searchName.compare(node->value)) {
+ size_t len = replaceName.length() + 1;
+ delete [] node->value;
+ char *str = new char [len];
+ memcpy(str, replaceName.c_str(), len);
+ node->value = str;
+ }
+ }
+
+ void visit(WString *node) {
}
void visit(Enum *node) {
@@ -212,17 +225,17 @@ sed_trace(Replacements &replacements, const char *inFileName, std::string &outFi
static bool
parseSubstOpt(Replacements &replacements, const char *opt)
{
+ char separator;
+
if (*opt++ != 's') {
return false;
}
- if (*opt++ != '/') {
- return false;
- }
+ separator = *opt++;
// Parse the search pattern
const char *search_begin = opt;
- while (*opt != '/') {
+ while (*opt != separator) {
if (*opt == 0) {
return false;
}
@@ -232,7 +245,7 @@ parseSubstOpt(Replacements &replacements, const char *opt)
// Parse the replace pattern
const char *replace_begin = opt;
- while (*opt != '/') {
+ while (*opt != separator) {
if (*opt == 0) {
return false;
}
@@ -247,6 +260,36 @@ parseSubstOpt(Replacements &replacements, const char *opt)
std::string search(search_begin, search_end);
std::string replace(replace_begin, replace_end);
+ // If search or replace strings are taken from a file, read the file
+ std::string file_subst = "@file(";
+
+ for (int i = 0; i < 2; i++) {
+ std::string *str = i ? &search : &replace;
+
+ if (!str->compare(0, file_subst.length(), file_subst)) {
+ if ((*str)[str->length()-1] != ')') {
+ return false;
+ }
+
+ std::string fname = str->substr(file_subst.length());
+ fname[fname.length()-1] = 0;
+ FILE *f = fopen(fname.c_str(), "rt");
+ if (!f) {
+ std::cerr << "error: cannot open file " << fname << "\n";
+ return false;
+ }
+ char buf[1024];
+ (*str) = "";
+ while (!feof(f)) {
+ if (fgets(buf, 1024, f)) {
+ str->append(buf);
+ }
+ }
+ fclose(f);
+ }
+ }
+
+
replacements.push_back(Replacer(search, replace));
return true;
@@ -270,7 +313,7 @@ command(int argc, char *argv[])
break;
case 'e':
if (!parseSubstOpt(replacements, optarg)) {
- std::cerr << "error: invalid replacement patter `" << optarg << "`\n";
+ std::cerr << "error: invalid replacement pattern `" << optarg << "`\n";
}
break;
default:
diff --git a/cli/cli_trace.cpp b/cli/cli_trace.cpp
index 54c20df2..adca8af3 100644
--- a/cli/cli_trace.cpp
+++ b/cli/cli_trace.cpp
@@ -32,9 +32,11 @@
#include <getopt.h>
#include <iostream>
+#include <fstream>
#include "os_string.hpp"
#include "os_process.hpp"
+#include "os_version.hpp"
#include "cli.hpp"
#include "cli_resources.hpp"
@@ -52,6 +54,8 @@
#endif
+#ifdef _WIN32
+
static inline bool
copyWrapper(const os::String & wrapperPath,
const char *programPath,
@@ -81,12 +85,14 @@ copyWrapper(const os::String & wrapperPath,
return true;
}
+#endif /* _WIN32 */
+
static int
traceProgram(trace::API api,
char * const *argv,
const char *output,
- bool verbose,
+ int verbose,
bool debug)
{
const char *wrapperFilename;
@@ -121,6 +127,10 @@ traceProgram(trace::API api,
wrapperFilename = "dxgitrace.dll";
useInject = true;
break;
+ case trace::API_D2D1:
+ wrapperFilename = "d2d1trace.dll";
+ useInject = true;
+ break;
#endif
default:
std::cerr << "error: unsupported API\n";
@@ -136,27 +146,21 @@ traceProgram(trace::API api,
#if defined(_WIN32)
/*
* Use DLL injection method on Windows, even for APIs that don't stricly
- * need it. Except when tracing OpenGL on Windows 8, as the injection
- * method seems to have troubles tracing the internal
- * gdi32.dll!SwapBuffers -> opengl32.dll!wglSwapBuffer calls, per github
- * issue #172.
+ * need it.
*/
- {
- OSVERSIONINFO osvi;
- ZeroMemory(&osvi, sizeof osvi);
- osvi.dwOSVersionInfoSize = sizeof osvi;
- GetVersionEx(&osvi);
- BOOL bIsWindows8orLater =
- osvi.dwMajorVersion > 6 ||
- (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 2);
- if (api != trace::API_GL || !bIsWindows8orLater) {
- useInject = true;
- }
- }
+ useInject = true;
if (useInject) {
args.push_back("inject");
+ if (debug) {
+ args.push_back("-d");
+ }
+ for (int i = 1; i < verbose; ++i) {
+ args.push_back("-v");
+ }
+ args.push_back("-D");
args.push_back(wrapperPath);
+ args.push_back("--");
} else {
/* On Windows copy the wrapper to the program directory.
*/
@@ -187,14 +191,50 @@ traceProgram(trace::API api,
wrapperPath.append(oldEnvVarValue);
}
+ std::string ex;
if (debug) {
- std::string ex("set exec-wrapper env " TRACE_VARIABLE "=");
- ex.append(wrapperPath.str());
+#if defined(__APPLE__)
+ bool lldb = true;
+#else
+ bool lldb = false;
+#endif
- args.push_back("gdb");
- args.push_back("--ex");
- args.push_back(ex.c_str());
- args.push_back("--args");
+ if (lldb) {
+ /*
+ * Debug with LLDB.
+ *
+ * See also http://lldb.llvm.org/lldb-gdb.html
+ */
+
+ char scriptFileName[] = "/tmp/apitrace.XXXXXX";
+ int scriptFD = mkstemp(scriptFileName);
+ if (scriptFD < 0) {
+ std::cerr << "error: failed to create temporary lldb script file\n";
+ exit(1);
+ }
+
+ FILE *scriptStream = fdopen(scriptFD, "w");
+ fprintf(scriptStream, "env " TRACE_VARIABLE "='%s'\n", wrapperPath.str());
+ fclose(scriptStream);
+
+ args.push_back("lldb");
+ args.push_back("-s");
+ args.push_back(scriptFileName);
+ args.push_back("--");
+ } else {
+ /*
+ * Debug with GDB.
+ */
+
+ ex = "set exec-wrapper env " TRACE_VARIABLE "='";
+ ex.append(wrapperPath.str());
+ ex.append("'");
+
+ args.push_back("gdb");
+ args.push_back("--ex");
+ args.push_back(ex.c_str());
+ args.push_back("--args");
+ }
os::unsetEnvironment(TRACE_VARIABLE);
} else {
@@ -287,7 +327,7 @@ usage(void)
" -o, --output=TRACE specify output trace file;\n"
" default is `PROGRAM.trace`\n"
#ifdef TRACE_VARIABLE
- " -d, --debug debug with gdb\n"
+ " -d, --debug run inside debugger (gdb/lldb)\n"
#endif
;
}
@@ -308,7 +348,7 @@ longOptions[] = {
static int
command(int argc, char *argv[])
{
- bool verbose = false;
+ int verbose = 0;
trace::API api = trace::API_GL;
const char *output = NULL;
bool debug = false;
@@ -320,14 +360,16 @@ command(int argc, char *argv[])
usage();
return 0;
case 'v':
- verbose = true;
+ ++verbose;
break;
case 'a':
if (strcmp(optarg, "gl") == 0) {
api = trace::API_GL;
} else if (strcmp(optarg, "egl") == 0) {
api = trace::API_EGL;
- } else if (strcmp(optarg, "d3d7") == 0) {
+ } else if (strcmp(optarg, "ddraw") == 0 ||
+ strcmp(optarg, "d3d6") == 0 ||
+ strcmp(optarg, "d3d7") == 0) {
api = trace::API_D3D7;
} else if (strcmp(optarg, "d3d8") == 0) {
api = trace::API_D3D8;
@@ -339,6 +381,9 @@ command(int argc, char *argv[])
strcmp(optarg, "d3d11") == 0 ||
strcmp(optarg, "d3d11_1") == 0) {
api = trace::API_DXGI;
+ } else if (strcmp(optarg, "d2d") == 0 ||
+ strcmp(optarg, "d2d1") == 0) {
+ api = trace::API_D2D1;
} else {
std::cerr << "error: unknown API `" << optarg << "`\n";
usage();
diff --git a/cli/cli_trim.cpp b/cli/cli_trim.cpp
index ed950e5c..b1e6b485 100644
--- a/cli/cli_trim.cpp
+++ b/cli/cli_trim.cpp
@@ -29,13 +29,10 @@
#include <limits.h> // for CHAR_MAX
#include <getopt.h>
-#include <set>
-
#include "cli.hpp"
#include "os_string.hpp"
-#include "trace_analyzer.hpp"
#include "trace_callset.hpp"
#include "trace_parser.hpp"
#include "trace_writer.hpp"
@@ -52,98 +49,15 @@ usage(void)
" -h, --help Show detailed help for trim options and exit\n"
" --calls=CALLSET Include specified calls in the trimmed output.\n"
" --frames=FRAMESET Include specified frames in the trimmed output.\n"
- " --deps Include additional calls to satisfy dependencies\n"
- " --no-deps Do not include any more calls than requestd\n"
- " --prune Omit calls without side effects from the output\n"
- " --no-prune Do not omit any requested calls\n"
- " -a, --auto Trim automatically to calls specified in --calls/--frames\n"
- " Equivalent to both --deps and --prune\n"
- " --exact Trim to exactly the calls specified in --calls/--frames\n"
- " Equivalent to both --no-deps and --no-prune\n"
- " --print-callset Print the final set of calls included in output\n"
- " --trim-spec=SPEC Only performing trimming as described in SPEC\n"
- " --thread=THREAD_ID Only retain calls from specified thread\n"
- " -o, --output=TRACE_FILE Output trace file\n"
- ;
-}
-
-static void
-help()
-{
- std::cout
- << "usage: apitrace trim [OPTIONS] TRACE_FILE...\n"
- << synopsis << "\n"
- "\n"
- " -h, --help Show this help message and exit\n"
- "\n"
- " --calls=CALLSET Include specified calls in the trimmed output.\n"
- " --frames=FRAMESET Include specified frames in the trimmed output.\n"
- "\n"
- " --deps Perform dependency analysis and include dependent\n"
- " calls as needed, (even if those calls were not\n"
- " explicitly requested with --calls or --frames).\n"
- " (On by default. See --no-deps or --exact)\n"
- "\n"
- " --no-deps Do not perform dependency analysis. Output will\n"
- " not include any additional calls beyond those\n"
- " explicitly requested with --calls or --frames).\n"
- "\n"
- " --prune Omit calls with no side effects, even if the call\n"
- " is within the range specified by --calls/--frames.\n"
- " (On by default. See --no-prune or --exact)\n"
- "\n"
- " --no-prune Never omit any calls from the range specified\n"
- " --calls/--frames.\n"
- "\n"
- " -a, --auto Use dependency analysis and pruning\n"
- " of uninteresting calls the resulting trace may\n"
- " include more and less calls than specified.\n"
- " This option is equivalent\n"
- " to passing both --deps and --prune and is on by\n"
- " default (see --no-deps, --no-prune and --exact)\n"
- "\n"
- " --exact Trim output to exact the calls or frames\n"
- " specified with --calls or --frames.\n"
- " This option is equivalent\n"
- " to passing both --no-deps and --no-prune.\n"
- "\n"
- " --print-callset Print to stdout the final set of calls included\n"
- " in the trim output. This can be useful for\n"
- " tweaking the trimmed callset from --auto on the\n"
- " command-line.\n"
- " Use --calls=@FILE to read callset from a file.\n"
- "\n"
- " --trim-spec=SPEC Specifies which classes of calls will be trimmed.\n"
- " This option only has an effect if dependency\n"
- " analysis is enabled. The argument is a comma-\n"
- " separated list of names from the following:\n"
- "\n"
- " no-side-effects Calls with no side effects\n"
- " textures Calls to setup unused textures\n"
- " shaders Calls to setup unused shaders\n"
- " drawing Calls that draw\n"
- "\n"
- " The default trim specification includes all of\n"
- " the above, (as much as possible will be trimmed).\n"
- "\n"
" --thread=THREAD_ID Only retain calls from specified thread\n"
- "\n"
" -o, --output=TRACE_FILE Output trace file\n"
- "\n"
;
}
enum {
CALLS_OPT = CHAR_MAX + 1,
FRAMES_OPT,
- DEPS_OPT,
- NO_DEPS_OPT,
- PRUNE_OPT,
- NO_PRUNE_OPT,
- THREAD_OPT,
- PRINT_CALLSET_OPT,
- TRIM_SPEC_OPT,
- EXACT_OPT
+ THREAD_OPT
};
const static char *
@@ -154,16 +68,8 @@ longOptions[] = {
{"help", no_argument, 0, 'h'},
{"calls", required_argument, 0, CALLS_OPT},
{"frames", required_argument, 0, FRAMES_OPT},
- {"deps", no_argument, 0, DEPS_OPT},
- {"no-deps", no_argument, 0, NO_DEPS_OPT},
- {"prune", no_argument, 0, PRUNE_OPT},
- {"no-prune", no_argument, 0, NO_PRUNE_OPT},
- {"auto", no_argument, 0, 'a'},
- {"exact", no_argument, 0, EXACT_OPT},
{"thread", required_argument, 0, THREAD_OPT},
{"output", required_argument, 0, 'o'},
- {"print-callset", no_argument, 0, PRINT_CALLSET_OPT},
- {"trim-spec", required_argument, 0, TRIM_SPEC_OPT},
{0, 0, 0, 0}
};
@@ -180,91 +86,24 @@ struct trim_options {
/* Frames to be included in trace. */
trace::CallSet frames;
- /* Whether dependency analysis should be performed. */
- bool dependency_analysis;
-
- /* Whether uninteresting calls should be pruned.. */
- bool prune_uninteresting;
-
/* Output filename */
std::string output;
/* Emit only calls from this thread (-1 == all threads) */
int thread;
-
- /* Print resulting callset */
- int print_callset;
-
- /* What kind of trimming to perform. */
- TrimFlags trim_flags;
};
static int
trim_trace(const char *filename, struct trim_options *options)
{
- trace::ParseBookmark beginning;
trace::Parser p;
- TraceAnalyzer analyzer(options->trim_flags);
- trace::FastCallSet *required;
unsigned frame;
- int call_range_first, call_range_last;
if (!p.open(filename)) {
std::cerr << "error: failed to open " << filename << "\n";
return 1;
}
- /* Mark the beginning so we can return here for pass 2. */
- p.getBookmark(beginning);
-
- /* In pass 1, analyze which calls are needed. */
- frame = 0;
- trace::Call *call;
- while ((call = p.parse_call())) {
-
- /* There's no use doing any work past the last call and frame
- * requested by the user. */
- if ((options->calls.empty() || call->no > options->calls.getLast()) &&
- (options->frames.empty() || frame > options->frames.getLast())) {
-
- delete call;
- break;
- }
-
- /* If requested, ignore all calls not belonging to the specified thread. */
- if (options->thread != -1 && call->thread_id != options->thread) {
- goto NEXT;
- }
-
- /* Also, prune if no side effects (unless the user asked for no pruning. */
- if (options->prune_uninteresting && call->flags & trace::CALL_FLAG_NO_SIDE_EFFECTS) {
- goto NEXT;
- }
-
- /* If this call is included in the user-specified call set,
- * then require it (and all dependencies) in the trimmed
- * output. */
- if (options->calls.contains(*call) ||
- options->frames.contains(frame, call->flags)) {
-
- analyzer.require(call);
- }
-
- /* Regardless of whether we include this call or not, we do
- * some dependency tracking (unless disabled by the user). We
- * do this even for calls we have included in the output so
- * that any state updates get performed. */
- if (options->dependency_analysis) {
- analyzer.analyze(call);
- }
-
- NEXT:
- if (call->flags & trace::CALL_FLAG_END_FRAME)
- frame++;
-
- delete call;
- }
-
/* Prepare output file and writer for output. */
if (options->output.empty()) {
os::String base(filename);
@@ -279,15 +118,9 @@ trim_trace(const char *filename, struct trim_options *options)
return 1;
}
- /* Reset bookmark for pass 2. */
- p.setBookmark(beginning);
-
- /* In pass 2, emit the calls that are required. */
- required = analyzer.get_required();
frame = 0;
- call_range_first = -1;
- call_range_last = -1;
+ trace::Call *call;
while ((call = p.parse_call())) {
/* There's no use doing any work past the last call and frame
@@ -299,23 +132,21 @@ trim_trace(const char *filename, struct trim_options *options)
break;
}
- if (required->contains(call->no)) {
- writer.writeCall(call);
+ /* If requested, ignore all calls not belonging to the specified thread. */
+ if (options->thread != -1 && call->thread_id != options->thread) {
+ goto NEXT;
+ }
+
+ /* If this call is included in the user-specified call set,
+ * then require it (and all dependencies) in the trimmed
+ * output. */
+ if (options->calls.contains(*call) ||
+ options->frames.contains(frame, call->flags)) {
- if (options->print_callset) {
- if (call_range_first < 0) {
- call_range_first = call->no;
- printf ("%d", call_range_first);
- } else if (call->no != call_range_last + 1) {
- if (call_range_last != call_range_first)
- printf ("-%d", call_range_last);
- call_range_first = call->no;
- printf (",%d", call_range_first);
- }
- call_range_last = call->no;
- }
+ writer.writeCall(call);
}
+ NEXT:
if (call->flags & trace::CALL_FLAG_END_FRAME) {
frame++;
}
@@ -323,71 +154,26 @@ trim_trace(const char *filename, struct trim_options *options)
delete call;
}
- if (options->print_callset) {
- if (call_range_last != call_range_first)
- printf ("-%d\n", call_range_last);
- }
-
std::cerr << "Trimmed trace is available as " << options->output << "\n";
return 0;
}
static int
-parse_trim_spec(const char *trim_spec, TrimFlags *flags)
-{
- std::string spec(trim_spec), word;
- size_t start = 0, comma = 0;
- *flags = 0;
-
- while (start < spec.size()) {
- comma = spec.find(',', start);
-
- if (comma == std::string::npos)
- word = std::string(spec, start);
- else
- word = std::string(spec, start, comma - start);
-
- if (strcmp(word.c_str(), "no-side-effects") == 0)
- *flags |= TRIM_FLAG_NO_SIDE_EFFECTS;
- else if (strcmp(word.c_str(), "textures") == 0)
- *flags |= TRIM_FLAG_TEXTURES;
- else if (strcmp(word.c_str(), "shaders") == 0)
- *flags |= TRIM_FLAG_SHADERS;
- else if (strcmp(word.c_str(), "drawing") == 0)
- *flags |= TRIM_FLAG_DRAWING;
- else {
- return 1;
- }
-
- if (comma == std::string::npos)
- break;
-
- start = comma + 1;
- }
-
- return 0;
-}
-
-static int
command(int argc, char *argv[])
{
struct trim_options options;
options.calls = trace::CallSet(trace::FREQUENCY_NONE);
options.frames = trace::CallSet(trace::FREQUENCY_NONE);
- options.dependency_analysis = true;
- options.prune_uninteresting = true;
options.output = "";
options.thread = -1;
- options.print_callset = 0;
- options.trim_flags = -1;
int opt;
while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
switch (opt) {
case 'h':
- help();
+ usage();
return 0;
case CALLS_OPT:
options.calls.merge(optarg);
@@ -395,42 +181,12 @@ command(int argc, char *argv[])
case FRAMES_OPT:
options.frames.merge(optarg);
break;
- case DEPS_OPT:
- options.dependency_analysis = true;
- break;
- case NO_DEPS_OPT:
- options.dependency_analysis = false;
- break;
- case PRUNE_OPT:
- options.prune_uninteresting = true;
- break;
- case NO_PRUNE_OPT:
- options.prune_uninteresting = false;
- break;
- case 'a':
- options.dependency_analysis = true;
- options.prune_uninteresting = true;
- break;
- case EXACT_OPT:
- options.dependency_analysis = false;
- options.prune_uninteresting = false;
- break;
case THREAD_OPT:
options.thread = atoi(optarg);
break;
case 'o':
options.output = optarg;
break;
- case PRINT_CALLSET_OPT:
- options.print_callset = 1;
- break;
- case TRIM_SPEC_OPT:
- if (parse_trim_spec(optarg, &options.trim_flags)) {
- std::cerr << "error: illegal value for trim-spec: " << optarg << "\n";
- std::cerr << "See \"apitrace help trim\" for help.\n";
- return 1;
- }
- break;
default:
std::cerr << "error: unexpected option `" << (char)opt << "`\n";
usage();
@@ -460,20 +216,12 @@ command(int argc, char *argv[])
return 1;
}
- if (options.dependency_analysis) {
- std::cerr <<
- "Note: The dependency analysis in \"apitrace trim\" is still experimental.\n"
- " We hope that it will be useful, but it may lead to incorrect results.\n"
- " If you find a trace that misbehaves while trimming, please share that\n"
- " by sending email to apitrace@lists.freedesktop.org, cworth@cworth.org\n";
- }
-
return trim_trace(argv[optind], &options);
}
const Command trim_command = {
"trim",
synopsis,
- help,
+ usage,
command
};
diff --git a/cli/cli_trim_auto.cpp b/cli/cli_trim_auto.cpp
new file mode 100644
index 00000000..685de21d
--- /dev/null
+++ b/cli/cli_trim_auto.cpp
@@ -0,0 +1,432 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * Copyright 2011 Intel corporation
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <sstream>
+#include <string.h>
+#include <limits.h> // for CHAR_MAX
+#include <getopt.h>
+
+#include <set>
+
+#include "cli.hpp"
+
+#include "os_string.hpp"
+
+#include "trace_callset.hpp"
+#include "trace_parser.hpp"
+#include "trace_writer.hpp"
+
+#include "cli_trim_auto_analyzer.hpp"
+
+static const char *synopsis = "Create a new trace by automatically trimming unecessary calls from an existing trace.";
+
+static void
+usage(void)
+{
+ std::cout
+ << "usage: apitrace trim-auto [OPTIONS] TRACE_FILE...\n"
+ << synopsis << "\n"
+ "\n"
+ " -h, --help Show this help message and exit\n"
+ "\n"
+ " --calls=CALLSET Include specified calls in the trimmed output.\n"
+ " --frames=FRAMESET Include specified frames in the trimmed output.\n"
+ "\n"
+ " --deps Perform dependency analysis and include dependent\n"
+ " calls as needed, (even if those calls were not\n"
+ " explicitly requested with --calls or --frames).\n"
+ " (On by default. See --no-deps or --exact)\n"
+ "\n"
+ " --no-deps Do not perform dependency analysis. Output will\n"
+ " not include any additional calls beyond those\n"
+ " explicitly requested with --calls or --frames).\n"
+ "\n"
+ " --prune Omit calls with no side effects, even if the call\n"
+ " is within the range specified by --calls/--frames.\n"
+ " (On by default. See --no-prune or --exact)\n"
+ "\n"
+ " --no-prune Never omit any calls from the range specified\n"
+ " --calls/--frames.\n"
+ "\n"
+ " --print-callset Print to stdout the final set of calls included\n"
+ " in the trim output. This can be useful for\n"
+ " tweaking the trimmed callset from --auto on the\n"
+ " command-line.\n"
+ " Use --calls=@FILE to read callset from a file.\n"
+ "\n"
+ " --trim-spec=SPEC Specifies which classes of calls will be trimmed.\n"
+ " This option only has an effect if dependency\n"
+ " analysis is enabled. The argument is a comma-\n"
+ " separated list of names from the following:\n"
+ "\n"
+ " no-side-effects Calls with no side effects\n"
+ " textures Calls to setup unused textures\n"
+ " shaders Calls to setup unused shaders\n"
+ " drawing Calls that draw\n"
+ "\n"
+ " The default trim specification includes all of\n"
+ " the above, (as much as possible will be trimmed).\n"
+ "\n"
+ " --thread=THREAD_ID Only retain calls from specified thread\n"
+ "\n"
+ " -o, --output=TRACE_FILE Output trace file\n"
+ "\n"
+ ;
+}
+
+enum {
+ CALLS_OPT = CHAR_MAX + 1,
+ FRAMES_OPT,
+ DEPS_OPT,
+ NO_DEPS_OPT,
+ PRUNE_OPT,
+ NO_PRUNE_OPT,
+ THREAD_OPT,
+ PRINT_CALLSET_OPT,
+ TRIM_SPEC_OPT
+};
+
+const static char *
+shortOptions = "ho:x";
+
+const static struct option
+longOptions[] = {
+ {"help", no_argument, 0, 'h'},
+ {"calls", required_argument, 0, CALLS_OPT},
+ {"frames", required_argument, 0, FRAMES_OPT},
+ {"deps", no_argument, 0, DEPS_OPT},
+ {"no-deps", no_argument, 0, NO_DEPS_OPT},
+ {"prune", no_argument, 0, PRUNE_OPT},
+ {"no-prune", no_argument, 0, NO_PRUNE_OPT},
+ {"thread", required_argument, 0, THREAD_OPT},
+ {"output", required_argument, 0, 'o'},
+ {"print-callset", no_argument, 0, PRINT_CALLSET_OPT},
+ {"trim-spec", required_argument, 0, TRIM_SPEC_OPT},
+ {0, 0, 0, 0}
+};
+
+struct stringCompare {
+ bool operator() (const char *a, const char *b) const {
+ return strcmp(a, b) < 0;
+ }
+};
+
+struct trim_auto_options {
+ /* Calls to be included in trace. */
+ trace::CallSet calls;
+
+ /* Frames to be included in trace. */
+ trace::CallSet frames;
+
+ /* Whether dependency analysis should be performed. */
+ bool dependency_analysis;
+
+ /* Whether uninteresting calls should be pruned.. */
+ bool prune_uninteresting;
+
+ /* Output filename */
+ std::string output;
+
+ /* Emit only calls from this thread (-1 == all threads) */
+ int thread;
+
+ /* Print resulting callset */
+ int print_callset;
+
+ /* What kind of trimming to perform. */
+ TrimFlags trim_flags;
+};
+
+static int
+trim_trace(const char *filename, struct trim_auto_options *options)
+{
+ trace::ParseBookmark beginning;
+ trace::Parser p;
+ TraceAnalyzer analyzer(options->trim_flags);
+ trace::FastCallSet *required;
+ unsigned frame;
+ int call_range_first, call_range_last;
+
+ if (!p.open(filename)) {
+ std::cerr << "error: failed to open " << filename << "\n";
+ return 1;
+ }
+
+ /* Mark the beginning so we can return here for pass 2. */
+ p.getBookmark(beginning);
+
+ /* In pass 1, analyze which calls are needed. */
+ frame = 0;
+ trace::Call *call;
+ while ((call = p.parse_call())) {
+
+ /* There's no use doing any work past the last call and frame
+ * requested by the user. */
+ if ((options->calls.empty() || call->no > options->calls.getLast()) &&
+ (options->frames.empty() || frame > options->frames.getLast())) {
+
+ delete call;
+ break;
+ }
+
+ /* If requested, ignore all calls not belonging to the specified thread. */
+ if (options->thread != -1 && call->thread_id != options->thread) {
+ goto NEXT;
+ }
+
+ /* Also, prune if no side effects (unless the user asked for no pruning. */
+ if (options->prune_uninteresting && call->flags & trace::CALL_FLAG_NO_SIDE_EFFECTS) {
+ goto NEXT;
+ }
+
+ /* If this call is included in the user-specified call set,
+ * then require it (and all dependencies) in the trimmed
+ * output. */
+ if (options->calls.contains(*call) ||
+ options->frames.contains(frame, call->flags)) {
+
+ analyzer.require(call);
+ }
+
+ /* Regardless of whether we include this call or not, we do
+ * some dependency tracking (unless disabled by the user). We
+ * do this even for calls we have included in the output so
+ * that any state updates get performed. */
+ if (options->dependency_analysis) {
+ analyzer.analyze(call);
+ }
+
+ NEXT:
+ if (call->flags & trace::CALL_FLAG_END_FRAME)
+ frame++;
+
+ delete call;
+ }
+
+ /* Prepare output file and writer for output. */
+ if (options->output.empty()) {
+ os::String base(filename);
+ base.trimExtension();
+
+ options->output = std::string(base.str()) + std::string("-trim.trace");
+ }
+
+ trace::Writer writer;
+ if (!writer.open(options->output.c_str())) {
+ std::cerr << "error: failed to create " << options->output << "\n";
+ return 1;
+ }
+
+ /* Reset bookmark for pass 2. */
+ p.setBookmark(beginning);
+
+ /* In pass 2, emit the calls that are required. */
+ required = analyzer.get_required();
+
+ frame = 0;
+ call_range_first = -1;
+ call_range_last = -1;
+ while ((call = p.parse_call())) {
+
+ /* There's no use doing any work past the last call and frame
+ * requested by the user. */
+ if ((options->calls.empty() || call->no > options->calls.getLast()) &&
+ (options->frames.empty() || frame > options->frames.getLast())) {
+
+ delete call;
+ break;
+ }
+
+ if (required->contains(call->no)) {
+ writer.writeCall(call);
+
+ if (options->print_callset) {
+ if (call_range_first < 0) {
+ call_range_first = call->no;
+ printf ("%d", call_range_first);
+ } else if (call->no != call_range_last + 1) {
+ if (call_range_last != call_range_first)
+ printf ("-%d", call_range_last);
+ call_range_first = call->no;
+ printf (",%d", call_range_first);
+ }
+ call_range_last = call->no;
+ }
+ }
+
+ if (call->flags & trace::CALL_FLAG_END_FRAME) {
+ frame++;
+ }
+
+ delete call;
+ }
+
+ if (options->print_callset) {
+ if (call_range_last != call_range_first)
+ printf ("-%d\n", call_range_last);
+ }
+
+ std::cerr << "Trimmed trace is available as " << options->output << "\n";
+
+ return 0;
+}
+
+static int
+parse_trim_spec(const char *trim_spec, TrimFlags *flags)
+{
+ std::string spec(trim_spec), word;
+ size_t start = 0, comma = 0;
+ *flags = 0;
+
+ while (start < spec.size()) {
+ comma = spec.find(',', start);
+
+ if (comma == std::string::npos)
+ word = std::string(spec, start);
+ else
+ word = std::string(spec, start, comma - start);
+
+ if (strcmp(word.c_str(), "no-side-effects") == 0)
+ *flags |= TRIM_FLAG_NO_SIDE_EFFECTS;
+ else if (strcmp(word.c_str(), "textures") == 0)
+ *flags |= TRIM_FLAG_TEXTURES;
+ else if (strcmp(word.c_str(), "shaders") == 0)
+ *flags |= TRIM_FLAG_SHADERS;
+ else if (strcmp(word.c_str(), "drawing") == 0)
+ *flags |= TRIM_FLAG_DRAWING;
+ else {
+ return 1;
+ }
+
+ if (comma == std::string::npos)
+ break;
+
+ start = comma + 1;
+ }
+
+ return 0;
+}
+
+static int
+command(int argc, char *argv[])
+{
+ struct trim_auto_options options;
+
+ options.calls = trace::CallSet(trace::FREQUENCY_NONE);
+ options.frames = trace::CallSet(trace::FREQUENCY_NONE);
+ options.dependency_analysis = true;
+ options.prune_uninteresting = true;
+ options.output = "";
+ options.thread = -1;
+ options.print_callset = 0;
+ options.trim_flags = -1;
+
+ int opt;
+ while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
+ switch (opt) {
+ case 'h':
+ usage();
+ return 0;
+ case CALLS_OPT:
+ options.calls.merge(optarg);
+ break;
+ case FRAMES_OPT:
+ options.frames.merge(optarg);
+ break;
+ case DEPS_OPT:
+ options.dependency_analysis = true;
+ break;
+ case NO_DEPS_OPT:
+ options.dependency_analysis = false;
+ break;
+ case PRUNE_OPT:
+ options.prune_uninteresting = true;
+ break;
+ case NO_PRUNE_OPT:
+ options.prune_uninteresting = false;
+ break;
+ case THREAD_OPT:
+ options.thread = atoi(optarg);
+ break;
+ case 'o':
+ options.output = optarg;
+ break;
+ case PRINT_CALLSET_OPT:
+ options.print_callset = 1;
+ break;
+ case TRIM_SPEC_OPT:
+ if (parse_trim_spec(optarg, &options.trim_flags)) {
+ std::cerr << "error: illegal value for trim-spec: " << optarg << "\n";
+ std::cerr << "See \"apitrace help trim\" for help.\n";
+ return 1;
+ }
+ break;
+ default:
+ std::cerr << "error: unexpected option `" << (char)opt << "`\n";
+ usage();
+ return 1;
+ }
+ }
+
+ /* If neither of --calls nor --frames was set, default to the
+ * entire set of calls. */
+ if (options.calls.empty() && options.frames.empty()) {
+ options.calls = trace::CallSet(trace::FREQUENCY_ALL);
+ }
+
+ if (optind >= argc) {
+ std::cerr << "error: apitrace trim requires a trace file as an argument.\n";
+ usage();
+ return 1;
+ }
+
+ if (argc > optind + 1) {
+ std::cerr << "error: extraneous arguments:";
+ for (int i = optind + 1; i < argc; i++) {
+ std::cerr << " " << argv[i];
+ }
+ std::cerr << "\n";
+ usage();
+ return 1;
+ }
+
+ if (options.dependency_analysis) {
+ std::cerr <<
+ "Note: The dependency analysis in \"apitrace trim-auto\" is still experimental.\n"
+ " We hope that it will be useful, but it may lead to incorrect results.\n"
+ " If you find a trace that misbehaves while trimming, please share that\n"
+ " by sending email to apitrace@lists.freedesktop.org, cworth@cworth.org\n";
+ }
+
+ return trim_trace(argv[optind], &options);
+}
+
+const Command trim_auto_command = {
+ "trim-auto",
+ synopsis,
+ usage,
+ command
+};
diff --git a/cli/trace_analyzer.cpp b/cli/cli_trim_auto_analyzer.cpp
index 79f95579..41d90180 100644
--- a/cli/trace_analyzer.cpp
+++ b/cli/cli_trim_auto_analyzer.cpp
@@ -25,7 +25,7 @@
#include <sstream>
-#include "trace_analyzer.hpp"
+#include "cli_trim_auto_analyzer.hpp"
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define STRNCMP_LITERAL(var, literal) strncmp((var), (literal), sizeof (literal) -1)
diff --git a/cli/trace_analyzer.hpp b/cli/cli_trim_auto_analyzer.hpp
index c344fb6a..c344fb6a 100644
--- a/cli/trace_analyzer.hpp
+++ b/cli/cli_trim_auto_analyzer.hpp
diff --git a/cli/pickle.hpp b/cli/pickle.hpp
index 59af6a7b..eff36e0d 100644
--- a/cli/pickle.hpp
+++ b/cli/pickle.hpp
@@ -27,12 +27,12 @@
* Python pickle writer
*/
-#ifndef _PICKLE_HPP_
-#define _PICKLE_HPP_
+#pragma once
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
+#include <wchar.h>
#include <ostream>
#include <string>
@@ -162,6 +162,23 @@ public:
os.put(TUPLE);
}
+ inline void beginTuple(unsigned length) {
+ if (length >= 4) {
+ os.put(MARK);
+ }
+ }
+
+ inline void endTuple(unsigned length) {
+ static const Opcode ops[4] = {
+ EMPTY_TUPLE,
+ TUPLE1,
+ TUPLE2,
+ TUPLE3,
+ };
+ Opcode op = length < 4 ? ops[length] : TUPLE;
+ os.put(op);
+ }
+
inline void writeString(const char *s, size_t length) {
if (!s) {
writeNone();
@@ -194,6 +211,34 @@ public:
writeString(s.c_str(), s.size());
}
+ inline void writeWString(const wchar_t *s, size_t length) {
+ if (!s) {
+ writeNone();
+ return;
+ }
+
+ /* FIXME: emit UTF-8 */
+ os.put(BINUNICODE);
+ putInt32(length);
+ for (size_t i = 0; i < length; ++i) {
+ wchar_t wc = s[i];
+ char c = wc >= 0 && wc < 0x80 ? (char)wc : '?';
+ os.put(c);
+ }
+
+ os.put(BINPUT);
+ os.put(1);
+ }
+
+ inline void writeWString(const wchar_t *s) {
+ if (!s) {
+ writeNone();
+ return;
+ }
+
+ writeWString(s, wcslen(s));
+ }
+
inline void writeNone(void) {
os.put(NONE);
}
@@ -255,7 +300,7 @@ public:
char c[8];
} u;
- assert(sizeof u.f == sizeof u.c);
+ static_assert(sizeof u.f == sizeof u.c, "double is not 8 bytes");
u.f = f;
os.put(BINFLOAT);
@@ -279,6 +324,16 @@ public:
os.put(REDUCE);
}
+ inline void writePointer(unsigned long long addr) {
+ os.put(GLOBAL);
+ os << "unpickle\nPointer\n";
+ os.put(BINPUT);
+ os.put(1);
+ writeInt(addr);
+ os.put(TUPLE1);
+ os.put(REDUCE);
+ }
+
protected:
inline void putInt16(uint16_t i) {
os.put( i & 0xff);
@@ -330,4 +385,3 @@ protected:
}
};
-#endif /* _Pickle_HPP_ */
diff --git a/cmake/ConvenienceLibrary.cmake b/cmake/ConvenienceLibrary.cmake
new file mode 100644
index 00000000..eb6443e1
--- /dev/null
+++ b/cmake/ConvenienceLibrary.cmake
@@ -0,0 +1,15 @@
+# Function for convenience libraries, ie., libraries which can be statically
+# linked into shared libraries.
+function (add_convenience_library)
+
+ set (name "${ARGV0}")
+ list (REMOVE_AT ARGV 0)
+
+ add_library ("${name}" STATIC ${ARGV})
+
+ set_target_properties ("${name}" PROPERTIES
+ # Ensure it can be statically linked onto shared libraries
+ POSITION_INDEPENDENT_CODE ON
+ )
+
+endfunction ()
diff --git a/cmake/FindDirectX.cmake b/cmake/FindDirectX.cmake
index e71a7733..34dbdd8c 100644
--- a/cmake/FindDirectX.cmake
+++ b/cmake/FindDirectX.cmake
@@ -1,286 +1,226 @@
-# - try to find DirectX include dirs and libraries
-
-
-if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
-
-
- if (CMAKE_CL_64)
- set (DirectX_ARCHITECTURE x64)
- else ()
- set (DirectX_ARCHITECTURE x86)
- endif ()
-
-
- # DirectX SDK
- find_path (DirectX_ROOT_DIR
- Include/d3d9.h
- PATHS
- "$ENV{DXSDK_DIR}"
- "$ENV{ProgramFiles}/Microsoft DirectX SDK (June 2010)"
- "$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (June 2010)"
- "$ENV{ProgramFiles}/Microsoft DirectX SDK (February 2010)"
- "$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (February 2010)"
- "$ENV{ProgramFiles}/Microsoft DirectX SDK (March 2009)"
- "$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (March 2009)"
- "$ENV{ProgramFiles}/Microsoft DirectX SDK (August 2008)"
- "$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (August 2008)"
- "$ENV{ProgramFiles}/Microsoft DirectX SDK (June 2008)"
- "$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (June 2008)"
- "$ENV{ProgramFiles}/Microsoft DirectX SDK (March 2008)"
- "$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (March 2008)"
- "$ENV{ProgramFiles}/Microsoft DirectX SDK (November 2007)"
- "$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (November 2007)"
- "$ENV{ProgramFiles}/Microsoft DirectX SDK (August 2007)"
- "$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK (August 2007)"
- "$ENV{ProgramFiles}/Microsoft DirectX SDK"
- "$ENV{ProgramFiles(x86)}/Microsoft DirectX SDK"
- DOC "DirectX SDK root directory"
- )
- if (DirectX_ROOT_DIR)
- set (DirectX_INC_SEARCH_PATH "${DirectX_ROOT_DIR}/Include")
- set (DirectX_LIB_SEARCH_PATH "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}")
- set (DirectX_BIN_SEARCH_PATH "${DirectX_ROOT_DIR}/Utilities/bin/x86")
- endif ()
-
-
- # With VS 2011 and Windows 8 SDK, the DirectX SDK is included as part of
- # the Windows SDK.
- #
- # See also:
- # - http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx
- # TODO: Allow using DirectX SDK with VS 2011
- if (DEFINED MSVC_VERSION AND NOT ${MSVC_VERSION} LESS 1700)
- find_path (WIN8_SDK_ROOT_DIR
- Include/um/windows.h
- PATHS
- "$ENV{ProgramFiles}/Windows Kits/8.0"
- "$ENV{ProgramFiles(x86)}/Windows Kits/8.0"
- DOC "Windows 8 SDK root directory"
- )
-
- if (WIN8_SDK_ROOT_DIR)
- set (DirectX_INC_SEARCH_PATH "${WIN8_SDK_ROOT_DIR}/Include/um" "${WIN8_SDK_ROOT_DIR}/Include/shared")
- set (DirectX_LIB_SEARCH_PATH "${WIN8_SDK_ROOT_DIR}/Lib/Win8/um/${DirectX_ARCHITECTURE}")
- set (DirectX_BIN_SEARCH_PATH "${WIN8_SDK_ROOT_DIR}/bin/x86")
- endif ()
- endif ()
-
-
- find_path (DirectX_D3D_INCLUDE_DIR d3d.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3d.h resides")
-
- find_path (DirectX_D3DX_INCLUDE_DIR d3dx.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3dx.h resides")
-
- find_library (DirectX_DDRAW_LIBRARY ddraw
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where ddraw resides")
-
- find_library (DirectX_D3DX_LIBRARY d3dx
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3dx resides")
-
- if (DirectX_D3D_INCLUDE_DIR AND DirectX_DDRAW_LIBRARY)
- set (DirectX_D3D_FOUND 1)
- if (DirectX_D3DX_INCLUDE_DIR AND DirectX_D3DX_LIBRARY)
- set (DirectX_D3DX_FOUND 1)
- endif ()
- endif ()
-
-
- find_path (DirectX_D3D8_INCLUDE_DIR d3d8.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3d8.h resides")
-
- find_path (DirectX_D3DX8_INCLUDE_DIR d3dx8.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3dx8.h resides")
-
- find_library (DirectX_D3D8_LIBRARY d3d8
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3d8 resides")
-
- find_library (DirectX_D3DX8_LIBRARY d3dx8
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3dx8 resides")
-
- if (DirectX_D3D8_INCLUDE_DIR AND DirectX_D3D8_LIBRARY)
- set (DirectX_D3D8_FOUND 1)
- if (DirectX_D3DX8_INCLUDE_DIR AND DirectX_D3DX8_LIBRARY)
- set (DirectX_D3DX8_FOUND 1)
- endif ()
- endif ()
-
-
- find_path (DirectX_D3D9_INCLUDE_DIR d3d9.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3d9.h resides")
-
- find_path (DirectX_D3DX9_INCLUDE_DIR d3dx9.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3dx9.h resides")
-
- find_library (DirectX_D3D9_LIBRARY d3d9
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3d9 resides")
-
- find_library (DirectX_D3DX9_LIBRARY d3dx9
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3dx9 resides")
-
- if (DirectX_D3D9_INCLUDE_DIR AND DirectX_D3D9_LIBRARY)
- set (DirectX_D3D9_FOUND 1)
- if (DirectX_D3DX9_INCLUDE_DIR AND DirectX_D3DX9_LIBRARY)
- set (DirectX_D3DX9_FOUND 1)
- endif ()
- endif ()
-
-
- find_path (DirectX_D3D10_INCLUDE_DIR d3d10.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3d10.h resides")
-
- find_path (DirectX_D3DX10_INCLUDE_DIR d3dx10.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3dx10.h resides")
-
- find_library (DirectX_D3D10_LIBRARY d3d10
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3d10 resides")
-
- find_library (DirectX_D3DX10_LIBRARY d3dx10
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3dx10 resides")
-
- if (DirectX_D3D10_INCLUDE_DIR AND DirectX_D3D10_LIBRARY)
- set (DirectX_D3D10_FOUND 1)
- if (DirectX_D3DX10_INCLUDE_DIR AND DirectX_D3DX10_LIBRARY)
- set (DirectX_D3DX10_FOUND 1)
- endif ()
- endif ()
-
-
- find_path (DirectX_D3D10_1_INCLUDE_DIR d3d10_1.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3d10_1.h resides")
-
- find_library (DirectX_D3D10_1_LIBRARY d3d10_1
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3d10_1 resides")
-
- if (DirectX_D3D10_1_INCLUDE_DIR AND DirectX_D3D10_1_LIBRARY)
- set (DirectX_D3D10_1_FOUND 1)
- endif ()
-
-
- find_path (DirectX_D3D11_INCLUDE_DIR d3d11.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3d11.h resides")
-
- find_path (DirectX_D3DX11_INCLUDE_DIR d3dx11.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3dx11.h resides")
-
- find_library (DirectX_D3D11_LIBRARY d3d11
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3d11 resides")
-
- find_library (DirectX_D3DX11_LIBRARY d3dx11
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d3dx11 resides")
-
- if (DirectX_D3D11_INCLUDE_DIR AND DirectX_D3D11_LIBRARY)
- set (DirectX_D3D11_FOUND 1)
- if (DirectX_D3DX11_INCLUDE_DIR AND DirectX_D3DX11_LIBRARY)
- set (DirectX_D3DX11_FOUND 1)
- endif ()
- endif ()
-
-
- find_path (DirectX_D3D11_1_INCLUDE_DIR d3d11_1.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d3d11_1.h resides")
-
- if (DirectX_D3D11_1_INCLUDE_DIR AND DirectX_D3D11_LIBRARY)
- set (DirectX_D3D11_1_FOUND 1)
- endif ()
-
-
- find_program (DirectX_FXC_EXECUTABLE fxc
- PATHS ${DirectX_BIN_SEARCH_PATH}
- DOC "Path to fxc.exe executable.")
-
-
- find_path (DirectX_D2D1_INCLUDE_DIR d2d1.h
- PATHS ${DirectX_INC_SEARCH_PATH}
- DOC "The directory where d2d1.h resides")
-
- find_library (DirectX_D2D1_LIBRARY d2d1
- PATHS ${DirectX_LIB_SEARCH_PATH}
- DOC "The directory where d2d1 resides")
-
- if (DirectX_D2D1_INCLUDE_DIR AND DirectX_D2D1_LIBRARY)
- set (DirectX_D2D1_FOUND 1)
- endif (DirectX_D2D1_INCLUDE_DIR AND DirectX_D2D1_LIBRARY)
-
-
- mark_as_advanced (
- DirectX_D3D_INCLUDE_DIR
- DirectX_D3D_INCLUDE_DIR
- DirectX_DDRAW_LIBRARY
- DirectX_DDRAW_LIBRARY
- DirectX_D3DX_INCLUDE_DIR
- DirectX_D3DX_INCLUDE_DIR
- DirectX_D3DX_LIBRARY
- DirectX_D3DX_LIBRARY
- DirectX_D3D8_INCLUDE_DIR
- DirectX_D3D8_INCLUDE_DIR
- DirectX_D3D8_LIBRARY
- DirectX_D3D8_LIBRARY
- DirectX_D3DX8_INCLUDE_DIR
- DirectX_D3DX8_INCLUDE_DIR
- DirectX_D3DX8_LIBRARY
- DirectX_D3DX8_LIBRARY
- DirectX_D3D9_INCLUDE_DIR
- DirectX_D3D9_LIBRARY
- DirectX_D3DX9_INCLUDE_DIR
- DirectX_D3DX9_LIBRARY
- DirectX_D3D10_INCLUDE_DIR
- DirectX_D3D10_LIBRARY
- DirectX_D3DX10_INCLUDE_DIR
- DirectX_D3DX10_LIBRARY
- DirectX_D3D10_1_INCLUDE_DIR
- DirectX_D3D10_1_LIBRARY
- DirectX_D3D11_INCLUDE_DIR
- DirectX_D3D11_LIBRARY
- DirectX_D3DX11_INCLUDE_DIR
- DirectX_D3DX11_LIBRARY
- DirectX_D3D11_1_INCLUDE_DIR
- DirectX_D2D1_INCLUDE_DIR
- DirectX_D2D1_LIBRARY
- )
-
+# - try to find DirectX include directories and libraries
+#
+# Once done this will define:
+#
+# DirectX_XYZ_FOUND - system has the XYZ API
+# DirectX_XYZ_INCLUDE_FOUND - system has the include for the XYZ API
+# DirectX_XYZ_INCLUDE_DIR - include directory for the XYZ API
+# DirectX_XYZ_LIBRARY - path/name for the XYZ library
+#
+# Where XYZ can be any of:
+#
+# DDRAW
+# D3D
+# D3DX
+# D3D8
+# D3DX8
+# D3D9
+# D3DX9
+# D3D10
+# D3D10_1
+# D3DX10
+# D3D11
+# D3D11_1
+# D3D11_2
+# D3DX11
+# D2D1
+#
+
+
+include (CheckIncludeFileCXX)
+include (FindPackageMessage)
+
+
+if (WIN32)
+
+ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set (DirectX_ARCHITECTURE x64)
+ else ()
+ set (DirectX_ARCHITECTURE x86)
+ endif ()
+
+ # Can't use "$ENV{ProgramFiles(x86)}" to avoid violating CMP0053. See
+ # http://public.kitware.com/pipermail/cmake-developers/2014-October/023190.html
+ set (ProgramFiles_x86 "ProgramFiles(x86)")
+ if ("$ENV{${ProgramFiles_x86}}")
+ set (ProgramFiles "$ENV{${ProgramFiles_x86}}")
+ else ()
+ set (ProgramFiles "$ENV{ProgramFiles}")
+ endif ()
+
+ find_path (DirectX_ROOT_DIR
+ Include/d3d9.h
+ PATHS
+ "$ENV{DXSDK_DIR}"
+ "${ProgramFiles}/Microsoft DirectX SDK (June 2010)"
+ "${ProgramFiles}/Microsoft DirectX SDK (February 2010)"
+ "${ProgramFiles}/Microsoft DirectX SDK (March 2009)"
+ "${ProgramFiles}/Microsoft DirectX SDK (August 2008)"
+ "${ProgramFiles}/Microsoft DirectX SDK (June 2008)"
+ "${ProgramFiles}/Microsoft DirectX SDK (March 2008)"
+ "${ProgramFiles}/Microsoft DirectX SDK (November 2007)"
+ "${ProgramFiles}/Microsoft DirectX SDK (August 2007)"
+ "${ProgramFiles}/Microsoft DirectX SDK"
+ DOC "DirectX SDK root directory"
+ )
+ if (DirectX_ROOT_DIR)
+ set (DirectX_INC_SEARCH_PATH "${DirectX_ROOT_DIR}/Include")
+ set (DirectX_LIB_SEARCH_PATH "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}")
+ set (DirectX_BIN_SEARCH_PATH "${DirectX_ROOT_DIR}/Utilities/bin/x86")
+ endif ()
+
+ # With VS 2011 and Windows 8 SDK, the DirectX SDK is included as part of
+ # the Windows SDK.
+ #
+ # See also:
+ # - http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx
+ if (DEFINED MSVC_VERSION AND NOT ${MSVC_VERSION} LESS 1700)
+ set (USE_WINSDK_HEADERS TRUE)
+ endif ()
+
+ # Find a header in the DirectX SDK
+ macro (find_dxsdk_header var_name header)
+ set (include_dir_var "DirectX_${var_name}_INCLUDE_DIR")
+ set (include_found_var "DirectX_${var_name}_INCLUDE_FOUND")
+ find_path (${include_dir_var} ${header}
+ HINTS ${DirectX_INC_SEARCH_PATH}
+ DOC "The directory where ${header} resides"
+ CMAKE_FIND_ROOT_PATH_BOTH
+ )
+ if (${include_dir_var})
+ set (${include_found_var} TRUE)
+ find_package_message (${var_name}_INC "Found ${header} header: ${${include_dir_var}}/${header}" "[${${include_dir_var}}]")
+ endif ()
+ mark_as_advanced (${include_found_var})
+ endmacro ()
+
+ # Find a library in the DirectX SDK
+ macro (find_dxsdk_library var_name library)
+ # DirectX SDK
+ set (library_var "DirectX_${var_name}_LIBRARY")
+ find_library (${library_var} ${library}
+ HINTS ${DirectX_LIB_SEARCH_PATH}
+ DOC "The directory where ${library} resides"
+ CMAKE_FIND_ROOT_PATH_BOTH
+ )
+ if (${library_var})
+ find_package_message (${var_name}_LIB "Found ${library} library: ${${library_var}}" "[${${library_var}}]")
+ endif ()
+ mark_as_advanced (${library_var})
+ endmacro ()
+
+ # Find a header in the Windows SDK
+ macro (find_winsdk_header var_name header)
+ if (USE_WINSDK_HEADERS)
+ # Windows SDK
+ set (include_dir_var "DirectX_${var_name}_INCLUDE_DIR")
+ set (include_found_var "DirectX_${var_name}_INCLUDE_FOUND")
+ check_include_file_cxx (${header} ${include_found_var})
+ set (${include_dir_var})
+ mark_as_advanced (${include_found_var})
+ else ()
+ find_dxsdk_header (${var_name} ${header})
+ endif ()
+ endmacro ()
+
+ # Find a library in the Windows SDK
+ macro (find_winsdk_library var_name library)
+ if (USE_WINSDK_HEADERS)
+ # XXX: We currently just assume the library exists
+ set (library_var "DirectX_${var_name}_LIBRARY")
+ set (${library_var} ${library})
+ mark_as_advanced (${library_var})
+ else ()
+ find_dxsdk_library (${var_name} ${library})
+ endif ()
+ endmacro ()
+
+ # Combine header and library variables into an API found variable
+ macro (find_combined var_name inc_var_name lib_var_name)
+ if (DirectX_${inc_var_name}_INCLUDE_FOUND AND DirectX_${lib_var_name}_LIBRARY)
+ set (DirectX_${var_name}_FOUND 1)
+ find_package_message (${var_name} "Found ${var_name} API" "[${DirectX_${lib_var_name}_LIBRARY}][${DirectX_${inc_var_name}_INCLUDE_DIR}]")
+ endif ()
+ endmacro ()
+
+ find_winsdk_header (DDRAW ddraw.h)
+ find_winsdk_library (DDRAW ddraw)
+ find_combined (DDRAW DDRAW DDRAW)
+
+ if (CMAKE_GENERATOR_TOOLSET MATCHES "_xp$")
+ set (WINDOWS_XP TRUE)
+ endif ()
+
+ if (WINDOWS_XP)
+ # Windows 7 SDKs, used by XP toolset, do not include d3d.h
+ find_dxsdk_header (D3D d3d.h)
+ else ()
+ find_winsdk_header (D3D d3d.h)
+ endif ()
+ find_combined (D3D D3D DDRAW)
+
+ find_dxsdk_header (D3DX d3dx.h)
+ find_combined (D3DX D3DX D3DX)
+
+ find_dxsdk_header (D3D8 d3d8.h)
+ find_dxsdk_library (D3D8 d3d8)
+ find_combined (D3D8 D3D8 D3D8)
+
+ find_dxsdk_header (D3DX8 d3dx8.h)
+ find_dxsdk_library (D3DX8 d3dx8)
+ find_combined (D3DX8 D3DX8 D3DX8)
+
+ find_winsdk_header (D3D9 d3d9.h)
+ find_winsdk_library (D3D9 d3d9)
+ find_combined (D3D9 D3D9 D3D9)
+
+ find_dxsdk_header (D3DX9 d3dx9.h)
+ find_dxsdk_library (D3DX9 d3dx9)
+ find_combined (D3DX9 D3DX9 D3DX9)
+
+ if (NOT WINDOWS_XP)
+ find_winsdk_header (DXGI dxgi.h)
+ find_winsdk_header (DXGI1_2 dxgi1_2.h)
+ find_winsdk_header (DXGI1_3 dxgi1_3.h)
+ find_winsdk_header (DXGI1_4 dxgi1_4.h)
+ find_winsdk_library (DXGI dxgi)
+
+ find_winsdk_header (D3D10 d3d10.h)
+ find_winsdk_library (D3D10 d3d10)
+ find_combined (D3D10 D3D10 D3D10)
+
+ find_winsdk_header (D3D10_1 d3d10_1.h)
+ find_winsdk_library (D3D10_1 d3d10_1)
+ find_combined (D3D10_1 D3D10_1 D3D10_1)
+
+ find_dxsdk_header (D3DX10 d3dx10.h)
+ find_dxsdk_library (D3DX10 d3dx10)
+ find_combined (D3DX10 D3DX10 D3DX10)
+
+ find_winsdk_header (D3D11 d3d11.h)
+ find_winsdk_library (D3D11 d3d11)
+ find_combined (D3D11 D3D11 D3D11)
+ find_winsdk_header (D3D11_1 d3d11_1.h)
+ find_combined (D3D11_1 D3D11_1 D3D11)
+ find_winsdk_header (D3D11_2 d3d11_2.h)
+ find_combined (D3D11_2 D3D11_2 D3D11)
+ find_winsdk_header (D3D11_3 d3d11_3.h)
+ find_combined (D3D11_3 D3D11_3 D3D11)
+
+ find_dxsdk_header (D3DX11 d3dx11.h)
+ find_dxsdk_library (D3DX11 d3dx11)
+ find_combined (D3DX11 D3DX11 D3DX11)
+
+ find_winsdk_header (D2D1 d2d1.h)
+ find_winsdk_library (D2D1 d2d1)
+ find_combined (D2D1 D2D1 D2D1)
+ find_winsdk_header (D2D1_1 d2d1_1.h)
+ find_combined (D2D1_1 D2D1_1 D2D1)
+ endif ()
+
+ find_program (DirectX_FXC_EXECUTABLE fxc
+ HINTS ${DirectX_BIN_SEARCH_PATH}
+ DOC "Path to fxc.exe executable."
+ )
endif ()
-
-
-mark_as_advanced (
- DirectX_D3D_FOUND
- DirectX_D3DX_FOUND
- DirectX_D3D8_FOUND
- DirectX_D3DX8_FOUND
- DirectX_D3D9_FOUND
- DirectX_D3DX9_FOUND
- DirectX_D3D10_FOUND
- DirectX_D3DX10_FOUND
- DirectX_D3D10_1_FOUND
- DirectX_D3D11_FOUND
- DirectX_D3DX11_FOUND
- DirectX_D3D11_1_FOUND
- DirectX_D2D1_FOUND
-)
-
-
-# vim:set sw=4 ts=4 noet:
diff --git a/cmake/FindSNAPPY.cmake b/cmake/FindSNAPPY.cmake
new file mode 100644
index 00000000..f50e154c
--- /dev/null
+++ b/cmake/FindSNAPPY.cmake
@@ -0,0 +1,13 @@
+# Find SNAPPY - A fast compressor/decompressor
+#
+# This module defines
+# SNAPPY_FOUND - whether the snappy library was found
+# SNAPPY_LIBRARIES - the snappy library
+# SNAPPY_INCLUDE_DIR - the include path of the snappy library
+#
+
+find_path (SNAPPY_INCLUDE_DIR NAMES snappy.h)
+find_library (SNAPPY_LIBRARIES NAMES snappy)
+
+include (FindPackageHandleStandardArgs)
+find_package_handle_standard_args (SNAPPY DEFAULT_MSG SNAPPY_LIBRARIES SNAPPY_INCLUDE_DIR)
diff --git a/cmake/FindWaffle.cmake b/cmake/FindWaffle.cmake
deleted file mode 100644
index 03be9cfd..00000000
--- a/cmake/FindWaffle.cmake
+++ /dev/null
@@ -1,38 +0,0 @@
-# - try to find Waffle include dirs and library
-
-if (ANDROID)
- set (Android_root_path "$ENV{OUT}")
- if (Android_root_path)
- set (Waffle_INC_SEARCH_PATH "$ENV{OUT}/obj/include/waffle-1"
- "$ENV{OUT}/obj/lib"
- "$ENV{ANDROID_BUILD_TOP}/external/waffle"
- )
-
- set (Waffle_LIB_SEARCH_PATH "$ENV{OUT}/obj/lib")
- endif ()
-endif ()
-
- find_path (Waffle_INCLUDE_DIR waffle.h
- PATHS ${Waffle_INC_SEARCH_PATH}
- DOC "The directory where waffle.h resides"
- NO_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH
- )
-
- find_library (Waffle_LIBRARY waffle-1
- PATHS ${Waffle_LIB_SEARCH_PATH}
- DOC "The directory where libwaffle-1 resides"
- NO_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH
- )
-
- if (Waffle_INCLUDE_DIR AND Waffle_LIBRARY)
- set (Waffle_FOUND 1)
- endif (Waffle_INCLUDE_DIR AND Waffle_LIBRARY)
-
- mark_as_advanced (
- Waffle_INCLUDE_DIR
- Waffle_LIBRARY
- )
-
-mark_as_advanced (
- Waffle_FOUND
-)
diff --git a/cmake/Findprocps.cmake b/cmake/Findprocps.cmake
new file mode 100644
index 00000000..e614d7cd
--- /dev/null
+++ b/cmake/Findprocps.cmake
@@ -0,0 +1,16 @@
+# - try to find procps directories and libraries
+#
+# Once done this will define:
+#
+# PROCPS_FOUND
+# PROCPS_INCLUDE_DIR
+# PROCPS_LIBRARY
+#
+
+include (FindPackageHandleStandardArgs)
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ find_path (PROCPS_INCLUDE_DIR proc/readproc.h)
+ find_library (PROCPS_LIBRARY NAMES proc procps)
+ find_package_handle_standard_args (procps DEFAULT_MSG PROCPS_LIBRARY PROCPS_INCLUDE_DIR)
+endif()
diff --git a/cmake/InstallPDB.cmake b/cmake/InstallPDB.cmake
new file mode 100644
index 00000000..d7ed7618
--- /dev/null
+++ b/cmake/InstallPDB.cmake
@@ -0,0 +1,17 @@
+function (INSTALL_PDB target_name)
+ if (MSVC)
+ get_target_property (target_output_name ${target_name} OUTPUT_NAME)
+ if (NOT target_output_name)
+ set (target_output_name ${target_name})
+ endif ()
+
+ # The documentation for the INSTALL command doesn't mention generator
+ # expressions, but they actually work quite well, both when building
+ # MSBuild and Ninja.
+ install (
+ FILES "$<TARGET_FILE_DIR:${target_name}>/${target_output_name}.pdb"
+ CONFIGURATIONS Debug RelWithDebInfo
+ ${ARGV}
+ )
+ endif()
+endfunction ()
diff --git a/cmake/Windows10SDK.cmake b/cmake/Windows10SDK.cmake
new file mode 100644
index 00000000..df189d5e
--- /dev/null
+++ b/cmake/Windows10SDK.cmake
@@ -0,0 +1,53 @@
+# - try to find and use Windows 10 SDK on VS 2013
+#
+# VS 2013 will never pick Windows 10 SDK -- one must manually set the include and library directories.
+#
+# See also:
+# - https://github.com/walbourn/directx-sdk-samples/commit/68575c40984f2581e3931157bd7e9f831ba70d69
+# - http://stackoverflow.com/a/28922582
+# - http://blogs.msdn.com/b/vcblog/archive/2012/11/23/using-the-windows-8-sdk-with-visual-studio-2010-configuring-multiple-projects.aspx
+
+if (MSVC AND ${MSVC_VERSION} LESS 1900 AND NOT CMAKE_GENERATOR_TOOLSET MATCHES "_xp$")
+
+ include (FindPackageMessage)
+
+ # Can't use "$ENV{ProgramFiles(x86)}" to avoid violating CMP0053. See
+ # http://public.kitware.com/pipermail/cmake-developers/2014-October/023190.html
+ set (ProgramFiles_x86 "ProgramFiles(x86)")
+ if ("$ENV{${ProgramFiles_x86}}")
+ set (ProgramFiles "$ENV{${ProgramFiles_x86}}")
+ else ()
+ set (ProgramFiles "$ENV{ProgramFiles}")
+ endif ()
+
+ set (WIN10_SDK_VER "10.0.10240.0")
+
+ find_path (WIN10_SDK_ROOT_DIR
+ SDKManifest.xml
+ PATHS
+ "${ProgramFiles}/Windows Kits/10"
+ DOC "Windows 10 SDK root directory"
+ )
+
+ if (CMAKE_SIZEOF_VOID_P EQUAL 4)
+ set (WIN10_SDK_ARCH x86)
+ else ()
+ set (WIN10_SDK_ARCH x64)
+ endif ()
+
+ if (WIN10_SDK_ROOT_DIR)
+ find_package_message (WIN10_SDK "Windows 10 SDK - found: ${WIN10_SDK_ROOT_DIR}" "[${WIN10_SDK_ROOT_DIR}]")
+ set (WIN10_SDK_INC_DIRS
+ "${WIN10_SDK_ROOT_DIR}/Include/${WIN10_SDK_VER}/um"
+ "${WIN10_SDK_ROOT_DIR}/Include/${WIN10_SDK_VER}/shared"
+ "${WIN10_SDK_ROOT_DIR}/Include/${WIN10_SDK_VER}/winrt"
+ )
+ include_directories (BEFORE ${WIN10_SDK_INC_DIRS})
+ list (APPEND CMAKE_REQUIRED_INCLUDES ${WIN10_SDK_INC_DIRS})
+ link_directories (
+ ${WIN10_SDK_ROOT_DIR}/Lib/${WIN10_SDK_VER}/${WIN10_SDK_ARCH}
+ )
+ else ()
+ find_package_message (WIN10_SDK "Windows 10 SDK - not found" "[]")
+ endif ()
+endif ()
diff --git a/cmake/toolchain/android.toolchain.cmake b/cmake/toolchain/android.toolchain.cmake
deleted file mode 100644
index 457164a1..00000000
--- a/cmake/toolchain/android.toolchain.cmake
+++ /dev/null
@@ -1,1776 +0,0 @@
-# Copyright (c) 2010-2011, Ethan Rublee
-# Copyright (c) 2011-2014, Andrey Kamaev
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from this
-# software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-# ------------------------------------------------------------------------------
-# Android CMake toolchain file, for use with the Android NDK r5-r9
-# Requires cmake 2.6.3 or newer (2.8.5 or newer is recommended).
-# See home page: https://github.com/taka-no-me/android-cmake
-#
-# The file is mantained by the OpenCV project. The latest version can be get at
-# http://code.opencv.org/projects/opencv/repository/revisions/master/changes/android/android.toolchain.cmake
-#
-# Usage Linux:
-# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk
-# $ mkdir build && cd build
-# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
-# $ make -j8
-#
-# Usage Linux (using standalone toolchain):
-# $ export ANDROID_STANDALONE_TOOLCHAIN=/absolute/path/to/android-toolchain
-# $ mkdir build && cd build
-# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
-# $ make -j8
-#
-# Usage Windows:
-# You need native port of make to build your project.
-# Android NDK r7 (or newer) already has make.exe on board.
-# For older NDK you have to install it separately.
-# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm
-#
-# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk
-# $ mkdir build && cd build
-# $ cmake.exe -G"MinGW Makefiles"
-# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake
-# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" ..
-# $ cmake.exe --build .
-#
-#
-# Options (can be set as cmake parameters: -D<option_name>=<value>):
-# ANDROID_NDK=/opt/android-ndk - path to the NDK root.
-# Can be set as environment variable. Can be set only at first cmake run.
-#
-# ANDROID_STANDALONE_TOOLCHAIN=/opt/android-toolchain - path to the
-# standalone toolchain. This option is not used if full NDK is found
-# (ignored if ANDROID_NDK is set).
-# Can be set as environment variable. Can be set only at first cmake run.
-#
-# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary
-# Interface (ABI). This option nearly matches to the APP_ABI variable
-# used by ndk-build tool from Android NDK.
-#
-# Possible targets are:
-# "armeabi" - matches to the NDK ABI with the same name.
-# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation.
-# "armeabi-v7a" - matches to the NDK ABI with the same name.
-# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation.
-# "armeabi-v7a with NEON" - same as armeabi-v7a, but
-# sets NEON as floating-point unit
-# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but
-# sets VFPV3 as floating-point unit (has 32 registers instead of 16).
-# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP.
-# "x86" - matches to the NDK ABI with the same name.
-# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation.
-# "mips" - matches to the NDK ABI with the same name.
-# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation.
-#
-# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for.
-# Option is read-only when standalone toolchain is used.
-#
-# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.6 - the name of compiler
-# toolchain to be used. The list of possible values depends on the NDK
-# version. For NDK r8c the possible values are:
-#
-# * arm-linux-androideabi-4.4.3
-# * arm-linux-androideabi-4.6
-# * arm-linux-androideabi-clang3.1
-# * mipsel-linux-android-4.4.3
-# * mipsel-linux-android-4.6
-# * mipsel-linux-android-clang3.1
-# * x86-4.4.3
-# * x86-4.6
-# * x86-clang3.1
-#
-# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions
-# instead of Thumb. Is not available for "x86" (inapplicable) and
-# "armeabi-v6 with VFP" (is forced to be ON) ABIs.
-#
-# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker
-# errors even if they are not used.
-#
-# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared
-# libraries. Automatically turned for NDK r5x and r6x due to GLESv2
-# problems.
-#
-# LIBRARY_OUTPUT_PATH_ROOT=${CMAKE_SOURCE_DIR} - where to output binary
-# files. See additional details below.
-#
-# ANDROID_SET_OBSOLETE_VARIABLES=ON - if set, then toolchain defines some
-# obsolete variables which were used by previous versions of this file for
-# backward compatibility.
-#
-# ANDROID_STL=gnustl_static - specify the runtime to use.
-#
-# Possible values are:
-# none -> Do not configure the runtime.
-# system -> Use the default minimal system C++ runtime library.
-# Implies -fno-rtti -fno-exceptions.
-# Is not available for standalone toolchain.
-# system_re -> Use the default minimal system C++ runtime library.
-# Implies -frtti -fexceptions.
-# Is not available for standalone toolchain.
-# gabi++_static -> Use the GAbi++ runtime as a static library.
-# Implies -frtti -fno-exceptions.
-# Available for NDK r7 and newer.
-# Is not available for standalone toolchain.
-# gabi++_shared -> Use the GAbi++ runtime as a shared library.
-# Implies -frtti -fno-exceptions.
-# Available for NDK r7 and newer.
-# Is not available for standalone toolchain.
-# stlport_static -> Use the STLport runtime as a static library.
-# Implies -fno-rtti -fno-exceptions for NDK before r7.
-# Implies -frtti -fno-exceptions for NDK r7 and newer.
-# Is not available for standalone toolchain.
-# stlport_shared -> Use the STLport runtime as a shared library.
-# Implies -fno-rtti -fno-exceptions for NDK before r7.
-# Implies -frtti -fno-exceptions for NDK r7 and newer.
-# Is not available for standalone toolchain.
-# gnustl_static -> Use the GNU STL as a static library.
-# Implies -frtti -fexceptions.
-# gnustl_shared -> Use the GNU STL as a shared library.
-# Implies -frtti -fno-exceptions.
-# Available for NDK r7b and newer.
-# Silently degrades to gnustl_static if not available.
-#
-# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on
-# chosen runtime. If disabled, then the user is responsible for settings
-# these options.
-#
-# What?:
-# android-cmake toolchain searches for NDK/toolchain in the following order:
-# ANDROID_NDK - cmake parameter
-# ANDROID_NDK - environment variable
-# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter
-# ANDROID_STANDALONE_TOOLCHAIN - environment variable
-# ANDROID_NDK - default locations
-# ANDROID_STANDALONE_TOOLCHAIN - default locations
-#
-# Make sure to do the following in your scripts:
-# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" )
-# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" )
-# The flags will be prepopulated with critical flags, so don't loose them.
-# Also be aware that toolchain also sets configuration-specific compiler
-# flags and linker flags.
-#
-# ANDROID and BUILD_ANDROID will be set to true, you may test any of these
-# variables to make necessary Android-specific configuration changes.
-#
-# Also ARMEABI or ARMEABI_V7A or X86 or MIPS will be set true, mutually
-# exclusive. NEON option will be set true if VFP is set to NEON.
-#
-# LIBRARY_OUTPUT_PATH_ROOT should be set in cache to determine where Android
-# libraries will be installed.
-# Default is ${CMAKE_SOURCE_DIR}, and the android libs will always be
-# under the ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}
-# (depending on the target ABI). This is convenient for Android packaging.
-#
-# Change Log:
-# - initial version December 2010
-# - April 2011
-# [+] added possibility to build with NDK (without standalone toolchain)
-# [+] support cross-compilation on Windows (native, no cygwin support)
-# [+] added compiler option to force "char" type to be signed
-# [+] added toolchain option to compile to 32-bit ARM instructions
-# [+] added toolchain option to disable SWIG search
-# [+] added platform "armeabi-v7a with VFPV3"
-# [~] ARM_TARGETS renamed to ARM_TARGET
-# [+] EXECUTABLE_OUTPUT_PATH is set by toolchain (required on Windows)
-# [~] Fixed bug with ANDROID_API_LEVEL variable
-# [~] turn off SWIG search if it is not found first time
-# - May 2011
-# [~] ANDROID_LEVEL is renamed to ANDROID_API_LEVEL
-# [+] ANDROID_API_LEVEL is detected by toolchain if not specified
-# [~] added guard to prevent changing of output directories on the first
-# cmake pass
-# [~] toolchain exits with error if ARM_TARGET is not recognized
-# - June 2011
-# [~] default NDK path is updated for version r5c
-# [+] variable CMAKE_SYSTEM_PROCESSOR is set based on ARM_TARGET
-# [~] toolchain install directory is added to linker paths
-# [-] removed SWIG-related stuff from toolchain
-# [+] added macro find_host_package, find_host_program to search
-# packages/programs on the host system
-# [~] fixed path to STL library
-# - July 2011
-# [~] fixed options caching
-# [~] search for all supported NDK versions
-# [~] allowed spaces in NDK path
-# - September 2011
-# [~] updated for NDK r6b
-# - November 2011
-# [*] rewritten for NDK r7
-# [+] x86 toolchain support (experimental)
-# [+] added "armeabi-v6 with VFP" ABI for ARMv6 processors.
-# [~] improved compiler and linker flags management
-# [+] support different build flags for Release and Debug configurations
-# [~] by default compiler flags the same as used by ndk-build (but only
-# where reasonable)
-# [~] ANDROID_NDK_TOOLCHAIN_ROOT is splitted to ANDROID_STANDALONE_TOOLCHAIN
-# and ANDROID_TOOLCHAIN_ROOT
-# [~] ARM_TARGET is renamed to ANDROID_ABI
-# [~] ARMEABI_NDK_NAME is renamed to ANDROID_NDK_ABI_NAME
-# [~] ANDROID_API_LEVEL is renamed to ANDROID_NATIVE_API_LEVEL
-# - January 2012
-# [+] added stlport_static support (experimental)
-# [+] added special check for cygwin
-# [+] filtered out hidden files (starting with .) while globbing inside NDK
-# [+] automatically applied GLESv2 linkage fix for NDK revisions 5-6
-# [+] added ANDROID_GET_ABI_RAWNAME to get NDK ABI names by CMake flags
-# - February 2012
-# [+] updated for NDK r7b
-# [~] fixed cmake try_compile() command
-# [~] Fix for missing install_name_tool on OS X
-# - March 2012
-# [~] fixed incorrect C compiler flags
-# [~] fixed CMAKE_SYSTEM_PROCESSOR change on ANDROID_ABI change
-# [+] improved toolchain loading speed
-# [+] added assembler language support (.S)
-# [+] allowed preset search paths and extra search suffixes
-# - April 2012
-# [+] updated for NDK r7c
-# [~] fixed most of problems with compiler/linker flags and caching
-# [+] added option ANDROID_FUNCTION_LEVEL_LINKING
-# - May 2012
-# [+] updated for NDK r8
-# [+] added mips architecture support
-# - August 2012
-# [+] updated for NDK r8b
-# [~] all intermediate files generated by toolchain are moved to CMakeFiles
-# [~] libstdc++ and libsupc are removed from explicit link libraries
-# [+] added CCache support (via NDK_CCACHE environment or cmake variable)
-# [+] added gold linker support for NDK r8b
-# [~] fixed mips linker flags for NDK r8b
-# - September 2012
-# [+] added NDK release name detection (see ANDROID_NDK_RELEASE)
-# [+] added support for all C++ runtimes from NDK
-# (system, gabi++, stlport, gnustl)
-# [+] improved warnings on known issues of NDKs
-# [~] use gold linker as default if available (NDK r8b)
-# [~] globally turned off rpath
-# [~] compiler options are aligned with NDK r8b
-# - October 2012
-# [~] fixed C++ linking: explicitly link with math library (OpenCV #2426)
-# - November 2012
-# [+] updated for NDK r8c
-# [+] added support for clang compiler
-# - December 2012
-# [+] suppress warning about unused CMAKE_TOOLCHAIN_FILE variable
-# [+] adjust API level to closest compatible as NDK does
-# [~] fixed ccache full path search
-# [+] updated for NDK r8d
-# [~] compiler options are aligned with NDK r8d
-# - March 2013
-# [+] updated for NDK r8e (x86 version)
-# [+] support x86_64 version of NDK
-# - April 2013
-# [+] support non-release NDK layouts (from Linaro git and Android git)
-# [~] automatically detect if explicit link to crtbegin_*.o is needed
-# - June 2013
-# [~] fixed stl include path for standalone toolchain made by NDK >= r8c
-# - July 2013
-# [+] updated for NDK r9
-# - November 2013
-# [+] updated for NDK r9b
-# - December 2013
-# [+] updated for NDK r9c
-# - January 2014
-# [~] fix copying of shared STL
-# ------------------------------------------------------------------------------
-
-cmake_minimum_required( VERSION 2.6.3 )
-
-if( DEFINED CMAKE_CROSSCOMPILING )
- # subsequent toolchain loading is not really needed
- return()
-endif()
-
-if( CMAKE_TOOLCHAIN_FILE )
- # touch toolchain variable only to suppress "unused variable" warning
-endif()
-
-get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE )
-if( _CMAKE_IN_TRY_COMPILE )
- include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL )
-endif()
-
-# this one is important
-set( CMAKE_SYSTEM_NAME Linux )
-# this one not so much
-set( CMAKE_SYSTEM_VERSION 1 )
-
-# rpath makes low sence for Android
-set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
-
-set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
-if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS)
- if( CMAKE_HOST_WIN32 )
- file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
- set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}/android-ndk" "$ENV{SystemDrive}/NVPACK/android-ndk" )
- else()
- file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS )
- set( ANDROID_NDK_SEARCH_PATHS /opt/android-ndk "${ANDROID_NDK_SEARCH_PATHS}/NVPACK/android-ndk" )
- endif()
-endif()
-if(NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH)
- set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain )
-endif()
-
-set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" )
-set( ANDROID_SUPPORTED_ABIS_x86 "x86" )
-set( ANDROID_SUPPORTED_ABIS_mipsel "mips" )
-
-set( ANDROID_DEFAULT_NDK_API_LEVEL 8 )
-set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 )
-set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 )
-
-
-macro( __LIST_FILTER listvar regex )
- if( ${listvar} )
- foreach( __val ${${listvar}} )
- if( __val MATCHES "${regex}" )
- list( REMOVE_ITEM ${listvar} "${__val}" )
- endif()
- endforeach()
- endif()
-endmacro()
-
-macro( __INIT_VARIABLE var_name )
- set( __test_path 0 )
- foreach( __var ${ARGN} )
- if( __var STREQUAL "PATH" )
- set( __test_path 1 )
- break()
- endif()
- endforeach()
- if( __test_path AND NOT EXISTS "${${var_name}}" )
- unset( ${var_name} CACHE )
- endif()
- if( "${${var_name}}" STREQUAL "" )
- set( __values 0 )
- foreach( __var ${ARGN} )
- if( __var STREQUAL "VALUES" )
- set( __values 1 )
- elseif( NOT __var STREQUAL "PATH" )
- set( __obsolete 0 )
- if( __var MATCHES "^OBSOLETE_.*$" )
- string( REPLACE "OBSOLETE_" "" __var "${__var}" )
- set( __obsolete 1 )
- endif()
- if( __var MATCHES "^ENV_.*$" )
- string( REPLACE "ENV_" "" __var "${__var}" )
- set( __value "$ENV{${__var}}" )
- elseif( DEFINED ${__var} )
- set( __value "${${__var}}" )
- else()
- if( __values )
- set( __value "${__var}" )
- else()
- set( __value "" )
- endif()
- endif()
- if( NOT "${__value}" STREQUAL "" )
- if( __test_path )
- if( EXISTS "${__value}" )
- file( TO_CMAKE_PATH "${__value}" ${var_name} )
- if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE )
- message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." )
- endif()
- break()
- endif()
- else()
- set( ${var_name} "${__value}" )
- if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE )
- message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." )
- endif()
- break()
- endif()
- endif()
- endif()
- endforeach()
- unset( __value )
- unset( __values )
- unset( __obsolete )
- elseif( __test_path )
- file( TO_CMAKE_PATH "${${var_name}}" ${var_name} )
- endif()
- unset( __test_path )
-endmacro()
-
-macro( __DETECT_NATIVE_API_LEVEL _var _path )
- SET( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*$" )
- FILE( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" )
- if( NOT __apiFileContent )
- message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." )
- endif()
- string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" )
- unset( __apiFileContent )
- unset( __ndkApiLevelRegex )
-endmacro()
-
-macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root )
- if( EXISTS "${_root}" )
- file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" )
- __LIST_FILTER( __gccExePath "^[.].*" )
- list( LENGTH __gccExePath __gccExePathsCount )
- if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE )
- message( WARNING "Could not determine machine name for compiler from ${_root}" )
- set( ${_var} "" )
- else()
- get_filename_component( __gccExeName "${__gccExePath}" NAME_WE )
- string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" )
- endif()
- unset( __gccExePath )
- unset( __gccExePathsCount )
- unset( __gccExeName )
- else()
- set( ${_var} "" )
- endif()
-endmacro()
-
-
-# fight against cygwin
-set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools")
-mark_as_advanced( ANDROID_FORBID_SYGWIN )
-if( ANDROID_FORBID_SYGWIN )
- if( CYGWIN )
- message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." )
- endif()
-
- if( CMAKE_HOST_WIN32 )
- # remove cygwin from PATH
- set( __new_path "$ENV{PATH}")
- __LIST_FILTER( __new_path "cygwin" )
- set(ENV{PATH} "${__new_path}")
- unset(__new_path)
- endif()
-endif()
-
-
-# detect current host platform
-if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) )
- set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" )
- mark_as_advanced( ANDROID_NDK_HOST_X64 )
-endif()
-
-set( TOOL_OS_SUFFIX "" )
-if( CMAKE_HOST_APPLE )
- set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" )
-elseif( CMAKE_HOST_WIN32 )
- set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" )
- set( TOOL_OS_SUFFIX ".exe" )
-elseif( CMAKE_HOST_UNIX )
- set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" )
-else()
- message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" )
-endif()
-
-if( NOT ANDROID_NDK_HOST_X64 )
- set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} )
-endif()
-
-# see if we have path to Android NDK
-__INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
-if( NOT ANDROID_NDK )
- # see if we have path to Android standalone toolchain
- __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN OBSOLETE_ANDROID_NDK_TOOLCHAIN_ROOT OBSOLETE_ENV_ANDROID_NDK_TOOLCHAIN_ROOT )
-
- if( NOT ANDROID_STANDALONE_TOOLCHAIN )
- #try to find Android NDK in one of the the default locations
- set( __ndkSearchPaths )
- foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} )
- foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} )
- list( APPEND __ndkSearchPaths "${__ndkSearchPath}${suffix}" )
- endforeach()
- endforeach()
- __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} )
- unset( __ndkSearchPaths )
-
- if( ANDROID_NDK )
- message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" )
- message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" )
- else()
- #try to find Android standalone toolchain in one of the the default locations
- __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
-
- if( ANDROID_STANDALONE_TOOLCHAIN )
- message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" )
- message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" )
- endif( ANDROID_STANDALONE_TOOLCHAIN )
- endif( ANDROID_NDK )
- endif( NOT ANDROID_STANDALONE_TOOLCHAIN )
-endif( NOT ANDROID_NDK )
-
-# remember found paths
-if( ANDROID_NDK )
- get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE )
- set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE )
- set( BUILD_WITH_ANDROID_NDK True )
- if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" )
- file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX r[0-9]+[a-z]? )
- string( REGEX MATCH r[0-9]+[a-z]? ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" )
- else()
- set( ANDROID_NDK_RELEASE "r1x" )
- set( ANDROID_NDK_RELEASE_FULL "unreleased" )
- endif()
-elseif( ANDROID_STANDALONE_TOOLCHAIN )
- get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE )
- # try to detect change
- if( CMAKE_AR )
- string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length )
- string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath )
- if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN )
- message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." )
- endif()
- unset( __androidStandaloneToolchainPreviousPath )
- unset( __length )
- endif()
- set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE )
- set( BUILD_WITH_STANDALONE_TOOLCHAIN True )
-else()
- list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH)
- message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain.
- You should either set an environment variable:
- export ANDROID_NDK=~/my-android-ndk
- or
- export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain
- or put the toolchain or NDK in the default path:
- sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}
- sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" )
-endif()
-
-# android NDK layout
-if( BUILD_WITH_ANDROID_NDK )
- if( NOT DEFINED ANDROID_NDK_LAYOUT )
- # try to automatically detect the layout
- if( EXISTS "${ANDROID_NDK}/RELEASE.TXT")
- set( ANDROID_NDK_LAYOUT "RELEASE" )
- elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" )
- set( ANDROID_NDK_LAYOUT "LINARO" )
- elseif( EXISTS "${ANDROID_NDK}/../../gcc/" )
- set( ANDROID_NDK_LAYOUT "ANDROID" )
- endif()
- endif()
- set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" )
- mark_as_advanced( ANDROID_NDK_LAYOUT )
- if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
- set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
- elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
- set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
- else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE"
- set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" )
- endif()
- get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE )
-
- # try to detect change of NDK
- if( CMAKE_AR )
- string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length )
- string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath )
- if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH )
- message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first.
- " )
- endif()
- unset( __androidNdkPreviousPath )
- unset( __length )
- endif()
-endif()
-
-
-# get all the details about standalone toolchain
-if( BUILD_WITH_STANDALONE_TOOLCHAIN )
- __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" )
- set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
- set( __availableToolchains "standalone" )
- __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" )
- if( NOT __availableToolchainMachines )
- message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." )
- endif()
- if( __availableToolchainMachines MATCHES i686 )
- set( __availableToolchainArchs "x86" )
- elseif( __availableToolchainMachines MATCHES arm )
- set( __availableToolchainArchs "arm" )
- elseif( __availableToolchainMachines MATCHES mipsel )
- set( __availableToolchainArchs "mipsel" )
- endif()
- execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion
- OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE )
- string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" )
- if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" )
- list( APPEND __availableToolchains "standalone-clang" )
- list( APPEND __availableToolchainMachines ${__availableToolchainMachines} )
- list( APPEND __availableToolchainArchs ${__availableToolchainArchs} )
- list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} )
- endif()
-endif()
-
-macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath )
- foreach( __toolchain ${${__availableToolchainsLst}} )
- if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
- string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" )
- else()
- set( __gcc_toolchain "${__toolchain}" )
- endif()
- __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" )
- if( __machine )
- string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" )
- if( __machine MATCHES i686 )
- set( __arch "x86" )
- elseif( __machine MATCHES arm )
- set( __arch "arm" )
- elseif( __machine MATCHES mipsel )
- set( __arch "mipsel" )
- endif()
- list( APPEND __availableToolchainMachines "${__machine}" )
- list( APPEND __availableToolchainArchs "${__arch}" )
- list( APPEND __availableToolchainCompilerVersions "${__version}" )
- list( APPEND ${__availableToolchainsVar} "${__toolchain}" )
- endif()
- unset( __gcc_toolchain )
- endforeach()
-endmacro()
-
-# get all the details about NDK
-if( BUILD_WITH_ANDROID_NDK )
- file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" )
- string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" )
- set( __availableToolchains "" )
- set( __availableToolchainMachines "" )
- set( __availableToolchainArchs "" )
- set( __availableToolchainCompilerVersions "" )
- if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" )
- # do not go through all toolchains if we know the name
- set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
- if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
- if( __availableToolchains )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
- endif()
- endif()
- endif()
- if( NOT __availableToolchains )
- file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
- if( __availableToolchains )
- list(SORT __availableToolchainsLst) # we need clang to go after gcc
- endif()
- __LIST_FILTER( __availableToolchainsLst "^[.]" )
- __LIST_FILTER( __availableToolchainsLst "llvm" )
- __LIST_FILTER( __availableToolchainsLst "renderscript" )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
- if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
- if( __availableToolchains )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
- endif()
- endif()
- endif()
- if( NOT __availableToolchains )
- message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." )
- endif()
-endif()
-
-# build list of available ABIs
-set( ANDROID_SUPPORTED_ABIS "" )
-set( __uniqToolchainArchNames ${__availableToolchainArchs} )
-list( REMOVE_DUPLICATES __uniqToolchainArchNames )
-list( SORT __uniqToolchainArchNames )
-foreach( __arch ${__uniqToolchainArchNames} )
- list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} )
-endforeach()
-unset( __uniqToolchainArchNames )
-if( NOT ANDROID_SUPPORTED_ABIS )
- message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." )
-endif()
-
-# choose target ABI
-__INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${ANDROID_SUPPORTED_ABIS} )
-# verify that target ABI is supported
-list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx )
-if( __androidAbiIdx EQUAL -1 )
- string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" )
- message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain.
- Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\"
- " )
-endif()
-unset( __androidAbiIdx )
-
-# set target ABI options
-if( ANDROID_ABI STREQUAL "x86" )
- set( X86 true )
- set( ANDROID_NDK_ABI_NAME "x86" )
- set( ANDROID_ARCH_NAME "x86" )
- set( ANDROID_ARCH_FULLNAME "x86" )
- set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" )
- set( CMAKE_SYSTEM_PROCESSOR "i686" )
-elseif( ANDROID_ABI STREQUAL "mips" )
- set( MIPS true )
- set( ANDROID_NDK_ABI_NAME "mips" )
- set( ANDROID_ARCH_NAME "mips" )
- set( ANDROID_ARCH_FULLNAME "mipsel" )
- set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" )
- set( CMAKE_SYSTEM_PROCESSOR "mips" )
-elseif( ANDROID_ABI STREQUAL "armeabi" )
- set( ARMEABI true )
- set( ANDROID_NDK_ABI_NAME "armeabi" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_ARCH_FULLNAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv5te" )
-elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" )
- set( ARMEABI_V6 true )
- set( ANDROID_NDK_ABI_NAME "armeabi" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_ARCH_FULLNAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv6" )
- # need always fallback to older platform
- set( ARMEABI true )
-elseif( ANDROID_ABI STREQUAL "armeabi-v7a")
- set( ARMEABI_V7A true )
- set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_ARCH_FULLNAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
-elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" )
- set( ARMEABI_V7A true )
- set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_ARCH_FULLNAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
- set( VFPV3 true )
-elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" )
- set( ARMEABI_V7A true )
- set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_ARCH_FULLNAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
- set( VFPV3 true )
- set( NEON true )
-else()
- message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." )
-endif()
-
-if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" )
- # really dirty hack
- # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run...
- file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" )
-endif()
-
-if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 )
- __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD OBSOLETE_FORCE_ARM VALUES OFF )
- set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE )
- mark_as_advanced( ANDROID_FORCE_ARM_BUILD )
-else()
- unset( ANDROID_FORCE_ARM_BUILD CACHE )
-endif()
-
-# choose toolchain
-if( ANDROID_TOOLCHAIN_NAME )
- list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx )
- if( __toolchainIdx EQUAL -1 )
- list( SORT __availableToolchains )
- string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" )
- set( toolchains_list " * ${toolchains_list}")
- message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain.
-To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" )
- endif()
- list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch )
- if( NOT __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME )
- message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." )
- endif()
-else()
- set( __toolchainIdx -1 )
- set( __applicableToolchains "" )
- set( __toolchainMaxVersion "0.0.0" )
- list( LENGTH __availableToolchains __availableToolchainsCount )
- math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" )
- foreach( __idx RANGE ${__availableToolchainsCount} )
- list( GET __availableToolchainArchs ${__idx} __toolchainArch )
- if( __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME )
- list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion )
- string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}")
- if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion )
- set( __toolchainMaxVersion "${__toolchainVersion}" )
- set( __toolchainIdx ${__idx} )
- endif()
- endif()
- endforeach()
- unset( __availableToolchainsCount )
- unset( __toolchainMaxVersion )
- unset( __toolchainVersion )
-endif()
-unset( __toolchainArch )
-if( __toolchainIdx EQUAL -1 )
- message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." )
-endif()
-list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME )
-list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME )
-list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION )
-
-unset( __toolchainIdx )
-unset( __availableToolchains )
-unset( __availableToolchainMachines )
-unset( __availableToolchainArchs )
-unset( __availableToolchainCompilerVersions )
-
-# choose native API level
-__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL )
-string( REGEX MATCH "[0-9]+" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" )
-# adjust API level
-set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} )
-foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
- if( NOT __level GREATER ANDROID_NATIVE_API_LEVEL AND NOT __level LESS __real_api_level )
- set( __real_api_level ${__level} )
- endif()
-endforeach()
-if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL EQUAL __real_api_level )
- message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'")
- set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} )
-endif()
-unset(__real_api_level)
-# validate
-list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx )
-if( __levelIdx EQUAL -1 )
- message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." )
-else()
- if( BUILD_WITH_ANDROID_NDK )
- __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" )
- if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL )
- message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." )
- endif()
- unset( __realApiLevel )
- endif()
- set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE )
- if( CMAKE_VERSION VERSION_GREATER "2.8" )
- list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS )
- set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
- endif()
-endif()
-unset( __levelIdx )
-
-
-# remember target ABI
-set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE )
-if( CMAKE_VERSION VERSION_GREATER "2.8" )
- list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME} )
- set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME}} )
-endif()
-
-
-# runtime choice (STL, rtti, exceptions)
-if( NOT ANDROID_STL )
- # honor legacy ANDROID_USE_STLPORT
- if( DEFINED ANDROID_USE_STLPORT )
- if( ANDROID_USE_STLPORT )
- set( ANDROID_STL stlport_static )
- endif()
- message( WARNING "You are using an obsolete variable ANDROID_USE_STLPORT to select the STL variant. Use -DANDROID_STL=stlport_static instead." )
- endif()
- if( NOT ANDROID_STL )
- set( ANDROID_STL gnustl_static )
- endif()
-endif()
-set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" )
-set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" )
-mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES )
-
-if( BUILD_WITH_ANDROID_NDK )
- if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$")
- message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
-The possible values are:
- none -> Do not configure the runtime.
- system -> Use the default minimal system C++ runtime library.
- system_re -> Same as system but with rtti and exceptions.
- gabi++_static -> Use the GAbi++ runtime as a static library.
- gabi++_shared -> Use the GAbi++ runtime as a shared library.
- stlport_static -> Use the STLport runtime as a static library.
- stlport_shared -> Use the STLport runtime as a shared library.
- gnustl_static -> (default) Use the GNU STL as a static library.
- gnustl_shared -> Use the GNU STL as a shared library.
-" )
- endif()
-elseif( BUILD_WITH_STANDALONE_TOOLCHAIN )
- if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$")
- message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
-The possible values are:
- none -> Do not configure the runtime.
- gnustl_static -> (default) Use the GNU STL as a static library.
- gnustl_shared -> Use the GNU STL as a shared library.
-" )
- endif()
-endif()
-
-unset( ANDROID_RTTI )
-unset( ANDROID_EXCEPTIONS )
-unset( ANDROID_STL_INCLUDE_DIRS )
-unset( __libstl )
-unset( __libsupcxx )
-
-if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" )
- message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf).
-You are strongly recommended to switch to another NDK release.
-" )
-endif()
-
-if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" )
- message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header:
-See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2
- diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
- index 5e28c64..65892a1 100644
- --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h
- +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
- @@ -51,7 +51,11 @@ typedef long int ssize_t;
- #endif
- #ifndef _PTRDIFF_T
- #define _PTRDIFF_T
- -typedef long ptrdiff_t;
- +# ifdef __ANDROID__
- + typedef int ptrdiff_t;
- +# else
- + typedef long ptrdiff_t;
- +# endif
- #endif
-" )
-endif()
-
-
-# setup paths and STL for standalone toolchain
-if( BUILD_WITH_STANDALONE_TOOLCHAIN )
- set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
- set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
- set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" )
-
- if( NOT ANDROID_STL STREQUAL "none" )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" )
- if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" )
- # old location ( pre r8c )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" )
- endif()
- if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" )
- list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" )
- elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" )
- list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" )
- else()
- list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" )
- endif()
- # always search static GNU STL to get the location of libsupc++.a
- if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" )
- elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" )
- elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" )
- elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" )
- endif()
- if( __libstl )
- set( __libsupcxx "${__libstl}/libsupc++.a" )
- set( __libstl "${__libstl}/libstdc++.a" )
- endif()
- if( NOT EXISTS "${__libsupcxx}" )
- message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain.
- Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c.
- You need to either upgrade to newer NDK or manually copy
- $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a
- to
- ${__libsupcxx}
- " )
- endif()
- if( ANDROID_STL STREQUAL "gnustl_shared" )
- if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
- elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
- elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
- endif()
- endif()
- endif()
-endif()
-
-# clang
-if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" )
- set( ANDROID_COMPILER_IS_CLANG 1 )
- execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE )
- string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}")
-elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" )
- string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}")
- string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-4.6" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
- if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" )
- message( FATAL_ERROR "Could not find the Clang compiler driver" )
- endif()
- set( ANDROID_COMPILER_IS_CLANG 1 )
- set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
-else()
- set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
- unset( ANDROID_COMPILER_IS_CLANG CACHE )
-endif()
-
-string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" )
-if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" )
- set( _clang_name "clang" )
-endif()
-
-
-# setup paths and STL for NDK
-if( BUILD_WITH_ANDROID_NDK )
- set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
- set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" )
-
- if( ANDROID_STL STREQUAL "none" )
- # do nothing
- elseif( ANDROID_STL STREQUAL "system" )
- set( ANDROID_RTTI OFF )
- set( ANDROID_EXCEPTIONS OFF )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
- elseif( ANDROID_STL STREQUAL "system_re" )
- set( ANDROID_RTTI ON )
- set( ANDROID_EXCEPTIONS ON )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
- elseif( ANDROID_STL MATCHES "gabi" )
- if( ANDROID_NDK_RELEASE STRLESS "r7" )
- message( FATAL_ERROR "gabi++ is not awailable in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.")
- endif()
- set( ANDROID_RTTI ON )
- set( ANDROID_EXCEPTIONS OFF )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" )
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" )
- elseif( ANDROID_STL MATCHES "stlport" )
- if( NOT ANDROID_NDK_RELEASE STRLESS "r8d" )
- set( ANDROID_EXCEPTIONS ON )
- else()
- set( ANDROID_EXCEPTIONS OFF )
- endif()
- if( ANDROID_NDK_RELEASE STRLESS "r7" )
- set( ANDROID_RTTI OFF )
- else()
- set( ANDROID_RTTI ON )
- endif()
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" )
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" )
- elseif( ANDROID_STL MATCHES "gnustl" )
- set( ANDROID_EXCEPTIONS ON )
- set( ANDROID_RTTI ON )
- if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
- if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" )
- # gnustl binary for 4.7 compiler is buggy :(
- # TODO: look for right fix
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" )
- else()
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
- endif()
- else()
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" )
- endif()
- set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" )
- if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
- set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
- else()
- set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
- endif()
- else()
- message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" )
- endif()
- # find libsupc++.a - rtti & exceptions
- if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" )
- set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer
- if( NOT EXISTS "${__libsupcxx}" )
- set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8
- endif()
- if( NOT EXISTS "${__libsupcxx}" ) # before r7
- if( ARMEABI_V7A )
- if( ANDROID_FORCE_ARM_BUILD )
- set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" )
- else()
- set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" )
- endif()
- elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD )
- set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" )
- else()
- set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" )
- endif()
- endif()
- if( NOT EXISTS "${__libsupcxx}")
- message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.")
- endif()
- endif()
-endif()
-
-
-# case of shared STL linkage
-if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl )
- string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" )
- # TODO: check if .so file exists before the renaming
-endif()
-
-
-# ccache support
-__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE )
-if( _ndk_ccache )
- if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE )
- unset( NDK_CCACHE CACHE )
- endif()
- find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary")
-else()
- unset( NDK_CCACHE CACHE )
-endif()
-unset( _ndk_ccache )
-
-
-# setup the cross-compiler
-if( NOT CMAKE_C_COMPILER )
- if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
- set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" )
- set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" )
- if( ANDROID_COMPILER_IS_CLANG )
- set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
- set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
- else()
- set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
- set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
- endif()
- else()
- if( ANDROID_COMPILER_IS_CLANG )
- set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
- set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
- else()
- set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" )
- set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" )
- endif()
- endif()
- set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" )
- set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" )
- set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
- set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" )
- set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" )
- set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" )
- set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" )
- set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" )
-endif()
-
-set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" )
-if( CMAKE_VERSION VERSION_LESS 2.8.5 )
- set( CMAKE_ASM_COMPILER_ARG1 "-c" )
-endif()
-if( APPLE )
- find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool )
- if( NOT CMAKE_INSTALL_NAME_TOOL )
- message( FATAL_ERROR "Could not find install_name_tool, please check your installation." )
- endif()
- mark_as_advanced( CMAKE_INSTALL_NAME_TOOL )
-endif()
-
-# Force set compilers because standard identification works badly for us
-include( CMakeForceCompiler )
-CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU )
-if( ANDROID_COMPILER_IS_CLANG )
- set( CMAKE_C_COMPILER_ID Clang)
-endif()
-set( CMAKE_C_PLATFORM_ID Linux )
-set( CMAKE_C_SIZEOF_DATA_PTR 4 )
-set( CMAKE_C_HAS_ISYSROOT 1 )
-set( CMAKE_C_COMPILER_ABI ELF )
-CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU )
-if( ANDROID_COMPILER_IS_CLANG )
- set( CMAKE_CXX_COMPILER_ID Clang)
-endif()
-set( CMAKE_CXX_PLATFORM_ID Linux )
-set( CMAKE_CXX_SIZEOF_DATA_PTR 4 )
-set( CMAKE_CXX_HAS_ISYSROOT 1 )
-set( CMAKE_CXX_COMPILER_ABI ELF )
-set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C )
-# force ASM compiler (required for CMake < 2.8.5)
-set( CMAKE_ASM_COMPILER_ID_RUN TRUE )
-set( CMAKE_ASM_COMPILER_ID GNU )
-set( CMAKE_ASM_COMPILER_WORKS TRUE )
-set( CMAKE_ASM_COMPILER_FORCED TRUE )
-set( CMAKE_COMPILER_IS_GNUASM 1)
-set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm )
-
-# flags and definitions
-remove_definitions( -DANDROID )
-add_definitions( -DANDROID )
-
-if( ANDROID_SYSROOT MATCHES "[ ;\"]" )
- if( CMAKE_HOST_WIN32 )
- # try to convert path to 8.3 form
- file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" )
- execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}"
- OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE
- RESULT_VARIABLE __result ERROR_QUIET )
- if( __result EQUAL 0 )
- file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT )
- set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
- else()
- set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" )
- endif()
- else()
- set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" )
- endif()
- if( NOT _CMAKE_IN_TRY_COMPILE )
- # quotes can break try_compile and compiler identification
- message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n")
- endif()
-else()
- set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
-endif()
-
-# NDK flags
-if( ARMEABI OR ARMEABI_V7A )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -funwind-tables" )
- if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 )
- set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" )
- set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
- if( NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" )
- endif()
- else()
- # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI
- set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" )
- set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
- if( NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
- endif()
- endif()
-elseif( X86 )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
- if( NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
- else()
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fPIC" )
- endif()
- set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
- set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" )
-elseif( MIPS )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0" )
- set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" )
- set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" )
- if( NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" )
- set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
- endif()
-elseif()
- set( ANDROID_CXX_FLAGS_RELEASE "" )
- set( ANDROID_CXX_FLAGS_DEBUG "" )
-endif()
-
-set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries
-
-if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" )
-endif()
-
-if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/
-endif()
-
-# ABI-specific flags
-if( ARMEABI_V7A )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" )
- if( NEON )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" )
- elseif( VFPV3 )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" )
- else()
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" )
- endif()
-elseif( ARMEABI_V6 )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2
-elseif( ARMEABI )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" )
-endif()
-
-if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
- set( CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
-else()
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
- set( CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
-endif()
-
-# STL
-if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" )
- if( EXISTS "${__libstl}" )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" )
- set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" )
- endif()
- if( EXISTS "${__libsupcxx}" )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
- set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
- # C objects:
- set( CMAKE_C_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
- set( CMAKE_C_CREATE_SHARED_MODULE "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
- set( CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
- set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
- set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
- set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
- endif()
- if( ANDROID_STL MATCHES "gnustl" )
- if( NOT EXISTS "${ANDROID_LIBM_PATH}" )
- set( ANDROID_LIBM_PATH -lm )
- endif()
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" )
- set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" )
- endif()
-endif()
-
-# variables controlling optional build flags
-if (ANDROID_NDK_RELEASE STRLESS "r7")
- # libGLESv2.so in NDK's prior to r7 refers to missing external symbols.
- # So this flag option is required for all projects using OpenGL from native.
- __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON )
-else()
- __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF )
-endif()
-__INIT_VARIABLE( ANDROID_NO_UNDEFINED OBSOLETE_NO_UNDEFINED VALUES ON )
-__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON )
-__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON )
-__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON )
-__INIT_VARIABLE( ANDROID_RELRO VALUES ON )
-
-set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" )
-set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
-set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
-set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker (only avaialble for NDK r8b for ARM and x86 architectures on linux-86 and darwin-x86 hosts)" )
-set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
-set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" )
-mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO )
-
-# linker flags
-set( ANDROID_LINKER_FLAGS "" )
-
-if( ARMEABI_V7A )
- # this is *required* to use the following linker flags that routes around
- # a CPU bug in some Cortex-A8 implementations:
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" )
-endif()
-
-if( ANDROID_NO_UNDEFINED )
- if( MIPS )
- # there is some sysroot-related problem in mips linker...
- if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" )
- endif()
- else()
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" )
- endif()
-endif()
-
-if( ANDROID_SO_UNDEFINED )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" )
-endif()
-
-if( ANDROID_FUNCTION_LEVEL_LINKING )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" )
-endif()
-
-if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" )
- if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE STRGREATER "r8b") AND (ARMEABI OR ARMEABI_V7A OR X86) )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" )
- elseif( ANDROID_NDK_RELEASE STRGREATER "r8b")
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" )
- elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE )
- message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342
- On Linux and OS X host platform you can workaround this problem using gold linker (default).
- Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems.
-" )
- endif()
-endif() # version 4.6
-
-if( ANDROID_NOEXECSTACK )
- if( ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" )
- else()
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" )
- endif()
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" )
-endif()
-
-if( ANDROID_RELRO )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" )
-endif()
-
-if( ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "-Qunused-arguments ${ANDROID_CXX_FLAGS}" )
- if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD )
- set( ANDROID_CXX_FLAGS_RELEASE "-target thumbv7-none-linux-androideabi ${ANDROID_CXX_FLAGS_RELEASE}" )
- set( ANDROID_CXX_FLAGS_DEBUG "-target ${ANDROID_LLVM_TRIPLE} ${ANDROID_CXX_FLAGS_DEBUG}" )
- else()
- set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} ${ANDROID_CXX_FLAGS}" )
- endif()
- if( BUILD_WITH_ANDROID_NDK )
- set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" )
- endif()
-endif()
-
-# cache flags
-set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" )
-set( CMAKE_C_FLAGS "" CACHE STRING "c flags" )
-set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" )
-set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" )
-set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" )
-set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" )
-set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" )
-set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" )
-set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" )
-
-# put flags to cache (for debug purpose only)
-set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" )
-set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" )
-set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" )
-set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" )
-
-# finish flags
-set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
-set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
-set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" )
-set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" )
-set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" )
-set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" )
-set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" )
-set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" )
-set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" )
-
-if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" )
- set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" )
- set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" )
- set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" )
-endif()
-
-# configure rtti
-if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES )
- if( ANDROID_RTTI )
- set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" )
- else()
- set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" )
- endif()
-endif()
-
-# configure exceptios
-if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES )
- if( ANDROID_EXCEPTIONS )
- set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" )
- set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" )
- else()
- set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" )
- set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" )
- endif()
-endif()
-
-# global includes and link directories
-include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} )
-get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning
-link_directories( "${__android_install_path}" )
-
-# detect if need link crtbegin_so.o explicitly
-if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK )
- set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" )
- string( REPLACE "<CMAKE_CXX_COMPILER>" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" )
- string( REPLACE "<CMAKE_C_COMPILER>" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" )
- string( REPLACE "<CMAKE_SHARED_LIBRARY_CXX_FLAGS>" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" )
- string( REPLACE "<LANGUAGE_COMPILE_FLAGS>" "" __cmd "${__cmd}" )
- string( REPLACE "<LINK_FLAGS>" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" )
- string( REPLACE "<CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS>" "-shared" __cmd "${__cmd}" )
- string( REPLACE "<CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG>" "" __cmd "${__cmd}" )
- string( REPLACE "<TARGET_SONAME>" "" __cmd "${__cmd}" )
- string( REPLACE "<TARGET>" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" )
- string( REPLACE "<OBJECTS>" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" )
- string( REPLACE "<LINK_LIBRARIES>" "" __cmd "${__cmd}" )
- separate_arguments( __cmd )
- foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN )
- if( ${__var} )
- set( __tmp "${${__var}}" )
- separate_arguments( __tmp )
- string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}")
- endif()
- endforeach()
- string( REPLACE "'" "" __cmd "${__cmd}" )
- string( REPLACE "\"" "" __cmd "${__cmd}" )
- execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET )
- if( __cmd_result EQUAL 0 )
- set( ANDROID_EXPLICIT_CRT_LINK ON )
- else()
- set( ANDROID_EXPLICIT_CRT_LINK OFF )
- endif()
-endif()
-
-if( ANDROID_EXPLICIT_CRT_LINK )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
-endif()
-
-# setup output directories
-set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" )
-set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
-
-if(NOT _CMAKE_IN_TRY_COMPILE)
- if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
- set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
- else()
- set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
- endif()
- set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "path for android libs" )
-endif()
-
-# copy shaed stl library to build directory
-if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" )
- get_filename_component( __libstlname "${__libstl}" NAME )
- execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess )
- if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}")
- message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" )
- endif()
- unset( __fileCopyProcess )
- unset( __libstlname )
-endif()
-
-
-# set these global flags for cmake client scripts to change behavior
-set( ANDROID True )
-set( BUILD_ANDROID True )
-
-# where is the target environment
-set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" )
-
-# only search for libraries and includes in the ndk toolchain
-set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
-set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
-set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
-
-
-# macro to find packages on the host OS
-macro( find_host_package )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
- if( CMAKE_HOST_WIN32 )
- SET( WIN32 1 )
- SET( UNIX )
- elseif( CMAKE_HOST_APPLE )
- SET( APPLE 1 )
- SET( UNIX )
- endif()
- find_package( ${ARGN} )
- SET( WIN32 )
- SET( APPLE )
- SET( UNIX 1 )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
-endmacro()
-
-
-# macro to find programs on the host OS
-macro( find_host_program )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
- if( CMAKE_HOST_WIN32 )
- SET( WIN32 1 )
- SET( UNIX )
- elseif( CMAKE_HOST_APPLE )
- SET( APPLE 1 )
- SET( UNIX )
- endif()
- find_program( ${ARGN} )
- SET( WIN32 )
- SET( APPLE )
- SET( UNIX 1 )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
-endmacro()
-
-
-macro( ANDROID_GET_ABI_RAWNAME TOOLCHAIN_FLAG VAR )
- if( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI" )
- set( ${VAR} "armeabi" )
- elseif( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI_V7A" )
- set( ${VAR} "armeabi-v7a" )
- elseif( "${TOOLCHAIN_FLAG}" STREQUAL "X86" )
- set( ${VAR} "x86" )
- elseif( "${TOOLCHAIN_FLAG}" STREQUAL "MIPS" )
- set( ${VAR} "mips" )
- else()
- set( ${VAR} "unknown" )
- endif()
-endmacro()
-
-
-# export toolchain settings for the try_compile() command
-if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" )
- set( __toolchain_config "")
- foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN ANDROID_SET_OBSOLETE_VARIABLES
- ANDROID_NDK_HOST_X64
- ANDROID_NDK
- ANDROID_NDK_LAYOUT
- ANDROID_STANDALONE_TOOLCHAIN
- ANDROID_TOOLCHAIN_NAME
- ANDROID_ABI
- ANDROID_NATIVE_API_LEVEL
- ANDROID_STL
- ANDROID_STL_FORCE_FEATURES
- ANDROID_FORCE_ARM_BUILD
- ANDROID_NO_UNDEFINED
- ANDROID_SO_UNDEFINED
- ANDROID_FUNCTION_LEVEL_LINKING
- ANDROID_GOLD_LINKER
- ANDROID_NOEXECSTACK
- ANDROID_RELRO
- ANDROID_LIBM_PATH
- ANDROID_EXPLICIT_CRT_LINK
- )
- if( DEFINED ${__var} )
- if( "${__var}" MATCHES " ")
- set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" )
- else()
- set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" )
- endif()
- endif()
- endforeach()
- file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" )
- unset( __toolchain_config )
-endif()
-
-
-# force cmake to produce / instead of \ in build commands for Ninja generator
-if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 )
- # it is a bad hack after all
- # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW
- set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW
- set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion
- enable_language( C )
- enable_language( CXX )
- # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it
- unset( MINGW )
-endif()
-
-
-# set some obsolete variables for backward compatibility
-set( ANDROID_SET_OBSOLETE_VARIABLES ON CACHE BOOL "Define obsolete Andrid-specific cmake variables" )
-mark_as_advanced( ANDROID_SET_OBSOLETE_VARIABLES )
-if( ANDROID_SET_OBSOLETE_VARIABLES )
- set( ANDROID_API_LEVEL ${ANDROID_NATIVE_API_LEVEL} )
- set( ARM_TARGET "${ANDROID_ABI}" )
- set( ARMEABI_NDK_NAME "${ANDROID_NDK_ABI_NAME}" )
-endif()
-
-
-# Variables controlling behavior or set by cmake toolchain:
-# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips"
-# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14 (depends on NDK version)
-# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none
-# ANDROID_FORBID_SYGWIN : ON/OFF
-# ANDROID_NO_UNDEFINED : ON/OFF
-# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version)
-# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF
-# ANDROID_GOLD_LINKER : ON/OFF
-# ANDROID_NOEXECSTACK : ON/OFF
-# ANDROID_RELRO : ON/OFF
-# ANDROID_FORCE_ARM_BUILD : ON/OFF
-# ANDROID_STL_FORCE_FEATURES : ON/OFF
-# ANDROID_SET_OBSOLETE_VARIABLES : ON/OFF
-# Can be set only at the first run:
-# ANDROID_NDK
-# ANDROID_STANDALONE_TOOLCHAIN
-# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain
-# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems)
-# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID)
-# LIBRARY_OUTPUT_PATH_ROOT : <any valid path>
-# NDK_CCACHE : <path to your ccache executable>
-# Obsolete:
-# ANDROID_API_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL
-# ARM_TARGET : superseded by ANDROID_ABI
-# ARM_TARGETS : superseded by ANDROID_ABI (can be set only)
-# ANDROID_NDK_TOOLCHAIN_ROOT : superseded by ANDROID_STANDALONE_TOOLCHAIN (can be set only)
-# ANDROID_USE_STLPORT : superseded by ANDROID_STL=stlport_static
-# ANDROID_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL (completely removed)
-#
-# Primary read-only variables:
-# ANDROID : always TRUE
-# ARMEABI : TRUE for arm v6 and older devices
-# ARMEABI_V6 : TRUE for arm v6
-# ARMEABI_V7A : TRUE for arm v7a
-# NEON : TRUE if NEON unit is enabled
-# VFPV3 : TRUE if VFP version 3 is enabled
-# X86 : TRUE if configured for x86
-# MIPS : TRUE if configured for mips
-# BUILD_ANDROID : always TRUE
-# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used
-# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used
-# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform
-# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86" or "mips" depending on ANDROID_ABI
-# ANDROID_NDK_RELEASE : one of r5, r5b, r5c, r6, r6b, r7, r7b, r7c, r8, r8b, r8c, r8d, r8e, r9, r9b, r9c; set only for NDK
-# ANDROID_ARCH_NAME : "arm" or "x86" or "mips" depending on ANDROID_ABI
-# ANDROID_SYSROOT : path to the compiler sysroot
-# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform
-# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used
-# Obsolete:
-# ARMEABI_NDK_NAME : superseded by ANDROID_NDK_ABI_NAME
-#
-# Secondary (less stable) read-only variables:
-# ANDROID_COMPILER_VERSION : GCC version used
-# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform
-# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI
-# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux"
-# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK)
-# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools
-# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK
-# ANDROID_STL_INCLUDE_DIRS : stl include paths
-# ANDROID_RTTI : if rtti is enabled by the runtime
-# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime
-# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used
-# ANDROID_CLANG_VERSION : version of clang compiler if clang is used
-# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product/<product_name>/obj/lib/libm.so) to workaround unresolved `sincos`
-#
-# Defaults:
-# ANDROID_DEFAULT_NDK_API_LEVEL
-# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH}
-# ANDROID_NDK_SEARCH_PATHS
-# ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH
-# ANDROID_SUPPORTED_ABIS_${ARCH}
-# ANDROID_SUPPORTED_NDK_VERSIONS
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
new file mode 100644
index 00000000..e4eab722
--- /dev/null
+++ b/common/CMakeLists.txt
@@ -0,0 +1,52 @@
+include_directories (
+ ${CMAKE_SOURCE_DIR}/guids
+)
+
+if (WIN32)
+ set (os os_win32.cpp)
+else ()
+ set (os os_posix.cpp)
+endif ()
+
+add_convenience_library (common
+ trace_callset.cpp
+ trace_dump.cpp
+ trace_fast_callset.cpp
+ trace_file.cpp
+ trace_file_read.cpp
+ trace_file_zlib.cpp
+ trace_file_snappy.cpp
+ trace_model.cpp
+ trace_parser.cpp
+ trace_parser_flags.cpp
+ trace_parser_loop.cpp
+ trace_writer.cpp
+ trace_writer_local.cpp
+ trace_writer_model.cpp
+ trace_profiler.cpp
+ trace_option.cpp
+ trace_ostream_snappy.cpp
+ trace_ostream_zlib.cpp
+ ${os}
+ os_backtrace.cpp
+ os_crtdbg.cpp
+ highlight.cpp
+)
+
+target_link_libraries (common
+ guids
+ ${LIBBACKTRACE_LIBRARIES}
+)
+if (WIN32)
+ target_link_libraries (common
+ shell32
+ )
+endif ()
+if (ANDROID)
+ target_link_libraries (common
+ log
+ )
+endif ()
+
+add_gtest (trace_parser_flags_test trace_parser_flags_test.cpp)
+target_link_libraries (trace_parser_flags_test common)
diff --git a/common/highlight.cpp b/common/highlight.cpp
index a80a2b02..a03fcf76 100644
--- a/common/highlight.cpp
+++ b/common/highlight.cpp
@@ -32,6 +32,7 @@
#include <windows.h>
#include <io.h> // _isatty
+#include <stdio.h> // _fileno
#ifndef COMMON_LVB_LEADING_BYTE
#define COMMON_LVB_LEADING_BYTE 0x0100
@@ -229,7 +230,7 @@ haveAnsi(void)
static bool result = false;
if (!checked) {
- // https://code.google.com/p/conemu-maximus5/wiki/AnsiEscapeCodes#Environment_variable
+ // https://conemu.github.io/en/ConEmuEnvironment.html
// XXX: Didn't quite work for me
if (0) {
const char *conEmuANSI = getenv("ConEmuANSI");
@@ -241,11 +242,21 @@ haveAnsi(void)
}
}
+ // Cygwin shell
+ if (1) {
+ const char *term = getenv("TERM");
+ if (term &&
+ strcmp(term, "xterm") == 0) {
+ result = true;
+ checked = true;
+ return result;
+ }
+ }
+
// http://wiki.winehq.org/DeveloperFaq#detect-wine
- HMODULE hNtDll = LoadLibraryA("ntdll");
+ HMODULE hNtDll = GetModuleHandleA("ntdll");
if (hNtDll) {
result = GetProcAddress(hNtDll, "wine_get_version") != NULL;
- FreeLibrary(hNtDll);
}
checked = true;
diff --git a/common/highlight.hpp b/common/highlight.hpp
index 9f6be8d4..bda49142 100644
--- a/common/highlight.hpp
+++ b/common/highlight.hpp
@@ -27,8 +27,7 @@
* Helpers for coloring output.
*/
-#ifndef _HIGHLIGHT_HPP_
-#define _HIGHLIGHT_HPP_
+#pragma once
#include <iostream>
@@ -85,4 +84,3 @@ defaultHighlighter(std::ostream & os);
} /* namespace highlight */
-#endif /* _HIGHLIGHT_HPP_ */
diff --git a/common/os.hpp b/common/os.hpp
index 62bb954a..10c7b7c7 100644
--- a/common/os.hpp
+++ b/common/os.hpp
@@ -27,8 +27,7 @@
* Simple OS abstraction layer.
*/
-#ifndef _OS_HPP_
-#define _OS_HPP_
+#pragma once
#include <stdlib.h>
#include <stdarg.h>
@@ -64,13 +63,8 @@ void log(const char *format, ...)
#endif
#define PRIVATE
#else
- #if __GNUC__ >= 4
- #define PUBLIC __attribute__ ((visibility("default")))
- #define PRIVATE __attribute__ ((visibility("hidden")))
- #else
- #define PUBLIC
- #define PRIVATE
- #endif
+ #define PUBLIC __attribute__ ((visibility("default")))
+ #define PRIVATE __attribute__ ((visibility("hidden")))
#endif
/**
@@ -79,7 +73,19 @@ void log(const char *format, ...)
* This should be called only from the wrappers, when there is no safe way of
* failing gracefully.
*/
-void abort(void);
+// coverity[+kill]
+#ifdef _MSC_VER
+__declspec(noreturn)
+#endif
+void abort(void)
+#ifdef __GNUC__
+ __attribute__((__noreturn__))
+#endif
+;
+
+void
+breakpoint(void);
+
void setExceptionCallback(void (*callback)(void));
void resetExceptionCallback(void);
@@ -106,4 +112,3 @@ bool queryVirtualAddress(const void *address, MemoryInfo *info);
} /* namespace os */
-#endif /* _OS_HPP_ */
diff --git a/common/os_backtrace.hpp b/common/os_backtrace.hpp
index 27dcc90f..72869c26 100644
--- a/common/os_backtrace.hpp
+++ b/common/os_backtrace.hpp
@@ -24,8 +24,7 @@
*
**************************************************************************/
-#ifndef _OS_BACKTRACE_HPP_
-#define _OS_BACKTRACE_HPP_
+#pragma once
#include <vector>
@@ -43,5 +42,3 @@ void dump_backtrace();
} /* namespace os */
-
-#endif
diff --git a/common/os_binary.hpp b/common/os_binary.hpp
index a231c709..c3a1d6ea 100644
--- a/common/os_binary.hpp
+++ b/common/os_binary.hpp
@@ -27,8 +27,7 @@
* Force binary mode standard files on Windows.
*/
-#ifndef _OS_BINARY_HPP_
-#define _OS_BINARY_HPP_
+#pragma once
#include <stdio.h>
@@ -58,4 +57,3 @@ void setBinaryMode(FILE *fp) {
} /* namespace os */
-#endif /* _OS_BINARY_HPP_ */
diff --git a/common/os_crtdbg.cpp b/common/os_crtdbg.cpp
new file mode 100644
index 00000000..21dec6ec
--- /dev/null
+++ b/common/os_crtdbg.cpp
@@ -0,0 +1,92 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "os_crtdbg.hpp"
+
+#include <assert.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#include <crtdbg.h>
+#endif
+
+#include "os.hpp"
+
+
+namespace os {
+
+
+#ifdef _WIN32
+
+static void
+invalidParameterHandler(const wchar_t* expression,
+ const wchar_t* function,
+ const wchar_t* file,
+ unsigned int line,
+ uintptr_t pReserved)
+{
+ fprintf(stderr, "Invalid parameter detected in function %S. File: %S Line: %d\n", function, file, line);
+ fprintf(stderr, "Expression: %S\n", expression);
+ if (IsDebuggerPresent()) {
+ os::breakpoint();
+ }
+ os::abort();
+}
+
+#endif // _WIN32
+
+
+void
+setDebugOutput(Output output)
+{
+
+#ifdef _WIN32
+ // Disable assertion failure message box
+ // http://msdn.microsoft.com/en-us/library/sas1dkb2.aspx
+ _set_error_mode(_OUT_TO_STDERR);
+#ifdef _MSC_VER
+ // Disable abort message box
+ // http://msdn.microsoft.com/en-us/library/e631wekh.aspx
+ _set_abort_behavior(0, _WRITE_ABORT_MSG);
+ // Direct debug reports to stderr
+ // https://msdn.microsoft.com/en-us/library/1y71x448.aspx
+ for (int reportType = 0; reportType < _CRT_ERRCNT; ++reportType) {
+ _CrtSetReportMode(reportType, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(reportType, _CRTDBG_FILE_STDERR);
+ }
+#endif /* _MSC_VER */
+ // Set our own invalid_parameter handler
+ // https://msdn.microsoft.com/en-us/library/a9yf33zb.aspx
+ _set_invalid_parameter_handler(invalidParameterHandler);
+#endif /* _WIN32 */
+
+
+ assert(output == OUTPUT_STDERR);
+}
+
+
+} /* namespace os */
diff --git a/common/os_crtdbg.hpp b/common/os_crtdbg.hpp
new file mode 100644
index 00000000..87a018ba
--- /dev/null
+++ b/common/os_crtdbg.hpp
@@ -0,0 +1,57 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Abstrations to force where CRT debug output should go.
+ */
+
+#pragma once
+
+
+#include <stdio.h>
+
+#ifdef _WIN32
+#include <assert.h>
+
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+
+namespace os {
+
+
+enum Output {
+ OUTPUT_STDERR,
+ OUTPUT_OUTDBG
+};
+
+
+void
+setDebugOutput(Output output);
+
+
+} /* namespace os */
+
diff --git a/common/os_dl.hpp b/common/os_dl.hpp
index da51d414..bf79d507 100644
--- a/common/os_dl.hpp
+++ b/common/os_dl.hpp
@@ -27,8 +27,7 @@
* Dynamic library linking abstraction.
*/
-#ifndef _OS_DL_HPP_
-#define _OS_DL_HPP_
+#pragma once
#if defined(_WIN32)
@@ -86,4 +85,3 @@ namespace os {
} /* namespace os */
-#endif /* _OS_DL_HPP_ */
diff --git a/common/os_memory.hpp b/common/os_memory.hpp
index 4774412d..5a852516 100644
--- a/common/os_memory.hpp
+++ b/common/os_memory.hpp
@@ -28,13 +28,16 @@
* Simple OS time measurement abstraction.
*/
-#ifndef _OS_MEMORY_HPP_
-#define _OS_MEMORY_HPP_
+#pragma once
#ifdef HAVE_READPROC_H
#include <proc/readproc.h>
+#endif
namespace os {
+
+#if defined(HAVE_READPROC_H)
+
inline long long
getVsize(void) {
proc_t proc;
@@ -48,10 +51,17 @@ namespace os {
look_up_our_self(&proc);
return proc.rss;
}
-} /* namespace os */
+
+#elif defined(__ANDROID__)
+
+ long long
+ getVsize(void);
+
+ long long
+ getRss(void);
#else
-namespace os {
+
inline long long
getVsize(void) {
return 0;
@@ -61,7 +71,8 @@ namespace os {
getRss(void) {
return 0;
}
-} /* namespace os */
+
#endif
-#endif /* _OS_MEMORY_HPP_ */
+} /* namespace os */
+
diff --git a/common/os_posix.cpp b/common/os_posix.cpp
index e29f9fbf..7f3b3f90 100644
--- a/common/os_posix.cpp
+++ b/common/os_posix.cpp
@@ -32,8 +32,11 @@
#include <stdint.h>
#include <unistd.h>
+#include <errno.h>
#include <sys/wait.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <pwd.h>
#include <fcntl.h>
#include <signal.h>
@@ -58,6 +61,10 @@
#define PATH_MAX 4096
#endif
+#ifdef __QNXNTO__
+#define SA_RESTART 0 // QNX does not have SA_RESTART
+#endif
+
#include "os.hpp"
#include "os_string.hpp"
#include "os_backtrace.hpp"
@@ -107,8 +114,18 @@ getProcessName(void)
}
}
}
+
+#ifdef __GLIBC__
+ // fallback to `program_invocation_name`
+ if (len <= 0) {
+ len = strlen(program_invocation_name);
+ buf = path.buf(len + 1);
+ strcpy(buf, program_invocation_name);
+ }
+#endif
+
+ // fallback to process ID
if (len <= 0) {
- // fallback to process ID
len = snprintf(buf, size, "%i", (int)getpid());
if (len >= size) {
len = size - 1;
@@ -127,10 +144,52 @@ getCurrentDir(void)
size_t size = PATH_MAX;
char *buf = path.buf(size);
- getcwd(buf, size);
- buf[size - 1] = 0;
+ if (getcwd(buf, size)) {
+ buf[size - 1] = 0;
+ path.truncate();
+ } else {
+ path.truncate(0);
+ }
- path.truncate();
+ return path;
+}
+
+String
+getConfigDir(void)
+{
+ String path;
+
+#ifdef __APPLE__
+ // Library/Preferences
+ const char *homeDir = getenv("HOME");
+ assert(homeDir);
+ if (homeDir) {
+ path = homeDir;
+ path.join("Library/Preferences");
+ }
+#else
+ // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+ const char *configHomeDir = getenv("XDG_CONFIG_HOME");
+ if (configHomeDir) {
+ path = configHomeDir;
+ } else {
+ const char *homeDir = getenv("HOME");
+ if (!homeDir) {
+ struct passwd *user = getpwuid(getuid());
+ if (user != NULL) {
+ homeDir = user->pw_dir;
+ }
+ }
+ assert(homeDir);
+ if (homeDir) {
+ path = homeDir;
+#if !defined(ANDROID)
+ path.join(".config");
+#endif
+ }
+ }
+#endif
+
return path;
}
@@ -227,6 +286,17 @@ abort(void)
}
+void
+breakpoint(void)
+{
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ asm("int3");
+#else
+ kill(getpid(), SIGTRAP);
+#endif
+}
+
+
static void (*gCallback)(void) = NULL;
#define NUM_SIGNALS 16
@@ -346,7 +416,6 @@ resetExceptionCallback(void)
gCallback = NULL;
}
-
#ifdef __linux__
struct MapRegion {
@@ -684,6 +753,42 @@ bool queryVirtualAddress(const void *address, MemoryInfo *info)
#endif /* __APPLE__ */
+#ifdef __ANDROID__
+#include "os_memory.hpp"
+#include <cassert>
+#include <cstdio>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+char statmBuff[256];
+static __uint64_t pageSize = sysconf(_SC_PAGESIZE);
+
+static long size, resident;
+
+static inline void parseStatm()
+{
+ int fd = open("/proc/self/statm", O_RDONLY, 0);
+ int sz = read(fd, statmBuff, 255);
+ close(fd);
+ statmBuff[sz] = 0;
+ sz = sscanf(statmBuff, "%ld %ld",
+ &size, &resident);
+ assert(sz == 2);
+}
+
+long long getVsize()
+{
+ parseStatm();
+ return pageSize * size;
+}
+
+long long getRss()
+{
+ parseStatm();
+ return pageSize * resident;
+}
+#endif
} /* namespace os */
diff --git a/common/os_process.hpp b/common/os_process.hpp
index e1b1df17..880242f8 100644
--- a/common/os_process.hpp
+++ b/common/os_process.hpp
@@ -27,8 +27,7 @@
* Sub-process abstraction.
*/
-#ifndef _OS_PROCESS_HPP_
-#define _OS_PROCESS_HPP_
+#pragma once
#ifdef _WIN32
@@ -88,4 +87,3 @@ int execute(char * const * args);
} /* namespace os */
-#endif /* _OS_PROCESS_HPP_ */
diff --git a/common/os_string.hpp b/common/os_string.hpp
index 996c6191..1feca2c5 100644
--- a/common/os_string.hpp
+++ b/common/os_string.hpp
@@ -27,8 +27,7 @@
* String manipulation.
*/
-#ifndef _OS_STRING_HPP_
-#define _OS_STRING_HPP_
+#pragma once
#include <assert.h>
@@ -424,6 +423,8 @@ public:
String getProcessName();
String getCurrentDir();
+String getConfigDir();
+
bool createDirectory(const String &path);
bool copyFile(const String &srcFileName, const String &dstFileName, bool override = true);
@@ -432,4 +433,3 @@ bool removeFile(const String &fileName);
} /* namespace os */
-#endif /* _OS_STRING_HPP_ */
diff --git a/common/os_thread.hpp b/common/os_thread.hpp
index 5d19f301..830ceb06 100644
--- a/common/os_thread.hpp
+++ b/common/os_thread.hpp
@@ -26,39 +26,53 @@
/*
* OS native thread abstraction.
*
- * Mimics C++11 threads.
+ * Mimics/leverages C++11 threads.
*/
-#ifndef _OS_THREAD_HPP_
-#define _OS_THREAD_HPP_
+#pragma once
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <pthread.h>
-#endif
+/* XXX: We still use our own implementation:
+ *
+ * - MSVC's C++11 threads implementation are hardcoded to use C++ exceptions
+ *
+ * - MinGW's C++11 threads implementation is often either missing or relies on
+ * winpthreads
+ *
+ * - clang 3.4 (used in Travis) fails to compile some of libstdc++ C++11 thread
+ * headers
+ */
-/*
- * This feature is not supported on Windows XP
- */
-#define USE_WIN32_CONDITION_VARIABLES 0
+#ifdef HAVE_CXX11_THREADS
+#include <thread>
+#include <mutex>
+#include <condition_variable>
-/**
- * Compiler TLS.
- *
- * See also:
- * - http://gcc.gnu.org/onlinedocs/gcc-4.6.3/gcc/Thread_002dLocal.html
- * - http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx
- */
-#if defined(HAVE_COMPILER_TLS)
-# define OS_THREAD_SPECIFIC(_type) HAVE_COMPILER_TLS _type
+namespace os {
+
+ using std::mutex;
+ using std::recursive_mutex;
+ using std::unique_lock;
+ using std::condition_variable;
+ using std::thread;
+
+} /* namespace os */
+
+
+#else /* !HAVE_CXX11_THREADS */
+
+
+#ifdef _WIN32
+# include <process.h>
+# include <windows.h>
+# if _WIN32_WINNT >= 0x0600
+# define HAVE_WIN32_CONDITION_VARIABLES
+# endif
#else
-# define OS_THREAD_SPECIFIC(_type) os::thread_specific< _type >
+# include <pthread.h>
#endif
-#define OS_THREAD_SPECIFIC_PTR(_type) OS_THREAD_SPECIFIC(_type *)
namespace os {
@@ -76,18 +90,11 @@ namespace os {
typedef pthread_mutex_t native_handle_type;
#endif
+ protected:
_base_mutex(void) {
-#ifdef _WIN32
- InitializeCriticalSection(&_native_handle);
-#else
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&_native_handle, &attr);
- pthread_mutexattr_destroy(&attr);
-#endif
}
+ public:
~_base_mutex() {
#ifdef _WIN32
DeleteCriticalSection(&_native_handle);
@@ -171,34 +178,34 @@ namespace os {
typedef Mutex mutex_type;
inline explicit
- unique_lock(mutex_type & mutex) :
- _mutex(&mutex)
+ unique_lock(mutex_type &m) :
+ _mutex(m)
{
- _mutex->lock();
+ _mutex.lock();
}
inline
~unique_lock() {
- _mutex->unlock();
+ _mutex.unlock();
}
inline void
lock() {
- _mutex->lock();
+ _mutex.lock();
}
inline void
unlock() {
- _mutex->unlock();
+ _mutex.unlock();
}
mutex_type *
mutex() const {
- return _mutex;
+ return &_mutex;
}
protected:
- mutex_type *_mutex;
+ mutex_type &_mutex;
};
@@ -209,8 +216,8 @@ namespace os {
{
private:
#ifdef _WIN32
-# if USE_WIN32_CONDITION_VARIABLES
- // XXX: Only supported on Vista an higher. Not yet supported by WINE.
+# ifdef HAVE_WIN32_CONDITION_VARIABLES
+ // Only supported on Vista an higher. Not yet supported by WINE.
typedef CONDITION_VARIABLE native_handle_type;
native_handle_type _native_handle;
#else
@@ -226,7 +233,7 @@ namespace os {
public:
condition_variable() {
#ifdef _WIN32
-# if USE_WIN32_CONDITION_VARIABLES
+# ifdef HAVE_WIN32_CONDITION_VARIABLES
InitializeConditionVariable(&_native_handle);
# else
cWaiters = 0;
@@ -239,7 +246,7 @@ namespace os {
~condition_variable() {
#ifdef _WIN32
-# if USE_WIN32_CONDITION_VARIABLES
+# ifdef HAVE_WIN32_CONDITION_VARIABLES
/* No-op */
# else
CloseHandle(hEvent);
@@ -250,9 +257,9 @@ namespace os {
}
inline void
- signal(void) {
+ notify_one(void) {
#ifdef _WIN32
-# if USE_WIN32_CONDITION_VARIABLES
+# ifdef HAVE_WIN32_CONDITION_VARIABLES
WakeConditionVariable(&_native_handle);
# else
if (cWaiters) {
@@ -268,7 +275,7 @@ namespace os {
wait(unique_lock<mutex> & lock) {
mutex::native_handle_type & mutex_native_handle = lock.mutex()->native_handle();
#ifdef _WIN32
-# if USE_WIN32_CONDITION_VARIABLES
+# ifdef HAVE_WIN32_CONDITION_VARIABLES
SleepConditionVariableCS(&_native_handle, &mutex_native_handle, INFINITE);
# else
InterlockedIncrement(&cWaiters);
@@ -386,13 +393,10 @@ namespace os {
}
template< class Function, class Arg >
- explicit thread( Function& f, Arg arg ) {
-#ifdef _WIN32
- DWORD id = 0;
- _native_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)f, (LPVOID)arg, 0, &id);
-#else
- pthread_create(&_native_handle, NULL, (void *(*) (void *))f, (void *)arg);
-#endif
+ explicit thread( Function &f, Arg arg ) {
+ typedef CallbackParam< Function, Arg > Param;
+ Param *pParam = new Param(f, arg);
+ _native_handle = _create(pParam);
}
inline thread &
@@ -418,17 +422,71 @@ namespace os {
private:
native_handle_type _native_handle;
-#if 0
-#ifdef _WIN32
- template< class Function, class Arg >
- static DWORD WINAPI
- ThreadProc(LPVOID lpParameter) {
+ template< typename Function, typename Arg >
+ struct CallbackParam {
+ Function &f;
+ Arg arg;
- );
+ inline
+ CallbackParam(Function &_f, Arg _arg) :
+ f(_f),
+ arg(_arg)
+ {}
+
+ inline void
+ operator () (void) {
+ f(arg);
+ }
+ };
+
+ template< typename Param >
+ static
+#ifdef _WIN32
+ unsigned __stdcall
+#else
+ void *
#endif
+ _callback(void *lpParameter) {
+ Param *pParam = static_cast<Param *>(lpParameter);
+ (*pParam)();
+ delete pParam;
+ return 0;
+ }
+
+ template< typename Param >
+ static inline native_handle_type
+ _create(Param *pParam) {
+#ifdef _WIN32
+ uintptr_t handle =_beginthreadex(NULL, 0, &_callback<Param>, static_cast<void *>(pParam), 0, NULL);
+ return reinterpret_cast<HANDLE>(handle);
+#else
+ pthread_t t;
+ pthread_create(&t, NULL, &_callback<Param>, static_cast<void *>(pParam));
+ return t;
#endif
+ }
};
} /* namespace os */
-#endif /* _OS_THREAD_HPP_ */
+
+#endif /* !HAVE_CXX11_THREADS */
+
+
+/**
+ * Compiler TLS.
+ *
+ * See also:
+ * - http://gcc.gnu.org/onlinedocs/gcc-4.6.3/gcc/Thread_002dLocal.html
+ * - http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx
+ */
+#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
+# define OS_THREAD_SPECIFIC(_type) os::thread_specific< _type >
+#elif defined(__GNUC__)
+# define OS_THREAD_SPECIFIC(_type) __thread _type
+#elif defined(_MSC_VER)
+# define OS_THREAD_SPECIFIC(_type) __declspec(thread) _type
+#else
+# define OS_THREAD_SPECIFIC(_type) os::thread_specific< _type >
+#endif
+#define OS_THREAD_SPECIFIC_PTR(_type) OS_THREAD_SPECIFIC(_type *)
diff --git a/common/os_time.hpp b/common/os_time.hpp
index 3e4960e7..e3f63aff 100644
--- a/common/os_time.hpp
+++ b/common/os_time.hpp
@@ -27,8 +27,7 @@
* Simple OS time measurement abstraction.
*/
-#ifndef _OS_TIME_HPP_
-#define _OS_TIME_HPP_
+#pragma once
#if defined(_WIN32)
@@ -103,4 +102,3 @@ namespace os {
} /* namespace os */
-#endif /* _OS_TIME_HPP_ */
diff --git a/common/os_version.hpp b/common/os_version.hpp
new file mode 100644
index 00000000..ad85de7d
--- /dev/null
+++ b/common/os_version.hpp
@@ -0,0 +1,61 @@
+/**************************************************************************
+ *
+ * Copyright 2014 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+
+#ifdef _WIN32
+
+
+#include <windows.h>
+
+
+/**
+ * VersionHelpers.h is not yet widely available (only available on certain MSVC
+ * and Windows SDK versions), so just define our own helpers.
+ *
+ * See http://msdn.microsoft.com/en-gb/library/windows/desktop/ms725491.aspx
+ */
+static inline bool
+IsWindows8OrGreater()
+{
+ OSVERSIONINFOEXW osvi;
+ ZeroMemory(&osvi, sizeof osvi);
+ osvi.dwOSVersionInfoSize = sizeof osvi;
+ osvi.dwMajorVersion = 6;
+ osvi.dwMinorVersion = 2;
+ osvi.wServicePackMajor = 0;
+ DWORDLONG dwlConditionMask = 0;
+ VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+ return VerifyVersionInfoW(&osvi,
+ VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
+ dwlConditionMask);
+}
+
+
+#endif /* _WIN32 */
diff --git a/common/os_win32.cpp b/common/os_win32.cpp
index cc7b2813..cce75395 100644
--- a/common/os_win32.cpp
+++ b/common/os_win32.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright 2010 VMware, Inc.
+ * Copyright 2010-2015 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -26,6 +26,7 @@
#ifdef _WIN32
#include <windows.h>
+#include <shlobj.h>
#include <assert.h>
#include <string.h>
@@ -71,6 +72,20 @@ getCurrentDir(void)
return path;
}
+String
+getConfigDir(void)
+{
+ String path;
+ char *buf = path.buf(MAX_PATH);
+ HRESULT hr = SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, buf);
+ if (SUCCEEDED(hr)) {
+ path.truncate();
+ } else {
+ path.truncate(0);
+ }
+ return path;
+}
+
bool
createDirectory(const String &path)
{
@@ -239,7 +254,23 @@ long long timeFrequency = 0LL;
void
abort(void)
{
- TerminateProcess(GetCurrentProcess(), 1);
+ TerminateProcess(GetCurrentProcess(), 3);
+#if defined(__GNUC__)
+ __builtin_unreachable();
+#endif
+}
+
+
+void
+breakpoint(void)
+{
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ asm("int3");
+#elif defined(_MSC_VER)
+ __debugbreak();
+#else
+ DebugBreak();
+#endif
}
@@ -247,60 +278,88 @@ abort(void)
#define DBG_PRINTEXCEPTION_C 0x40010006
#endif
+#ifndef DBG_PRINTEXCEPTION_WIDE_C
+#define DBG_PRINTEXCEPTION_WIDE_C 0x4001000A
+#endif
+
static PVOID prevExceptionFilter = NULL;
static void (*gCallback)(void) = NULL;
static LONG CALLBACK
unhandledExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{
+ /*
+ * Before Vista KiUserExceptionDispatcher does not clear the direction
+ * flag.
+ *
+ * See also:
+ * - https://bugs.chromium.org/p/nativeclient/issues/detail?id=1495
+ */
+#ifdef _MSC_VER
+#ifndef _WIN64
+ __asm cld;
+#endif
+#else
+ asm("cld");
+#endif
+
PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
+ DWORD ExceptionCode = pExceptionRecord->ExceptionCode;
+
+ // https://msdn.microsoft.com/en-us/library/het71c37.aspx
+ switch (ExceptionCode >> 30) {
+ case 0: // success
+ return EXCEPTION_CONTINUE_SEARCH;
+ case 1: // informational
+ case 2: // warning
+ case 3: // error
+ break;
+ }
/*
- * Ignore OutputDebugStringA exception.
+ * Ignore OutputDebugStringA/W exceptions.
*/
- if (pExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C) {
+ if (ExceptionCode == DBG_PRINTEXCEPTION_C ||
+ ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C) {
return EXCEPTION_CONTINUE_SEARCH;
}
/*
- * Ignore C++ exceptions
+ * Ignore C++ exceptions, as some applications generate a lot of these with
+ * no harm. But don't ignore them on debug builds, as bugs in apitrace can
+ * easily lead the applicationa and/or runtime to raise them, and catching
+ * them helps debugging.
*
- * http://support.microsoft.com/kb/185294
- * http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
+ * See also:
+ * - http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
+ * - http://support.microsoft.com/kb/185294
*/
- if (pExceptionRecord->ExceptionCode == 0xe06d7363) {
+#ifdef NDEBUG
+ if (ExceptionCode == 0xe06d7363) {
return EXCEPTION_CONTINUE_SEARCH;
}
+#endif
/*
* Ignore thread naming exception.
*
* http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
*/
- if (pExceptionRecord->ExceptionCode == 0x406d1388) {
+ if (ExceptionCode == 0x406d1388) {
return EXCEPTION_CONTINUE_SEARCH;
}
/*
- * Ignore .NET exception.
+ * Ignore .NET exceptions.
*
* http://ig2600.blogspot.co.uk/2011/01/why-do-i-keep-getting-exception-code.html
+ * https://github.com/dotnet/coreclr/blob/master/src/jit/importer.cpp
*/
- if (pExceptionRecord->ExceptionCode == 0xe0434352) {
+ if (ExceptionCode == 0xe0434352 ||
+ ExceptionCode == 0xe0564552) {
return EXCEPTION_CONTINUE_SEARCH;
}
- // Clear direction flag
-#ifdef _MSC_VER
-#ifndef _WIN64
- __asm {
- cld
- };
-#endif
-#else
- asm("cld");
-#endif
-
log("apitrace: warning: caught exception 0x%08lx\n", pExceptionRecord->ExceptionCode);
static int recursion_count = 0;
diff --git a/common/trace_api.hpp b/common/trace_api.hpp
index 3d491fe1..3b119f8e 100644
--- a/common/trace_api.hpp
+++ b/common/trace_api.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _TRACE_API_HPP_
-#define _TRACE_API_HPP_
+#pragma once
#include <stdlib.h>
@@ -49,9 +48,9 @@ enum API {
API_D3D8,
API_D3D9,
API_DXGI, // D3D10.x, D3D11.x
+ API_D2D1, // Direct2D
};
} /* namespace trace */
-#endif /* _TRACE_API_HPP_ */
diff --git a/common/trace_callset.cpp b/common/trace_callset.cpp
index dca39d09..3722ea65 100644
--- a/common/trace_callset.cpp
+++ b/common/trace_callset.cpp
@@ -27,10 +27,9 @@
#include <assert.h>
#include <stdlib.h>
-#include <limits>
#include <fstream>
#include <iostream>
-#include <string>
+#include <sstream>
#include <trace_callset.hpp>
@@ -233,12 +232,22 @@ CallSet::merge(const char *string)
firstmerge = false;
}
- if (*string == '@') {
- FileCallSetParser parser(*this, &string[1]);
- parser.parse();
- } else {
- StringCallSetParser parser(*this, string);
- parser.parse();
+ /*
+ * Parse a comma-separated list of files or ranges
+ */
+ std::stringstream calls_arg(string);
+ std::string token;
+ const char *str;
+
+ while (std::getline(calls_arg, token, ',')) {
+ str = token.c_str();
+ if (str[0] == '@') {
+ FileCallSetParser parser(*this, &str[1]);
+ parser.parse();
+ } else {
+ StringCallSetParser parser(*this, str);
+ parser.parse();
+ }
}
}
diff --git a/common/trace_callset.hpp b/common/trace_callset.hpp
index 53bad986..4070a4b8 100644
--- a/common/trace_callset.hpp
+++ b/common/trace_callset.hpp
@@ -44,8 +44,7 @@
*
*/
-#ifndef _TRACE_CALLSET_HPP_
-#define _TRACE_CALLSET_HPP_
+#pragma once
#include <limits>
@@ -194,4 +193,3 @@ namespace trace {
} /* namespace trace */
-#endif /* _TRACE_CALLSET_HPP_ */
diff --git a/common/trace_dump.cpp b/common/trace_dump.cpp
index f81c1473..5147e806 100644
--- a/common/trace_dump.cpp
+++ b/common/trace_dump.cpp
@@ -26,8 +26,12 @@
#include <limits>
+#include <assert.h>
+#include <string.h>
+
#include "highlight.hpp"
#include "trace_dump.hpp"
+#include "guids.hpp"
namespace trace {
@@ -93,24 +97,30 @@ public:
os.precision(oldPrecision);
}
- void visit(String *node) {
+ template< typename C >
+ void visitString(const C *value) {
os << literal << "\"";
- for (const char *it = node->value; *it; ++it) {
- unsigned char c = (unsigned char) *it;
+ for (const C *it = value; *it; ++it) {
+ unsigned c = (unsigned) *it;
if (c == '\"')
os << "\\\"";
else if (c == '\\')
os << "\\\\";
else if (c >= 0x20 && c <= 0x7e)
- os << c;
+ os << (char)c;
else if (c == '\t') {
os << "\t";
} else if (c == '\r') {
// Ignore carriage-return
} else if (c == '\n') {
- // Reset formatting so that it looks correct with 'less -R'
- os << normal << '\n' << literal;
+ if (dumpFlags & DUMP_FLAG_NO_MULTILINE) {
+ os << "\\n";
+ } else {
+ // Reset formatting so that it looks correct with 'less -R'
+ os << normal << '\n' << literal;
+ }
} else {
+ // FIXME: handle wchar_t octals properly
unsigned octal0 = c & 0x7;
unsigned octal1 = (c >> 3) & 0x7;
unsigned octal2 = (c >> 3) & 0x7;
@@ -125,6 +135,15 @@ public:
os << "\"" << normal;
}
+ void visit(String *node) {
+ visitString(node->value);
+ }
+
+ void visit(WString *node) {
+ os << literal << "L";
+ visitString(node->value);
+ }
+
void visit(Enum *node) {
const EnumValue *it = node->lookup();
if (it) {
@@ -185,6 +204,25 @@ public:
}
void visit(Struct *s) {
+ // Replace GUIDs with their symbolic name
+ // TODO: Move this to parsing, so it can be shared everywhere
+ if (s->members.size() == 4 &&
+ strcmp(s->sig->name, "GUID") == 0) {
+ GUID guid;
+ guid.Data1 = s->members[0]->toUInt();
+ guid.Data2 = s->members[1]->toUInt();
+ guid.Data3 = s->members[2]->toUInt();
+ Array *data4 = s->members[3]->toArray();
+ assert(data4);
+ assert(data4->values.size() == 8);
+ for (int i = 0; i < sizeof guid.Data4; ++i) {
+ guid.Data4[i] = data4->values[i]->toUInt();
+ }
+ const char *name = getGuidName(guid);
+ os << literal << name << normal;
+ return;
+ }
+
os << "{";
visitMembers(s);
os << "}";
@@ -274,14 +312,16 @@ public:
os << " // " << red << "incomplete" << normal;
}
- os << "\n";
-
- if (call->backtrace != NULL) {
- os << bold << red << "Backtrace:\n" << normal;
- visit(*call->backtrace);
- }
- if (callFlags & CALL_FLAG_END_FRAME) {
+ if (!(dumpFlags & DUMP_FLAG_NO_MULTILINE)) {
os << "\n";
+
+ if (call->backtrace != NULL) {
+ os << bold << red << "Backtrace:\n" << normal;
+ visit(*call->backtrace);
+ }
+ if (callFlags & CALL_FLAG_END_FRAME) {
+ os << "\n";
+ }
}
}
};
diff --git a/common/trace_dump.hpp b/common/trace_dump.hpp
index 2d22027e..4c756ca4 100644
--- a/common/trace_dump.hpp
+++ b/common/trace_dump.hpp
@@ -27,8 +27,7 @@
* Human-readible dumping.
*/
-#ifndef _TRACE_DUMP_HPP_
-#define _TRACE_DUMP_HPP_
+#pragma once
#include <iostream>
@@ -46,6 +45,7 @@ enum {
DUMP_FLAG_NO_ARG_NAMES = (1 << 1),
DUMP_FLAG_NO_CALL_NO = (1 << 2),
DUMP_FLAG_THREAD_IDS = (1 << 3),
+ DUMP_FLAG_NO_MULTILINE = (1 << 4),
};
@@ -74,4 +74,3 @@ inline std::ostream & operator <<(std::ostream &os, Call &call) {
} /* namespace trace */
-#endif /* _TRACE_DUMP_HPP_ */
diff --git a/common/trace_fast_callset.hpp b/common/trace_fast_callset.hpp
index 4b27c7ac..55d507df 100644
--- a/common/trace_fast_callset.hpp
+++ b/common/trace_fast_callset.hpp
@@ -26,8 +26,7 @@
*
*********************************************************************/
-#ifndef _TRACE_FAST_CALLSET_HPP_
-#define _TRACE_FAST_CALLSET_HPP_
+#pragma once
#include "trace_model.hpp"
@@ -139,4 +138,3 @@ public:
} /* namespace trace */
-#endif /* _TRACE_FAST_CALLSET_HPP_ */
diff --git a/common/trace_file.cpp b/common/trace_file.cpp
index 3657fd29..8bd255d1 100644
--- a/common/trace_file.cpp
+++ b/common/trace_file.cpp
@@ -32,13 +32,11 @@
using namespace trace;
-File::File(const std::string &filename,
- File::Mode mode)
- : m_mode(mode),
- m_isOpened(false)
+File::File(const std::string &filename)
+ : m_isOpened(false)
{
if (!filename.empty()) {
- open(filename, m_mode);
+ open(filename);
}
}
diff --git a/common/trace_file.hpp b/common/trace_file.hpp
index 0c176aab..17e6756b 100644
--- a/common/trace_file.hpp
+++ b/common/trace_file.hpp
@@ -24,26 +24,17 @@
**************************************************************************/
-#ifndef TRACE_FILE_HPP
-#define TRACE_FILE_HPP
+#pragma once
#include <string>
#include <fstream>
#include <stdint.h>
-#define SNAPPY_BYTE1 'a'
-#define SNAPPY_BYTE2 't'
-
-
namespace trace {
class File {
public:
- enum Mode {
- Read,
- Write
- };
struct Offset {
Offset(uint64_t _chunk = 0, uint32_t _offsetInChunk = 0)
: chunk(_chunk),
@@ -57,20 +48,15 @@ public:
static File *createZLib(void);
static File *createSnappy(void);
static File *createForRead(const char *filename);
- static File *createForWrite(const char *filename);
public:
- File(const std::string &filename = std::string(),
- File::Mode mode = File::Read);
+ File(const std::string &filename = std::string());
virtual ~File();
bool isOpened() const;
- File::Mode mode() const;
- bool open(const std::string &filename, File::Mode mode);
- bool write(const void *buffer, size_t length);
+ bool open(const std::string &filename);
size_t read(void *buffer, size_t length);
void close();
- void flush(void);
int getc();
bool skip(size_t length);
int percentRead();
@@ -79,17 +65,14 @@ public:
virtual File::Offset currentOffset() = 0;
virtual void setCurrentOffset(const File::Offset &offset);
protected:
- virtual bool rawOpen(const std::string &filename, File::Mode mode) = 0;
- virtual bool rawWrite(const void *buffer, size_t length) = 0;
+ virtual bool rawOpen(const std::string &filename) = 0;
virtual size_t rawRead(void *buffer, size_t length) = 0;
virtual int rawGetc() = 0;
virtual void rawClose() = 0;
- virtual void rawFlush() = 0;
virtual bool rawSkip(size_t length) = 0;
virtual int rawPercentRead() = 0;
protected:
- File::Mode m_mode;
bool m_isOpened;
};
@@ -98,33 +81,19 @@ inline bool File::isOpened() const
return m_isOpened;
}
-inline File::Mode File::mode() const
-{
- return m_mode;
-}
-
-inline bool File::open(const std::string &filename, File::Mode mode)
+inline bool File::open(const std::string &filename)
{
if (m_isOpened) {
close();
}
- m_isOpened = rawOpen(filename, mode);
- m_mode = mode;
+ m_isOpened = rawOpen(filename);
return m_isOpened;
}
-inline bool File::write(const void *buffer, size_t length)
-{
- if (!m_isOpened || m_mode != File::Write) {
- return false;
- }
- return rawWrite(buffer, length);
-}
-
inline size_t File::read(void *buffer, size_t length)
{
- if (!m_isOpened || m_mode != File::Read) {
+ if (!m_isOpened) {
return 0;
}
return rawRead(buffer, length);
@@ -132,7 +101,7 @@ inline size_t File::read(void *buffer, size_t length)
inline int File::percentRead()
{
- if (!m_isOpened || m_mode != File::Read) {
+ if (!m_isOpened) {
return 0;
}
return rawPercentRead();
@@ -146,16 +115,9 @@ inline void File::close()
}
}
-inline void File::flush(void)
-{
- if (m_mode == File::Write) {
- rawFlush();
- }
-}
-
inline int File::getc()
{
- if (!m_isOpened || m_mode != File::Read) {
+ if (!m_isOpened) {
return -1;
}
return rawGetc();
@@ -163,7 +125,7 @@ inline int File::getc()
inline bool File::skip(size_t length)
{
- if (!m_isOpened || m_mode != File::Read) {
+ if (!m_isOpened) {
return false;
}
return rawSkip(length);
@@ -205,5 +167,3 @@ operator<=(const File::Offset &one, const File::Offset &two)
} /* namespace trace */
-
-#endif
diff --git a/common/trace_file_read.cpp b/common/trace_file_read.cpp
index 46c83ff2..c4198550 100644
--- a/common/trace_file_read.cpp
+++ b/common/trace_file_read.cpp
@@ -28,6 +28,7 @@
#include "os.hpp"
#include "trace_file.hpp"
+#include "trace_snappy.hpp"
using namespace trace;
@@ -59,7 +60,7 @@ File::createForRead(const char *filename)
return NULL;
}
- if (!file->open(filename, File::Read)) {
+ if (!file->open(filename)) {
os::log("error: could not open %s for reading\n", filename);
delete file;
return NULL;
diff --git a/common/trace_file_snappy.cpp b/common/trace_file_snappy.cpp
index 41d86ea0..1154c68e 100644
--- a/common/trace_file_snappy.cpp
+++ b/common/trace_file_snappy.cpp
@@ -60,6 +60,7 @@
#include <string.h>
#include "trace_file.hpp"
+#include "trace_snappy.hpp"
#define SNAPPY_CHUNK_SIZE (1 * 1024 * 1024)
@@ -71,20 +72,17 @@ using namespace trace;
class SnappyFile : public File {
public:
- SnappyFile(const std::string &filename = std::string(),
- File::Mode mode = File::Read);
+ SnappyFile(const std::string &filename = std::string());
virtual ~SnappyFile();
virtual bool supportsOffsets() const;
virtual File::Offset currentOffset();
virtual void setCurrentOffset(const File::Offset &offset);
protected:
- virtual bool rawOpen(const std::string &filename, File::Mode mode);
- virtual bool rawWrite(const void *buffer, size_t length);
+ virtual bool rawOpen(const std::string &filename);
virtual size_t rawRead(void *buffer, size_t length);
virtual int rawGetc();
virtual void rawClose();
- virtual void rawFlush();
virtual bool rawSkip(size_t length);
virtual int rawPercentRead();
@@ -125,8 +123,7 @@ private:
std::streampos m_endPos;
};
-SnappyFile::SnappyFile(const std::string &filename,
- File::Mode mode)
+SnappyFile::SnappyFile(const std::string &filename)
: File(),
m_cacheMaxSize(SNAPPY_CHUNK_SIZE),
m_cacheSize(m_cacheMaxSize),
@@ -145,20 +142,15 @@ SnappyFile::~SnappyFile()
delete [] m_cache;
}
-bool SnappyFile::rawOpen(const std::string &filename, File::Mode mode)
+bool SnappyFile::rawOpen(const std::string &filename)
{
- std::ios_base::openmode fmode = std::fstream::binary;
- if (mode == File::Write) {
- fmode |= (std::fstream::out | std::fstream::trunc);
- createCache(SNAPPY_CHUNK_SIZE);
- } else if (mode == File::Read) {
- fmode |= std::fstream::in;
- }
+ std::ios_base::openmode fmode = std::fstream::binary
+ | std::fstream::in;
m_stream.open(filename.c_str(), fmode);
//read in the initial buffer if we're reading
- if (m_stream.is_open() && mode == File::Read) {
+ if (m_stream.is_open()) {
m_stream.seekg(0, std::ios::end);
m_endPos = m_stream.tellg();
m_stream.seekg(0, std::ios::beg);
@@ -170,44 +162,10 @@ bool SnappyFile::rawOpen(const std::string &filename, File::Mode mode)
assert(byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);
flushReadCache();
- } else if (m_stream.is_open() && mode == File::Write) {
- // write the snappy file identifier
- m_stream << SNAPPY_BYTE1;
- m_stream << SNAPPY_BYTE2;
}
return m_stream.is_open();
}
-bool SnappyFile::rawWrite(const void *buffer, size_t length)
-{
- if (freeCacheSize() > length) {
- memcpy(m_cachePtr, buffer, length);
- m_cachePtr += length;
- } else if (freeCacheSize() == length) {
- memcpy(m_cachePtr, buffer, length);
- m_cachePtr += length;
- flushWriteCache();
- } else {
- size_t sizeToWrite = length;
-
- while (sizeToWrite >= freeCacheSize()) {
- size_t endSize = freeCacheSize();
- size_t offset = length - sizeToWrite;
- memcpy(m_cachePtr, (const char*)buffer + offset, endSize);
- sizeToWrite -= endSize;
- m_cachePtr += endSize;
- flushWriteCache();
- }
- if (sizeToWrite) {
- size_t offset = length - sizeToWrite;
- memcpy(m_cachePtr, (const char*)buffer + offset, sizeToWrite);
- m_cachePtr += sizeToWrite;
- }
- }
-
- return true;
-}
-
size_t SnappyFile::rawRead(void *buffer, size_t length)
{
if (endOfData()) {
@@ -248,57 +206,38 @@ int SnappyFile::rawGetc()
void SnappyFile::rawClose()
{
- if (m_mode == File::Write) {
- flushWriteCache();
- }
m_stream.close();
delete [] m_cache;
m_cache = NULL;
m_cachePtr = NULL;
}
-void SnappyFile::rawFlush()
-{
- assert(m_mode == File::Write);
- flushWriteCache();
- m_stream.flush();
-}
-
-void SnappyFile::flushWriteCache()
-{
- size_t inputLength = usedCacheSize();
-
- if (inputLength) {
- size_t compressedLength;
-
- ::snappy::RawCompress(m_cache, inputLength,
- m_compressedCache, &compressedLength);
-
- writeCompressedLength(compressedLength);
- m_stream.write(m_compressedCache, compressedLength);
- m_cachePtr = m_cache;
- }
- assert(m_cachePtr == m_cache);
-}
-
void SnappyFile::flushReadCache(size_t skipLength)
{
//assert(m_cachePtr == m_cache + m_cacheSize);
m_currentOffset.chunk = m_stream.tellg();
size_t compressedLength;
compressedLength = readCompressedLength();
+ if (!compressedLength) {
+ // Reached end of file
+ createCache(0);
+ return;
+ }
- if (compressedLength) {
- m_stream.read((char*)m_compressedCache, compressedLength);
- ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
- &m_cacheSize);
- createCache(m_cacheSize);
- if (skipLength < m_cacheSize) {
- ::snappy::RawUncompress(m_compressedCache, compressedLength,
- m_cache);
- }
- } else {
+ m_stream.read((char*)m_compressedCache, compressedLength);
+ if (m_stream.fail()) {
+ // XXX: Unforunately Snappy's interface is not expressive enough
+ // to allow recovering part of the uncompressed bytes.
+ std::cerr << "warning: unexpected end of file while reading trace\n";
createCache(0);
+ return;
+ }
+ ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
+ &m_cacheSize);
+ createCache(m_cacheSize);
+ if (skipLength < m_cacheSize) {
+ ::snappy::RawUncompress(m_compressedCache, compressedLength,
+ m_cache);
}
}
diff --git a/common/trace_file_zlib.cpp b/common/trace_file_zlib.cpp
index a432ccde..db54427e 100644
--- a/common/trace_file_zlib.cpp
+++ b/common/trace_file_zlib.cpp
@@ -31,9 +31,8 @@
#include <string.h>
#include <zlib.h>
-#include <gzguts.h>
-// for lseek
+#include <fcntl.h>
#ifdef _WIN32
#include <io.h>
#else
@@ -51,30 +50,27 @@ using namespace trace;
class ZLibFile : public File {
public:
- ZLibFile(const std::string &filename = std::string(),
- File::Mode mode = File::Read);
+ ZLibFile(const std::string &filename = std::string());
virtual ~ZLibFile();
virtual bool supportsOffsets() const;
virtual File::Offset currentOffset();
protected:
- virtual bool rawOpen(const std::string &filename, File::Mode mode);
- virtual bool rawWrite(const void *buffer, size_t length);
+ virtual bool rawOpen(const std::string &filename);
virtual size_t rawRead(void *buffer, size_t length);
virtual int rawGetc();
virtual void rawClose();
- virtual void rawFlush();
virtual bool rawSkip(size_t length);
virtual int rawPercentRead();
private:
+ int fd;
gzFile m_gzFile;
double m_endOffset;
};
-ZLibFile::ZLibFile(const std::string &filename,
- File::Mode mode)
- : File(filename, mode),
+ZLibFile::ZLibFile(const std::string &filename)
+ : File(filename),
m_gzFile(NULL)
{
}
@@ -84,30 +80,40 @@ ZLibFile::~ZLibFile()
close();
}
-bool ZLibFile::rawOpen(const std::string &filename, File::Mode mode)
+bool ZLibFile::rawOpen(const std::string &filename)
{
- m_gzFile = gzopen(filename.c_str(),
- (mode == File::Write) ? "wb" : "rb");
+ int flags = O_RDONLY;
+#ifdef O_BINARY
+ flags |= O_BINARY;
+#endif
+#ifdef O_LARGEFILE
+ flags |= O_LARGEFILE;
+#endif
+
+#ifdef _WIN32
+ fd = _open(filename.c_str(), flags, 0666);
+#else
+ fd = ::open(filename.c_str(), flags, 0666);
+#endif
+ if (fd < 0) {
+ return false;
+ }
+
+ m_gzFile = gzdopen(fd, "rb");
- if (mode == File::Read && m_gzFile) {
+ if (m_gzFile) {
//XXX: unfortunately zlib doesn't support
// SEEK_END or we could've done:
//m_endOffset = gzseek(m_gzFile, 0, SEEK_END);
//gzrewind(m_gzFile);
- gz_state *state = (gz_state *)m_gzFile;
- off_t loc = lseek(state->fd, 0, SEEK_CUR);
- m_endOffset = lseek(state->fd, 0, SEEK_END);
- lseek(state->fd, loc, SEEK_SET);
+ off_t loc = lseek(fd, 0, SEEK_CUR);
+ m_endOffset = lseek(fd, 0, SEEK_END);
+ lseek(fd, loc, SEEK_SET);
}
return m_gzFile != NULL;
}
-bool ZLibFile::rawWrite(const void *buffer, size_t length)
-{
- return gzwrite(m_gzFile, buffer, unsigned(length)) != -1;
-}
-
size_t ZLibFile::rawRead(void *buffer, size_t length)
{
int ret = gzread(m_gzFile, buffer, unsigned(length));
@@ -127,11 +133,6 @@ void ZLibFile::rawClose()
}
}
-void ZLibFile::rawFlush()
-{
- gzflush(m_gzFile, Z_SYNC_FLUSH);
-}
-
File::Offset ZLibFile::currentOffset()
{
return File::Offset(gztell(m_gzFile));
@@ -149,8 +150,7 @@ bool ZLibFile::rawSkip(size_t)
int ZLibFile::rawPercentRead()
{
- gz_state *state = (gz_state *)m_gzFile;
- return int(100 * (lseek(state->fd, 0, SEEK_CUR) / m_endOffset));
+ return int(100 * (lseek(fd, 0, SEEK_CUR) / m_endOffset));
}
diff --git a/common/trace_format.hpp b/common/trace_format.hpp
index 9f2a3ea6..4c6d821e 100644
--- a/common/trace_format.hpp
+++ b/common/trace_format.hpp
@@ -29,8 +29,7 @@
* See FORMAT.markdown for details.
*/
-#ifndef _TRACE_FORMAT_HPP_
-#define _TRACE_FORMAT_HPP_
+#pragma once
namespace trace {
@@ -67,6 +66,7 @@ enum Type {
TYPE_STRUCT,
TYPE_OPAQUE,
TYPE_REPR,
+ TYPE_WSTRING,
};
enum BacktraceDetail {
@@ -81,4 +81,3 @@ enum BacktraceDetail {
} /* namespace trace */
-#endif /* _TRACE_FORMAT_HPP_ */
diff --git a/common/trace_loader.cpp b/common/trace_loader.cpp
deleted file mode 100644
index 6a3d7de0..00000000
--- a/common/trace_loader.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-#include "trace_loader.hpp"
-
-
-using namespace trace;
-
-Loader::Loader()
- : m_frameMarker(FrameMarker_SwapBuffers)
-{
-}
-
-Loader::~Loader()
-{
- close();
-}
-
-Loader::FrameMarker Loader::frameMarker() const
-{
- return m_frameMarker;
-}
-
-void Loader::setFrameMarker(Loader::FrameMarker marker)
-{
- m_frameMarker = marker;
-}
-
-unsigned Loader::numberOfFrames() const
-{
- return unsigned(m_frameBookmarks.size());
-}
-
-unsigned Loader::numberOfCallsInFrame(unsigned frameIdx) const
-{
- if (frameIdx > m_frameBookmarks.size()) {
- return 0;
- }
- FrameBookmarks::const_iterator itr =
- m_frameBookmarks.find(frameIdx);
- return itr->second.numberOfCalls;
-}
-
-bool Loader::open(const char *filename)
-{
- if (!m_parser.open(filename)) {
- std::cerr << "error: failed to open " << filename << "\n";
- return false;
- }
- if (!m_parser.supportsOffsets()) {
- std::cerr << "error: " <<filename<< " doesn't support seeking "
- << "\n";
- return false;
- }
-
- trace::Call *call;
- ParseBookmark startBookmark;
- unsigned numOfFrames = 0;
- unsigned numOfCalls = 0;
- int lastPercentReport = 0;
-
- m_parser.getBookmark(startBookmark);
-
- while ((call = m_parser.scan_call())) {
- ++numOfCalls;
-
- if (isCallAFrameMarker(call)) {
- FrameBookmark frameBookmark(startBookmark);
- frameBookmark.numberOfCalls = numOfCalls;
-
- m_frameBookmarks[numOfFrames] = frameBookmark;
- ++numOfFrames;
-
- if (m_parser.percentRead() - lastPercentReport >= 5) {
- std::cerr << "\tPercent scanned = "
- << m_parser.percentRead()
- << "..."<<std::endl;
- lastPercentReport = m_parser.percentRead();
- }
-
- m_parser.getBookmark(startBookmark);
- numOfCalls = 0;
- }
- //call->dump(std::cout, color);
- delete call;
- }
- return true;
-}
-
-void Loader::close()
-{
- m_parser.close();
-}
-
-bool Loader::isCallAFrameMarker(const trace::Call *call) const
-{
- std::string name = call->name();
-
- switch (m_frameMarker) {
- case FrameMarker_SwapBuffers:
- return call->flags & trace::CALL_FLAG_END_FRAME;
- break;
- case FrameMarker_Flush:
- return name == "glFlush";
- break;
- case FrameMarker_Finish:
- return name == "glFinish";
- break;
- case FrameMarker_Clear:
- return name == "glClear";
- break;
- }
- return false;
-}
-
-std::vector<trace::Call *> Loader::frame(unsigned idx)
-{
- unsigned numOfCalls = numberOfCallsInFrame(idx);
- if (numOfCalls) {
- const FrameBookmark &frameBookmark = m_frameBookmarks[idx];
- std::vector<trace::Call*> calls(numOfCalls);
- m_parser.setBookmark(frameBookmark.start);
-
- trace::Call *call;
- unsigned parsedCalls = 0;
- while ((call = m_parser.parse_call())) {
-
- calls[parsedCalls] = call;
- ++parsedCalls;
-
- if (isCallAFrameMarker(call)) {
- break;
- }
-
- }
- assert(parsedCalls == numOfCalls);
- return calls;
- }
- return std::vector<trace::Call*>();
-}
diff --git a/common/trace_loader.hpp b/common/trace_loader.hpp
deleted file mode 100644
index 6873c964..00000000
--- a/common/trace_loader.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef TRACE_LOADER_HPP
-#define TRACE_LOADER_HPP
-
-#include "trace_file.hpp"
-#include "trace_parser.hpp"
-
-#include <string>
-#include <map>
-#include <queue>
-#include <vector>
-
-namespace trace {
-
-class Frame;
-
-class Loader
-{
-public:
- enum FrameMarker {
- FrameMarker_SwapBuffers,
- FrameMarker_Flush,
- FrameMarker_Finish,
- FrameMarker_Clear
- };
-public:
- Loader();
- ~Loader();
-
- Loader::FrameMarker frameMarker() const;
- void setFrameMarker(Loader::FrameMarker marker);
-
- unsigned numberOfFrames() const;
- unsigned numberOfCallsInFrame(unsigned frameIdx) const;
-
- bool open(const char *filename);
- void close();
-
- std::vector<trace::Call*> frame(unsigned idx);
-
-private:
- struct FrameBookmark {
- FrameBookmark()
- : numberOfCalls(0)
- {}
- FrameBookmark(const ParseBookmark &s)
- : start(s),
- numberOfCalls(0)
- {}
-
- ParseBookmark start;
- unsigned numberOfCalls;
- };
- bool isCallAFrameMarker(const trace::Call *call) const;
-
-private:
- trace::Parser m_parser;
- FrameMarker m_frameMarker;
-
- typedef std::map<int, FrameBookmark> FrameBookmarks;
- FrameBookmarks m_frameBookmarks;
-};
-
-}
-
-#endif // TRACE_LOADER_HPP
diff --git a/common/trace_lookup.hpp b/common/trace_lookup.hpp
index 7134778d..55655027 100644
--- a/common/trace_lookup.hpp
+++ b/common/trace_lookup.hpp
@@ -27,8 +27,7 @@
* Helper code for function name indexed lookup tables.
*/
-#ifndef _TRACE_LOOKUP_HPP_
-#define _TRACE_LOOKUP_HPP_
+#pragma once
#include <assert.h>
@@ -108,4 +107,3 @@ entryLookup(const char *name, const Entry<T> (& entries)[n], const T & default_)
} /* namespace trace */
-#endif /* _TRACE_LOOKUP_HPP_ */
diff --git a/common/trace_model.cpp b/common/trace_model.cpp
index baebc18f..c91a9943 100644
--- a/common/trace_model.cpp
+++ b/common/trace_model.cpp
@@ -25,6 +25,7 @@
#include <string.h>
+#include <deque>
#include "trace_model.hpp"
@@ -61,6 +62,11 @@ String::~String() {
}
+WString::~WString() {
+ delete [] value;
+}
+
+
Struct::~Struct() {
for (std::vector<Value *>::iterator it = members.begin(); it != members.end(); ++it) {
delete *it;
@@ -74,17 +80,75 @@ Array::~Array() {
}
}
+
+#define BLOB_MAX_BOUND_SIZE (1*1024*1024*1024)
+
+class BoundBlob {
+public:
+ static size_t totalSize;
+
+private:
+ size_t size;
+ char *buf;
+
+public:
+ inline
+ BoundBlob(size_t _size, char *_buf) :
+ size(_size),
+ buf(_buf)
+ {
+ assert(totalSize + size >= totalSize);
+ totalSize += size;
+ }
+
+ inline
+ ~BoundBlob() {
+ assert(totalSize >= size);
+ totalSize -= size;
+ delete [] buf;
+ }
+
+ // Fake move constructor
+ // std::deque:push_back with move semantics was added only from c++11.
+ BoundBlob(const BoundBlob & other)
+ {
+ size = other.size;
+ buf = other.buf;
+ const_cast<BoundBlob &>(other).size = 0;
+ const_cast<BoundBlob &>(other).buf = 0;
+ }
+
+ // Disallow assignment operator
+ BoundBlob& operator = (const BoundBlob &);
+};
+
+size_t BoundBlob::totalSize = 0;
+
+typedef std::deque<BoundBlob> BoundBlobQueue;
+static BoundBlobQueue boundBlobQueue;
+
+
Blob::~Blob() {
// Blobs are often bound and referred during many calls, so we can't delete
// them here in that case.
//
// Once bound there is no way to know when they were unbound, which
- // effectively means we have to leak them. A better solution would be to
- // keep a list of bound pointers, and defer the destruction to when the
- // trace in question has been fully processed.
+ // effectively means we have to leak them. But some applications
+ // (particularly OpenGL applications that use vertex arrays in user memory)
+ // we can easily exhaust all memory. So instead we maintain a queue of
+ // bound blobs and keep the total size bounded.
+
if (!bound) {
delete [] buf;
+ return;
}
+
+ while (!boundBlobQueue.empty() &&
+ BoundBlob::totalSize + size > BLOB_MAX_BOUND_SIZE) {
+ boundBlobQueue.pop_front();
+ }
+
+ boundBlobQueue.push_back(BoundBlob(size, buf));
}
StackFrame::~StackFrame() {
@@ -108,6 +172,7 @@ bool UInt ::toBool(void) const { return value != 0; }
bool Float ::toBool(void) const { return value != 0; }
bool Double ::toBool(void) const { return value != 0; }
bool String ::toBool(void) const { return true; }
+bool WString::toBool(void) const { return true; }
bool Struct ::toBool(void) const { return true; }
bool Array ::toBool(void) const { return true; }
bool Blob ::toBool(void) const { return true; }
@@ -195,6 +260,7 @@ void UInt ::visit(Visitor &visitor) { visitor.visit(this); }
void Float ::visit(Visitor &visitor) { visitor.visit(this); }
void Double ::visit(Visitor &visitor) { visitor.visit(this); }
void String ::visit(Visitor &visitor) { visitor.visit(this); }
+void WString::visit(Visitor &visitor) { visitor.visit(this); }
void Enum ::visit(Visitor &visitor) { visitor.visit(this); }
void Bitmask::visit(Visitor &visitor) { visitor.visit(this); }
void Struct ::visit(Visitor &visitor) { visitor.visit(this); }
@@ -211,6 +277,7 @@ void Visitor::visit(UInt *) { assert(0); }
void Visitor::visit(Float *) { assert(0); }
void Visitor::visit(Double *) { assert(0); }
void Visitor::visit(String *) { assert(0); }
+void Visitor::visit(WString *) { assert(0); }
void Visitor::visit(Enum *node) { assert(0); }
void Visitor::visit(Bitmask *node) { visit(static_cast<UInt *>(node)); }
void Visitor::visit(Struct *) { assert(0); }
diff --git a/common/trace_model.hpp b/common/trace_model.hpp
index 164b1ab4..821adf65 100644
--- a/common/trace_model.hpp
+++ b/common/trace_model.hpp
@@ -27,8 +27,7 @@
* Object hierarchy for describing the traces in memory.
*/
-#ifndef _TRACE_MODEL_HPP_
-#define _TRACE_MODEL_HPP_
+#pragma once
#include <assert.h>
@@ -240,6 +239,19 @@ public:
};
+class WString : public Value
+{
+public:
+ WString(const wchar_t * _value) : value(_value) {}
+ ~WString();
+
+ bool toBool(void) const;
+ void visit(Visitor &visitor);
+
+ const wchar_t * value;
+};
+
+
class Enum : public SInt
{
public:
@@ -424,6 +436,7 @@ public:
virtual void visit(Float *);
virtual void visit(Double *);
virtual void visit(String *);
+ virtual void visit(WString *);
virtual void visit(Enum *);
virtual void visit(Bitmask *);
virtual void visit(Struct *);
@@ -570,4 +583,3 @@ public:
} /* namespace trace */
-#endif /* _TRACE_MODEL_HPP_ */
diff --git a/common/trace_option.cpp b/common/trace_option.cpp
index 5c4563fe..feae1496 100644
--- a/common/trace_option.cpp
+++ b/common/trace_option.cpp
@@ -28,6 +28,7 @@
#include <string.h>
#include <iostream>
+#include <stdlib.h>
namespace trace {
@@ -50,4 +51,12 @@ boolOption(const char *option, bool default_) {
return default_;
}
+int
+intOption(const char *option, int default_) {
+ if (!option) {
+ return default_;
+ }
+ return atoi(option);
+}
+
} /* namespace trace */
diff --git a/common/trace_option.hpp b/common/trace_option.hpp
index e22a422c..f11d4658 100644
--- a/common/trace_option.hpp
+++ b/common/trace_option.hpp
@@ -24,14 +24,15 @@
*
**************************************************************************/
-#ifndef _TRACE_OPTION_HPP_
-#define _TRACE_OPTION_HPP_
+#pragma once
namespace trace {
bool
boolOption(const char *option, bool default_ = true);
+int
+intOption(const char *option, int default_ = 0);
+
} /* namespace trace */
-#endif /* _TRACE_CALLSET_HPP_ */
diff --git a/common/trace_ostream.hpp b/common/trace_ostream.hpp
new file mode 100644
index 00000000..502905b4
--- /dev/null
+++ b/common/trace_ostream.hpp
@@ -0,0 +1,52 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * Copyright 2011 Zack Rusin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+#include <stdlib.h>
+
+
+namespace trace {
+
+
+class OutStream {
+public:
+ virtual ~OutStream() {}
+
+ virtual bool write(const void *buffer, size_t length) = 0;
+ virtual void flush(void) = 0;
+};
+
+
+OutStream *
+createSnappyStream(const char *filename);
+
+OutStream *
+createZLibStream(const char *filename);
+
+
+} /* namespace trace */
diff --git a/common/trace_ostream_snappy.cpp b/common/trace_ostream_snappy.cpp
new file mode 100644
index 00000000..a1a28673
--- /dev/null
+++ b/common/trace_ostream_snappy.cpp
@@ -0,0 +1,206 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * Copyright 2011 Zack Rusin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "trace_ostream.hpp"
+
+#include <fstream>
+
+#include <assert.h>
+#include <string.h>
+
+#include <snappy.h>
+
+#include "os.hpp"
+#include "trace_snappy.hpp"
+
+
+#define SNAPPY_CHUNK_SIZE (1 * 1024 * 1024)
+
+
+using namespace trace;
+
+
+class SnappyOutStream : public OutStream {
+public:
+ SnappyOutStream(const char *filename);
+ ~SnappyOutStream();
+
+ SnappyOutStream(void);
+ bool write(const void *buffer, size_t length);
+ void flush(void);
+ bool isOpen(void) {
+ return m_stream.is_open();
+ }
+
+
+private:
+ void close();
+
+ inline size_t usedCacheSize() const
+ {
+ assert(m_cachePtr >= m_cache);
+ return m_cachePtr - m_cache;
+ }
+ inline size_t freeCacheSize() const
+ {
+ assert(m_cacheSize >= usedCacheSize());
+ if (m_cacheSize > 0) {
+ return m_cacheSize - usedCacheSize();
+ } else {
+ return 0;
+ }
+ }
+ inline bool endOfData() const
+ {
+ return m_stream.eof() && freeCacheSize() == 0;
+ }
+ void flushWriteCache();
+ void createCache(size_t size);
+ void writeCompressedLength(size_t length);
+private:
+ std::ofstream m_stream;
+ size_t m_cacheMaxSize;
+ size_t m_cacheSize;
+ char *m_cache;
+ char *m_cachePtr;
+
+ char *m_compressedCache;
+};
+
+SnappyOutStream::SnappyOutStream(const char *filename)
+ : m_cacheMaxSize(SNAPPY_CHUNK_SIZE),
+ m_cacheSize(m_cacheMaxSize),
+ m_cache(new char [m_cacheMaxSize]),
+ m_cachePtr(m_cache)
+{
+ size_t maxCompressedLength =
+ snappy::MaxCompressedLength(SNAPPY_CHUNK_SIZE);
+ m_compressedCache = new char[maxCompressedLength];
+
+ std::ios_base::openmode fmode = std::fstream::binary
+ | std::fstream::out
+ | std::fstream::trunc;
+ m_stream.open(filename, fmode);
+ if (m_stream.is_open()) {
+ m_stream << SNAPPY_BYTE1;
+ m_stream << SNAPPY_BYTE2;
+ }
+}
+
+SnappyOutStream::~SnappyOutStream()
+{
+ close();
+ delete [] m_compressedCache;
+ delete [] m_cache;
+}
+
+bool SnappyOutStream::write(const void *buffer, size_t length)
+{
+ if (freeCacheSize() > length) {
+ memcpy(m_cachePtr, buffer, length);
+ m_cachePtr += length;
+ } else if (freeCacheSize() == length) {
+ memcpy(m_cachePtr, buffer, length);
+ m_cachePtr += length;
+ flushWriteCache();
+ } else {
+ size_t sizeToWrite = length;
+
+ while (sizeToWrite >= freeCacheSize()) {
+ size_t endSize = freeCacheSize();
+ size_t offset = length - sizeToWrite;
+ memcpy(m_cachePtr, (const char*)buffer + offset, endSize);
+ sizeToWrite -= endSize;
+ m_cachePtr += endSize;
+ flushWriteCache();
+ }
+ if (sizeToWrite) {
+ size_t offset = length - sizeToWrite;
+ memcpy(m_cachePtr, (const char*)buffer + offset, sizeToWrite);
+ m_cachePtr += sizeToWrite;
+ }
+ }
+
+ return true;
+}
+
+void SnappyOutStream::close()
+{
+ flushWriteCache();
+ m_stream.close();
+ delete [] m_cache;
+ m_cache = NULL;
+ m_cachePtr = NULL;
+}
+
+void SnappyOutStream::flush(void)
+{
+ flushWriteCache();
+ m_stream.flush();
+}
+
+void SnappyOutStream::flushWriteCache(void)
+{
+ size_t inputLength = usedCacheSize();
+
+ if (inputLength) {
+ size_t compressedLength;
+
+ ::snappy::RawCompress(m_cache, inputLength,
+ m_compressedCache, &compressedLength);
+
+ writeCompressedLength(compressedLength);
+ m_stream.write(m_compressedCache, compressedLength);
+ m_cachePtr = m_cache;
+ }
+ assert(m_cachePtr == m_cache);
+}
+
+void SnappyOutStream::writeCompressedLength(size_t length)
+{
+ unsigned char buf[4];
+ buf[0] = length & 0xff; length >>= 8;
+ buf[1] = length & 0xff; length >>= 8;
+ buf[2] = length & 0xff; length >>= 8;
+ buf[3] = length & 0xff; length >>= 8;
+ assert(length == 0);
+ m_stream.write((const char *)buf, sizeof buf);
+}
+
+
+OutStream *
+trace::createSnappyStream(const char *filename)
+{
+ SnappyOutStream *outStream = new SnappyOutStream(filename);
+ if (!outStream->isOpen()) {
+ os::log("error: could not open %s for writing\n", filename);
+ delete outStream;
+ outStream = nullptr;
+ }
+
+ return outStream;
+}
diff --git a/common/trace_ostream_zlib.cpp b/common/trace_ostream_zlib.cpp
new file mode 100644
index 00000000..54893870
--- /dev/null
+++ b/common/trace_ostream_zlib.cpp
@@ -0,0 +1,99 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * Copyright 2011 Zack Rusin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "trace_ostream.hpp"
+
+
+#include <assert.h>
+#include <string.h>
+
+#include <zlib.h>
+
+#include "os.hpp"
+
+#include <iostream>
+
+
+using namespace trace;
+
+
+class ZLibOutStream : public OutStream {
+public:
+ ZLibOutStream(gzFile file);
+ virtual ~ZLibOutStream();
+
+protected:
+ virtual bool write(const void *buffer, size_t length);
+ virtual void close();
+ virtual void flush();
+private:
+ gzFile m_gzFile;
+};
+
+ZLibOutStream::ZLibOutStream(gzFile file)
+ : m_gzFile(file)
+{
+}
+
+ZLibOutStream::~ZLibOutStream()
+{
+ close();
+}
+
+bool ZLibOutStream::write(const void *buffer, size_t length)
+{
+ return gzwrite(m_gzFile, buffer, unsigned(length)) != -1;
+}
+
+void ZLibOutStream::close()
+{
+ if (m_gzFile) {
+ gzclose(m_gzFile);
+ m_gzFile = nullptr;
+ }
+}
+
+void ZLibOutStream::flush()
+{
+ gzflush(m_gzFile, Z_SYNC_FLUSH);
+}
+
+
+OutStream *
+trace::createZLibStream(const char *filename)
+{
+ gzFile file = gzopen(filename, "wb");
+ if (!file) {
+ return nullptr;
+ }
+
+ // Currently we only use gzip for offline compression, so aim for maximum
+ // compression
+ gzsetparams(file, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY);
+
+ return new ZLibOutStream(file);
+}
diff --git a/common/trace_parser.cpp b/common/trace_parser.cpp
index a9cdd0fb..99fa5e83 100644
--- a/common/trace_parser.cpp
+++ b/common/trace_parser.cpp
@@ -673,6 +673,9 @@ Value *Parser::parse_value(void) {
case trace::TYPE_REPR:
value = parse_repr();
break;
+ case trace::TYPE_WSTRING:
+ value = parse_wstring();
+ break;
default:
std::cerr << "error: unknown type " << c << "\n";
exit(1);
@@ -734,6 +737,9 @@ void Parser::scan_value(void) {
case trace::TYPE_REPR:
scan_repr();
break;
+ case trace::TYPE_WSTRING:
+ scan_wstring();
+ break;
default:
std::cerr << "error: unknown type " << c << "\n";
exit(1);
@@ -918,6 +924,28 @@ void Parser::scan_repr() {
}
+Value *Parser::parse_wstring() {
+ size_t len = read_uint();
+ wchar_t * value = new wchar_t[len + 1];
+ for (size_t i = 0; i < len; ++i) {
+ value[i] = read_uint();
+ }
+ value[len] = 0;
+#if TRACE_VERBOSE
+ std::cerr << "\tWSTRING \"" << value << "\"\n";
+#endif
+ return new WString(value);
+}
+
+
+void Parser::scan_wstring() {
+ size_t len = read_uint();
+ for (size_t i = 0; i < len; ++i) {
+ skip_uint();
+ }
+}
+
+
const char * Parser::read_string(void) {
size_t len = read_uint();
char * value = new char[len + 1];
diff --git a/common/trace_parser.hpp b/common/trace_parser.hpp
index 7bf0a7dc..b638aa11 100644
--- a/common/trace_parser.hpp
+++ b/common/trace_parser.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _TRACE_PARSER_HPP_
-#define _TRACE_PARSER_HPP_
+#pragma once
#include <iostream>
@@ -46,7 +45,21 @@ struct ParseBookmark
};
-class Parser
+// Parser interface
+class AbstractParser
+{
+public:
+ virtual ~AbstractParser() {}
+ virtual Call *parse_call(void) = 0;
+ virtual void getBookmark(ParseBookmark &bookmark) = 0;
+ virtual void setBookmark(const ParseBookmark &bookmark) = 0;
+ virtual bool open(const char *filename) = 0;
+ virtual void close(void) = 0;
+ virtual unsigned long long getVersion(void) const = 0;
+};
+
+
+class Parser: public AbstractParser
{
protected:
File *file;
@@ -96,8 +109,8 @@ protected:
unsigned next_call_no;
-public:
unsigned long long version;
+public:
API api;
Parser();
@@ -121,6 +134,10 @@ public:
void setBookmark(const ParseBookmark &bookmark);
+ unsigned long long getVersion(void) const {
+ return version;
+ }
+
int percentRead()
{
return file->percentRead();
@@ -139,9 +156,11 @@ protected:
EnumSig *parse_enum_sig();
BitmaskSig *parse_bitmask_sig();
+public:
static CallFlags
lookupCallFlags(const char *name);
+protected:
Call *parse_Call(Mode mode);
void parse_enter(Mode mode);
@@ -204,6 +223,9 @@ protected:
Value *parse_repr();
void scan_repr();
+ Value *parse_wstring();
+ void scan_wstring();
+
const char * read_string(void);
void skip_string(void);
@@ -218,6 +240,9 @@ protected:
};
+AbstractParser *
+lastFrameLoopParser(AbstractParser *parser, int loopCount);
+
+
} /* namespace trace */
-#endif /* _TRACE_PARSER_HPP_ */
diff --git a/common/trace_parser_flags.cpp b/common/trace_parser_flags.cpp
index 35bac214..d4a07257 100644
--- a/common/trace_parser_flags.cpp
+++ b/common/trace_parser_flags.cpp
@@ -1,5 +1,7 @@
+/* Generated by re2c 0.13.5 */
/**************************************************************************
*
+ * Copyright 2015 VMware, Inc.
* Copyright 2011 Jose Fonseca
* All Rights Reserved.
*
@@ -24,14 +26,23 @@
**************************************************************************/
-/**
+/*
* Label functions based on their name.
+ *
+ * Compile with RE2C as
+ *
+ * re2c -is --no-generation-date trace_parser_flags.cpp.re > trace_parser_flags.cpp
+ *
+ * TODO: Use std::regex once GCC 4.9 becomes widely available -- https://github.com/apitrace/apitrace/issues/370
*/
-#include "trace_lookup.hpp"
#include "trace_parser.hpp"
+#include <assert.h>
+
+#include "trace_lookup.hpp"
+
using namespace trace;
@@ -57,43 +68,12 @@ const Entry<CallFlags>
callFlagTable[] = {
{ "CGLFlushDrawable", CALL_FLAG_END_FRAME },
{ "CGLGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
- { "ID3D10Device1::CheckMultisampleQualityLevels", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
- { "ID3D10Device1::Draw", CALL_FLAG_RENDER },
- { "ID3D10Device1::DrawAuto", CALL_FLAG_RENDER },
- { "ID3D10Device1::DrawIndexed", CALL_FLAG_RENDER },
- { "ID3D10Device1::DrawIndexedInstanced", CALL_FLAG_RENDER },
- { "ID3D10Device1::DrawInstanced", CALL_FLAG_RENDER },
- { "ID3D10Device1::OMSetRenderTargets", CALL_FLAG_SWAP_RENDERTARGET },
- { "ID3D10Device::CheckMultisampleQualityLevels", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
- { "ID3D10Device::Draw", CALL_FLAG_RENDER },
- { "ID3D10Device::DrawAuto", CALL_FLAG_RENDER },
- { "ID3D10Device::DrawIndexed", CALL_FLAG_RENDER },
- { "ID3D10Device::DrawIndexedInstanced", CALL_FLAG_RENDER },
- { "ID3D10Device::DrawInstanced", CALL_FLAG_RENDER },
- { "ID3D10Device::OMSetRenderTargets", CALL_FLAG_SWAP_RENDERTARGET },
- { "ID3D11Device::CheckMultisampleQualityLevels", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
- { "ID3D11DeviceContext1::Draw", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext1::DrawAuto", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext1::DrawIndexed", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext1::DrawIndexedInstanced", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext1::DrawIndexedInstancedIndirect", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext1::DrawInstanced", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext1::DrawInstancedIndirect", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext1::ExecuteCommandList", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext1::OMSetRenderTargets", CALL_FLAG_SWAP_RENDERTARGET },
- { "ID3D11DeviceContext1::OMSetRenderTargetsAndUnorderedAccessViews", CALL_FLAG_SWAP_RENDERTARGET },
- { "ID3D11DeviceContext::Draw", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext::DrawAuto", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext::DrawIndexed", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext::DrawIndexedInstanced", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext::DrawIndexedInstancedIndirect", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext::DrawInstanced", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext::DrawInstancedIndirect", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext::ExecuteCommandList", CALL_FLAG_RENDER },
- { "ID3D11DeviceContext::OMSetRenderTargets", CALL_FLAG_SWAP_RENDERTARGET },
- { "ID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews", CALL_FLAG_SWAP_RENDERTARGET },
- { "IDXGISwapChain::Present", CALL_FLAG_SWAPBUFFERS },
- { "IDXGISwapChainDWM::Present", CALL_FLAG_SWAPBUFFERS },
+ { "D3DPERF_BeginEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "D3DPERF_EndEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP },
+ { "D3DPERF_SetMarker", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER },
+ { "ID3DUserDefinedAnnotation::BeginEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "ID3DUserDefinedAnnotation::EndEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP },
+ { "ID3DUserDefinedAnnotation::SetMarker", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER },
{ "IDirect3D8::CheckDeviceFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "IDirect3D8::EnumAdapterModes", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "IDirect3D8::GetAdapterModeCount", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
@@ -106,6 +86,21 @@ callFlagTable[] = {
{ "IDirect3D9Ex::EnumAdapterModes", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "IDirect3D9Ex::GetAdapterModeCount", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "IDirect3D9Ex::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3DDevice2::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice2::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawIndexedPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawIndexedPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawIndexedPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawIndexedPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawPrimitiveVB", CALL_FLAG_RENDER },
{ "IDirect3DDevice8::Clear", CALL_FLAG_RENDER },
{ "IDirect3DDevice8::DrawIndexedPrimitive", CALL_FLAG_RENDER },
{ "IDirect3DDevice8::DrawIndexedPrimitiveUP", CALL_FLAG_RENDER },
@@ -141,6 +136,10 @@ callFlagTable[] = {
{ "IDirect3DDevice9Ex::SetRenderTarget", CALL_FLAG_SWAP_RENDERTARGET },
{ "IDirect3DSwapChain9::Present", CALL_FLAG_SWAPBUFFERS },
{ "IDirect3DSwapChain9Ex::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DViewport2::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DViewport3::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DViewport3::Clear2", CALL_FLAG_RENDER },
+ { "IDirect3DViewport::Clear", CALL_FLAG_RENDER },
{ "eglGetConfigAttrib", CALL_FLAG_VERBOSE },
{ "eglGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "eglQueryString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
@@ -148,47 +147,14 @@ callFlagTable[] = {
{ "glAreProgramsResidentNV", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glAreTexturesResident", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glAreTexturesResidentEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glBindFramebuffer", CALL_FLAG_SWAP_RENDERTARGET },
- { "glBindFramebufferEXT", CALL_FLAG_SWAP_RENDERTARGET },
- { "glBindFramebufferOES", CALL_FLAG_SWAP_RENDERTARGET },
- { "glBlitFramebuffer", CALL_FLAG_RENDER },
- { "glBlitFramebufferEXT", CALL_FLAG_RENDER },
{ "glBufferRegionEnabled", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glCallList", CALL_FLAG_RENDER },
- { "glCallLists", CALL_FLAG_RENDER },
- { "glClear", CALL_FLAG_RENDER },
{ "glDebugMessageControl", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glDebugMessageControlARB", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glDebugMessageEnableAMD", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glDebugMessageInsert", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
{ "glDebugMessageInsertAMD", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
{ "glDebugMessageInsertARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
- { "glDrawArrays", CALL_FLAG_RENDER },
- { "glDrawArraysEXT", CALL_FLAG_RENDER },
- { "glDrawArraysIndirect", CALL_FLAG_RENDER },
- { "glDrawArraysInstanced", CALL_FLAG_RENDER },
- { "glDrawArraysInstancedARB", CALL_FLAG_RENDER },
- { "glDrawArraysInstancedBaseInstance", CALL_FLAG_RENDER },
- { "glDrawArraysInstancedEXT", CALL_FLAG_RENDER },
- { "glDrawElementArrayAPPLE", CALL_FLAG_RENDER },
- { "glDrawElementArrayATI", CALL_FLAG_RENDER },
- { "glDrawElements", CALL_FLAG_RENDER },
- { "glDrawElementsBaseVertex", CALL_FLAG_RENDER },
- { "glDrawElementsIndirect", CALL_FLAG_RENDER },
- { "glDrawElementsInstanced", CALL_FLAG_RENDER },
- { "glDrawElementsInstancedARB", CALL_FLAG_RENDER },
- { "glDrawElementsInstancedBaseInstance", CALL_FLAG_RENDER },
- { "glDrawElementsInstancedBaseVertex", CALL_FLAG_RENDER },
- { "glDrawElementsInstancedBaseVertexBaseInstance", CALL_FLAG_RENDER },
- { "glDrawElementsInstancedEXT", CALL_FLAG_RENDER },
- { "glDrawMeshArraysSUN", CALL_FLAG_RENDER },
- { "glDrawPixels", CALL_FLAG_RENDER },
- { "glDrawRangeElementArrayAPPLE", CALL_FLAG_RENDER },
- { "glDrawRangeElementArrayATI", CALL_FLAG_RENDER },
- { "glDrawRangeElements", CALL_FLAG_RENDER },
- { "glDrawRangeElementsBaseVertex", CALL_FLAG_RENDER },
- { "glDrawRangeElementsEXT", CALL_FLAG_RENDER },
- { "glEnd", CALL_FLAG_RENDER },
+ { "glDebugMessageInsertKHR", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
{ "glFrameTerminatorGREMEDY", CALL_FLAG_END_FRAME },
{ "glGetActiveAtomicCounterBufferiv", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetActiveAttrib", CALL_FLAG_NO_SIDE_EFFECTS },
@@ -246,9 +212,6 @@ callFlagTable[] = {
{ "glGetFenceivNV", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetFinalCombinerInputParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetFinalCombinerInputParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetFloatIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetFloati_v", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetFloatv", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetFogFuncSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetFragDataIndex", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetFragmentLightfvSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
@@ -270,13 +233,6 @@ callFlagTable[] = {
{ "glGetImageTransformParameterivHP", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetInfoLogARB", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetInstrumentsSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetInteger64i_v", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetInteger64v", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetIntegerIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetIntegeri_v", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetIntegerui64i_vNV", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetIntegerui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetIntegerv", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetInternalformati64v", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetInternalformativ", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetInvariantBooleanvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
@@ -416,21 +372,6 @@ callFlagTable[] = {
{ "glGetTexGendv", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetTexGenfv", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetTexGeniv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTexLevelParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTexLevelParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTexParameterIiv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTexParameterIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTexParameterIuiv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTexParameterIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTexParameterPointervAPPLE", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTexParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTexParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTextureLevelParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTextureLevelParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTextureParameterIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTextureParameterIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTextureParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetTextureParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetTrackMatrixivNV", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetTransformFeedbackVarying", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetTransformFeedbackVaryingEXT", CALL_FLAG_NO_SIDE_EFFECTS },
@@ -456,28 +397,6 @@ callFlagTable[] = {
{ "glGetVertexArrayIntegervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetVertexArrayPointeri_vEXT", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetVertexArrayPointervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribArrayObjectfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribArrayObjectivATI", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribIiv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribIuiv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribLdv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribLdvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribLi64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribLui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribPointerv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribPointervARB", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribPointervNV", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribdv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribdvNV", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribfv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribiv", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribivARB", CALL_FLAG_NO_SIDE_EFFECTS },
- { "glGetVertexAttribivNV", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetVideoCaptureStreamdvNV", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetVideoCaptureStreamfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glGetVideoCaptureStreamivNV", CALL_FLAG_NO_SIDE_EFFECTS },
@@ -530,30 +449,25 @@ callFlagTable[] = {
{ "glIsVertexArray", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "glIsVertexArrayAPPLE", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "glIsVertexAttribEnabledAPPLE", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
- { "glMultiDrawArrays", CALL_FLAG_RENDER },
- { "glMultiDrawArraysEXT", CALL_FLAG_RENDER },
- { "glMultiDrawArraysIndirect", CALL_FLAG_RENDER },
- { "glMultiDrawArraysIndirectAMD", CALL_FLAG_RENDER },
- { "glMultiDrawElementArrayAPPLE", CALL_FLAG_RENDER },
- { "glMultiDrawElements", CALL_FLAG_RENDER },
- { "glMultiDrawElementsBaseVertex", CALL_FLAG_RENDER },
- { "glMultiDrawElementsEXT", CALL_FLAG_RENDER },
- { "glMultiDrawElementsIndirect", CALL_FLAG_RENDER },
- { "glMultiDrawElementsIndirectAMD", CALL_FLAG_RENDER },
- { "glMultiDrawRangeElementArrayAPPLE", CALL_FLAG_RENDER },
- { "glMultiModeDrawArraysIBM", CALL_FLAG_RENDER },
- { "glMultiModeDrawElementsIBM", CALL_FLAG_RENDER },
{ "glObjectLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glObjectLabelKHR", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glObjectPtrLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glObjectPtrLabelKHR", CALL_FLAG_NO_SIDE_EFFECTS },
{ "glPopDebugGroup", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP},
+ { "glPopDebugGroupKHR", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP},
{ "glPopGroupMarkerEXT", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP},
{ "glPushDebugGroup", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "glPushDebugGroupKHR", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
{ "glPushGroupMarkerEXT", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
{ "glStringMarkerGREMEDY", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER },
{ "glXGetClientString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetConfig", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "glXGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "glXGetCurrentDisplay", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentDisplayEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "glXGetCurrentDrawable", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentReadDrawable", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentReadDrawableSGI", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "glXGetFBConfigAttrib", CALL_FLAG_VERBOSE },
{ "glXGetFBConfigAttribSGIX", CALL_FLAG_VERBOSE },
{ "glXGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
@@ -567,7 +481,11 @@ callFlagTable[] = {
{ "wglGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "wglGetCurrentDC", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "wglGetDefaultProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetExtensionsStringARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetExtensionsStringEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "wglGetPixelFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetPixelFormatAttribivARB", CALL_FLAG_VERBOSE },
+ { "wglGetPixelFormatAttribivEXT", CALL_FLAG_VERBOSE },
{ "wglGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
{ "wglSwapBuffers", CALL_FLAG_SWAPBUFFERS },
{ "wglSwapLayerBuffers", CALL_FLAG_SWAPBUFFERS },
@@ -580,6 +498,4523 @@ callFlagTable[] = {
* Lookup call flags by name.
*/
CallFlags
-Parser::lookupCallFlags(const char *name) {
- return entryLookup(name, callFlagTable, defaultCallFlags);
+Parser::lookupCallFlags(const char *name)
+{
+ const char *p = name;
+ const char *q;
+
+
+ {
+ char yych;
+
+ yych = *p;
+ if (yych == 'I') goto yy4;
+ if (yych != 'g') goto yy5;
+ yych = *(q = ++p);
+ if (yych == 'l') goto yy150;
+yy3:
+ { return entryLookup(name, callFlagTable, defaultCallFlags); }
+yy4:
+ yych = *(q = ++p);
+ if (yych == 'D') goto yy6;
+ goto yy3;
+yy5:
+ yych = *++p;
+ goto yy3;
+yy6:
+ yych = *++p;
+ if (yych == '3') goto yy9;
+ if (yych == 'X') goto yy8;
+yy7:
+ p = q;
+ goto yy3;
+yy8:
+ yych = *++p;
+ if (yych == 'G') goto yy120;
+ goto yy7;
+yy9:
+ yych = *++p;
+ if (yych != 'D') goto yy7;
+ yych = *++p;
+ if (yych != '1') goto yy7;
+ yych = *++p;
+ if (yych <= '/') goto yy7;
+ if (yych <= '0') goto yy12;
+ if (yych <= '1') goto yy13;
+ goto yy7;
+yy12:
+ yych = *++p;
+ if (yych == 'D') goto yy111;
+ goto yy7;
+yy13:
+ yych = *++p;
+ if (yych != 'D') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'v') goto yy7;
+ yych = *++p;
+ if (yych != 'i') goto yy7;
+ yych = *++p;
+ if (yych != 'c') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'C') goto yy22;
+ yych = *++p;
+ if (yych == 'o') goto yy56;
+ goto yy7;
+yy21:
+ ++p;
+ yych = *p;
+yy22:
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy21;
+ if (yych >= ';') goto yy7;
+ yych = *++p;
+ if (yych != ':') goto yy7;
+ yych = *++p;
+ if (yych != 'C') goto yy7;
+yy25:
+ yych = *++p;
+ if (yych != 'h') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'c') goto yy7;
+ yych = *++p;
+ if (yych != 'k') goto yy7;
+ yych = *++p;
+ if (yych != 'M') goto yy7;
+ yych = *++p;
+ if (yych != 'u') goto yy7;
+ yych = *++p;
+ if (yych != 'l') goto yy7;
+ yych = *++p;
+ if (yych != 't') goto yy7;
+ yych = *++p;
+ if (yych != 'i') goto yy7;
+ yych = *++p;
+ if (yych != 's') goto yy7;
+ yych = *++p;
+ if (yych != 'a') goto yy7;
+ yych = *++p;
+ if (yych != 'm') goto yy7;
+ yych = *++p;
+ if (yych != 'p') goto yy7;
+ yych = *++p;
+ if (yych != 'l') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'Q') goto yy7;
+ yych = *++p;
+ if (yych != 'u') goto yy7;
+ yych = *++p;
+ if (yych != 'a') goto yy7;
+ yych = *++p;
+ if (yych != 'l') goto yy7;
+ yych = *++p;
+ if (yych != 'i') goto yy7;
+ yych = *++p;
+ if (yych != 't') goto yy7;
+ yych = *++p;
+ if (yych != 'y') goto yy7;
+ yych = *++p;
+ if (yych != 'L') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'v') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'l') goto yy7;
+ yych = *++p;
+ if (yych != 's') goto yy7;
+ yych = *++p;
+ if (yych >= 0x01) goto yy7;
+ ++p;
+ {
+ return CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE;
+ }
+yy56:
+ yych = *++p;
+ if (yych != 'n') goto yy7;
+ yych = *++p;
+ if (yych != 't') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'x') goto yy7;
+ yych = *++p;
+ if (yych != 't') goto yy7;
+yy61:
+ ++p;
+ yych = *p;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy61;
+ if (yych >= ';') goto yy7;
+ yych = *++p;
+ if (yych != ':') goto yy7;
+ yych = *++p;
+ if (yych <= 'E') {
+ if (yych <= 'C') goto yy7;
+ if (yych <= 'D') goto yy66;
+ goto yy67;
+ } else {
+ if (yych != 'O') goto yy7;
+ }
+yy65:
+ yych = *++p;
+ if (yych == 'M') goto yy91;
+ goto yy7;
+yy66:
+ yych = *++p;
+ if (yych == 'r') goto yy87;
+ goto yy7;
+yy67:
+ yych = *++p;
+ if (yych != 'x') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'c') goto yy7;
+ yych = *++p;
+ if (yych != 'u') goto yy7;
+ yych = *++p;
+ if (yych != 't') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'C') goto yy7;
+ yych = *++p;
+ if (yych != 'o') goto yy7;
+ yych = *++p;
+ if (yych != 'm') goto yy7;
+ yych = *++p;
+ if (yych != 'm') goto yy7;
+ yych = *++p;
+ if (yych != 'a') goto yy7;
+ yych = *++p;
+ if (yych != 'n') goto yy7;
+ yych = *++p;
+ if (yych != 'd') goto yy7;
+ yych = *++p;
+ if (yych != 'L') goto yy7;
+ yych = *++p;
+ if (yych != 'i') goto yy7;
+ yych = *++p;
+ if (yych != 's') goto yy7;
+ yych = *++p;
+ if (yych != 't') goto yy7;
+ yych = *++p;
+ if (yych >= 0x01) goto yy7;
+yy85:
+ ++p;
+ {
+ return CALL_FLAG_RENDER;
+ }
+yy87:
+ yych = *++p;
+ if (yych != 'a') goto yy7;
+ yych = *++p;
+ if (yych != 'w') goto yy7;
+yy89:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy85;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy89;
+ if (yych <= '@') goto yy7;
+ goto yy89;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ goto yy89;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy89;
+ goto yy7;
+ }
+ }
+yy91:
+ yych = *++p;
+ if (yych != 'S') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 't') goto yy7;
+ yych = *++p;
+ if (yych != 'R') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'n') goto yy7;
+ yych = *++p;
+ if (yych != 'd') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'r') goto yy7;
+ yych = *++p;
+ if (yych != 'T') goto yy7;
+ yych = *++p;
+ if (yych != 'a') goto yy7;
+ yych = *++p;
+ if (yych != 'r') goto yy7;
+ yych = *++p;
+ if (yych != 'g') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 't') goto yy7;
+ yych = *++p;
+ if (yych != 's') goto yy7;
+yy107:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych >= 0x01) goto yy7;
+ } else {
+ if (yych <= '9') goto yy107;
+ if (yych <= '@') goto yy7;
+ goto yy107;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ goto yy107;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy107;
+ goto yy7;
+ }
+ }
+ ++p;
+ {
+ return CALL_FLAG_SWAP_RENDERTARGET;
+ }
+yy111:
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'v') goto yy7;
+ yych = *++p;
+ if (yych != 'i') goto yy7;
+ yych = *++p;
+ if (yych != 'c') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+yy116:
+ ++p;
+ yych = *p;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy116;
+ if (yych >= ';') goto yy7;
+ yych = *++p;
+ if (yych != ':') goto yy7;
+ yych = *++p;
+ if (yych <= 'D') {
+ if (yych <= 'B') goto yy7;
+ if (yych <= 'C') goto yy25;
+ goto yy66;
+ } else {
+ if (yych <= 'E') goto yy67;
+ if (yych == 'O') goto yy65;
+ goto yy7;
+ }
+yy120:
+ yych = *++p;
+ if (yych != 'I') goto yy7;
+ yych = *++p;
+ if (yych == 'D') goto yy122;
+ if (yych == 'S') goto yy123;
+ goto yy7;
+yy122:
+ yych = *++p;
+ if (yych == 'e') goto yy145;
+ goto yy7;
+yy123:
+ yych = *++p;
+ if (yych != 'w') goto yy7;
+ yych = *++p;
+ if (yych != 'a') goto yy7;
+ yych = *++p;
+ if (yych != 'p') goto yy7;
+ yych = *++p;
+ if (yych != 'C') goto yy7;
+ yych = *++p;
+ if (yych != 'h') goto yy7;
+ yych = *++p;
+ if (yych != 'a') goto yy7;
+ yych = *++p;
+ if (yych != 'i') goto yy7;
+ yych = *++p;
+ if (yych != 'n') goto yy7;
+yy131:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= '/') goto yy7;
+ goto yy131;
+ } else {
+ if (yych <= ':') goto yy133;
+ if (yych <= '@') goto yy7;
+ goto yy131;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ goto yy131;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy131;
+ goto yy7;
+ }
+ }
+yy133:
+ yych = *++p;
+ if (yych != ':') goto yy7;
+ yych = *++p;
+ if (yych != 'P') goto yy7;
+ yych = *++p;
+ if (yych != 'r') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 's') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych != 'n') goto yy7;
+ yych = *++p;
+ if (yych != 't') goto yy7;
+yy141:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych >= 0x01) goto yy7;
+ } else {
+ if (yych <= '9') goto yy141;
+ if (yych <= '@') goto yy7;
+ goto yy141;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ goto yy141;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy141;
+ goto yy7;
+ }
+ }
+ ++p;
+ {
+ return CALL_FLAG_END_FRAME;
+ }
+yy145:
+ yych = *++p;
+ if (yych != 'c') goto yy7;
+ yych = *++p;
+ if (yych != 'o') goto yy7;
+ yych = *++p;
+ if (yych != 'd') goto yy7;
+ yych = *++p;
+ if (yych != 'e') goto yy7;
+ yych = *++p;
+ if (yych == 'S') goto yy123;
+ goto yy7;
+yy150:
+ yych = *++p;
+ switch (yych) {
+ case 'A':
+ case 'F':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z': goto yy151;
+ case 'B': goto yy152;
+ case 'C': goto yy153;
+ case 'D': goto yy154;
+ case 'E': goto yy155;
+ case 'G': goto yy156;
+ case 'R': goto yy157;
+ default: goto yy7;
+ }
+yy151:
+ ++p;
+ yych = *p;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy152:
+ yych = *++p;
+ if (yych <= 'i') {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'h') goto yy159;
+ goto yy440;
+ } else {
+ if (yych == 'l') goto yy441;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+yy153:
+ yych = *++p;
+ if (yych <= 'k') {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy431;
+ goto yy159;
+ } else {
+ if (yych <= 'l') goto yy430;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+yy154:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'r') goto yy344;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy155:
+ yych = *++p;
+ if (yych <= 'n') {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'm') goto yy159;
+ goto yy335;
+ } else {
+ if (yych == 'v') goto yy334;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+yy156:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'e') goto yy228;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy157:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'e') goto yy158;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy158:
+ yych = *++p;
+ if (yych == 'c') goto yy218;
+ goto yy160;
+yy159:
+ ++p;
+ yych = *p;
+yy160:
+ if (yych <= 'D') {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy151;
+ } else {
+ if (yych <= 'Z') goto yy151;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+yy161:
+ ++p;
+ yych = *p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'r') goto yy162;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy162:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy163;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+yy163:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'v') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'w') goto yy164;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy164:
+ ++p;
+ yych = *p;
+ if (yych <= 'L') {
+ if (yych <= 'C') {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'A') goto yy167;
+ goto yy151;
+ } else {
+ if (yych <= 'D') goto yy161;
+ if (yych <= 'E') goto yy168;
+ goto yy151;
+ }
+ } else {
+ if (yych <= 'R') {
+ if (yych <= 'M') goto yy166;
+ if (yych <= 'Q') goto yy151;
+ } else {
+ if (yych <= 'Z') goto yy151;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy165:
+ ++p;
+ yych = *p;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy215;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy166:
+ ++p;
+ yych = *p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'e') goto yy212;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy167:
+ ++p;
+ yych = *p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'r') goto yy208;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy168:
+ ++p;
+ yych = *p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'l') goto yy169;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy169:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'e') goto yy170;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy170:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'l') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'm') goto yy171;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy171:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'e') goto yy172;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy172:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'm') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'n') goto yy173;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy173:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 's') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 't') goto yy174;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy174:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'r') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 's') goto yy175;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy175:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ if (yych >= 'D') goto yy177;
+ } else {
+ if (yych <= 'Z') goto yy176;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+yy176:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ goto yy183;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+yy177:
+ ++p;
+ yych = *p;
+ if (yych <= '`') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy183;
+ goto yy7;
+ } else {
+ if (yych == 'r') goto yy182;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+yy178:
+ ++p;
+yy179:
+ {
+ return CALL_FLAG_RENDER;
+ }
+yy180:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy176;
+ goto yy177;
+ } else {
+ if (yych <= 'Z') goto yy176;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+yy182:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy176;
+ goto yy177;
+ } else {
+ if (yych <= '`') {
+ if (yych <= 'Z') goto yy176;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy185;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy183:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ goto yy183;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy183;
+ goto yy7;
+ }
+yy185:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'v') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'w') goto yy186;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy186:
+ ++p;
+ yych = *p;
+ if (yych <= 'L') {
+ if (yych <= 'A') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ } else {
+ if (yych <= 'C') goto yy176;
+ if (yych <= 'D') goto yy177;
+ if (yych <= 'E') goto yy188;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'R') {
+ if (yych <= 'M') goto yy189;
+ if (yych <= 'Q') goto yy176;
+ goto yy190;
+ } else {
+ if (yych <= 'Z') goto yy176;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy187:
+ ++p;
+ yych = *p;
+ if (yych <= '`') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy183;
+ goto yy7;
+ } else {
+ if (yych == 'r') goto yy204;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+yy188:
+ ++p;
+ yych = *p;
+ if (yych <= '`') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy183;
+ goto yy7;
+ } else {
+ if (yych == 'l') goto yy197;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+yy189:
+ ++p;
+ yych = *p;
+ if (yych <= '`') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy183;
+ goto yy7;
+ } else {
+ if (yych == 'e') goto yy195;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+yy190:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ goto yy183;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy191;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+yy191:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'm') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'n') goto yy192;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy192:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'f') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'g') goto yy193;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy193:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'e') goto yy194;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy194:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych <= 'A') goto yy187;
+ if (yych <= 'C') goto yy176;
+ goto yy177;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'E') goto yy188;
+ goto yy176;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy195:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'r') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 's') goto yy196;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy196:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'g') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'h') goto yy194;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy197:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'e') goto yy198;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy198:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'l') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'm') goto yy199;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy199:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'e') goto yy200;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy200:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'm') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'n') goto yy201;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy201:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 's') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 't') goto yy202;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy202:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'r') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 's') goto yy203;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy203:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy176;
+ goto yy177;
+ } else {
+ if (yych <= 'Z') goto yy176;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+yy204:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'r') goto yy205;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy205:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= 0x00) goto yy178;
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy176;
+ goto yy177;
+ } else {
+ if (yych <= '`') {
+ if (yych <= 'Z') goto yy176;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy206;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy206:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'x') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 'y') goto yy207;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy207:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy178;
+ goto yy7;
+ } else {
+ if (yych == 'D') goto yy177;
+ goto yy176;
+ }
+ } else {
+ if (yych <= 'r') {
+ if (yych <= '`') goto yy7;
+ goto yy180;
+ } else {
+ if (yych <= 's') goto yy203;
+ if (yych <= 'z') goto yy180;
+ goto yy7;
+ }
+ }
+yy208:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'r') goto yy209;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy209:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy210;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+yy210:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'x') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'y') goto yy211;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy211:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'r') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 's') goto yy175;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy212:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'r') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 's') goto yy213;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy213:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'g') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'h') goto yy214;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy214:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'A') goto yy167;
+ if (yych <= 'C') goto yy151;
+ goto yy161;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'E') goto yy168;
+ goto yy151;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy215:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'm') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'n') goto yy216;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy216:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'f') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'g') goto yy217;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy217:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy161;
+ goto yy151;
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '`') goto yy7;
+ goto yy159;
+ } else {
+ if (yych <= 'e') goto yy214;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+ }
+ }
+yy218:
+ yych = *++p;
+ if (yych != 't') goto yy160;
+ yych = *++p;
+ switch (yych) {
+ case 'd':
+ case 'f':
+ case 'i':
+ case 's': goto yy220;
+ default: goto yy160;
+ }
+yy220:
+ yych = *++p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy223;
+ if (yych == 'D') goto yy225;
+ goto yy224;
+ } else {
+ if (yych <= 'u') {
+ if (yych <= '`') goto yy223;
+ goto yy159;
+ } else {
+ if (yych <= 'v') goto yy221;
+ if (yych <= 'z') goto yy159;
+ goto yy223;
+ }
+ }
+yy221:
+ yych = *++p;
+ if (yych <= 'D') {
+ if (yych <= '@') goto yy223;
+ if (yych <= 'C') goto yy224;
+ goto yy225;
+ } else {
+ if (yych <= 'Z') goto yy224;
+ if (yych <= '`') goto yy223;
+ if (yych <= 'z') goto yy159;
+ goto yy223;
+ }
+yy222:
+ ++p;
+ yych = *p;
+yy223:
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy222;
+ goto yy7;
+ }
+yy224:
+ yych = *++p;
+ if (yych <= '`') goto yy223;
+ if (yych <= 'z') goto yy159;
+ goto yy223;
+yy225:
+ yych = *++p;
+ if (yych <= '`') goto yy223;
+ if (yych == 'r') goto yy162;
+ if (yych <= 'z') goto yy159;
+ goto yy223;
+yy226:
+ ++p;
+ {
+ return CALL_FLAG_RENDER;
+ }
+yy228:
+ yych = *++p;
+ if (yych != 't') goto yy160;
+ yych = *++p;
+ switch (yych) {
+ case 'F': goto yy233;
+ case 'I': goto yy232;
+ case 'T': goto yy230;
+ case 'V': goto yy231;
+ default: goto yy160;
+ }
+yy230:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'e') goto yy315;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy231:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'e') goto yy305;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy232:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'n') goto yy300;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy233:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'l') goto yy234;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy234:
+ yych = *++p;
+ if (yych != 'o') goto yy160;
+ yych = *++p;
+ if (yych != 'a') goto yy160;
+ yych = *++p;
+ if (yych != 't') goto yy160;
+yy237:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy240;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= 'Z') goto yy240;
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy239:
+ ++p;
+ yych = *p;
+ if (yych <= '^') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy241;
+ goto yy7;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ goto yy237;
+ } else {
+ if (yych <= 'r') goto yy245;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy240:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy243;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy241;
+ if (yych <= '@') goto yy7;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy241:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych >= 0x01) goto yy7;
+ } else {
+ if (yych <= '9') goto yy241;
+ if (yych <= '@') goto yy7;
+ goto yy241;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy241;
+ goto yy7;
+ }
+ }
+yy243:
+ ++p;
+ {
+ return CALL_FLAG_NO_SIDE_EFFECTS;
+ }
+yy245:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy240;
+ goto yy239;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= 'Z') goto yy240;
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy246;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy246:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'w') goto yy247;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy247:
+ ++p;
+ yych = *p;
+ if (yych <= 'L') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy241;
+ goto yy7;
+ } else {
+ if (yych <= 'C') {
+ if (yych <= 'A') goto yy250;
+ goto yy240;
+ } else {
+ if (yych <= 'D') goto yy239;
+ if (yych <= 'E') goto yy251;
+ goto yy240;
+ }
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'M') goto yy249;
+ if (yych != 'R') goto yy240;
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+ }
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy243;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy241;
+ if (yych <= '@') goto yy7;
+ goto yy241;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy297;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy249:
+ ++p;
+ yych = *p;
+ if (yych <= '^') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy241;
+ goto yy7;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ goto yy237;
+ } else {
+ if (yych <= 'e') goto yy294;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy250:
+ ++p;
+ yych = *p;
+ if (yych <= '^') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy241;
+ goto yy7;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ goto yy237;
+ } else {
+ if (yych <= 'r') goto yy290;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy251:
+ ++p;
+ yych = *p;
+ if (yych <= '^') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy241;
+ goto yy7;
+ }
+ } else {
+ if (yych <= 'k') {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ goto yy237;
+ } else {
+ if (yych <= 'l') goto yy252;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy252:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'e') goto yy253;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy253:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'm') goto yy254;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy254:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'e') goto yy255;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy255:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'n') goto yy256;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy256:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 't') goto yy257;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy257:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 's') goto yy258;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy258:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych >= 'D') goto yy260;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= 'Z') goto yy259;
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy259:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy261;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy241;
+ if (yych <= '@') goto yy7;
+ goto yy262;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy260:
+ ++p;
+ yych = *p;
+ if (yych <= '^') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy262;
+ goto yy7;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ goto yy264;
+ } else {
+ if (yych <= 'r') goto yy266;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy261:
+ yych = *++p;
+ goto yy179;
+yy262:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy261;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy241;
+ if (yych <= '@') goto yy7;
+ goto yy262;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy262;
+ goto yy7;
+ }
+ }
+yy264:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy259;
+ goto yy260;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= 'Z') goto yy259;
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy266:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy259;
+ goto yy260;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= 'Z') goto yy259;
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy267;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy267:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'w') goto yy268;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy268:
+ ++p;
+ yych = *p;
+ if (yych <= 'L') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy241;
+ goto yy7;
+ } else {
+ if (yych <= 'C') {
+ if (yych >= 'B') goto yy259;
+ } else {
+ if (yych <= 'D') goto yy260;
+ if (yych <= 'E') goto yy270;
+ goto yy259;
+ }
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'M') goto yy271;
+ if (yych == 'R') goto yy272;
+ goto yy259;
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+ }
+yy269:
+ ++p;
+ yych = *p;
+ if (yych <= '^') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy262;
+ goto yy7;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ goto yy264;
+ } else {
+ if (yych <= 'r') goto yy286;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy270:
+ ++p;
+ yych = *p;
+ if (yych <= '^') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy262;
+ goto yy7;
+ }
+ } else {
+ if (yych <= 'k') {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ goto yy264;
+ } else {
+ if (yych <= 'l') goto yy279;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy271:
+ ++p;
+ yych = *p;
+ if (yych <= '^') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy262;
+ goto yy7;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ goto yy264;
+ } else {
+ if (yych <= 'e') goto yy277;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy272:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy261;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy241;
+ if (yych <= '@') goto yy7;
+ goto yy262;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy273;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy273:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'n') goto yy274;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy274:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'g') goto yy275;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy275:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'e') goto yy276;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy276:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'A') goto yy269;
+ if (yych <= 'C') goto yy259;
+ goto yy260;
+ }
+ } else {
+ if (yych <= '^') {
+ if (yych <= 'E') goto yy270;
+ if (yych <= 'Z') goto yy259;
+ goto yy7;
+ } else {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy277:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 's') goto yy278;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy278:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'h') goto yy276;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy279:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'e') goto yy280;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy280:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'm') goto yy281;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy281:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'e') goto yy282;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy282:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'n') goto yy283;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy283:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 't') goto yy284;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy284:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 's') goto yy285;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy285:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy259;
+ goto yy260;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= 'Z') goto yy259;
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy286:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'r') goto yy287;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy287:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy259;
+ goto yy260;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= 'Z') goto yy259;
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy288;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy288:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'y') goto yy289;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy289:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy261;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy260;
+ goto yy259;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 's') goto yy285;
+ if (yych <= 'z') goto yy264;
+ goto yy7;
+ }
+ }
+yy290:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'r') goto yy291;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy291:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy240;
+ goto yy239;
+ }
+ } else {
+ if (yych <= '_') {
+ if (yych <= 'Z') goto yy240;
+ if (yych <= '^') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy292;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy292:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'y') goto yy293;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy293:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 's') goto yy258;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy294:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 's') goto yy295;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy295:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'h') goto yy296;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy296:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'A') goto yy250;
+ if (yych <= 'C') goto yy240;
+ goto yy239;
+ }
+ } else {
+ if (yych <= '^') {
+ if (yych <= 'E') goto yy251;
+ if (yych <= 'Z') goto yy240;
+ goto yy7;
+ } else {
+ if (yych <= '_') goto yy241;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy297:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'n') goto yy298;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy298:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'g') goto yy299;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy299:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy243;
+ if (yych <= '/') goto yy7;
+ goto yy241;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych == 'D') goto yy239;
+ goto yy240;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych == '_') goto yy241;
+ goto yy7;
+ } else {
+ if (yych == 'e') goto yy296;
+ if (yych <= 'z') goto yy237;
+ goto yy7;
+ }
+ }
+yy300:
+ yych = *++p;
+ if (yych != 't') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych != 'g') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych == 'r') goto yy237;
+ goto yy160;
+yy305:
+ yych = *++p;
+ if (yych != 'r') goto yy160;
+ yych = *++p;
+ if (yych != 't') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych != 'x') goto yy160;
+ yych = *++p;
+ if (yych != 'A') goto yy160;
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 't') goto yy311;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy311:
+ yych = *++p;
+ if (yych != 't') goto yy160;
+ yych = *++p;
+ if (yych != 'r') goto yy160;
+ yych = *++p;
+ if (yych != 'i') goto yy160;
+ yych = *++p;
+ if (yych == 'b') goto yy237;
+ goto yy160;
+yy315:
+ yych = *++p;
+ if (yych != 'x') goto yy160;
+ yych = *++p;
+ if (yych <= 'O') {
+ if (yych != 'L') goto yy160;
+ } else {
+ if (yych <= 'P') goto yy318;
+ if (yych == 't') goto yy319;
+ goto yy160;
+ }
+yy317:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'e') goto yy330;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy318:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'a') goto yy323;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy319:
+ yych = *++p;
+ if (yych != 'u') goto yy160;
+ yych = *++p;
+ if (yych != 'r') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych == 'L') goto yy317;
+ if (yych == 'P') goto yy318;
+ goto yy160;
+yy323:
+ yych = *++p;
+ if (yych != 'r') goto yy160;
+ yych = *++p;
+ if (yych != 'a') goto yy160;
+ yych = *++p;
+ if (yych != 'm') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych != 't') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych == 'r') goto yy237;
+ goto yy160;
+yy330:
+ yych = *++p;
+ if (yych != 'v') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych != 'l') goto yy160;
+ yych = *++p;
+ if (yych == 'P') goto yy318;
+ goto yy160;
+yy334:
+ yych = *++p;
+ if (yych == 'a') goto yy336;
+ goto yy160;
+yy335:
+ yych = *++p;
+ if (yych == 'd') goto yy221;
+ goto yy160;
+yy336:
+ yych = *++p;
+ if (yych != 'l') goto yy160;
+ yych = *++p;
+ if (yych != 'M') goto yy160;
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'e') goto yy339;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy339:
+ yych = *++p;
+ if (yych != 's') goto yy160;
+ yych = *++p;
+ if (yych != 'h') goto yy160;
+ yych = *++p;
+ if (yych <= 'D') {
+ if (yych <= 0x00) goto yy7;
+ if (yych <= '@') goto yy343;
+ if (yych <= 'C') goto yy151;
+ goto yy161;
+ } else {
+ if (yych <= 'Z') goto yy151;
+ if (yych <= '`') goto yy343;
+ if (yych <= 'z') goto yy159;
+ goto yy343;
+ }
+yy342:
+ ++p;
+ yych = *p;
+yy343:
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy342;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy222;
+ goto yy7;
+ }
+yy344:
+ yych = *++p;
+ if (yych != 'a') goto yy160;
+ yych = *++p;
+ if (yych != 'w') goto yy160;
+ yych = *++p;
+ switch (yych) {
+ case 'A': goto yy167;
+ case 'E': goto yy168;
+ case 'M': goto yy166;
+ case 'P': goto yy347;
+ case 'R': goto yy165;
+ case 'T': goto yy348;
+ default: goto yy160;
+ }
+yy347:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'i') goto yy426;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy348:
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'r') goto yy349;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy349:
+ yych = *++p;
+ if (yych != 'a') goto yy160;
+ yych = *++p;
+ if (yych != 'n') goto yy160;
+ yych = *++p;
+ if (yych != 's') goto yy160;
+ yych = *++p;
+ if (yych != 'f') goto yy160;
+ yych = *++p;
+ if (yych != 'o') goto yy160;
+ yych = *++p;
+ if (yych != 'r') goto yy160;
+ yych = *++p;
+ if (yych != 'm') goto yy160;
+ yych = *++p;
+ if (yych != 'F') goto yy160;
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'e') goto yy358;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy358:
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych != 'd') goto yy160;
+ yych = *++p;
+ if (yych != 'b') goto yy160;
+ yych = *++p;
+ if (yych != 'a') goto yy160;
+ yych = *++p;
+ if (yych != 'c') goto yy160;
+ yych = *++p;
+ if (yych != 'k') goto yy160;
+ yych = *++p;
+ if (yych <= 'D') {
+ if (yych <= '@') goto yy223;
+ if (yych >= 'D') goto yy366;
+ } else {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy223;
+ if (yych <= 'z') goto yy159;
+ goto yy223;
+ }
+yy365:
+ ++p;
+ yych = *p;
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy222;
+ goto yy7;
+ } else {
+ if (yych <= 'Z') goto yy370;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+yy366:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy226;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy370;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '`') goto yy7;
+ } else {
+ if (yych <= 'r') goto yy369;
+ if (yych >= '{') goto yy7;
+ }
+ }
+yy367:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy226;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy365;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'D') goto yy366;
+ goto yy365;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy369:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy226;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy365;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych <= 'D') goto yy366;
+ if (yych <= 'Z') goto yy365;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy372;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy370:
+ ++p;
+ yych = *p;
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy222;
+ goto yy7;
+ } else {
+ if (yych <= 'Z') goto yy370;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy370;
+ goto yy7;
+ }
+yy372:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'v') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'w') goto yy373;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy373:
+ ++p;
+ yych = *p;
+ if (yych <= 'E') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy222;
+ goto yy7;
+ } else {
+ if (yych <= 'A') goto yy374;
+ if (yych <= 'C') goto yy365;
+ if (yych <= 'D') goto yy366;
+ goto yy375;
+ }
+ } else {
+ if (yych <= 'R') {
+ if (yych == 'M') goto yy376;
+ if (yych <= 'Q') goto yy365;
+ goto yy377;
+ } else {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy374:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy226;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy370;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'r') goto yy422;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy375:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy226;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy370;
+ }
+ } else {
+ if (yych <= 'k') {
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'l') goto yy384;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy376:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy226;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy370;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'e') goto yy382;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy377:
+ ++p;
+ yych = *p;
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy222;
+ goto yy7;
+ } else {
+ if (yych <= '`') {
+ if (yych <= 'Z') goto yy370;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy378;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy378:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'm') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'n') goto yy379;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy379:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'f') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'g') goto yy380;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy380:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'e') goto yy381;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy381:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'A') goto yy374;
+ goto yy365;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'D') goto yy366;
+ if (yych <= 'E') goto yy375;
+ goto yy365;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy382:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'r') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 's') goto yy383;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy383:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'g') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'h') goto yy381;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy384:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'e') goto yy385;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy385:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'l') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'm') goto yy386;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy386:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'e') goto yy387;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy387:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'm') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'n') goto yy388;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy388:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 's') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 't') goto yy389;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy389:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'r') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 's') goto yy390;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy390:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy393;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'D') goto yy392;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy391:
+ ++p;
+ yych = *p;
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy222;
+ goto yy7;
+ } else {
+ if (yych <= 'Z') goto yy397;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+yy392:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych >= 0x01) goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy397;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'r') goto yy396;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy393:
+ yych = *++p;
+ goto yy179;
+yy394:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy393;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy391;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'D') goto yy392;
+ goto yy391;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy396:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy393;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy391;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych <= 'D') goto yy392;
+ if (yych <= 'Z') goto yy391;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy399;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy397:
+ ++p;
+ yych = *p;
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy222;
+ goto yy7;
+ } else {
+ if (yych <= 'Z') goto yy397;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy397;
+ goto yy7;
+ }
+yy399:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'v') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'w') goto yy400;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy400:
+ ++p;
+ yych = *p;
+ if (yych <= 'E') {
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy222;
+ goto yy7;
+ } else {
+ if (yych <= 'A') goto yy401;
+ if (yych <= 'C') goto yy391;
+ if (yych <= 'D') goto yy392;
+ goto yy402;
+ }
+ } else {
+ if (yych <= 'R') {
+ if (yych == 'M') goto yy403;
+ if (yych <= 'Q') goto yy391;
+ goto yy404;
+ } else {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy401:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy393;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy397;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'r') goto yy418;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy402:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy393;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy397;
+ }
+ } else {
+ if (yych <= 'k') {
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'l') goto yy411;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy403:
+ ++p;
+ yych = *p;
+ if (yych <= 'Z') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy393;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy397;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'e') goto yy409;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy404:
+ ++p;
+ yych = *p;
+ if (yych <= '@') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ if (yych <= '9') goto yy222;
+ goto yy7;
+ } else {
+ if (yych <= '`') {
+ if (yych <= 'Z') goto yy397;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy405;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy405:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'm') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'n') goto yy406;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy406:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'f') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'g') goto yy407;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy407:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'e') goto yy408;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy408:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'A') goto yy401;
+ goto yy391;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'D') goto yy392;
+ if (yych <= 'E') goto yy402;
+ goto yy391;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy409:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'r') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 's') goto yy410;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy410:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'g') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'h') goto yy408;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy411:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'e') goto yy412;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy412:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'l') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'm') goto yy413;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy413:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'e') goto yy414;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy414:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'm') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'n') goto yy415;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy415:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 's') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 't') goto yy416;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy416:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'r') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 's') goto yy417;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy417:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy393;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy391;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= 'D') goto yy392;
+ goto yy391;
+ } else {
+ if (yych <= '`') goto yy7;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy418:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'r') goto yy419;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy419:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy393;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy391;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych <= 'D') goto yy392;
+ if (yych <= 'Z') goto yy391;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy420;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy420:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'x') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 'y') goto yy421;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy421:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy393;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy391;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'r') {
+ if (yych <= 'Z') goto yy391;
+ if (yych <= '`') goto yy7;
+ goto yy394;
+ } else {
+ if (yych <= 's') goto yy417;
+ if (yych <= 'z') goto yy394;
+ goto yy7;
+ }
+ }
+yy422:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'r') goto yy423;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy423:
+ ++p;
+ yych = *p;
+ if (yych <= 'C') {
+ if (yych <= '/') {
+ if (yych <= 0x00) goto yy226;
+ goto yy7;
+ } else {
+ if (yych <= '9') goto yy222;
+ if (yych <= '@') goto yy7;
+ goto yy365;
+ }
+ } else {
+ if (yych <= '`') {
+ if (yych <= 'D') goto yy366;
+ if (yych <= 'Z') goto yy365;
+ goto yy7;
+ } else {
+ if (yych <= 'a') goto yy424;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy424:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'x') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 'y') goto yy425;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy425:
+ ++p;
+ yych = *p;
+ if (yych <= 'D') {
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy226;
+ if (yych <= '/') goto yy7;
+ goto yy222;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'C') goto yy365;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'r') {
+ if (yych <= 'Z') goto yy365;
+ if (yych <= '`') goto yy7;
+ goto yy367;
+ } else {
+ if (yych <= 's') goto yy390;
+ if (yych <= 'z') goto yy367;
+ goto yy7;
+ }
+ }
+yy426:
+ yych = *++p;
+ if (yych != 'x') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych != 'l') goto yy160;
+ yych = *++p;
+ if (yych == 's') goto yy221;
+ goto yy160;
+yy430:
+ yych = *++p;
+ if (yych == 'e') goto yy438;
+ goto yy160;
+yy431:
+ yych = *++p;
+ if (yych != 'l') goto yy160;
+ yych = *++p;
+ if (yych != 'l') goto yy160;
+ yych = *++p;
+ if (yych != 'L') goto yy160;
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'i') goto yy435;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy435:
+ yych = *++p;
+ if (yych != 's') goto yy160;
+ yych = *++p;
+ if (yych != 't') goto yy160;
+ yych = *++p;
+ if (yych <= 'Z') {
+ if (yych <= '@') goto yy223;
+ if (yych == 'D') goto yy225;
+ goto yy224;
+ } else {
+ if (yych <= 'r') {
+ if (yych <= '`') goto yy223;
+ goto yy159;
+ } else {
+ if (yych <= 's') goto yy221;
+ if (yych <= 'z') goto yy159;
+ goto yy223;
+ }
+ }
+yy438:
+ yych = *++p;
+ if (yych != 'a') goto yy160;
+ yych = *++p;
+ if (yych == 'r') goto yy221;
+ goto yy160;
+yy440:
+ yych = *++p;
+ if (yych == 'n') goto yy454;
+ goto yy160;
+yy441:
+ yych = *++p;
+ if (yych != 'i') goto yy160;
+ yych = *++p;
+ if (yych != 't') goto yy160;
+ yych = *++p;
+ if (yych != 'F') goto yy160;
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'r') goto yy445;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy445:
+ yych = *++p;
+ if (yych != 'a') goto yy160;
+ yych = *++p;
+ if (yych != 'm') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych != 'b') goto yy160;
+ yych = *++p;
+ if (yych != 'u') goto yy160;
+ yych = *++p;
+ if (yych != 'f') goto yy160;
+ yych = *++p;
+ if (yych != 'f') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych == 'r') goto yy221;
+ goto yy160;
+yy454:
+ yych = *++p;
+ if (yych != 'd') goto yy160;
+ yych = *++p;
+ if (yych != 'F') goto yy160;
+ yych = *++p;
+ if (yych <= '`') goto yy7;
+ if (yych == 'r') goto yy457;
+ if (yych <= 'z') goto yy159;
+ goto yy7;
+yy457:
+ yych = *++p;
+ if (yych != 'a') goto yy160;
+ yych = *++p;
+ if (yych != 'm') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych != 'b') goto yy160;
+ yych = *++p;
+ if (yych != 'u') goto yy160;
+ yych = *++p;
+ if (yych != 'f') goto yy160;
+ yych = *++p;
+ if (yych != 'f') goto yy160;
+ yych = *++p;
+ if (yych != 'e') goto yy160;
+ yych = *++p;
+ if (yych != 'r') goto yy160;
+ yych = *++p;
+ if (yych <= 'D') {
+ if (yych <= '@') goto yy468;
+ if (yych <= 'C') goto yy469;
+ goto yy470;
+ } else {
+ if (yych <= 'Z') goto yy469;
+ if (yych <= '`') goto yy468;
+ if (yych <= 'z') goto yy159;
+ goto yy468;
+ }
+yy467:
+ ++p;
+ yych = *p;
+yy468:
+ if (yych <= '9') {
+ if (yych <= 0x00) goto yy471;
+ if (yych <= '/') goto yy7;
+ goto yy467;
+ } else {
+ if (yych <= '@') goto yy7;
+ if (yych <= 'Z') goto yy467;
+ goto yy7;
+ }
+yy469:
+ yych = *++p;
+ if (yych <= '`') goto yy468;
+ if (yych <= 'z') goto yy159;
+ goto yy468;
+yy470:
+ yych = *++p;
+ if (yych <= '`') goto yy468;
+ if (yych == 'r') goto yy162;
+ if (yych <= 'z') goto yy159;
+ goto yy468;
+yy471:
+ ++p;
+ {
+ return CALL_FLAG_SWAP_RENDERTARGET;
+ }
+ }
+
}
diff --git a/common/trace_parser_flags.cpp.re b/common/trace_parser_flags.cpp.re
new file mode 100644
index 00000000..b3536c0c
--- /dev/null
+++ b/common/trace_parser_flags.cpp.re
@@ -0,0 +1,565 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/*
+ * Label functions based on their name.
+ *
+ * Compile with RE2C as
+ *
+ * re2c -is --no-generation-date trace_parser_flags.cpp.re > trace_parser_flags.cpp
+ *
+ * TODO: Use std::regex once GCC 4.9 becomes widely available -- https://github.com/apitrace/apitrace/issues/370
+ */
+
+
+#include "trace_parser.hpp"
+
+#include <assert.h>
+
+#include "trace_lookup.hpp"
+
+
+using namespace trace;
+
+
+/**
+ * Shortcut for SwapBuffers, which terminate and swap bound render buffer.
+ */
+#define CALL_FLAG_SWAPBUFFERS (CALL_FLAG_END_FRAME | CALL_FLAG_SWAP_RENDERTARGET)
+
+
+
+/**
+ * Default call flags.
+ */
+const CallFlags
+defaultCallFlags = 0;
+
+
+/**
+ * Call flags lookup table.
+ */
+const Entry<CallFlags>
+callFlagTable[] = {
+ { "CGLFlushDrawable", CALL_FLAG_END_FRAME },
+ { "CGLGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "D3DPERF_BeginEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "D3DPERF_EndEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP },
+ { "D3DPERF_SetMarker", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER },
+ { "ID3DUserDefinedAnnotation::BeginEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "ID3DUserDefinedAnnotation::EndEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP },
+ { "ID3DUserDefinedAnnotation::SetMarker", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER },
+ { "IDirect3D8::CheckDeviceFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D8::EnumAdapterModes", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D8::GetAdapterModeCount", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D8::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9::CheckDeviceFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9::EnumAdapterModes", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9::GetAdapterModeCount", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9Ex::CheckDeviceFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9Ex::EnumAdapterModes", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9Ex::GetAdapterModeCount", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9Ex::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3DDevice2::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice2::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawIndexedPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawIndexedPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawIndexedPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawIndexedPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawIndexedPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawRectPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawTriPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3DDevice8::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DDevice8::SetRenderTarget", CALL_FLAG_SWAP_RENDERTARGET },
+ { "IDirect3DDevice9::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawIndexedPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawRectPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawTriPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3DDevice9::GetRenderTargetData", CALL_FLAG_END_FRAME },
+ { "IDirect3DDevice9::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DDevice9::SetRenderTarget", CALL_FLAG_SWAP_RENDERTARGET },
+ { "IDirect3DDevice9Ex::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawIndexedPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawRectPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawTriPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3DDevice9Ex::GetRenderTargetData", CALL_FLAG_END_FRAME },
+ { "IDirect3DDevice9Ex::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DDevice9Ex::PresentEx", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DDevice9Ex::SetRenderTarget", CALL_FLAG_SWAP_RENDERTARGET },
+ { "IDirect3DSwapChain9::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DSwapChain9Ex::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DViewport2::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DViewport3::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DViewport3::Clear2", CALL_FLAG_RENDER },
+ { "IDirect3DViewport::Clear", CALL_FLAG_RENDER },
+ { "eglGetConfigAttrib", CALL_FLAG_VERBOSE },
+ { "eglGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "eglQueryString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "eglSwapBuffers", CALL_FLAG_SWAPBUFFERS },
+ { "glAreProgramsResidentNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glAreTexturesResident", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glAreTexturesResidentEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glBufferRegionEnabled", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glDebugMessageControl", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glDebugMessageControlARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glDebugMessageEnableAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glDebugMessageInsert", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glDebugMessageInsertAMD", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glDebugMessageInsertARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glDebugMessageInsertKHR", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glFrameTerminatorGREMEDY", CALL_FLAG_END_FRAME },
+ { "glGetActiveAtomicCounterBufferiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveAttrib", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveAttribARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveSubroutineName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveSubroutineUniformName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveSubroutineUniformiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniform", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformBlockName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformBlockiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformsiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveVaryingNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetArrayObjectfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetArrayObjectivATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetAttachedObjectsARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetAttachedShaders", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBooleanIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBooleani_v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBooleanv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferParameteri64v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferParameterivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferParameterui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferPointerv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferPointervARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferSubData", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferSubDataARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetClipPlane", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTable", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterfvSGI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterivSGI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableSGI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerInputParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerInputParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerOutputParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerOutputParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerStageParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionFilterEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetDetailTexFuncSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetDoubleIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetDoublei_v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetDoublev", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetError", CALL_FLAG_NO_SIDE_EFFECTS }, // verbose will be set later for GL_NO_ERROR
+ { "glGetFenceivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFinalCombinerInputParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFinalCombinerInputParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFogFuncSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragDataIndex", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragmentLightfvSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragmentLightivSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragmentMaterialfvSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragmentMaterialivSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFramebufferAttachmentParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFramebufferAttachmentParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFramebufferParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFramebufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetGraphicsResetStatusARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHandleARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetImageTransformParameterfvHP", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetImageTransformParameterivHP", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInfoLogARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInstrumentsSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInternalformati64v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInternalformativ", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInvariantBooleanvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInvariantFloatvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInvariantIntegervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLightfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLightiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetListParameterfvSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetListParameterivSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLocalConstantBooleanvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLocalConstantFloatvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLocalConstantIntegervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapAttribParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapAttribParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapControlPointsNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapdv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMaterialfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMaterialiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexEnvfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexEnvivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexGendvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexGenfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexGenivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexLevelParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexLevelParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexParameterIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexParameterIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultisamplefv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultisamplefvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedBufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedBufferParameterui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedBufferPointervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedBufferSubDataEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedFramebufferAttachmentParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedFramebufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramLocalParameterIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramLocalParameterIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramLocalParameterdvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramLocalParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramStringEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedRenderbufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedStringARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedStringivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectBufferfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectBufferivATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectParameterfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectParameterivAPPLE", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectParameterivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectPtrLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetOcclusionQueryivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetOcclusionQueryuivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorCounterDataAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorCounterInfoAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorCounterStringAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorCountersAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorGroupStringAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorGroupsAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPixelTexGenParameterfvSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPixelTexGenParameterivSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPointerIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPointerv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPointervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramBinary", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramEnvParameterIivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramEnvParameterIuivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramEnvParameterdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramEnvParameterfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramInfoLog", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramInterfaceiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramLocalParameterIivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramLocalParameterIuivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramLocalParameterdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramLocalParameterfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramNamedParameterdvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramNamedParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramParameterdvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramPipelineInfoLog", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramPipelineiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceIndex", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceLocation", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceLocationIndex", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramStageiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramStringARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramStringNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramSubroutineParameteruivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryIndexediv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjecti64v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjecti64vEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectui64v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectui64vEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectuivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetRenderbufferParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetRenderbufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSamplerParameterIiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSamplerParameterIuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSamplerParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSamplerParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSeparableFilterEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderInfoLog", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderPrecisionFormat", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderSource", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderSourceARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSharpenTexFuncSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glGetStringi", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glGetSynciv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexBumpParameterfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexBumpParameterivATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexEnvfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexEnviv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexFilterFuncSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexGendv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexGenfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexGeniv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTrackMatrixivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTransformFeedbackVarying", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTransformFeedbackVaryingEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTransformFeedbackVaryingNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformIndices", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformSubroutineuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformdv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformi64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantArrayObjectfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantArrayObjectivATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantBooleanvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantFloatvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantIntegervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantPointervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexArrayIntegeri_vEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexArrayIntegervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexArrayPointeri_vEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexArrayPointervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoCaptureStreamdvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoCaptureStreamfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoCaptureStreamivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoCaptureivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoi64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideouivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnMapdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnMapfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnMapivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnUniformdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnUniformfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnUniformivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnUniformuivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glInsertEventMarkerEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glIsAsyncMarkerSGIX", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsBuffer", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsBufferARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsBufferResidentNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsEnabled", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsEnabledIndexedEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsEnabledi", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsFenceAPPLE", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsFenceNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsFramebuffer", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsFramebufferEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsList", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsNameAMD", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsNamedBufferResidentNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsNamedStringARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsObjectBufferATI", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsOcclusionQueryNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsProgram", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsProgramARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsProgramNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsProgramPipeline", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsQuery", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsQueryARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsRenderbuffer", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsRenderbufferEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsSampler", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsShader", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsSync", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsTexture", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsTextureEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsTransformFeedback", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsTransformFeedbackNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsVariantEnabledEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsVertexArray", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsVertexArrayAPPLE", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsVertexAttribEnabledAPPLE", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glObjectLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glObjectLabelKHR", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glObjectPtrLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glObjectPtrLabelKHR", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glPopDebugGroup", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP},
+ { "glPopDebugGroupKHR", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP},
+ { "glPopGroupMarkerEXT", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP},
+ { "glPushDebugGroup", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "glPushDebugGroupKHR", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "glPushGroupMarkerEXT", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "glStringMarkerGREMEDY", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER },
+ { "glXGetClientString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetConfig", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentDisplay", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentDisplayEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentDrawable", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentReadDrawable", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentReadDrawableSGI", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetFBConfigAttrib", CALL_FLAG_VERBOSE },
+ { "glXGetFBConfigAttribSGIX", CALL_FLAG_VERBOSE },
+ { "glXGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetProcAddressARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXIsDirect", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXQueryExtension", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXQueryExtensionsString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXQueryVersion", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXSwapBuffers", CALL_FLAG_SWAPBUFFERS },
+ { "wglDescribePixelFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetCurrentDC", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetDefaultProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetExtensionsStringARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetExtensionsStringEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetPixelFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetPixelFormatAttribivARB", CALL_FLAG_VERBOSE },
+ { "wglGetPixelFormatAttribivEXT", CALL_FLAG_VERBOSE },
+ { "wglGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglSwapBuffers", CALL_FLAG_SWAPBUFFERS },
+ { "wglSwapLayerBuffers", CALL_FLAG_SWAPBUFFERS },
+ { "wglSwapMultipleBuffers", CALL_FLAG_SWAPBUFFERS },
+ // NOTE: New entries must be sorted alphabetically
+};
+
+
+/**
+ * Lookup call flags by name.
+ */
+CallFlags
+Parser::lookupCallFlags(const char *name)
+{
+ const char *p = name;
+ const char *q;
+
+ /*!re2c
+ re2c:define:YYCTYPE = "char";
+ re2c:define:YYCURSOR = p;
+ re2c:define:YYMARKER = q;
+ re2c:yyfill:enable = 0;
+ re2c:indent:string = " ";
+ re2c:indent:top = 1;
+
+ D = [0-9];
+ W = [_A-Z0-9a-z];
+ END = "\000";
+
+ "gl"([A-Z][a-z]+)*"Draw"("Range"|"Mesh")?("Arrays"|"Elements")([A-Z][a-zA-Z]*)? END {
+ return CALL_FLAG_RENDER;
+ }
+
+ "gl" (
+ "CallList" "s"? |
+ "Clear" |
+ "End" |
+ "DrawPixels" |
+ "DrawTransformFeedback" ([A-Z][a-zA-Z]*)? |
+ "BlitFramebuffer" |
+ "Rect" [dfis] "v"? |
+ "EvalMesh" [0-9]+
+ ) [0-9A-Z]* END {
+ return CALL_FLAG_RENDER;
+ }
+
+ "glBindFramebuffer" [0-9A-Z]* END {
+ return CALL_FLAG_SWAP_RENDERTARGET;
+ }
+
+ "gl" (
+ "GetFloat" |
+ "GetInteger" |
+ "GetVertexAttrib" |
+ "GetTex"("ture")?("Level")?"Parameter"
+ ) W* END {
+ return CALL_FLAG_NO_SIDE_EFFECTS;
+ }
+
+ "IDXGI" ("Decode")? "SwapChain" W* "::Present" W* END {
+ return CALL_FLAG_END_FRAME;
+ }
+
+ "ID3D1" ("0Device"|"1DeviceContext") D* "::" ("Draw" W* | "ExecuteCommandList") END {
+ return CALL_FLAG_RENDER;
+ }
+
+ "ID3D1" ("0Device"|"1DeviceContext") D* "::" "OMSetRenderTargets" W* END {
+ return CALL_FLAG_SWAP_RENDERTARGET;
+ }
+
+ "ID3D1" [01] "Device" D* "::CheckMultisampleQualityLevels" END {
+ return CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE;
+ }
+
+ [^] { return entryLookup(name, callFlagTable, defaultCallFlags); }
+ */
+}
diff --git a/common/trace_parser_flags_test.cpp b/common/trace_parser_flags_test.cpp
new file mode 100644
index 00000000..43135737
--- /dev/null
+++ b/common/trace_parser_flags_test.cpp
@@ -0,0 +1,652 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "trace_parser.hpp"
+
+#include "gtest/gtest.h"
+
+#include "trace_lookup.hpp"
+
+using namespace trace;
+
+
+/**
+ * Shortcut for SwapBuffers, which terminate and swap bound render buffer.
+ */
+#define CALL_FLAG_SWAPBUFFERS (CALL_FLAG_END_FRAME | CALL_FLAG_SWAP_RENDERTARGET)
+
+
+
+/**
+ * Call flags lookup table.
+ */
+static const Entry<CallFlags>
+entries[] = {
+ { "CGLFlushDrawable", CALL_FLAG_END_FRAME },
+ { "CGLGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "D3DPERF_BeginEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "D3DPERF_EndEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP },
+ { "D3DPERF_SetMarker", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER },
+ { "ID3D10Device1::CheckMultisampleQualityLevels", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "ID3D10Device1::Draw", CALL_FLAG_RENDER },
+ { "ID3D10Device1::DrawAuto", CALL_FLAG_RENDER },
+ { "ID3D10Device1::DrawIndexed", CALL_FLAG_RENDER },
+ { "ID3D10Device1::DrawIndexedInstanced", CALL_FLAG_RENDER },
+ { "ID3D10Device1::DrawInstanced", CALL_FLAG_RENDER },
+ { "ID3D10Device1::OMSetRenderTargets", CALL_FLAG_SWAP_RENDERTARGET },
+ { "ID3D10Device::CheckMultisampleQualityLevels", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "ID3D10Device::Draw", CALL_FLAG_RENDER },
+ { "ID3D10Device::DrawAuto", CALL_FLAG_RENDER },
+ { "ID3D10Device::DrawIndexed", CALL_FLAG_RENDER },
+ { "ID3D10Device::DrawIndexedInstanced", CALL_FLAG_RENDER },
+ { "ID3D10Device::DrawInstanced", CALL_FLAG_RENDER },
+ { "ID3D10Device::OMSetRenderTargets", CALL_FLAG_SWAP_RENDERTARGET },
+ { "ID3D11Device::CheckMultisampleQualityLevels", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "ID3D11DeviceContext1::Draw", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext1::DrawAuto", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext1::DrawIndexed", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext1::DrawIndexedInstanced", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext1::DrawIndexedInstancedIndirect", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext1::DrawInstanced", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext1::DrawInstancedIndirect", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext1::ExecuteCommandList", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext1::OMSetRenderTargets", CALL_FLAG_SWAP_RENDERTARGET },
+ { "ID3D11DeviceContext1::OMSetRenderTargetsAndUnorderedAccessViews", CALL_FLAG_SWAP_RENDERTARGET },
+ { "ID3D11DeviceContext::Draw", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext::DrawAuto", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext::DrawIndexed", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext::DrawIndexedInstanced", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext::DrawIndexedInstancedIndirect", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext::DrawInstanced", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext::DrawInstancedIndirect", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext::ExecuteCommandList", CALL_FLAG_RENDER },
+ { "ID3D11DeviceContext::OMSetRenderTargets", CALL_FLAG_SWAP_RENDERTARGET },
+ { "ID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews", CALL_FLAG_SWAP_RENDERTARGET },
+ { "ID3DUserDefinedAnnotation::BeginEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "ID3DUserDefinedAnnotation::EndEvent", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP },
+ { "ID3DUserDefinedAnnotation::SetMarker", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER },
+ { "IDXGIDecodeSwapChain::PresentBuffer", CALL_FLAG_END_FRAME /* CALL_FLAG_SWAPBUFFERS */ },
+ { "IDXGISwapChain1::Present", CALL_FLAG_END_FRAME /* CALL_FLAG_SWAPBUFFERS */ },
+ { "IDXGISwapChain1::Present1", CALL_FLAG_END_FRAME /* CALL_FLAG_SWAPBUFFERS */ },
+ { "IDXGISwapChain2::Present", CALL_FLAG_END_FRAME /* CALL_FLAG_SWAPBUFFERS */ },
+ { "IDXGISwapChain2::Present1", CALL_FLAG_END_FRAME /* CALL_FLAG_SWAPBUFFERS */ },
+ { "IDXGISwapChain::Present", CALL_FLAG_END_FRAME /* CALL_FLAG_SWAPBUFFERS */ },
+ { "IDXGISwapChainDWM::Present", CALL_FLAG_END_FRAME /* CALL_FLAG_SWAPBUFFERS */ },
+ { "IDirect3D8::CheckDeviceFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D8::EnumAdapterModes", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D8::GetAdapterModeCount", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D8::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9::CheckDeviceFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9::EnumAdapterModes", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9::GetAdapterModeCount", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9Ex::CheckDeviceFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9Ex::EnumAdapterModes", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9Ex::GetAdapterModeCount", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3D9Ex::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3DDevice2::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice2::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawIndexedPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawIndexedPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice3::DrawPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawIndexedPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawIndexedPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawPrimitiveStrided", CALL_FLAG_RENDER },
+ { "IDirect3DDevice7::DrawPrimitiveVB", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawIndexedPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawRectPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::DrawTriPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice8::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3DDevice8::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DDevice8::SetRenderTarget", CALL_FLAG_SWAP_RENDERTARGET },
+ { "IDirect3DDevice9::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawIndexedPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawRectPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::DrawTriPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3DDevice9::GetRenderTargetData", CALL_FLAG_END_FRAME },
+ { "IDirect3DDevice9::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DDevice9::SetRenderTarget", CALL_FLAG_SWAP_RENDERTARGET },
+ { "IDirect3DDevice9Ex::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawIndexedPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawIndexedPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawPrimitive", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawPrimitiveUP", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawRectPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::DrawTriPatch", CALL_FLAG_RENDER },
+ { "IDirect3DDevice9Ex::GetDeviceCaps", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "IDirect3DDevice9Ex::GetRenderTargetData", CALL_FLAG_END_FRAME },
+ { "IDirect3DDevice9Ex::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DDevice9Ex::PresentEx", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DDevice9Ex::SetRenderTarget", CALL_FLAG_SWAP_RENDERTARGET },
+ { "IDirect3DSwapChain9::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DSwapChain9Ex::Present", CALL_FLAG_SWAPBUFFERS },
+ { "IDirect3DViewport2::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DViewport3::Clear", CALL_FLAG_RENDER },
+ { "IDirect3DViewport3::Clear2", CALL_FLAG_RENDER },
+ { "IDirect3DViewport::Clear", CALL_FLAG_RENDER },
+ { "eglGetConfigAttrib", CALL_FLAG_VERBOSE },
+ { "eglGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "eglQueryString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "eglSwapBuffers", CALL_FLAG_SWAPBUFFERS },
+ { "glAreProgramsResidentNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glAreTexturesResident", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glAreTexturesResidentEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glBindFramebuffer", CALL_FLAG_SWAP_RENDERTARGET },
+ { "glBindFramebufferEXT", CALL_FLAG_SWAP_RENDERTARGET },
+ { "glBindFramebufferOES", CALL_FLAG_SWAP_RENDERTARGET },
+ { "glBlitFramebuffer", CALL_FLAG_RENDER },
+ { "glBlitFramebufferANGLE", CALL_FLAG_RENDER },
+ { "glBlitFramebufferEXT", CALL_FLAG_RENDER },
+ { "glBlitFramebufferNV", CALL_FLAG_RENDER },
+ { "glBufferRegionEnabled", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glCallList", CALL_FLAG_RENDER },
+ { "glCallLists", CALL_FLAG_RENDER },
+ { "glClear", CALL_FLAG_RENDER },
+ { "glDebugMessageControl", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glDebugMessageControlARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glDebugMessageEnableAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glDebugMessageInsert", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glDebugMessageInsertAMD", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glDebugMessageInsertARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glDebugMessageInsertKHR", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glDrawArrays", CALL_FLAG_RENDER },
+ { "glDrawArraysEXT", CALL_FLAG_RENDER },
+ { "glDrawArraysIndirect", CALL_FLAG_RENDER },
+ { "glDrawArraysInstanced", CALL_FLAG_RENDER },
+ { "glDrawArraysInstancedANGLE", CALL_FLAG_RENDER },
+ { "glDrawArraysInstancedARB", CALL_FLAG_RENDER },
+ { "glDrawArraysInstancedBaseInstance", CALL_FLAG_RENDER },
+ { "glDrawArraysInstancedEXT", CALL_FLAG_RENDER },
+ { "glDrawElements", CALL_FLAG_RENDER },
+ { "glDrawElementsBaseVertex", CALL_FLAG_RENDER },
+ { "glDrawElementsIndirect", CALL_FLAG_RENDER },
+ { "glDrawElementsInstanced", CALL_FLAG_RENDER },
+ { "glDrawElementsInstancedANGLE", CALL_FLAG_RENDER },
+ { "glDrawElementsInstancedARB", CALL_FLAG_RENDER },
+ { "glDrawElementsInstancedBaseInstance", CALL_FLAG_RENDER },
+ { "glDrawElementsInstancedBaseVertex", CALL_FLAG_RENDER },
+ { "glDrawElementsInstancedBaseVertexBaseInstance", CALL_FLAG_RENDER },
+ { "glDrawElementsInstancedEXT", CALL_FLAG_RENDER },
+ { "glDrawMeshArraysSUN", CALL_FLAG_RENDER },
+ { "glDrawPixels", CALL_FLAG_RENDER },
+ { "glDrawRangeElementArrayAPPLE", 0 },
+ { "glDrawRangeElementArrayATI", 0 },
+ { "glDrawRangeElements", CALL_FLAG_RENDER },
+ { "glDrawRangeElementsBaseVertex", CALL_FLAG_RENDER },
+ { "glDrawRangeElementsEXT", CALL_FLAG_RENDER },
+ { "glDrawTransformFeedback", CALL_FLAG_RENDER },
+ { "glDrawTransformFeedbackInstanced", CALL_FLAG_RENDER },
+ { "glDrawTransformFeedbackNV", CALL_FLAG_RENDER },
+ { "glDrawTransformFeedbackStream", CALL_FLAG_RENDER },
+ { "glDrawTransformFeedbackStreamInstanced", CALL_FLAG_RENDER },
+ { "glEnd", CALL_FLAG_RENDER },
+ { "glEvalMesh1", CALL_FLAG_RENDER },
+ { "glEvalMesh2", CALL_FLAG_RENDER },
+ { "glFrameTerminatorGREMEDY", CALL_FLAG_END_FRAME },
+ { "glGetActiveAtomicCounterBufferiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveAttrib", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveAttribARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveSubroutineName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveSubroutineUniformName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveSubroutineUniformiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniform", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformBlockName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformBlockiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveUniformsiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetActiveVaryingNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetArrayObjectfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetArrayObjectivATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetAttachedObjectsARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetAttachedShaders", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBooleanIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBooleani_v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBooleanv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferParameteri64v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferParameterivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferParameterui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferPointerv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferPointervARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferSubData", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetBufferSubDataARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetClipPlane", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTable", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterfvSGI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableParameterivSGI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetColorTableSGI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerInputParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerInputParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerOutputParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerOutputParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetCombinerStageParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionFilterEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetConvolutionParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetDetailTexFuncSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetDoubleIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetDoublei_v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetDoublev", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetError", CALL_FLAG_NO_SIDE_EFFECTS }, // verbose will be set later for GL_NO_ERROR
+ { "glGetFenceivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFinalCombinerInputParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFinalCombinerInputParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFloatIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFloati_v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFloatv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFogFuncSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragDataIndex", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragmentLightfvSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragmentLightivSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragmentMaterialfvSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFragmentMaterialivSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFramebufferAttachmentParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFramebufferAttachmentParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFramebufferParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetFramebufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetGraphicsResetStatusARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHandleARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetHistogramParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetImageTransformParameterfvHP", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetImageTransformParameterivHP", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInfoLogARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInstrumentsSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInteger64i_v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInteger64v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetIntegerIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetIntegeri_v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetIntegerui64i_vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetIntegerui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetIntegerv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInternalformati64v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInternalformativ", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInvariantBooleanvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInvariantFloatvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetInvariantIntegervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLightfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLightiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetListParameterfvSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetListParameterivSGIX", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLocalConstantBooleanvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLocalConstantFloatvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetLocalConstantIntegervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapAttribParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapAttribParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapControlPointsNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapParameterivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapdv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMapiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMaterialfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMaterialiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMinmaxParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexEnvfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexEnvivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexGendvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexGenfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexGenivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexLevelParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexLevelParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexParameterIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexParameterIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultiTexParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultisamplefv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetMultisamplefvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedBufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedBufferParameterui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedBufferPointervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedBufferSubDataEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedFramebufferAttachmentParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedFramebufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramLocalParameterIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramLocalParameterIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramLocalParameterdvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramLocalParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramStringEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedProgramivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedRenderbufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedStringARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetNamedStringivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectBufferfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectBufferivATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectParameterfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectParameterivAPPLE", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectParameterivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetObjectPtrLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetOcclusionQueryivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetOcclusionQueryuivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorCounterDataAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorCounterInfoAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorCounterStringAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorCountersAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorGroupStringAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPerfMonitorGroupsAMD", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPixelTexGenParameterfvSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPixelTexGenParameterivSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPointerIndexedvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPointerv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetPointervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramBinary", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramEnvParameterIivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramEnvParameterIuivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramEnvParameterdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramEnvParameterfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramInfoLog", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramInterfaceiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramLocalParameterIivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramLocalParameterIuivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramLocalParameterdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramLocalParameterfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramNamedParameterdvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramNamedParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramParameterdvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramParameterfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramPipelineInfoLog", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramPipelineiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceIndex", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceLocation", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceLocationIndex", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceName", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramResourceiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramStageiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramStringARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramStringNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramSubroutineParameteruivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetProgramivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryIndexediv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjecti64v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjecti64vEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectui64v", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectui64vEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryObjectuivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetQueryivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetRenderbufferParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetRenderbufferParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSamplerParameterIiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSamplerParameterIuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSamplerParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSamplerParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSeparableFilterEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderInfoLog", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderPrecisionFormat", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderSource", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderSourceARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetShaderiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetSharpenTexFuncSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glGetStringi", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glGetSynciv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexBumpParameterfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexBumpParameterivATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexEnvfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexEnviv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexFilterFuncSGIS", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexGendv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexGenfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexGeniv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexLevelParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexLevelParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexParameterIiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexParameterIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexParameterIuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexParameterIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexParameterPointervAPPLE", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexParameterfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTexParameteriv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTextureLevelParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTextureLevelParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTextureParameterIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTextureParameterIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTextureParameterfvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTextureParameterivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTrackMatrixivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTransformFeedbackVarying", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTransformFeedbackVaryingEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetTransformFeedbackVaryingNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformIndices", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformSubroutineuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformdv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformi64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetUniformuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantArrayObjectfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantArrayObjectivATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantBooleanvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantFloatvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantIntegervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVariantPointervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexArrayIntegeri_vEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexArrayIntegervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexArrayPointeri_vEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexArrayPointervEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribArrayObjectfvATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribArrayObjectivATI", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribIiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribIivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribIuiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribIuivEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribLdv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribLdvEXT", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribLi64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribLui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribPointerv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribPointervARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribPointervNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribdv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribdvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribfv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribiv", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVertexAttribivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoCaptureStreamdvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoCaptureStreamfvNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoCaptureStreamivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoCaptureivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoi64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideoui64vNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetVideouivNV", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnMapdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnMapfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnMapivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnUniformdvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnUniformfvARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnUniformivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glGetnUniformuivARB", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glInsertEventMarkerEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_MARKER },
+ { "glIsAsyncMarkerSGIX", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsBuffer", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsBufferARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsBufferResidentNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsEnabled", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsEnabledIndexedEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsEnabledi", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsFenceAPPLE", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsFenceNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsFramebuffer", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsFramebufferEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsList", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsNameAMD", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsNamedBufferResidentNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsNamedStringARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsObjectBufferATI", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsOcclusionQueryNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsProgram", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsProgramARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsProgramNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsProgramPipeline", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsQuery", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsQueryARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsRenderbuffer", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsRenderbufferEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsSampler", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsShader", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsSync", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsTexture", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsTextureEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsTransformFeedback", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsTransformFeedbackNV", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsVariantEnabledEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsVertexArray", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsVertexArrayAPPLE", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glIsVertexAttribEnabledAPPLE", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glMultiDrawArrays", CALL_FLAG_RENDER },
+ { "glMultiDrawArraysEXT", CALL_FLAG_RENDER },
+ { "glMultiDrawArraysIndirect", CALL_FLAG_RENDER },
+ { "glMultiDrawArraysIndirectAMD", CALL_FLAG_RENDER },
+ { "glMultiDrawArraysIndirectBindlessNV", CALL_FLAG_RENDER },
+ { "glMultiDrawArraysIndirectCountARB", CALL_FLAG_RENDER },
+ { "glMultiDrawElementArrayAPPLE", 0 },
+ { "glMultiDrawElements", CALL_FLAG_RENDER },
+ { "glMultiDrawElementsBaseVertex", CALL_FLAG_RENDER },
+ { "glMultiDrawElementsEXT", CALL_FLAG_RENDER },
+ { "glMultiDrawElementsIndirect", CALL_FLAG_RENDER },
+ { "glMultiDrawElementsIndirectAMD", CALL_FLAG_RENDER },
+ { "glMultiDrawElementsIndirectBindlessNV", CALL_FLAG_RENDER },
+ { "glMultiDrawElementsIndirectCountARB", CALL_FLAG_RENDER },
+ { "glMultiDrawRangeElementArrayAPPLE", 0 },
+ { "glMultiModeDrawArraysIBM", CALL_FLAG_RENDER },
+ { "glMultiModeDrawElementsIBM", CALL_FLAG_RENDER },
+ { "glObjectLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glObjectLabelKHR", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glObjectPtrLabel", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glObjectPtrLabelKHR", CALL_FLAG_NO_SIDE_EFFECTS },
+ { "glPopDebugGroup", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP},
+ { "glPopDebugGroupKHR", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP},
+ { "glPopGroupMarkerEXT", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP},
+ { "glPushDebugGroup", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "glPushDebugGroupKHR", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "glPushGroupMarkerEXT", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH },
+ { "glRectd", CALL_FLAG_RENDER },
+ { "glRectdv", CALL_FLAG_RENDER },
+ { "glRectf", CALL_FLAG_RENDER },
+ { "glRectfv", CALL_FLAG_RENDER },
+ { "glRecti", CALL_FLAG_RENDER },
+ { "glRectiv", CALL_FLAG_RENDER },
+ { "glRects", CALL_FLAG_RENDER },
+ { "glRectsv", CALL_FLAG_RENDER },
+ { "glStringMarkerGREMEDY", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER },
+ { "glXGetClientString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetConfig", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentDisplay", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentDisplayEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentDrawable", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentReadDrawable", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetCurrentReadDrawableSGI", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetFBConfigAttrib", CALL_FLAG_VERBOSE },
+ { "glXGetFBConfigAttribSGIX", CALL_FLAG_VERBOSE },
+ { "glXGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXGetProcAddressARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXIsDirect", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXQueryExtension", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXQueryExtensionsString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXQueryVersion", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "glXSwapBuffers", CALL_FLAG_SWAPBUFFERS },
+ { "wglDescribePixelFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetCurrentDC", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetDefaultProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetExtensionsStringARB", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetExtensionsStringEXT", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetPixelFormat", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglGetPixelFormatAttribivARB", CALL_FLAG_VERBOSE },
+ { "wglGetPixelFormatAttribivEXT", CALL_FLAG_VERBOSE },
+ { "wglGetProcAddress", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+ { "wglSwapBuffers", CALL_FLAG_SWAPBUFFERS },
+ { "wglSwapLayerBuffers", CALL_FLAG_SWAPBUFFERS },
+ { "wglSwapMultipleBuffers", CALL_FLAG_SWAPBUFFERS },
+};
+
+
+TEST(common_parser, lookupCallFlags)
+{
+ typedef const Entry<CallFlags> * ConstIterator;
+
+ ConstIterator first = &entries[0];
+ ConstIterator last = &entries[sizeof entries / sizeof entries[0]];
+
+ for (ConstIterator it = first; it != last; ++it) {
+ CallFlags flags = Parser::lookupCallFlags(it->name);
+
+ EXPECT_EQ(flags, it->value) << "flags differ for " << it->name;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/common/trace_parser_loop.cpp b/common/trace_parser_loop.cpp
new file mode 100644
index 00000000..45772210
--- /dev/null
+++ b/common/trace_parser_loop.cpp
@@ -0,0 +1,111 @@
+/**************************************************************************
+ *
+ * Copyright 2014 LunarG, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "trace_parser.hpp"
+
+
+namespace trace {
+
+
+// Decorator for parser which loops
+class LastFrameLoopParser : public AbstractParser {
+public:
+ LastFrameLoopParser(AbstractParser *p, int c) {
+ parser = p;
+ loopCount = c;
+ }
+
+ ~LastFrameLoopParser() {
+ delete parser;
+ }
+
+ Call *parse_call(void);
+
+ // Delegate to Parser
+ void getBookmark(ParseBookmark &bookmark) { parser->getBookmark(bookmark); }
+ void setBookmark(const ParseBookmark &bookmark) { parser->setBookmark(bookmark); }
+ bool open(const char *filename);
+ void close(void) { parser->close(); }
+ unsigned long long getVersion(void) const { return parser->getVersion(); }
+private:
+ int loopCount;
+ AbstractParser *parser;
+ ParseBookmark frameStart;
+ ParseBookmark lastFrameStart;
+};
+
+
+bool
+LastFrameLoopParser::open(const char *filename)
+{
+ bool ret = parser->open(filename);
+ if (ret) {
+ /* If the user wants to loop we need to get a bookmark target. We
+ * usually get this after replaying a call that ends a frame, but
+ * for a trace that has only one frame we need to get it at the
+ * beginning. */
+ parser->getBookmark(frameStart);
+ lastFrameStart = frameStart;
+ }
+ return ret;
+}
+
+Call *
+LastFrameLoopParser::parse_call(void)
+{
+ trace::Call *call;
+
+ call = parser->parse_call();
+
+ /* Restart last frame when looping is requested. */
+ if (call) {
+ lastFrameStart = frameStart;
+ if (call->flags & trace::CALL_FLAG_END_FRAME) {
+ parser->getBookmark(frameStart);
+ }
+ } else {
+ if (loopCount) {
+ frameStart = lastFrameStart;
+ parser->setBookmark(frameStart);
+ call = parser->parse_call();
+ if (loopCount > 0) {
+ --loopCount;
+ }
+ }
+ }
+
+ return call;
+}
+
+
+AbstractParser *
+lastFrameLoopParser(AbstractParser *parser, int loopCount)
+{
+ return new LastFrameLoopParser(parser, loopCount);
+}
+
+
+} /* namespace trace */
diff --git a/common/trace_profiler.cpp b/common/trace_profiler.cpp
index b7653409..65c91aad 100644
--- a/common/trace_profiler.cpp
+++ b/common/trace_profiler.cpp
@@ -116,7 +116,6 @@ void Profiler::addCall(unsigned no,
gpuStart -= baseGpuTime;
} else {
gpuStart = 0;
- gpuDuration = 0;
}
if (cpuTimes && cpuStart) {
diff --git a/common/trace_profiler.hpp b/common/trace_profiler.hpp
index e3ae016b..ebe28b46 100644
--- a/common/trace_profiler.hpp
+++ b/common/trace_profiler.hpp
@@ -24,8 +24,7 @@
*
**************************************************************************/
-#ifndef TRACE_PROFILER_H
-#define TRACE_PROFILER_H
+#pragma once
#include <string>
#include <vector>
@@ -142,4 +141,3 @@ private:
};
}
-#endif // TRACE_PROFILER_H
diff --git a/common/trace_snappy.hpp b/common/trace_snappy.hpp
new file mode 100644
index 00000000..57d47a8d
--- /dev/null
+++ b/common/trace_snappy.hpp
@@ -0,0 +1,61 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * Copyright 2011 Zack Rusin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/*
+ * Snappy file format.
+ * -------------------
+ *
+ * Snappy at its core is just a compressoin algorithm so we're
+ * creating a new file format which uses snappy compression
+ * to hold the trace data.
+ *
+ * The file is composed of a number of chunks, they are:
+ * chunk {
+ * uint32 - specifying the length of the compressed data
+ * compressed data, in little endian
+ * }
+ * File can contain any number of such chunks.
+ * The default size of an uncompressed chunk is specified in
+ * SNAPPY_CHUNK_SIZE.
+ *
+ * Note:
+ * Currently the default size for a a to-be-compressed data is
+ * 1mb, meaning that the compressed data will be <= 1mb.
+ * The reason it's 1mb is because it seems
+ * to offer a pretty good compression/disk io speed ratio
+ * but that might change.
+ *
+ */
+
+
+#pragma once
+
+
+#define SNAPPY_BYTE1 'a'
+#define SNAPPY_BYTE2 't'
+
+
diff --git a/common/trace_writer.cpp b/common/trace_writer.cpp
index e7e3df21..3ad06e4f 100644
--- a/common/trace_writer.cpp
+++ b/common/trace_writer.cpp
@@ -29,10 +29,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include <vector>
#include "os.hpp"
-#include "trace_file.hpp"
+#include "trace_ostream.hpp"
#include "trace_writer.hpp"
#include "trace_format.hpp"
@@ -42,27 +43,26 @@ namespace trace {
Writer::Writer() :
call_no(0)
{
- m_file = File::createSnappy();
- close();
+ m_file = nullptr;
}
Writer::~Writer()
{
close();
- delete m_file;
- m_file = NULL;
}
void
Writer::close(void) {
- m_file->close();
+ delete m_file;
+ m_file = nullptr;
}
bool
Writer::open(const char *filename) {
close();
- if (!m_file->open(filename, File::Write)) {
+ m_file = createSnappyStream(filename);
+ if (!m_file) {
return false;
}
@@ -109,13 +109,13 @@ Writer::_writeUInt(unsigned long long value) {
void inline
Writer::_writeFloat(float value) {
- assert(sizeof value == 4);
+ static_assert(sizeof value == 4, "float is not 4 bytes");
_write((const char *)&value, sizeof value);
}
void inline
Writer::_writeDouble(double value) {
- assert(sizeof value == 8);
+ static_assert(sizeof value == 8, "double is not 8 bytes");
_write((const char *)&value, sizeof value);
}
@@ -278,13 +278,37 @@ void Writer::writeString(const char *str, size_t len) {
_write(str, len);
}
-void Writer::writeWString(const wchar_t *str) {
+void Writer::writeWString(const wchar_t *str, size_t len) {
if (!str) {
Writer::writeNull();
return;
}
+ /* XXX: Encode wide-strings as ASCII for now, to avoid introducing a trace format version bump. */
+#if 0
+ _writeByte(trace::TYPE_WSTRING);
+ size_t len = wcslen(str);
+ _writeUInt(len);
+ for (size_t i = 0; i < len; ++i) {
+ _writeUInt(str[i]);
+ }
+#else
_writeByte(trace::TYPE_STRING);
- _writeString("<wide-string>");
+ _writeUInt(len);
+ for (size_t i = 0; i < len; ++i) {
+ wchar_t wc = str[i];
+ char c = wc >= 0 && wc < 0x80 ? (char)wc : '?';
+ _writeByte(c);
+ }
+#endif
+}
+
+void Writer::writeWString(const wchar_t *str) {
+ if (!str) {
+ Writer::writeNull();
+ return;
+ }
+ size_t len = wcslen(str);
+ writeWString(str, len);
}
void Writer::writeBlob(const void *data, size_t size) {
diff --git a/common/trace_writer.hpp b/common/trace_writer.hpp
index 4c954778..e293a938 100644
--- a/common/trace_writer.hpp
+++ b/common/trace_writer.hpp
@@ -27,8 +27,7 @@
* Trace writing functions.
*/
-#ifndef _TRACE_WRITER_HPP_
-#define _TRACE_WRITER_HPP_
+#pragma once
#include <stddef.h>
@@ -38,11 +37,11 @@
#include "trace_model.hpp"
namespace trace {
- class File;
+ class OutStream;
class Writer {
protected:
- File *m_file;
+ OutStream *m_file;
unsigned call_no;
std::vector<bool> functions;
@@ -94,6 +93,7 @@ namespace trace {
void writeString(const char *str);
void writeString(const char *str, size_t size);
void writeWString(const wchar_t *str);
+ void writeWString(const wchar_t *str, size_t size);
void writeBlob(const void *data, size_t size);
void writeEnum(const EnumSig *sig, signed long long value);
void writeBitmask(const BitmaskSig *sig, unsigned long long value);
@@ -114,4 +114,3 @@ namespace trace {
} /* namespace trace */
-#endif /* _TRACE_WRITER_HPP_ */
diff --git a/common/trace_writer_local.cpp b/common/trace_writer_local.cpp
index 72f636aa..a30c4d74 100644
--- a/common/trace_writer_local.cpp
+++ b/common/trace_writer_local.cpp
@@ -39,7 +39,8 @@
#include "os_thread.hpp"
#include "os_string.hpp"
#include "range.hpp"
-#include "trace_file.hpp"
+#include "os_version.hpp"
+#include "trace_ostream.hpp"
#include "trace_writer_local.hpp"
#include "trace_format.hpp"
#include "os_backtrace.hpp"
@@ -70,7 +71,8 @@ static void exceptionCallback(void)
LocalWriter::LocalWriter() :
acquired(0)
{
- os::log("apitrace: loaded\n");
+ os::String process = os::getProcessName();
+ os::log("apitrace: loaded into %s\n", process.str());
// Install the signal handlers as early as possible, to prevent
// interfering with the application's signal handling.
@@ -81,6 +83,9 @@ LocalWriter::~LocalWriter()
{
os::resetExceptionCallback();
checkProcessId();
+
+ os::String process = os::getProcessName();
+ os::log("apitrace: unloaded from %s\n", process.str());
}
void
@@ -100,10 +105,22 @@ LocalWriter::open(void) {
process.trimDirectory();
#ifdef ANDROID
- os::String prefix = "/data/data";
- prefix.join(process);
+ os::String prefix = "/data/data";
+ prefix.join(process);
#else
- os::String prefix = os::getCurrentDir();
+ os::String prefix = os::getCurrentDir();
+#ifdef _WIN32
+ // Avoid writing into Windows' system directory as quite often access
+ // will be denied.
+ if (IsWindows8OrGreater()) {
+ char szDirectory[MAX_PATH + 1];
+ GetSystemDirectoryA(szDirectory, sizeof szDirectory);
+ if (stricmp(prefix, szDirectory) == 0) {
+ GetTempPathA(sizeof szDirectory, szDirectory);
+ prefix = szDirectory;
+ }
+ }
+#endif
#endif
prefix.join(process);
@@ -147,13 +164,13 @@ static OS_THREAD_SPECIFIC(uintptr_t)
thread_num;
void LocalWriter::checkProcessId(void) {
- if (m_file->isOpened() &&
+ if (m_file &&
os::getCurrentProcessId() != pid) {
// We are a forked child process that inherited the trace file, so
// create a new file. We can't call any method of the current
// file, as it may cause it to flush and corrupt the parent's
// trace, so we effectively leak the old file object.
- m_file = File::createSnappy();
+ close();
// Don't want to open the same file again
os::unsetEnvironment("TRACE_FILE");
open();
@@ -165,7 +182,7 @@ unsigned LocalWriter::beginEnter(const FunctionSig *sig, bool fake) {
++acquired;
checkProcessId();
- if (!m_file->isOpened()) {
+ if (!m_file) {
open();
}
@@ -219,7 +236,7 @@ void LocalWriter::flush(void) {
os::log("apitrace: ignoring exception while tracing\n");
} else {
++acquired;
- if (m_file->isOpened()) {
+ if (m_file) {
if (os::getCurrentProcessId() != pid) {
os::log("apitrace: ignoring exception in child process\n");
} else {
@@ -422,5 +439,41 @@ void LocalWriter::updateRegion(const void *ptr, size_t size) {
LocalWriter localWriter;
+void fakeMemcpy(const void *ptr, size_t size) {
+ assert(ptr);
+ if (!size) {
+ return;
+ }
+
+ unsigned _call = localWriter.beginEnter(&memcpy_sig, true);
+
+#if defined(_WIN32) && !defined(NDEBUG)
+ size_t maxSize = 0;
+ MEMORY_BASIC_INFORMATION mi;
+ while (VirtualQuery((const uint8_t *)ptr + maxSize, &mi, sizeof mi) == sizeof mi &&
+ mi.Protect & (PAGE_READONLY|PAGE_READWRITE)) {
+ maxSize = (const uint8_t *)mi.BaseAddress + mi.RegionSize - (const uint8_t *)ptr;
+ }
+ if (maxSize < size) {
+ os::log("apitrace: warning: %u: clamping size from %Iu to %Iu\n", _call, size, maxSize);
+ size = maxSize;
+ }
+#endif
+
+ localWriter.beginArg(0);
+ localWriter.writePointer((uintptr_t)ptr);
+ localWriter.endArg();
+ localWriter.beginArg(1);
+ localWriter.writeBlob(ptr, size);
+ localWriter.endArg();
+ localWriter.beginArg(2);
+ localWriter.writeUInt(size);
+ localWriter.endArg();
+ localWriter.endEnter();
+ localWriter.beginLeave(_call);
+ localWriter.endLeave();
+}
+
+
} /* namespace trace */
diff --git a/common/trace_writer_local.hpp b/common/trace_writer_local.hpp
index e2fbb982..cb4c7437 100644
--- a/common/trace_writer_local.hpp
+++ b/common/trace_writer_local.hpp
@@ -27,8 +27,7 @@
* Trace writing functions, used to trace calls in the current process.
*/
-#ifndef _TRACE_WRITER_LOCAL_HPP_
-#define _TRACE_WRITER_LOCAL_HPP_
+#pragma once
#include <stdint.h>
@@ -118,6 +117,7 @@ namespace trace {
*/
extern LocalWriter localWriter;
+ void fakeMemcpy(const void *ptr, size_t size);
+
} /* namespace trace */
-#endif /* _TRACE_WRITER_LOCAL_HPP_ */
diff --git a/common/trace_writer_model.cpp b/common/trace_writer_model.cpp
index 4cf82f65..af5a2b0c 100644
--- a/common/trace_writer_model.cpp
+++ b/common/trace_writer_model.cpp
@@ -68,6 +68,10 @@ public:
writer.writeString(node->value);
}
+ void visit(WString *node) {
+ writer.writeWString(node->value);
+ }
+
void visit(Enum *node) {
writer.writeEnum(node->sig, node->value);
}
diff --git a/common/ubjson.hpp b/common/ubjson.hpp
new file mode 100644
index 00000000..04c8b08a
--- /dev/null
+++ b/common/ubjson.hpp
@@ -0,0 +1,111 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+
+#include <stdint.h>
+#include <stdlib.h>
+
+
+namespace ubjson {
+
+
+// http://ubjson.org/type-reference/
+enum Marker {
+ MARKER_EOF = -1,
+ MARKER_NULL = 'Z',
+ MARKER_NOOP = 'N',
+ MARKER_TRUE = 'T',
+ MARKER_FALSE = 'F',
+ MARKER_INT8 = 'i',
+ MARKER_UINT8 = 'U',
+ MARKER_INT16 = 'I',
+ MARKER_INT32 = 'l',
+ MARKER_INT64 = 'L',
+ MARKER_FLOAT32 = 'd',
+ MARKER_FLOAT64 = 'D',
+ MARKER_HIGH_PRECISION = 'H',
+ MARKER_CHAR = 'C',
+ MARKER_STRING = 'S',
+ MARKER_ARRAY_BEGIN = '[',
+ MARKER_ARRAY_END = ']',
+ MARKER_OBJECT_BEGIN = '{',
+ MARKER_OBJECT_END = '}',
+ MARKER_TYPE = '$',
+ MARKER_COUNT = '#',
+};
+
+
+inline uint16_t
+bigEndian16(uint16_t x) {
+#ifdef HAVE_BIGENDIAN
+ return x;
+#elif defined(_MSC_VER)
+ return _byteswap_ushort(x);
+#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408
+ return __builtin_bswap16(x);
+#else
+ return (x << 8) | (x >> 8);
+#endif
+}
+
+inline uint32_t
+bigEndian32(uint32_t x) {
+#ifdef HAVE_BIGENDIAN
+ return x;
+#elif defined(_MSC_VER)
+ return _byteswap_ulong(x);
+#else
+ return __builtin_bswap32(x);
+#endif
+}
+
+inline uint64_t
+bigEndian64(uint64_t x) {
+#ifdef HAVE_BIGENDIAN
+ return x;
+#elif defined(_MSC_VER)
+ return _byteswap_uint64(x);
+#else
+ return __builtin_bswap64(x);
+#endif
+}
+
+
+union Float32 {
+ float f;
+ uint32_t i;
+};
+
+
+union Float64 {
+ double f;
+ uint64_t i;
+};
+
+
+}
diff --git a/dispatch/.gitignore b/dispatch/.gitignore
index 213c471d..0cc522b3 100644
--- a/dispatch/.gitignore
+++ b/dispatch/.gitignore
@@ -1 +1,2 @@
glproc.hpp
+glproc.cpp
diff --git a/dispatch/CMakeLists.txt b/dispatch/CMakeLists.txt
index 0dad67fe..d023e6e9 100644
--- a/dispatch/CMakeLists.txt
+++ b/dispatch/CMakeLists.txt
@@ -1,14 +1,16 @@
##############################################################################
# Dispatch
-include_directories (
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}
-)
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
add_custom_command (
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glproc.py > ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
+ OUTPUT
+ ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
+ ${CMAKE_CURRENT_BINARY_DIR}/glproc.cpp
+ COMMAND ${PYTHON_EXECUTABLE}
+ ${CMAKE_CURRENT_SOURCE_DIR}/glproc.py
+ ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
+ ${CMAKE_CURRENT_BINARY_DIR}/glproc.cpp
DEPENDS
glproc.py
dispatch.py
@@ -16,7 +18,6 @@ add_custom_command (
${CMAKE_SOURCE_DIR}/specs/glxapi.py
${CMAKE_SOURCE_DIR}/specs/cglapi.py
${CMAKE_SOURCE_DIR}/specs/eglapi.py
- ${CMAKE_SOURCE_DIR}/specs/glesapi.py
${CMAKE_SOURCE_DIR}/specs/glapi.py
${CMAKE_SOURCE_DIR}/specs/gltypes.py
${CMAKE_SOURCE_DIR}/specs/stdapi.py
@@ -26,30 +27,25 @@ add_custom_command (
# Wrap glproc.hpp as a target to prevent the command from being executed
# multiple times simulatenously, when the targets that depend on it are built
# in parallel.
-add_custom_target (glproc DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp)
+add_custom_target (glproc DEPENDS
+ ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
+ ${CMAKE_CURRENT_BINARY_DIR}/glproc.cpp
+)
-add_library (glproc_gl STATIC EXCLUDE_FROM_ALL
+add_convenience_library (glproc_gl EXCLUDE_FROM_ALL
glproc_gl.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/glproc.cpp
)
add_dependencies (glproc_gl glproc)
-set_target_properties (glproc_gl PROPERTIES
- # Ensure it can be statically linked in shared libraries
- COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}"
-)
-
if (ENABLE_EGL)
- add_library (glproc_egl STATIC EXCLUDE_FROM_ALL
+ add_convenience_library (glproc_egl EXCLUDE_FROM_ALL
glproc_egl.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/glproc.cpp
)
add_dependencies (glproc_egl glproc)
-
- set_target_properties (glproc_egl PROPERTIES
- # Ensure it can be statically linked in shared libraries
- COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}"
- )
endif ()
diff --git a/dispatch/compat.h b/dispatch/compat.h
index 6f55ca54..9b73c4f8 100644
--- a/dispatch/compat.h
+++ b/dispatch/compat.h
@@ -30,6 +30,21 @@
#ifdef __MINGW32__
+#include <windows.h>
+
+
+/*
+ * Several of the defines below clash with libstdc++ internal variables,
+ * so include the headers now, before they are re-defined.
+ */
+#ifdef __cplusplus
+#include <algorithm>
+#include <iostream>
+#include <memory>
+#include <vector>
+#endif
+
+
/*
* Dummy definitions Standard Annotation Language (SAL) definitions
*
@@ -40,6 +55,7 @@
#define _Always_(annos)
#define _Analysis_noreturn_
+#define _Analysis_assume_(expr)
#define _At_(target, annos)
#define _At_buffer_(target, iter, bound, annos)
#define _COM_Outptr_
@@ -736,6 +752,14 @@
#define DECLSPEC_NOVTABLE
#endif
+#ifndef DECLSPEC_NOTHROW
+#define DECLSPEC_NOTHROW
+#endif
+
+#ifndef COM_DECLSPEC_NOTHROW
+#define COM_DECLSPEC_NOTHROW DECLSPEC_NOTHROW
+#endif
+
#ifndef __MINGW64_VERSION_MAJOR
#define INT8 signed char
#define UINT8 unsigned char
diff --git a/dispatch/d2dimports.hpp b/dispatch/d2dimports.hpp
index 4a2594b9..b4243fce 100644
--- a/dispatch/d2dimports.hpp
+++ b/dispatch/d2dimports.hpp
@@ -27,16 +27,19 @@
* Central place for all D2D/DWRITE includes, and respective OS dependent headers.
*/
-#ifndef _D2DIMPORTS_HPP_
-#define _D2DIMPORTS_HPP_
+#pragma once
#include <windows.h>
#include <tchar.h>
#include "compat.h"
-#include <d2d1.h>
-#include <dwrite.h>
+#include <d2d1_1.h>
+#include <dwrite_1.h>
+
+#ifndef WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
+#define WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT 0x88982f80
+#endif
DEFINE_GUID(IID_ID2D1Resource,0x2cd90691,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9);
DEFINE_GUID(IID_ID2D1Bitmap,0xa2296057,0xea42,0x4099,0x98,0x3b,0x53,0x9f,0xb6,0x50,0x54,0x26);
@@ -95,4 +98,3 @@ DEFINE_GUID(IID_IDWriteGdiInterop,0x1edd9491,0x9853,0x4299,0x89,0x8f,0x64,0x32,0
DEFINE_GUID(IID_IDWriteGlyphRunAnalysis,0x7d97dbf7,0xe085,0x42d4,0x81,0xe3,0x6a,0x88,0x3b,0xde,0xd1,0x18);
DEFINE_GUID(IID_IDWriteFactory,0xb859ee5a,0xd838,0x4b5b,0xa2,0xe8,0x1a,0xdc,0x7d,0x93,0xdb,0x48);
-#endif /* _D2DIMPORTS_HPP_ */
diff --git a/dispatch/d3d10imports.hpp b/dispatch/d3d10imports.hpp
index 04d4119d..80116fe1 100644
--- a/dispatch/d3d10imports.hpp
+++ b/dispatch/d3d10imports.hpp
@@ -27,22 +27,17 @@
* Central place for all D3D10 includes, and respective OS dependent headers.
*/
-#ifndef _D3D10IMPORTS_HPP_
-#define _D3D10IMPORTS_HPP_
+#pragma once
#include <windows.h>
#include "compat.h"
-#include <d3d10.h>
+#include <d3d10_1.h>
#include "d3derr.hpp"
#include "dxgiint.h"
-#define D3D10_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY 0x0080
-#define D3D10_CREATE_DEVICE_STRICT_VALIDATION 0x0200
-#define D3D10_CREATE_DEVICE_DEBUGGABLE 0x0400
-#endif /* _D3D10IMPORTS_HPP_ */
diff --git a/dispatch/d3d11imports.hpp b/dispatch/d3d11imports.hpp
index b667bf85..4b101e6c 100644
--- a/dispatch/d3d11imports.hpp
+++ b/dispatch/d3d11imports.hpp
@@ -27,19 +27,17 @@
* Central place for all D3D11 includes, and respective OS dependent headers.
*/
-#ifndef _D3D11IMPORTS_HPP_
-#define _D3D11IMPORTS_HPP_
+#pragma once
#include <windows.h>
#include "compat.h"
-#include <d3d11.h>
+#include <d3d11_3.h>
#include "d3derr.hpp"
#include "dxgiint.h"
-#endif /* _D3D11IMPORTS_HPP_ */
diff --git a/dispatch/d3d8imports.hpp b/dispatch/d3d8imports.hpp
index d0813794..f0fd8814 100644
--- a/dispatch/d3d8imports.hpp
+++ b/dispatch/d3d8imports.hpp
@@ -27,8 +27,7 @@
* Central place for all D3D8 includes, and respective OS dependent headers.
*/
-#ifndef _D3D8IMPORTS_HPP_
-#define _D3D8IMPORTS_HPP_
+#pragma once
#include <windows.h>
@@ -36,4 +35,3 @@
#include <d3d8.h>
-#endif /* _D3D8IMPORTS_HPP_ */
diff --git a/dispatch/d3d9imports.hpp b/dispatch/d3d9imports.hpp
index b4e81873..675430ba 100644
--- a/dispatch/d3d9imports.hpp
+++ b/dispatch/d3d9imports.hpp
@@ -27,8 +27,7 @@
* Central place for all D3D9 includes, and respective OS dependent headers.
*/
-#ifndef _D3D9IMPORTS_HPP_
-#define _D3D9IMPORTS_HPP_
+#pragma once
#include <windows.h>
@@ -99,4 +98,3 @@
#endif
-#endif /* _D3D9IMPORTS_HPP_ */
diff --git a/dispatch/d3derr.hpp b/dispatch/d3derr.hpp
index 39a3e9c4..39ebc9ab 100644
--- a/dispatch/d3derr.hpp
+++ b/dispatch/d3derr.hpp
@@ -24,7 +24,7 @@
**************************************************************************/
/*
- * D3DERR return codes.
+ * Direct3D error codes.
*
* These were defined in d3dx10.h/d3dx11.h on DirectX SDK, and moved to
* winerror.h on Windows 8 SDK.
@@ -35,12 +35,14 @@
* - http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554.aspx
*/
-#ifndef _D3DERR_HPP_
-#define _D3DERR_HPP_
+#pragma once
+
+
+#include <windows.h>
#ifndef _FACD3D
-#define _FACD3D 0x876
+#define _FACD3D 0x876
#endif
#ifndef MAKE_D3DHRESULT
@@ -60,4 +62,38 @@
#endif
-#endif /* _D3DERR_HPP_ */
+#ifndef DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED
+#define DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED MAKE_DXGI_HRESULT(35)
+#endif
+
+#ifndef DXGI_ERROR_REMOTE_OUTOFMEMORY
+#define DXGI_ERROR_REMOTE_OUTOFMEMORY MAKE_DXGI_HRESULT(36)
+#endif
+
+
+#ifndef D3D10_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS
+#define D3D10_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS MAKE_D3D10_HRESULT(1)
+#endif
+
+#ifndef D3D10_ERROR_FILE_NOT_FOUND
+#define D3D10_ERROR_FILE_NOT_FOUND MAKE_D3D10_HRESULT(2)
+#endif
+
+
+#ifndef D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS
+#define D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS MAKE_D3D11_HRESULT(1)
+#endif
+
+#ifndef D3D11_ERROR_FILE_NOT_FOUND
+#define D3D11_ERROR_FILE_NOT_FOUND MAKE_D3D11_HRESULT(2)
+#endif
+
+#ifndef D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS
+#define D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS MAKE_D3D11_HRESULT(3)
+#endif
+
+#ifndef D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD
+#define D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD MAKE_D3D11_HRESULT(4)
+#endif
+
+
diff --git a/dispatch/d3d10_1imports.hpp b/dispatch/d3dimports.hpp
index 2b97cf3c..69836fe0 100644
--- a/dispatch/d3d10_1imports.hpp
+++ b/dispatch/d3dimports.hpp
@@ -24,25 +24,34 @@
**************************************************************************/
/*
- * Central place for all D3D10.1 includes, and respective OS dependent headers.
+ * Central place for all DDraw/D3D includes, and respective OS dependent headers.
*/
-#ifndef _D3D10_1IMPORTS_HPP_
-#define _D3D10_1IMPORTS_HPP_
+#pragma once
#include <windows.h>
#include "compat.h"
-#include <d3d10_1.h>
+#include <ddraw.h>
+#include <d3d.h>
-#include "d3derr.hpp"
-#include "dxgiint.h"
+#ifndef DDBLT_EXTENDED_FLAGS
+#define DDBLT_EXTENDED_FLAGS 0x40000000l
+#endif
+
+#ifndef DDBLT_EXTENDED_LINEAR_CONTENT
+#define DDBLT_EXTENDED_LINEAR_CONTENT 0x00000004l
+#endif
+
+#ifndef D3DLIGHT_PARALLELPOINT
+#define D3DLIGHT_PARALLELPOINT (D3DLIGHTTYPE)4
+#endif
+
+#ifndef D3DLIGHT_GLSPOT
+#define D3DLIGHT_GLSPOT (D3DLIGHTTYPE)5
+#endif
-#define D3D10_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY 0x0080
-#define D3D10_CREATE_DEVICE_STRICT_VALIDATION 0x0200
-#define D3D10_CREATE_DEVICE_DEBUGGABLE 0x0400
-#endif /* _D3D10_1IMPORTS_HPP_ */
diff --git a/dispatch/dispatch.py b/dispatch/dispatch.py
index 60f95073..9e778561 100644
--- a/dispatch/dispatch.py
+++ b/dispatch/dispatch.py
@@ -42,25 +42,18 @@ def function_pointer_type(function):
def function_pointer_value(function):
- return '_' + function.name + '_ptr'
+ return '_' + function.name
class Dispatcher:
- def header(self):
- # Must be implemented by derived classes, which should define, declare,
- # or implement something like:
- #
- # typedef void (*_PROC)(void);
- #
- # static _PROC _getPublicProcAddress(const char *name);
- # static _PROC _getPrivateProcAddress(const char *name);
- #
- raise NotImplementedError
-
def dispatchModule(self, module):
+ self.dispatchModuleDecl(module)
+ self.dispatchModuleImpl(module)
+
+ def dispatchModuleDecl(self, module):
for function in module.functions:
- self.dispatchFunction(module, function)
+ self.dispatchFunctionDecl(module, function)
# define standard name aliases for convenience, but only when not
# tracing, as that would cause symbol clashing with the tracing
@@ -70,55 +63,67 @@ class Dispatcher:
print '#define %s _%s' % (function.name, function.name)
print '#endif /* RETRACE */'
print
-
- def dispatchFunction(self, module, function):
+
+ def dispatchFunctionDecl(self, module, function):
ptype = function_pointer_type(function)
pvalue = function_pointer_value(function)
print 'typedef ' + function.prototype('* %s' % ptype) + ';'
- print 'static %s %s = NULL;' % (ptype, pvalue)
+ print 'extern %s %s;' % (ptype, pvalue)
print
- print 'static inline ' + function.prototype('_' + function.name) + ' {'
- print ' const char *_name = "%s";' % function.name
+
+ def dispatchModuleImpl(self, module):
+ for function in module.functions:
+ self.dispatchFunctionImpl(module, function)
+
+ def dispatchFunctionImpl(self, module, function):
+ ptype = function_pointer_type(function)
+ pvalue = function_pointer_value(function)
+
if function.type is stdapi.Void:
ret = ''
else:
ret = 'return '
+
+ print 'static ' + function.prototype('_fail_' + function.name) + ' {'
+ self.failFunction(function)
+ print '}'
+ print
+
+ print 'static ' + function.prototype('_get_' + function.name) + ' {'
self.invokeGetProcAddress(module, function)
print ' %s%s(%s);' % (ret, pvalue, ', '.join([str(arg.name) for arg in function.args]))
print '}'
print
- def isFunctionPublic(self, module, function):
- return True
+ print '%s %s = &%s;' % (ptype, pvalue, '_get_' + function.name)
+ print
def getProcAddressName(self, module, function):
- if self.isFunctionPublic(module, function):
- return '_getPublicProcAddress'
- else:
- return '_getPrivateProcAddress'
+ raise NotImplementedError
def invokeGetProcAddress(self, module, function):
ptype = function_pointer_type(function)
pvalue = function_pointer_value(function)
getProcAddressName = self.getProcAddressName(module, function)
- print ' if (!%s) {' % (pvalue,)
- print ' %s = (%s)%s(_name);' % (pvalue, ptype, getProcAddressName)
- print ' if (!%s) {' % (pvalue,)
- self.failFunction(function)
- print ' }'
+ print ' %s _ptr;' % (ptype,)
+ print ' _ptr = (%s)%s("%s");' % (ptype, getProcAddressName, function.name)
+ print ' if (!_ptr) {'
+ print ' _ptr = &%s;' % ('_fail_' + function.name)
print ' }'
+ print ' %s = _ptr;' % (pvalue,)
def failFunction(self, function):
+ print r' const char *_name = "%s";' % function.name
if function.type is stdapi.Void or function.fail is not None:
- print r' os::log("warning: ignoring call to unavailable function %s\n", _name);'
+ print r' os::log("warning: ignoring call to unavailable function %s\n", _name);'
if function.type is stdapi.Void:
assert function.fail is None
- print ' return;'
+ print ' return;'
else:
assert function.fail is not None
- print ' return %s;' % function.fail
+ print ' return %s;' % function.fail
else:
- print r' os::log("error: unavailable function %s\n", _name);'
- print r' os::abort();'
+ print r' os::log("error: unavailable function %s\n", _name);'
+ print r' os::abort();'
diff --git a/dispatch/dlopen.hpp b/dispatch/dlopen.hpp
index c1a71ba8..d6eba006 100644
--- a/dispatch/dlopen.hpp
+++ b/dispatch/dlopen.hpp
@@ -27,8 +27,7 @@
* Provides access to real dlopen, as tracing libraries interpose it.
*/
-#ifndef _DLOPEN_HPP_
-#define _DLOPEN_HPP_
+#pragma once
#include <dlfcn.h>
@@ -63,4 +62,3 @@ _dlopen(const char *filename, int flag)
return dlopen_ptr(filename, flag);
}
-#endif /* _DLOPEN_HPP_ */
diff --git a/dispatch/dxgiint.h b/dispatch/dxgiint.h
index 13853b34..3bfa5944 100644
--- a/dispatch/dxgiint.h
+++ b/dispatch/dxgiint.h
@@ -24,8 +24,7 @@
**************************************************************************/
-#ifndef _DXGIINT_H_
-#define _DXGIINT_H_
+#pragma once
#include <windows.h>
@@ -34,17 +33,7 @@
#include <dxgi.h>
-static const GUID IID_IDXGIFactoryDWM = {0x713F394E,0x92CA,0x47E7,{0xAB,0x81,0x11,0x59,0xC2,0x79,0x1E,0x54}};
-static const GUID IID_IDXGISwapChainDWM = {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}; // XXX
-
-struct IDXGIFactoryDWM;
-struct IDXGISwapChainDWM;
-
-struct IDXGIFactoryDWM: public IUnknown
-{
- virtual HRESULT STDMETHODCALLTYPE CreateSwapChain(IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGIOutput *pOutput, IDXGISwapChainDWM **ppSwapChain) = 0;
-};
-
+static const GUID IID_IDXGISwapChainDWM = {0xF69F223B,0x45D3,0x4AA0,{0x98,0xC8,0xC4,0x0C,0x2B,0x23,0x10,0x29}};
struct IDXGISwapChainDWM: public IDXGIDeviceSubObject
{
virtual HRESULT STDMETHODCALLTYPE Present(UINT SyncInterval, UINT Flags) = 0;
@@ -55,8 +44,17 @@ struct IDXGISwapChainDWM: public IDXGIDeviceSubObject
virtual HRESULT STDMETHODCALLTYPE GetContainingOutput(IDXGIOutput **ppOutput) = 0;
virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats) = 0;
virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT *pLastPresentCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE SetFullscreenState(BOOL Fullscreen, IDXGIOutput *pTarget) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetFullscreenState(BOOL *pFullscreen, IDXGIOutput **ppTarget) = 0;
};
-#endif /* _DXGIINT_H_ */
+static const GUID IID_IDXGIFactoryDWM = {0x713F394E,0x92CA,0x47E7,{0xAB,0x81,0x11,0x59,0xC2,0x79,0x1E,0x54}};
+struct IDXGIFactoryDWM: public IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE CreateSwapChain(IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGIOutput *pOutput, IDXGISwapChainDWM **ppSwapChain) = 0;
+};
+
+
+static const GUID IID_IWarpPrivateAPI = {0xF13EBCD1,0x672C,0x4F8B,{0xA6,0x31,0x95,0x39,0xCA,0x74,0x8D,0x71}};
+struct IWarpPrivateAPI: public IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE WarpEscape(void *pData) = 0;
+};
diff --git a/dispatch/dxva2imports.hpp b/dispatch/dxva2imports.hpp
new file mode 100644
index 00000000..9d2e02be
--- /dev/null
+++ b/dispatch/dxva2imports.hpp
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * Copyright 2012 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+#include "d3d9imports.hpp"
+
+#include <dxva2api.h>
+
+
+#ifndef DXVA2_E_NOT_INITIALIZED
+#define DXVA2_E_NOT_INITIALIZED ((HRESULT)0x80041000L)
+#endif
+
+#ifndef DXVA2_E_NEW_VIDEO_DEVICE
+#define DXVA2_E_NEW_VIDEO_DEVICE ((HRESULT)0x80041001L)
+#endif
+
+#ifndef DXVA2_E_VIDEO_DEVICE_LOCKED
+#define DXVA2_E_VIDEO_DEVICE_LOCKED ((HRESULT)0x80041002L)
+#endif
+
+#ifndef DXVA2_E_NOT_AVAILABLE
+#define DXVA2_E_NOT_AVAILABLE ((HRESULT)0x80041003L)
+#endif
+
diff --git a/dispatch/dxvaint.h b/dispatch/dxvaint.h
deleted file mode 100644
index 8a5ecfdc..00000000
--- a/dispatch/dxvaint.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2012 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#include <dxva2api.h>
-
-
-#ifndef DXVA2_E_NOT_INITIALIZED
-#define DXVA2_E_NOT_INITIALIZED ((HRESULT)0x80041000L)
-#endif
-
-#ifndef DXVA2_E_NEW_VIDEO_DEVICE
-#define DXVA2_E_NEW_VIDEO_DEVICE ((HRESULT)0x80041001L)
-#endif
-
-#ifndef DXVA2_E_VIDEO_DEVICE_LOCKED
-#define DXVA2_E_VIDEO_DEVICE_LOCKED ((HRESULT)0x80041002L)
-#endif
-
-#ifndef DXVA2_E_NOT_AVAILABLE
-#define DXVA2_E_NOT_AVAILABLE ((HRESULT)0x80041003L)
-#endif
-
-
-typedef struct _DXVA2_DECODEBUFFERDESC {
- IDirect3DSurface9 *pRenderTarget;
- DWORD CompressedBufferType;
- DWORD BufferIndex;
- DWORD DataOffset;
- DWORD DataSize;
- DWORD FirstMBaddress;
- DWORD NumMBsInBuffer;
- DWORD Width;
- DWORD Height;
- DWORD Stride;
- DWORD ReservedBits;
- PVOID pCipherCounter;
-} DXVA2_DECODEBUFFERDESC;
-
-typedef struct _DXVA2_DECODEEXECUTE {
- UINT NumCompBuffers;
- DXVA2_DECODEBUFFERDESC *pCompressedBuffers;
-} DXVA2_DECODEEXECUTE;
-
-typedef struct _DXVA2_VIDEOSAMPLE {
- REFERENCE_TIME Start;
- REFERENCE_TIME End;
- DXVA2_ExtendedFormat SampleFormat;
- DWORD SampleFlags;
- IDirect3DSurface9* SrcSurface;
- RECT SrcRect;
- RECT DstRect;
- DXVA2_AYUVSample8 Pal[16];
- DXVA2_Fixed32 PlanarAlpha;
-} DXVA2_VIDEOSAMPLE;
-
-/**
- * See also:
- * - D3DDDIARG_VIDEOPROCESSBLT
- * - DXVA2_VideoProcessBltParams
- */
-typedef struct _DXVA2_VIDEOPROCESSBLT {
- REFERENCE_TIME TargetFrame;
- RECT TargetRect;
- SIZE ConstrictionSize;
- DWORD StreamingFlags;
- DXVA2_AYUVSample16 BackgroundColor;
- DXVA2_ExtendedFormat DestFormat;
- DWORD DestFlags;
- DXVA2_ProcAmpValues ProcAmpValues;
- DXVA2_Fixed32 Alpha;
- DXVA2_FilterValues NoiseFilterLuma;
- DXVA2_FilterValues NoiseFilterChroma;
- DXVA2_FilterValues DetailFilterLuma;
- DXVA2_FilterValues DetailFilterChroma;
- DXVA2_VIDEOSAMPLE *pSrcSurfaces;
- UINT NumSrcSurfaces;
-} DXVA2_VIDEOPROCESSBLT;
-
-typedef struct _DXVA2_DECODEBUFFERINFO DXVA2_DECODEBUFFERINFO; /* XXX */
-
-typedef struct _DXVA2_EXTENSIONEXECUTE DXVA2_EXTENSIONEXECUTE; /* XXX */
-
-
-static const GUID IID_IDirect3DDecodeDevice9 = {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}; /* XXX */
-static const GUID IID_IDirect3DVideoProcessDevice9 = {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} /* XXX */;
-static const GUID IID_IDirect3DDXVAExtensionDevice9 = {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}; /* XXX */
-static const GUID IID_IDirect3DDxva2Container9 = {0x126D0349,0x4787,0x4AA6,{0x8E,0x1B,0x40,0xC1,0x77,0xC6,0x0A,0x01}};
-
-
-typedef struct DECLSPEC_ALIGN(16) _DXVA2_PVP_KEY128
-{
- BYTE Data[16];
-} DXVA2_PVP_KEY128;
-
-typedef struct _DXVA2_PVP_SETKEY
-{
- DXVA2_PVP_KEY128 ContentKey;
-} DXVA2_PVP_SETKEY;
-
-class IDirect3DDecodeDevice9 : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE DecodeBeginFrame(DXVA2_PVP_SETKEY *pPVPSetKey) = 0;
- virtual HRESULT STDMETHODCALLTYPE DecodeEndFrame(HANDLE *pHandleComplete) = 0;
- virtual HRESULT STDMETHODCALLTYPE DecodeSetRenderTarget(IDirect3DSurface9 *pRenderTarget) = 0;
- virtual HRESULT STDMETHODCALLTYPE DecodeExecute(DXVA2_DECODEEXECUTE /* const */ *pExecuteParams) = 0;
-};
-
-
-class IDirect3DVideoProcessDevice9 : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE VideoProcessBeginFrame(void) = 0;
- virtual HRESULT STDMETHODCALLTYPE VideoProcessEndFrame(HANDLE *pHandleComplete) = 0;
- virtual HRESULT STDMETHODCALLTYPE VideoProcessSetRenderTarget(IDirect3DSurface9 *pRenderTarget) = 0;
- virtual HRESULT STDMETHODCALLTYPE VideoProcessBlt(DXVA2_VIDEOPROCESSBLT /* const */ *pData) = 0;
-};
-
-
-class IDirect3DDXVAExtensionDevice9 : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE ExtensionExecute(DXVA2_EXTENSIONEXECUTE *pData) = 0;
-};
-
-
-class IDirect3DDxva2Container9 : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE CreateSurface(UINT Width, UINT Height, UINT BackBuffers, D3DFORMAT Format, D3DPOOL Pool, DWORD Usage, DWORD DxvaType, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE VidToSysBlt(IDirect3DSurface9 *pSourceSurface, RECT *pSourceRect, IDirect3DSurface9 *pDestSurface, RECT *pDestRect) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetDecodeGuidCount(UINT *pCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetDecodeGuids(UINT Count, GUID *pGuids) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetDecodeRenderTargetFormatCount(REFGUID Guid, UINT *pCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetDecodeRenderTargets(REFGUID Guid, UINT Count, D3DFORMAT *pFormats) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetDecodeCompressedBufferCount(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, UINT *pCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetDecodeCompressedBuffers(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, UINT Count, DXVA2_DECODEBUFFERINFO *pBufferInfo) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetDecodeConfigurationCount(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, UINT *pCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetDecodeConfigurations(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, UINT Count, DXVA2_ConfigPictureDecode *pConfigs) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateDecodeDevice(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, DXVA2_ConfigPictureDecode const *pConfig, IDirect3DSurface9 * *ppDecoderRenderTargets, UINT NumSurfaces, IDirect3DDecodeDevice9 ** ppDecode) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetVideoProcessorDeviceGuidCount(const DXVA2_VideoDesc *pVideoDesc, UINT *pCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetVideoProcessorDeviceGuids(const DXVA2_VideoDesc *pVideoDesc, UINT Count, GUID *pGuids) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetVideoProcessorCaps(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT Format, DXVA2_VideoProcessorCaps *pCaps) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetProcAmpRange(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT Format, UINT ProcAmpCap, DXVA2_ValueRange *pRange) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetFilterPropertyRange(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT Format, UINT FilterSetting, DXVA2_ValueRange *pRange) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetVideoProcessorRenderTargetCount(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, UINT *pCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetVideoProcessorRenderTargets(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, UINT Count, D3DFORMAT *pFormats) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetVideoProcessorSubStreamFormatCount(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT Format, UINT *pCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetVideoProcessorSubStreamFormats(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT Format, UINT Count, D3DFORMAT *pFormats) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateVideoProcessDevice(REFGUID Guid, const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT Format, UINT, IDirect3DVideoProcessDevice9 * * ppVideoProcessDevice) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetExtensionGuidCount(DWORD Extension, UINT *pCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetExtensionGuids(DWORD Extension, UINT Count, GUID *pGuids) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetExtensionCaps(REFGUID Guid, UINT, void *, UINT, void *, UINT) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateExtensionDevice(REFGUID Guid, void *, UINT, IDirect3DDXVAExtensionDevice9 ** ppExtension) = 0;
-};
-
diff --git a/dispatch/eglimports.hpp b/dispatch/eglimports.hpp
index 49cf177a..29b3342a 100644
--- a/dispatch/eglimports.hpp
+++ b/dispatch/eglimports.hpp
@@ -28,8 +28,7 @@
* directly, or indirectly through glimports.h.
*/
-#ifndef _EGLIMPORTS_HPP_
-#define _EGLIMPORTS_HPP_
+#pragma once
#include <KHR/khrplatform.h>
@@ -58,6 +57,9 @@
#define GL_NV_coverage_sample
#include "GLES2/gl2ext.h"
+// GLDEBUGPROCKHR is not defined because GL_KHR_debug was already defined
+typedef void (GL_APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+
// OpenGL ES 1.1
typedef int32_t GLfixed;
@@ -86,6 +88,3 @@ typedef int32_t GLclampx;
#undef _glext_h_
#include "GLES/glext.h"
-
-
-#endif /* _EGLIMPORTS_HPP_ */
diff --git a/dispatch/glimports.hpp b/dispatch/glimports.hpp
index 50689b30..12cb1710 100644
--- a/dispatch/glimports.hpp
+++ b/dispatch/glimports.hpp
@@ -27,8 +27,7 @@
* Central place for all GL includes, and respective OS dependent headers.
*/
-#ifndef _GLIMPORTS_HPP_
-#define _GLIMPORTS_HPP_
+#pragma once
#if defined(_WIN32)
@@ -77,6 +76,7 @@
#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311
#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312
#define GL_PATH_SAMPLE_QUALITY_NV 0x9085
+#define GL_PATH_STROKE_BOUND_NV 0x9086
#define GL_PATH_STROKE_OVERSAMPLE_COUNT_NV 0x9087
#define GL_MULTI_HULLS_NV 0x908C
#define GL_PROJECTIVE_2D_NV 0x9093
@@ -85,6 +85,10 @@
#define GL_TRANSPOSE_PROJECTIVE_3D_NV 0x9099
+// GL_VMWX_map_buffer_debug
+#define GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX 0x80000000
+
+
#if defined(_WIN32)
#include <GL/wglext.h>
@@ -92,6 +96,9 @@
#ifndef PFD_SUPPORT_DIRECTDRAW
#define PFD_SUPPORT_DIRECTDRAW 0x00002000
#endif
+#ifndef PFD_DIRECT3D_ACCELERATED
+#define PFD_DIRECT3D_ACCELERATED 0x00004000
+#endif
#ifndef PFD_SUPPORT_COMPOSITION
#define PFD_SUPPORT_COMPOSITION 0x00008000
#endif
@@ -160,6 +167,53 @@ typedef struct __IOSurface *IOSurfaceRef;
#define kCGLRPMajorGLVersion 133
#endif
+// OpenGL/CGLProfiler.h seems to no longer be included with XCode
+#define kCGLCPComment ((CGLContextParameter)1232)
+#define kCGLCPDumpState ((CGLContextParameter)1233)
+#define kCGLCPEnableForceFlush ((CGLContextParameter)1234)
+#define kCGLGOComment ((CGLGlobalOption)1506)
+#define kCGLGOEnableFunctionTrace ((CGLGlobalOption)1507)
+#define kCGLGOEnableFunctionStatistics ((CGLGlobalOption)1508)
+#define kCGLGOResetFunctionTrace ((CGLGlobalOption)1509)
+#define kCGLGOPageBreak ((CGLGlobalOption)1510)
+#define kCGLGOResetFunctionStatistics ((CGLGlobalOption)1511)
+#define kCGLGOEnableDebugAttach ((CGLGlobalOption)1512)
+#define kCGLGOHideObjects ((CGLGlobalOption)1513)
+#define kCGLGOEnableBreakpoint ((CGLGlobalOption)1514)
+#define kCGLGOForceSlowRenderingPath ((CGLGlobalOption)1609)
+#define kCGLGODisableImmediateRenderPath ((CGLGlobalOption)1610)
+#define kCGLGODisableCVARenderPath ((CGLGlobalOption)1611)
+#define kCGLGODisableVARRenderPath ((CGLGlobalOption)1612)
+#define kCGLGOForceWireframeRendering ((CGLGlobalOption)1613)
+#define kCGLGOSubmitOnImmediateRenderCommand ((CGLGlobalOption)1614)
+#define kCGLGOSubmitOnCVARenderCommand ((CGLGlobalOption)1615)
+#define kCGLGOSubmitOnVAORenderCommand ((CGLGlobalOption)1616)
+#define kCGLGOSubmitOnClearCommand ((CGLGlobalOption)1617)
+#define kCGLGOForceSoftwareTransformLighting ((CGLGlobalOption)1618)
+#define kCGLGOForceSoftwareTexgen ((CGLGlobalOption)1619)
+#define kCGLGOForceSoftwareTRUFORM_ATI ((CGLGlobalOption)1620)
+#define kCGLGOForceSoftwareVertexShaders ((CGLGlobalOption)1621)
+#define kCGLGODisableFragmentShaders_ATI ((CGLGlobalOption)1622)
+#define kCGLGODisableTexturing ((CGLGlobalOption)1623)
+#define kCGLGOOutlineTexture ((CGLGlobalOption)1624)
+#define kCGLGOOutlineTextureColor ((CGLGlobalOption)1625)
+#define kCGLGOForceSlowBitmapPath ((CGLGlobalOption)1626)
+#define kCGLGODisableBitmap ((CGLGlobalOption)1627)
+#define kCGLGOForceSlowReadPixelsPath ((CGLGlobalOption)1630)
+#define kCGLGODisableReadPixels ((CGLGlobalOption)1631)
+#define kCGLGOOutlineReadPixelsBuffer ((CGLGlobalOption)1632)
+#define kCGLGOOutlineReadPixelsBufferColor ((CGLGlobalOption)1633)
+#define kCGLGOForceSlowDrawPixelsPath ((CGLGlobalOption)1634)
+#define kCGLGODisableDrawPixels ((CGLGlobalOption)1635)
+#define kCGLGOOutlineDrawPixelsBuffer ((CGLGlobalOption)1636)
+#define kCGLGOOutlineDrawPixelsBufferColor ((CGLGlobalOption)1637)
+#define kCGLGOForceSlowCopyPixelsPath ((CGLGlobalOption)1638)
+#define kCGLGODisableCopyPixels ((CGLGlobalOption)1639)
+#define kCGLGOOutlineCopyPixelsBuffer ((CGLGlobalOption)1640)
+#define kCGLGOOutlineCopyPixelsBufferColor ((CGLGlobalOption)1641)
+#define kCGLGOMakeAllGLObjectsRequireUpdate ((CGLGlobalOption)1642)
+#define kCGLGOMakeAllGLStateRequireUpdate ((CGLGlobalOption)1643)
+
extern "C" {
// From http://www.opensource.apple.com/source/gdb/gdb-954/libcheckpoint/cpcg.c
@@ -190,4 +244,3 @@ CGLError CGLUpdateContext(CGLContextObj ctx);
#include "eglimports.hpp"
-#endif /* _GLIMPORTS_HPP_ */
diff --git a/dispatch/glproc.py b/dispatch/glproc.py
index 5b6f707c..f26a4f7d 100644
--- a/dispatch/glproc.py
+++ b/dispatch/glproc.py
@@ -29,6 +29,8 @@ covers all the functions we support.
"""
+import sys
+
from dispatch import Dispatcher
import specs.stdapi as stdapi
from specs.glapi import glapi
@@ -36,7 +38,6 @@ from specs.glxapi import glxapi
from specs.wglapi import wglapi
from specs.cglapi import cglapi
from specs.eglapi import eglapi
-from specs.glesapi import glesapi
# See http://www.opengl.org/registry/ABI/
@@ -491,78 +492,181 @@ public_symbols.update([
class GlDispatcher(Dispatcher):
- def header(self):
- print '''
-#if defined(_WIN32)
-extern HMODULE _libGlHandle;
-#else
-extern void * _libGlHandle;
-#endif
-
-void * _getPublicProcAddress(const char *procName);
-void * _getPrivateProcAddress(const char *procName);
-'''
-
def isFunctionPublic(self, module, function):
return function.name in public_symbols or function.name.startswith('CGL')
+ def getProcAddressName(self, module, function):
+ if self.isFunctionPublic(module, function):
+ return '_getPublicProcAddress'
+ else:
+ return '_getPrivateProcAddress'
+
def failFunction(self, function):
- # We fake this when they are not available
- if function.name in ('glGetObjectLabel', 'glGetObjectPtrLabel', 'glGetObjectLabelEXT'):
+ # We fake these when they are not available
+ if sys.platform == 'darwin':
+ # Fallback to EXT_debug_label on MacOSX, some enums need to be translated.
+ if function.name in ('glObjectLabel', 'glObjectLabelKHR'):
+ print r' if (translateDebugLabelIdentifier(identifier)) {'
+ print r' _glLabelObjectEXT(identifier, name, length < 0 ? 0 : length, length == 0 ? "" : label);'
+ print r' return;'
+ print r' }'
+ if function.name in ('glGetObjectLabel', 'glGetObjectLabelKHR'):
+ print r' if (translateDebugLabelIdentifier(identifier)) {'
+ print r' _glGetObjectLabelEXT(identifier, name, bufSize, length, label);'
+ print r' return;'
+ print r' }'
+ if function.name in (
+ # GL_KHR_debug
+ 'glDebugMessageControl',
+ 'glDebugMessageInsert',
+ 'glDebugMessageCallback',
+ 'glPushDebugGroup',
+ 'glPopDebugGroup',
+ 'glObjectLabel',
+ 'glObjectPtrLabel',
+ # GL_KHR_debug (OpenGL ES)
+ 'glDebugMessageControlKHR',
+ 'glDebugMessageInsertKHR',
+ 'glDebugMessageCallbackKHR',
+ 'glPushDebugGroupKHR',
+ 'glPopDebugGroupKHR',
+ 'glObjectLabelKHR',
+ 'glObjectPtrLabelKHR',
+ # GL_ARB_debug_output
+ 'glDebugMessageControlARB',
+ 'glDebugMessageInsertARB',
+ 'glDebugMessageCallbackARB',
+ # GL_AMD_debug_output
+ 'glDebugMessageEnableAMD',
+ 'glDebugMessageInsertAMD',
+ 'glDebugMessageCallbackAMD',
+ # GL_EXT_debug_label
+ 'glLabelObjectEXT',
+ # GL_EXT_debug_marker
+ 'glInsertEventMarkerEXT',
+ 'glPushGroupMarkerEXT',
+ 'glPopGroupMarkerEXT',
+ ):
+ return
+ if function.name.startswith('glGetObjectLabel'):
print r' if (length != 0) *length = 0;'
print r' if (label != 0 && bufSize > 0) *label = 0;'
return
- if function.name in ('glGetDebugMessageLog', 'glGetDebugMessageLogARB'):
- print r' if (sources != 0) *sources = 0;'
- print r' if (types != 0) *types = 0;'
+ if function.name == 'glGetDebugMessageLogAMD':
+ print r' if (categories != 0) *categories = 0;'
print r' if (ids != 0) *ids = 0;'
print r' if (severities != 0) *severities = 0;'
print r' if (lengths != 0) *lengths = 0;'
- print r' if (messageLog != 0 && bufsize > 0) *messageLog = 0;'
+ print r' if (message != 0 && bufsize > 0) *message = 0;'
+ print r' return 0;'
return
- if function.name in ('glGetDebugMessageLogAMD'):
- print r' if (categories != 0) *categories = 0;'
+ if function.name.startswith('glGetDebugMessageLog'):
+ print r' if (sources != 0) *sources = 0;'
+ print r' if (types != 0) *types = 0;'
print r' if (ids != 0) *ids = 0;'
print r' if (severities != 0) *severities = 0;'
print r' if (lengths != 0) *lengths = 0;'
- print r' if (message != 0 && bufsize > 0) *message = 0;'
+ print r' if (messageLog != 0 && bufsize > 0) *messageLog = 0;'
+ print r' return 0;'
return
Dispatcher.failFunction(self, function)
if __name__ == '__main__':
+ decl, impl = sys.argv[1:]
+
+ sys.stdout = open(decl, 'wt')
+ print
+ print '#pragma once'
print
- print '#ifndef _GLPROC_HPP_'
- print '#define _GLPROC_HPP_'
- print
print '#include "glimports.hpp"'
- print '#include "os.hpp"'
print
- dispatcher = GlDispatcher()
+ print '#if defined(_WIN32)'
+ print 'extern HMODULE _libGlHandle;'
+ print '#else'
+ print 'extern void * _libGlHandle;'
+ print '#endif'
print
- dispatcher.header()
+ print 'void * _getPublicProcAddress(const char *procName);'
+ print 'void * _getPrivateProcAddress(const char *procName);'
print
- dispatcher.dispatchModule(eglapi)
+ dispatcher = GlDispatcher()
+ print
+ dispatcher.dispatchModuleDecl(eglapi)
print
print '#if defined(_WIN32)'
print
- dispatcher.dispatchModule(wglapi)
+ dispatcher.dispatchModuleDecl(wglapi)
print
print '#elif defined(__APPLE__)'
print
- dispatcher.dispatchModule(cglapi)
+ dispatcher.dispatchModuleDecl(cglapi)
print
print '#elif defined(HAVE_X11)'
print
- dispatcher.dispatchModule(glxapi)
+ dispatcher.dispatchModuleDecl(glxapi)
print
print '#endif'
print
- dispatcher.dispatchModule(glapi)
- print
- dispatcher.dispatchModule(glesapi)
+ dispatcher.dispatchModuleDecl(glapi)
print
- print '#endif /* !_GLPROC_HPP_ */'
+ sys.stdout = open(impl, 'wt')
+ print
+ print '#include "glproc.hpp"'
+ print '#include "os.hpp"'
+ print
+ dispatcher = GlDispatcher()
+ print
+ dispatcher.dispatchModuleImpl(eglapi)
+ print
+ print '#if defined(_WIN32)'
+ print
+ dispatcher.dispatchModuleImpl(wglapi)
+ print
+ print '#elif defined(__APPLE__)'
+ print
+ print 'static inline bool'
+ print 'translateDebugLabelIdentifier(GLenum & identifier)'
+ print '{'
+ print ' switch (identifier) {'
+ print ' case GL_TEXTURE:'
+ print ' case GL_FRAMEBUFFER:'
+ print ' case GL_RENDERBUFFER:'
+ print ' case GL_SAMPLER:'
+ print ' case GL_TRANSFORM_FEEDBACK:'
+ print ' return true;'
+ print ' case GL_BUFFER:'
+ print ' identifier = GL_BUFFER_OBJECT_EXT;'
+ print ' return true;'
+ print ' case GL_SHADER:'
+ print ' identifier = GL_SHADER_OBJECT_EXT;'
+ print ' return true;'
+ print ' case GL_PROGRAM:'
+ print ' identifier = GL_PROGRAM_OBJECT_EXT;'
+ print ' return true;'
+ print ' case GL_VERTEX_ARRAY:'
+ print ' identifier = GL_VERTEX_ARRAY_OBJECT_EXT;'
+ print ' return true;'
+ print ' case GL_QUERY:'
+ print ' identifier = GL_QUERY_OBJECT_EXT;'
+ print ' return true;'
+ print ' case GL_PROGRAM_PIPELINE:'
+ print ' identifier = GL_PROGRAM_PIPELINE_OBJECT_EXT;'
+ print ' return true;'
+ print ' default:'
+ print ' return false;'
+ print ' }'
+ print '}'
+ print
+ dispatcher.dispatchModuleImpl(cglapi)
+ print
+ print '#elif defined(HAVE_X11)'
+ print
+ dispatcher.dispatchModuleImpl(glxapi)
+ print
+ print '#endif'
+ print
+ dispatcher.dispatchModuleImpl(glapi)
print
diff --git a/dispatch/glproc_egl.cpp b/dispatch/glproc_egl.cpp
index abba7275..07714ae8 100644
--- a/dispatch/glproc_egl.cpp
+++ b/dispatch/glproc_egl.cpp
@@ -61,19 +61,29 @@ void *_libGlHandle = NULL;
* (extensions) entry-points. Core entry-points should be taken directly from
* the API specific libraries.
*
- * We cannot tell here which API a symbol is meant for here (as some are
- * exported by many). So this code assumes that the appropriate shared
- * libraries have been loaded previously (either dlopened with RTLD_GLOBAL, or
- * as part of the executable dependencies), and that their symbols available
- * for quering via dlsym(RTLD_NEXT, ...).
*/
void *
_getPublicProcAddress(const char *procName)
{
-#if defined(ANDROID)
+ void *proc;
+
/*
- * Android does not support LD_PRELOAD. It is assumed that applications
- * are explicitely loading egltrace.so.
+ * We rely on dlsym(RTLD_NEXT, ...) whenever we can, because certain gl*
+ * symbols are exported by multiple APIs/SOs, and it's not trivial to
+ * determine which API/SO we should get the current symbol from.
+ */
+ proc = dlsym(RTLD_NEXT, procName);
+ if (proc) {
+ return proc;
+ }
+
+ /*
+ * dlsym(RTLD_NEXT, ...) will fail when the SO containing the symbol was
+ * loaded with RTLD_LOCAL. We try to override RTLD_LOCAL with RTLD_GLOBAL
+ * when tracing but this doesn't always work. So we try to guess and load
+ * the shared object directly.
+ *
+ * See https://github.com/apitrace/apitrace/issues/349#issuecomment-113316990
*/
if (procName[0] == 'e' && procName[1] == 'g' && procName[2] == 'l') {
@@ -87,19 +97,48 @@ _getPublicProcAddress(const char *procName)
return dlsym(libEGL, procName);
}
+ /*
+ * This might happen when:
+ *
+ * - the application is querying non-extensions functions via
+ * eglGetProcAddress (either because EGL_KHR_get_all_proc_addresses
+ * is advertised, or merely because the EGL implementation supports
+ * it regardless, like Mesa does)
+ *
+ * - libGLES*.so nor libGL*.so was ever loaded.
+ *
+ * - we need to resolve entrypoints that application never asked (e.g.,
+ * glGetIntegerv), for internal purposes
+ *
+ * Therefore, we try to fallback to eglGetProcAddress.
+ *
+ * See https://github.com/apitrace/apitrace/issues/301#issuecomment-68532248
+ */
+ if (strcmp(procName, "eglGetProcAddress") != 0) {
+ proc = (void *) _eglGetProcAddress(procName);
+ if (proc) {
+ return proc;
+ }
+ }
+
+ /*
+ * TODO: We could futher mitigate against using the wrong SO by:
+ * - using RTLD_NOLOAD to ensure we only use an existing SO
+ * - the determine the right SO via eglQueryAPI and glGetString(GL_VERSION)
+ */
+
if (procName[0] == 'g' && procName[1] == 'l') {
/* TODO: Use GLESv1/GLESv2 on a per-context basis. */
- static void *sym = NULL;
static void *libGLESv2 = NULL;
if (!libGLESv2) {
libGLESv2 = _dlopen("libGLESv2.so", RTLD_LOCAL | RTLD_LAZY);
}
if (libGLESv2) {
- sym = dlsym(libGLESv2, procName);
+ proc = dlsym(libGLESv2, procName);
}
- if (sym) {
- return sym;
+ if (proc) {
+ return proc;
}
static void *libGLESv1 = NULL;
@@ -107,17 +146,14 @@ _getPublicProcAddress(const char *procName)
libGLESv1 = _dlopen("libGLESv1_CM.so", RTLD_LOCAL | RTLD_LAZY);
}
if (libGLESv1) {
- sym = dlsym(libGLESv1, procName);
+ proc = dlsym(libGLESv1, procName);
}
- if (sym) {
- return sym;
+ if (proc) {
+ return proc;
}
}
return NULL;
-#else
- return dlsym(RTLD_NEXT, procName);
-#endif
}
/*
diff --git a/dispatch/glproc_gl.cpp b/dispatch/glproc_gl.cpp
index fdbea05c..8ae40d42 100644
--- a/dispatch/glproc_gl.cpp
+++ b/dispatch/glproc_gl.cpp
@@ -25,6 +25,7 @@
#include "glproc.hpp"
+#include "os.hpp"
#if !defined(_WIN32)
diff --git a/Dalvik.markdown b/docs/Android.markdown
index 4564e3b8..23064b83 100644
--- a/Dalvik.markdown
+++ b/docs/Android.markdown
@@ -1,20 +1,18 @@
-Tracing Dalvik VM (Java) applications on Android
-================================================
+# Tracing Java applications on Android #
-Android's Java virtual machine, Dalvik, runs as a system service (started at
+Android's Java virtual machine, runs as a system service (started at
bootup by `init`) and Java applications are run by forks of the initial
resident process. Thus, injecting apitrace's tracing library is different from
other operating systems.
-The following discussion assumes that tracing library is copied to '/data':
+The following discussion assumes that tracing library is copied to `/data`:
- adb push /path/to/apitrace/build/wrappers/egltrace.so /data
+ adb push /path/to/apitrace/libs/[arch]/egltrace.so /data
-Tracing on Android 4.0 and newer
---------------------------------
+## Tracing on Android 4.0 and newer ##
-Starting from Android 4.0 (Ice Cream Sandwich) release, Dalvik supports
+Starting from Android 4.0 (Ice Cream Sandwich) release, the system supports
running designated processes with wrappers, in which case a new Java VM is
started with 'system()' library call for that process.
@@ -23,33 +21,25 @@ Obtain the process name of the application to be traced (the one reported in
PROCNAME=com.android.settings
adb root
- adb shell setprop wrap.$PROCNAME LD_PRELOAD=/data/egltrace.so
+ adb shell ln -s /data/data/apitrace.github.io.eglretrace/libgnustl.so /data/libgnustl.so
+ adb shell setprop wrap.$PROCNAME LD_PRELOAD="/data/libgnustl_shared.so:/data/egltrace.so"
adb shell setprop debug.apitrace.procname $PROCNAME
(the former is read by Dalvik and specifies wrapping prefix, the latter is
read by apitrace itself and used in case apitrace is preloaded into Java VM
-globally to specify which process should be traced). Elevating priviliges
+globally to specify which process should be traced). Elevating privileges
via `adb root` is required to set the first property.
+If the `wrap.$PROCNAME` property name is longer than 31 characters [you'll need
+to truncate it](https://github.com/apitrace/apitrace/issues/296).
+
Make sure the process is not loaded before starting to trace it, for example
use `-S` flag to `am start`:
adb shell am start -S $PROCNAME
Use `adb logcat \*:S apitrace` to examine apitrace debug output. Trace files
-are saved into '/data/data/$PROCNAME' directory by default:
+are saved into `/data/data/$PROCNAME` directory by default:
adb pull /data/data/$PROCNAME/$PROCNAME.trace
adb shell rm /data/data/$PROCNAME/$PROCNAME.trace
-
-
-Tracing on Android pre-4.0
---------------------------
-
-`LD_PRELOAD` is supported since Android 2.3 "Gingerbread" and newer, but
-injecting tracing library globally is no longer supported, as the
-`debug.apitrace.procname` system propery is no longer honored.
-
-Consider checking out an
-[older commit](https://github.com/apitrace/apitrace/commit/888112983ef9564b3a9d15699faa17c337d3942b)
-if you need to trace on Android pre-4.0.
diff --git a/BUGS.markdown b/docs/BUGS.markdown
index 535c839e..2c35bac7 100644
--- a/BUGS.markdown
+++ b/docs/BUGS.markdown
@@ -1,5 +1,4 @@
-Reporting bugs
-==============
+# Reporting bugs #
Before reporting, please skim through the known issues below.
@@ -11,8 +10,7 @@ always including the following information:
* OpenGL/D3D driver name and version
-Known issues
-============
+# Known issues #
These are issues that the developers are already aware of, but for which there
is no immediate plan to address them, because either:
@@ -34,8 +32,7 @@ if:
sooner rather than later.
-Tracing
--------
+## Tracing ##
* Fake calls may be emitted in the trace, in order to provide complete
information for retracing. The typical case is OpenGL vertex arrays in user
@@ -63,8 +60,7 @@ Tracing
* On MacOSX, the internal OpenGL calls done by GLU are not traced yet.
-Retracing
----------
+## Retracing ##
* Replaying can take substantially more CPU due to the overhead of reading the
trace file from disk.
@@ -95,15 +91,13 @@ Retracing
share state. This is by far the most common case though.
-GUI
----
+## GUI ##
* Not all types of arguments can be edited.
-Proprietary/confidential applications
-=====================================
+# Proprietary/confidential applications #
Issues should be preferably filed on github to facilitate collaborative
development and for future reference.
@@ -129,8 +123,7 @@ Failure to do so will render the apitrace authors powerless to address the
issue.
-Attachments
-===========
+# Attachments #
github issue tracker doesn't support attachments.
@@ -138,16 +131,16 @@ Please attach long logs to https://gist.github.com/ and paste the URL into the
issue description.
For big attachments, such as traces, please upload them temporarily to a web
-server you control, or use a file upload service such as http://dropbox.com/
-and paste the URL into the issue description.
+server you control, or use a file upload service such as [Google
+Drive](https://www.google.com/drive/) or [Dropbox](https://dropbox.com/) and
+paste the URL into the issue description.
Trace files are only slightly compressed (for performance reasons). You can
further reduce their size when attaching/uploading by compressing with
[XZ](http://tukaani.org/xz/) or [7-Zip](http://www.7-zip.org/).
-Bugs on tracing
-===============
+# Bugs on tracing #
For bugs that happen while tracing (e.g., crashes while tracing the
application, or incorrect traces) please:
@@ -157,8 +150,7 @@ application, or incorrect traces) please:
* describe how you were using it when the issue happened.
-Bugs on retracing/GUI
-=====================
+# Bugs on retracing/GUI #
For bugs on retracing (e.g. crashes when retracing the application,
incorrect inconsistent rendering, or viewing with the GUI) please:
@@ -168,25 +160,24 @@ incorrect inconsistent rendering, or viewing with the GUI) please:
* describe the results you got, and what results you were expecting.
-Obtaining stack back-traces
-===========================
-
-
-Linux/MacOSX
-------------
+# Obtaining stack back-traces #
Please rebuild apitrace with debugging information, by passing
`-DCMAKE_BUILD_TYPE=Debug` to cmake, or editing its value in `CMakeCache.txt`
and rebuilding.
+## Linux ##
+
To obtain a stack back-trace, run the application with gdb from a terminal:
$ gdb --args application arg1 arg2 ...
(gdb) run
...
(gdb) bt
+ ...
+ (gdb) quit
-On Linux, to trace an application inside gdb invoke apitrace as:
+To trace an application inside GDB invoke apitrace as:
apitrace trace --verbose --debug application arg1 ...
@@ -201,9 +192,24 @@ See also more detailed and Distro specific instructions:
* http://live.gnome.org/GettingTraces
-Windows
--------
+## Mac OS X ##
+
+Before you can debug you must first enable developer mode on the machine if you
+haven't done so before:
+
+ sudo /usr/sbin/DevToolsSecurity --enable
+
+To trace an application inside LLDB and obtain a stack backtrace invoke apitrace as:
+
+ $ apitrace trace --verbose --debug application arg1 ...
+ ...
+ (lldb) bt
+ ...
+ (lldb) quit
+
+
+## Windows ##
See:
-* https://developer.mozilla.org/en/how_to_get_a_stacktrace_with_windbg
+* <https://developer.mozilla.org/en/how_to_get_a_stacktrace_with_windbg>
diff --git a/FORMAT.markdown b/docs/FORMAT.markdown
index 70692d26..08288a7c 100644
--- a/FORMAT.markdown
+++ b/docs/FORMAT.markdown
@@ -99,6 +99,7 @@ and the call number is implied for the enter event.
| 0x0c struct_sig value* // structure
| 0x0d uint // opaque pointer
| 0x0e value value // human-machine representation
+ | 0x0f wstring // wide character string value (zero terminator implied)
enum_sig = id count (name value)+ // first occurrence
| id // follow-on occurrences
@@ -112,6 +113,8 @@ and the call number is implied for the enter event.
name = string
member_name = string
+ wstring = count uint*
+
### Backtraces ###
frame = id frame_detail+ // first occurrence
diff --git a/docs/HACKING.markdown b/docs/HACKING.markdown
new file mode 100644
index 00000000..a8041b46
--- /dev/null
+++ b/docs/HACKING.markdown
@@ -0,0 +1,245 @@
+# Overview #
+
+Although focus was and still is on graphical APIs, apitrace has a
+generic infrastructure to trace any kind of API:
+
+ * the API's types and calls are specified in Python files in specs
+ sub-directory;
+
+ * there is a type hierarchy in `specs/stdapi.py`, capable of representing
+ most types in C language, and additional semantic metadata
+
+ * Python scripts generate C++ code to trace and serialize calls parameters to
+ a file, and vice-versa.
+
+ * The _Visitor_ design pattern is used to navigate over the types.
+
+ * The _Template_ design pattern is used to enable any step of code
+ generation to be overriden by derived classes, allowing to handle
+ cases that need special treatment without sacrifycing code reuse.
+
+apitrace's architecture is composed of several layers/components. There are
+too many to show in a single graph, so only those relevant for OpenGL API are
+illustrated below:
+
+ specs
+ ^
+ |
+ glproc
+ ^ ^ ^
+ | | |
+ /------/ | \--\
+ | | |
+ helpers | |
+ ^ ^ ^ | |
+ | | | | |
+ /--------/ | \----\ | |
+ | | | | |
+ | | | | |
+ trace retrace glstate glws
+ ^ ^ ^ ^
+ | | | |
+ | \-----\ | /---/
+ | | | |
+ | | | |
+ gltrace glretrace
+ ^ ^ ^ ^
+ | | | |
+ /------/ | \-----\ |
+ | | | |
+ | | | |
+ glxtrace wgltrace cgltrace qapitrace
+
+Here is a quick synopsis of what the layers do:
+
+ * `specs` -- specifies the types, functions, and interfaces of the API,
+ expressed as a hierarchy of Python objects
+
+ * `dispatch` -- runtime dispatch of calls to DLLs (open the DLL, get the symbol
+ address, and call it passing all arguments as-is)
+
+ * `glproc` -- specialization of the dispatch generation for GL APIs
+
+ * `helpers` -- helper functions to determine sizes of arrays, blobs, etc. It
+ often needs to dispatch calls to give the answers.
+
+ * `trace` -- generate C++ code for tracing an API based on its spec
+
+ * `gltrace` -- specialization of the tracing generation for GL API, with extra
+ code to generate
+
+ * `glxtrace`,` wgltrace`, `cgltrace` -- specialization of the tracing code for the
+ GLX, WGL, and CGL APIs.
+
+ * `retrace` -- generate C++ code to interpret calls from trace, based on the
+ API's spec
+
+ * `glretrace` -- specialization of the retrace code for the GL API
+
+ * `glstate` -- code to dump OpenGL state to a JSON file
+
+ * `glws` -- abstraction of the window system specific APIs (GXL, WGL, CGL), to
+ enable cross-platform portability of `glretrace`
+
+ * `qapitrace` -- the GUI; it reads traces directly, and gets JSON state by
+ invoking `glretrace`
+
+The architecture for Direct3D APIs is similar, with the exception that, because
+it's not cross platform, there are less specialized variations.
+
+
+# Coding Style #
+
+These are guidelines for new code. Admittedly some of the existing code hasn't
+been updated to follow these conventions yet.
+
+Whitespace (all languages):
+
+ * indentation is 4 spaces
+
+ * never use tabs as indents, except on Makefiles
+
+ * otherwise tab equals to 8 spaces
+
+ * separate classes with two empty lines
+
+Naming convention:
+
+ * `camelCase` for functions/methods
+
+ * `UpperCase` for structures/classes
+
+ * `lowercase` for namespaces/modules
+
+ * `UPPER_CASE` for #defines
+
+ * single underscore prefix for variables/functions in automatically generated
+ code
+
+C++:
+
+ * enclose single statement `if` clauses in `{` `}`, specially for
+ automatically generated code
+
+ * `} else {`
+
+ * use `inline` keyword for functions/methods which are called with high-frequency
+
+CMake:
+
+ * `lower_case` commands
+
+ * space between `(` and precedent name
+
+
+And when in doubt, be consistent with the existing code.
+
+
+# Commit policy #
+
+Feature development:
+
+* Existing features in master branch should not degrade at any time, for any
+ platform. Unless they are seldom used or redundant, and there is agreement.
+
+ * In particular, new features / changes must not introduce any sort of
+ instability when tracing.
+
+ While application developers and driver developers may be able to
+ workaround quirks in apitrace, we want to be able to obtain traces from
+ non-technical end-users with minimal intervention.
+
+ This implies that tracing should not make any non-standard assumptions, and
+ care must be taken to ensure the tracing code is robust against invalid
+ parameters, multiple threads, etc.
+
+* It's fine to add new features for only some platforms or APIs.
+
+* Non-trivial changes should be staged in a branch, to allow review and
+ regression testing. Feature branches should be deleted once they have been
+ merged.
+
+* Releases are tagged commits from master. There are no stable branches.
+
+
+Backwards compatibility:
+
+* Backwards binary compatibility with old traces must be always maintained: all
+ tools, including `glretrace`, must handle old traces without regressions.
+
+* No backwards compatibility guarantees for derived data (ASCII dumps, state,
+ images, etc).
+
+* There should be no gratuitous changes to command line tool interfaces, but no
+ guarantees are given.
+
+
+# Regression testing #
+
+There is a regression test suite under development in
+https://github.com/apitrace/apitrace-tests .
+
+
+# Further reading #
+
+* [Writing ELF Shared Library Wrappers](https://github.com/amonakov/on-wrapping/blob/master/interposers-discussion.asciidoc)
+* [Intercepting and Instrumenting COM Applications](https://www.usenix.org/legacy/events/coots99/full_papers/hunt/hunt_html)
+* [Proxy-Dll: Intercept Calls to DirectX](http://www.mikoweb.eu/index.php?node=21)
+
+
+# How to's #
+
+## How to support a new OpenGL extension ##
+
+All OpenGL (and OpenGL ES) function prototypes live in `specs/glapi.py`. This
+file is semi-automatically derived from Khronos XML description of OpenGL /
+OpenGL ES. To refresh do
+
+ $ make -C specs/scripts/ glapi.py
+ $ meld specs/glapi.py specs/scripts/glapi.py
+
+and then port over new prototypes. See also `specs/scripts/README.markdown`.
+
+The upstream XML description is not rich enough to describe all semantic
+details that apitrace needs, therefore one needs to manually tweak the
+specifications:
+
+* Fix-up the types of array, blob, and pointer arguments.
+
+ * For `glGet*` you can use `"_gl_param_size(pname)"` for automatically determining the number of parameters written, e.g.
+
+ GlFunction(Void, "glGetIntegerv", [(GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+
+* Add the `sideeffects=False` keyword argument where appropriate, so that those
+ calls can be merely ignored by `glretrace`.
+
+* Replace generically type `GLuint` object IDs with typed ones, (e.g., replace
+ `(GLuint, "texture")` into `(GLtexture, "texture")`, so that `glretrace` can
+ swizzle the objects IDs, when replaying on a different OpenGL implementation.
+
+
+## Dump more OpenGL state ##
+
+TBD.
+
+
+## Dump more D3D10/D3D11 parameter state ##
+
+In short, to dump another piece of state (e.g., `D3DXX_FOO_STATE`) you need to:
+
+* declare a
+
+ void dumpStateObject(JSONWriter &, const D3DXX_FOO_STATE &);
+
+ in `retrace/dxgistate_so.hpp`
+
+* add
+
+ d3dxx.D3DXX_FOO_STATE,
+
+ to the bottom of `retrace/dxgistate_so.py` so that C++ code to dump that structure is generated.
+
+* add a new `dumpFooState` function to `retrace/d3d10state.cpp` or `retrace/d3d11state.cpp`, similar to the existing `dumpBlendState` function, which gets the state object, and then calls `dumpStateObjectDesc` template and the generated `dumpStateObject` functions to do the grunt work.
+
+* update `dumpParameters` to call `dumpFooState`
+
diff --git a/docs/INSTALL.markdown b/docs/INSTALL.markdown
new file mode 100644
index 00000000..10dcbc19
--- /dev/null
+++ b/docs/INSTALL.markdown
@@ -0,0 +1,204 @@
+# Requirements #
+
+Requirements common for all platforms:
+
+* C++ compiler
+
+* Python version 2.7
+
+ * Python Image Library
+
+* CMake version 2.8.11 or higher (tested with version 2.8.12.2)
+
+Optional dependencies:
+
+* zlib 1.2.6 or higher
+
+* libpng
+
+The GUI also dependends on:
+
+* Qt version 5.2.1 or higher (tested with version 5.4.0 and 5.3.0; use the
+ [6.1 release](https://github.com/apitrace/apitrace/releases/tag/6.1), if you
+ must build with Qt4)
+
+Qt will be required if `-DENABLE_GUI=TRUE` is passed to CMake, and never used
+if `-DENABLE_GUI=FALSE` is passed instead. The implicit default is
+`-DENABLE_GUI=AUTO`, which will build the GUI if Qt is available.
+
+
+The code also depends on snappy libraries, but the bundled sources are always
+used regardless of system availability, to make the wrapper shared-objects/DLL
+self contained, and to prevent symbol collisions when tracing.
+
+
+# Linux #
+
+Optional dependencies:
+
+* Xlib headers
+
+* libprocps (procps development libraries)
+
+* libdwarf
+
+Build as:
+
+ cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ make -C build
+
+Other possible values for `CMAKE_BUILD_TYPE` `Debug`, `Release`,
+`RelWithDebInfo`, and `MinSizeRel`.
+
+You can also build the 32-bits GL wrapper on a 64-bits distribution, provided
+you have a multilib gcc and 32-bits X11 libraries, by doing:
+
+ cmake \
+ -H. -Bbuild32 \
+ -DCMAKE_C_FLAGS=-m32 \
+ -DCMAKE_CXX_FLAGS=-m32 \
+ -DCMAKE_SYSTEM_LIBRARY_PATH=/usr/lib32 \
+ -DENABLE_GUI=FALSE
+ make -C build32 glxtrace
+
+The `/usr/lib32` refers to the path where the 32-bits shared objects are may
+differ depending on the actual Linux distribution.
+
+
+# Mac OS X #
+
+Build as:
+
+ cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=~/QtX.Y.Z/X.Y/clang_64
+ make -C build
+
+
+# Android #
+
+Additional requirements:
+
+* [Android CMake](https://github.com/taka-no-me/android-cmake)
+* [Android NDK](http://developer.android.com/sdk/ndk/index.html)
+* [Android SDK](http://developer.android.com/sdk/index.html#Other). **Make sure you have Android 4.4.2 (API 19) platform SDK installed and Android build tools "21.1.2". API 19 is needed only to build the APK, but it will still run on lower API versions (with works starting with API 12).**
+
+Build as:
+
+ wget -N https://raw.githubusercontent.com/taka-no-me/android-cmake/master/android.toolchain.cmake
+
+ cmake \
+ -H. -Bbuild \
+ -DCMAKE_TOOLCHAIN_FILE=$PWD/android.toolchain.cmake \
+ -DANDROID_NDK=/path/to/your/ndk \
+ -DANDROID_API_LEVEL=9 \
+ -DANDROID_STL=gnustl_shared \
+ [-DANDROID_SDK=/path/to/your/sdk]
+
+ make -C build
+ [make -C build retraceAPK] will build Android retrace APK.
+ [make -C build installRetraceAPK] will build & install Android retrace APK on the connected device.
+
+You can also choose a particular ABI by passing `ANDROID_ABI` variable to
+cmake, e.g., `-DANDROID_ABI=x86`. Currently, when targeting AArch64 you [must
+build with GCC](https://github.com/apitrace/apitrace/issues/312), by invoking
+CMake as:
+
+ cmake \
+ -H. -Bbuild \
+ -DCMAKE_TOOLCHAIN_FILE=$PWD/android.toolchain.cmake \
+ -DANDROID_API_LEVEL=9 \
+ -DANDROID_TOOLCHAIN_NAME=aarch64-linux-android-4.9 \
+ -DANDROID_ABI=arm64-v8a
+
+** You'll need Android SDK only to build the retrace APK. **
+
+
+# FirefoxOS #
+
+Put Apitrace source tree into `B2GROOT/external/apitrace/` and the `Android.mk`
+file (`B2GROOT/external/apitrace/Android.mk`) will do the needful to compile
+and install apitrace appropriately into the system image as part of FirefoxOS
+build process. It expects a linaro-type of Android NDK to be present in
+`../../prebuilt/ndk/android-ndk-r7` (ie `B2GROOT/prebuilt/ndk/android-ndk-r7`).
+
+
+# Windows #
+
+## Microsoft Visual Studio ##
+
+Additional requirements:
+
+* Microsoft Visual Studio 2013 or newer (tested with 2013)
+
+* [Windows 10 SDK](https://dev.windows.com/en-us/downloads/windows-10-sdk)
+ for D3D11.3 headers.
+
+* Microsoft DirectX SDK is now part of Microsoft Visual Studio (from version
+ 2012), but D3D8 headers are not included, so if you want D3D8 support you'll
+ need to donwload and install the
+ [August 2007 release of DirectX SDK](http://www.microsoft.com/downloads/details.aspx?familyid=529F03BE-1339-48C4-BD5A-8506E5ACF571)
+
+### CMake GUI ###
+
+To build with Visual Studio first invoke CMake GUI as:
+
+ cmake-gui -H. -Bbuild -DCMAKE_PREFIX_PATH=C:\Qt\QtX.Y.Z\X.Y\msvc2013
+
+and press the _Configure_ button.
+
+It will try to detect most required/optional dependencies automatically. When
+not found automatically, you can manually specify the location of the
+dependencies from the CMake GUI.
+
+If the source/build/compiler/tools are spread across multiple drives, you might
+need to [use absolute paths](https://github.com/apitrace/apitrace/issues/352).
+
+After you've successfully configured, you can start the build by opening the
+generated `build\apitrace.sln` solution file
+
+### CMake CLI ###
+
+Another option is to use the commandline to configure the project. First of all find out which
+generators are available on your system:
+
+ cmake --help
+
+At the end of the output, choose a generator and start configuring the project:
+
+ cmake -H. -Bbuild -DCMAKE_PREFIX_PATH=C:\Qt\QtX.Y.Z\X.Y\msvc2013 -G "Visual Studio 12 2013"
+
+After you've successfully configured, you can start the build by invoking CMake as:
+
+ cmake --build build --config MinSizeRel
+
+### Deployment ###
+
+To run qapitrace, either ensure that `C:\Qt\QtX.Y.Z\X.Y\msvc2013\bin` is in the system path, or use
+[Qt's Windows deployment tool](http://doc.qt.io/qt-5/windows-deployment.html#the-windows-deployment-tool)
+to copy all necessary DLLs, like:
+
+ set Path=C:\Qt\QtX.Y.Z\X.Y\msvc2013\bin;%Path%
+ windeployqt build\qapitrace.exe
+
+### 64-bits ###
+
+The steps to build 64-bits version are similar, but choosing _Visual Studio xx
+Win64_ instead of _Visual Studio xx_, and using `C:\Qt\QtX.Y.Z\X.Y\msvc2013_64`
+for Qt path.
+
+### Windows XP ###
+
+By default, binaries generated by recent builds of Visual Studio will not work
+on Windows XP. If you want to obtain binaries that work on Windows XP then
+pass the `-T v120_xp` options to CMake when building with Visual Studio 2013.
+
+## MinGW ##
+
+Additional requirements:
+
+* [MinGW-w64](http://mingw-w64.sourceforge.net/) (tested with mingw-w64's gcc version 4.9)
+
+* [DirectX headers](https://github.com/apitrace/dxsdk)
+
+It's also possible to cross-compile Windows binaries from Linux with
+[MinGW cross compilers](http://www.cmake.org/Wiki/CmakeMingw).
+
diff --git a/docs/NEWS.markdown b/docs/NEWS.markdown
new file mode 100644
index 00000000..003eb3d1
--- /dev/null
+++ b/docs/NEWS.markdown
@@ -0,0 +1,102 @@
+This file lists the major user visible improvements. For a full list of changes
+and their authors see the git history.
+
+
+# Version 7 #
+
+* Native Android retrace with remote GUI
+
+* OpenGL ES 3 support
+
+* GUI ported to Qt5
+
+* Thumbnails per draw call in GUI
+
+* Rudimentary D3D7 retrace support
+
+
+# Version 6 #
+
+* OpenGL 4.5 support
+
+* DXGI 1.3 support
+
+* Support exporting buffers to disk from GUI
+
+
+# Version 5 #
+
+* OpenGL 4.4 support
+
+* Stack backtraces on Linux
+
+* Better tracing of enums in attribute arrays
+
+* MD5 snapshots
+
+* Better surface viewer
+
+
+# Version 4 #
+
+* Support tracing in Android, both native and Java applications
+
+* Show frame thumbnails in the GUI
+
+* Basic D3D 10.1, 11, and 11.1 trace support
+
+* Basic D3D retrace support
+
+* Multi-threaded trace/retrace support
+
+* Several OpenGL ES state dump fixes
+
+* GPU profiling
+
+* Thumbnails in GUI
+
+* Trim improvements
+
+
+# Version 3 #
+
+* Top-level `apitrace` command
+
+* Trace and replay support for EGL, GLES1, and GLES2 APIs on Linux
+
+* Ability to trim traces
+
+* Basic CPU profiling when retracing
+
+* Basic D3D10 trace support
+
+
+# Version 2 #
+
+* Flush/sync trace file only when there is an uncaught signal/exception,
+ yielding a 5x speed up while tracing
+
+* Employ snappy compression library instead of zlib, yielding a 2x speed up
+ while tracing
+
+* Implement and advertise `GL_GREMEDY_string_marker` and
+ `GL_GREMEDY_frame_terminator` extensions
+
+* Mac OS X support
+
+* Support up-to OpenGL 4.2 calls
+
+* Better GUI performance with very large traces, by loading frames from disk on
+ demand
+
+
+# Version 1 #
+
+* Qt GUI, capable of visualizing the calls, the state, and editing the state
+
+
+# Version 0 #
+
+* D3D8 and D3D9 trace support
+
+* OpenGL replay support
diff --git a/TODO.markdown b/docs/TODO.markdown
index d8375aee..d8375aee 100644
--- a/TODO.markdown
+++ b/docs/TODO.markdown
diff --git a/docs/USAGE.markdown b/docs/USAGE.markdown
new file mode 100644
index 00000000..89dcccf4
--- /dev/null
+++ b/docs/USAGE.markdown
@@ -0,0 +1,566 @@
+# Basic usage #
+
+Run the application you want to trace as
+
+ apitrace trace --api API /path/to/application [args...]
+
+and it will generate a trace named `application.trace` in the current
+directory. You can specify the written trace filename by passing the
+`--output` command line option.
+
+Problems while tracing (e.g, if the application uses calls/parameters
+unsupported by apitrace) will be reported via stderr output on Unices. On
+Windows you'll need to run
+[DebugView](http://technet.microsoft.com/en-us/sysinternals/bb896647) to view
+these messages.
+
+If you cannot obtain a trace, check the [application specific instructions on
+the wiki](https://github.com/apitrace/apitrace/wiki/Applications), or the
+[manual tracing instructions below](#tracing-manually).
+
+View the trace with
+
+ apitrace dump application.trace
+
+Replay an OpenGL trace with
+
+ apitrace replay application.trace
+
+Pass the `--sb` option to use a single buffered visual. Pass `--help` to
+`apitrace replay` for more options.
+
+If you run into problems [check if it is a known issue and file an issue if
+not](BUGS.markdown).
+
+
+# Basic GUI usage #
+
+Start the GUI as
+
+ qapitrace application.trace
+
+You can also tell the GUI to go directly to a specific call
+
+ qapitrace application.trace 12345
+
+Press `Ctrl-T` to see per-frame thumbnails. And while inspecting frame calls,
+press again `Ctrl-T` to see per-draw call thumbnails.
+
+
+# Backtrace Capturing #
+
+apitrace now has the ability to capture the call stack to an OpenGL call on
+certain OSes (only Android and Linux at the moment). This can be helpful in
+determing which piece of code made that glDrawArrays call.
+
+To use the feature you need to set an environment variable with the list of GL
+call prefixes you wish to capture stack traces to.
+
+ export APITRACE_BACKTRACE="glDraw* glUniform*"
+
+The backtrace data will show up in qapitrace in the bottom section as a new tab.
+
+
+# Advanced command line usage #
+
+
+## Call sets ##
+
+Several tools take `CALLSET` arguments, e.g:
+
+ apitrace dump --calls=CALLSET foo.trace
+ apitrace dump-images --calls=CALLSET foo.trace
+ apitrace trim --calls=CALLSET1 --calls=CALLSET2 foo.trace
+
+The call syntax is very flexible. Here are a few examples:
+
+ * `4` one call
+
+ * `0,2,4,5` set of calls
+
+ * `"0 2 4 5"` set of calls (commas are optional and can be replaced with whitespace)
+
+ * `0-100/2` calls 1, 3, 5, ..., 99
+
+ * `0-1000/draw` all draw calls between 0 and 1000
+
+ * `0-1000/fbo` all fbo changes between calls 0 and 1000
+
+ * `frame` all calls at end of frames
+
+ * `@foo.txt` read call numbers from `foo.txt`, using the same syntax as above
+
+
+
+## Tracing manually ##
+
+### Linux ###
+
+On 64 bits systems, you'll need to determine whether the application is 64 bits
+or 32 bits. This can be done by doing
+
+ file /path/to/application
+
+But beware of wrapper shell scripts -- what matters is the architecture of the
+main process.
+
+Run the GLX application you want to trace as
+
+ LD_PRELOAD=/path/to/apitrace/wrappers/glxtrace.so /path/to/application
+
+and it will generate a trace named `application.trace` in the current
+directory. You can specify the written trace filename by setting the
+`TRACE_FILE` environment variable before running.
+
+For EGL applications you will need to use `egltrace.so` instead of
+`glxtrace.so`.
+
+The `LD_PRELOAD` mechanism should work with the majority of applications. There
+are some applications (e.g., Unigine Heaven, Android GPU emulator, etc.), that
+have global function pointers with the same name as OpenGL entrypoints, living in a
+shared object that wasn't linked with `-Bsymbolic` flag, so relocations to
+those global function pointers get overwritten with the address to our wrapper
+library, and the application will segfault when trying to write to them. For
+these applications it is possible to trace by using `glxtrace.so` as an
+ordinary `libGL.so` and injecting it via `LD_LIBRARY_PATH`:
+
+ ln -s glxtrace.so wrappers/libGL.so
+ ln -s glxtrace.so wrappers/libGL.so.1
+ ln -s glxtrace.so wrappers/libGL.so.1.2
+ export LD_LIBRARY_PATH=/path/to/apitrace/wrappers:$LD_LIBRARY_PATH
+ export TRACE_LIBGL=/path/to/real/libGL.so.1
+ /path/to/application
+
+If you are an application developer, you can avoid this either by linking with
+`-Bsymbolic` flag, or by using some unique prefix for your function pointers.
+
+See the `ld.so` man page for more information about `LD_PRELOAD` and
+`LD_LIBRARY_PATH` environment flags.
+
+### Android ###
+
+To trace standalone native OpenGL ES applications, use
+`LD_PRELOAD=/path/to/egltrace.so /path/to/application` as described in the
+previous section. To trace Java applications, refer to Android.markdown.
+
+### Mac OS X ###
+
+Run the application you want to trace as
+
+ DYLD_FRAMEWORK_PATH=/path/to/apitrace/wrappers /path/to/application
+
+Note that although Mac OS X has an `LD_PRELOAD` equivalent,
+`DYLD_INSERT_LIBRARIES`, it is mostly useless because it only works with
+`DYLD_FORCE_FLAT_NAMESPACE=1` which breaks most applications. See the `dyld` man
+page for more details about these environment flags.
+
+### Windows ###
+
+When tracing third-party applications, you can identify the target
+application's main executable, either by:
+
+* right clicking on the application's icon in the _Start Menu_, choose
+ _Properties_, and see the _Target_ field;
+
+* or by starting the application, run Windows Task Manager (taskmgr.exe), right
+ click on the application name in the _Applications_ tab, choose _Go To Process_,
+ note the highlighted _Image Name_, and search it on `C:\Program Files` or
+ `C:\Program Files (x86)`.
+
+On 64 bits Windows, you'll need to determine ether the application is a 64 bits
+or 32 bits. 32 bits applications will have a `*32` suffix in the _Image Name_
+column of the _Processes_ tab of _Windows Task Manager_ window.
+
+You also need to know which graphics API is being used. If you are unsure, the
+simplest way to determine what API an application uses is to:
+
+* download and run [Process Explorer](http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx)
+
+* search and select the application's process in _Process Explorer_
+
+* list the DLLs by pressing `Ctrl + D`
+
+* sort DLLs alphabetically, and look for the DLLs such as `opengl32.dll`,
+ `d3d9.dll`, `d3d10.dll`, etc.
+
+Copy the appropriate `opengl32.dll`, `d3d8.dll`, or `d3d9.dll` from the
+wrappers directory to the directory with the application you want to trace.
+Then run the application as usual.
+
+You can specify the written trace filename by setting the `TRACE_FILE`
+environment variable before running.
+
+For D3D10 and higher you really must use `apitrace trace -a DXGI ...`. This is
+because D3D10-11 API span many DLLs which depend on each other, and once a DLL
+with a given name is loaded Windows will reuse it for LoadLibrary calls of the
+same name, causing internal calls to be traced erroneously. `apitrace trace`
+solves this issue by injecting a DLL `dxgitrace.dll` and patching all modules
+to hook only the APIs of interest.
+
+
+## Emitting annotations to the trace ##
+
+### OpenGL annotations ###
+
+From within OpenGL applications you can embed annotations in the trace file
+through the following extensions:
+
+* [`GL_KHR_debug`](http://www.opengl.org/registry/specs/KHR/debug.txt)
+
+* [`GL_ARB_debug_output`](http://www.opengl.org/registry/specs/ARB/debug_output.txt)
+
+* [`GL_EXT_debug_marker`](http://www.khronos.org/registry/gles/extensions/EXT/EXT_debug_marker.txt)
+
+* [`GL_EXT_debug_label`](http://www.opengl.org/registry/specs/EXT/EXT_debug_label.txt)
+
+* [`GL_AMD_debug_output`](http://www.opengl.org/registry/specs/AMD/debug_output.txt)
+
+* [`GL_GREMEDY_string_marker`](http://www.opengl.org/registry/specs/GREMEDY/string_marker.txt)
+
+* [`GL_GREMEDY_frame_terminator`](http://www.opengl.org/registry/specs/GREMEDY/frame_terminator.txt)
+
+**apitrace** will advertise and intercept these OpenGL extensions regardless
+of whether the OpenGL implementation supports them or not. So all you have
+to do is to use these extensions when available, and you can be sure they
+will be available when tracing inside **apitrace**.
+
+For example, if you use [GLEW](http://glew.sourceforge.net/) to dynamically
+detect and use OpenGL extensions, you could easily accomplish this by doing:
+
+ void foo() {
+
+ if (GLEW_KHR_debug) {
+ glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, __FUNCTION__);
+ }
+
+ ...
+
+ if (GLEW_KHR_debug) {
+ glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER,
+ 0, GL_DEBUG_SEVERITY_MEDIUM, -1, "bla bla");
+ }
+
+ ...
+
+ if (GLEW_KHR_debug) {
+ glPopDebugGroup();
+ }
+
+ }
+
+This has the added advantage of working equally well with other OpenGL debugging tools.
+
+Also, provided that the OpenGL implementation supports `GL_KHR_debug`, labels
+defined via glObjectLabel() , and the labels of several objects (textures,
+framebuffers, samplers, etc. ) will appear in the GUI state dumps, in the
+parameters tab.
+
+
+For OpenGL ES applications you can embed annotations in the trace file through the
+[`GL_KHR_debug`](http://www.khronos.org/registry/gles/extensions/KHR/debug.txt) or
+[`GL_EXT_debug_marker`](http://www.khronos.org/registry/gles/extensions/EXT/EXT_debug_marker.txt)
+extensions.
+
+
+### Direct3D annotations ###
+
+For Direct3D applications you can follow the standard procedure for
+[adding user defined events to Visual Studio Graphics Debugger / PIX](http://msdn.microsoft.com/en-us/library/vstudio/hh873200.aspx):
+
+- `D3DPERF_BeginEvent`, `D3DPERF_EndEvent`, and `D3DPERF_SetMarker` for D3D9,
+ D3D10, and D3D11.0 applications.
+
+- `ID3DUserDefinedAnnotation::BeginEvent`,
+ `ID3DUserDefinedAnnotation::EndEvent`, and
+ `ID3DUserDefinedAnnotation::SetMarker` for D3D11.1 applications.
+
+And for [naming objects](http://blogs.msdn.com/b/chuckw/archive/2010/04/15/object-naming.aspx)
+which support `SetPrivateData` method:
+
+ pObject->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(szName), szName);
+
+Note that [programmatic capture interfaces](https://msdn.microsoft.com/en-us/library/hh780905.aspx)
+are currently _not_ supported.
+
+See also:
+
+* <http://seanmiddleditch.com/direct3d-11-debug-api-tricks/>
+
+* <http://blogs.msdn.com/b/chuckw/archive/2012/11/30/direct3d-sdk-debug-layer-tricks.aspx>
+
+
+## Mask OpenGL features ##
+
+It's now possible to mask some of OpenGL features while tracing via a configuration file:
+
+ * `$XDG_CONFIG_HOME/apitrace/gltrace.conf` or `$HOME/.config/apitrace/gltrace.conf` on Linux
+
+ * `$HOME/Library/Preferences/apitrace/gltrace.conf` on MacOS X
+
+ * `%LOCALAPPDATA%\apitrace\gltrace.conf` on Windows
+
+Here's an example `gltrace.conf` config file showing some variables:
+
+ # comment line
+ GL_VERSION = "2.0"
+ GL_VENDOR = "Acme, Inc."
+ GL_EXTENSIONS = "GL_EXT_texture_swizzle GL_ARB_multitexture"
+ GL_RENDERER = "Acme rasterizer"
+ GL_SHADING_LANGUAGE_VERSION = "1.30"
+ GL_MAX_TEXTURE_SIZE = 1024
+
+This basically overrides the respective `glGetString()` and `glGetIntegerv()`
+parameters.
+
+String values are contained inside `""` pairs and may span multiple lines.
+Integer values are given without quotes.
+
+## Identify OpenGL object leaks ##
+
+You can identify OpenGL object leaks by running:
+
+ apitrace leaks application.trace
+
+This will print leaked object list and its generated call numbers.
+
+apitrace provides very basic leak tracking: it tracks all textures/
+framebuffers/renderbuffers/buffers name generate and delete call. If a object is not
+deleted until context destruction, it's treated as 'leaked'. This logic doesn't
+consider multi-context in multi-thread situation, so may report incorrect
+results in such scenarios.
+
+To use this fomr the GUI, go to menu -> Trace -> LeakTrace
+
+## Dump OpenGL state at a particular call ##
+
+You can get a dump of the bound OpenGL state at call 12345 by doing:
+
+ apitrace replay -D 12345 application.trace > 12345.json
+
+This is precisely the mechanism the GUI uses to obtain its own state.
+
+You can compare two state dumps by doing:
+
+ apitrace diff-state 12345.json 67890.json
+
+
+## Comparing two traces side by side ##
+
+ apitrace diff trace1.trace trace2.trace
+
+This works only on Unices, and it will truncate the traces due to performance
+limitations.
+
+
+## Recording a video with FFmpeg/Libav ##
+
+You can make a video of the output with FFmpeg by doing
+
+ apitrace dump-images -o - application.trace \
+ | ffmpeg -r 30 -f image2pipe -vcodec ppm -i pipe: -vcodec mpeg4 -y output.mp4
+
+or Libav (which replaces FFmpeg on recent Debian/Ubuntu distros) doing
+
+ apitrace dump-images -o - application.trace \
+ | avconv -r 30 -f image2pipe -vcodec ppm -i - -vcodec mpeg4 -y output.mp4
+
+
+## Recording a video with gstreamer ##
+
+You can make a video of the output with gstreamer by doing
+
+ glretrace --snapshot-format=RGB -s - smokinguns.trace | gst-launch-0.10 fdsrc blocksize=409600 ! queue \
+ ! videoparse format=rgb width=1920 height=1080 ! queue ! ffmpegcolorspace ! queue \
+ ! vaapiupload direct-rendering=0 ! queue ! vaapiencodeh264 ! filesink location=xxx.264
+
+
+## Trimming a trace ##
+
+You can truncate a trace by doing:
+
+ apitrace trim --calls 0-12345 -o trimed.trace application.trace
+
+If you need precise control over which calls to trim you can specify the
+individual call numbers in a plain text file, as described in the 'Call sets'
+section above.
+
+There is also experimental support for automatically trimming the calls
+necessary for a given frame or call:
+
+ apitrace trim-auto --calls=12345 -o trimed.trace application.trace
+ apitrace trim-auto --frames=12345 -o trimed.trace application.trace
+
+
+## Profiling a trace ##
+
+You can perform gpu and cpu profiling with the command line options:
+
+ * `--pgpu` record gpu times for frames and draw calls.
+
+ * `--pcpu` record cpu times for frames and draw calls.
+
+ * `--ppd` record pixels drawn for each draw call.
+
+The results from these can then be read by hand or analyzed with a script.
+
+`scripts/profileshader.py` will read the profile results and format them into a
+table which displays profiling results per shader.
+
+For example, to record all profiling data and utilise the per shader script:
+
+ apitrace replay --pgpu --pcpu --ppd foo.trace | ./scripts/profileshader.py
+
+
+# Advanced usage for OpenGL implementers #
+
+There are several advanced usage examples meant for OpenGL implementors.
+
+
+## Regression testing ##
+
+These are the steps to create a regression test-suite around **apitrace**:
+
+* obtain a trace
+
+* obtain reference snapshots, by doing on a reference system:
+
+ mkdir /path/to/reference/snapshots/
+ apitrace dump-images -o /path/to/reference/snapshots/ application.trace
+
+* prune the snapshots which are not interesting
+
+* to do a regression test, use `apitrace diff-images`:
+
+ apitrace dump-images -o /path/to/test/snapshots/ application.trace
+ apitrace diff-images --output summary.html /path/to/reference/snapshots/ /path/to/test/snapshots/
+
+
+## Automated git-bisection ##
+
+With tracecheck.py it is possible to automate git bisect and pinpoint the
+commit responsible for a regression.
+
+Below is an example of using tracecheck.py to bisect a regression in the
+Mesa-based Intel 965 driver. But the procedure could be applied to any OpenGL
+driver hosted on a git repository.
+
+First, create a build script, named build-script.sh, containing:
+
+ #!/bin/sh
+ set -e
+ export PATH=/usr/lib/ccache:$PATH
+ export CFLAGS='-g'
+ export CXXFLAGS='-g'
+ ./autogen.sh --disable-egl --disable-gallium --disable-glut --disable-glu --disable-glw --with-dri-drivers=i965
+ make clean
+ make "$@"
+
+It is important that builds are both robust, and efficient. Due to broken
+dependency discovery in Mesa's makefile system, it was necessary to invoke `make
+clean` in every iteration step. `ccache` should be installed to avoid
+recompiling unchanged source files.
+
+Then do:
+
+ cd /path/to/mesa
+ export LIBGL_DEBUG=verbose
+ export LD_LIBRARY_PATH=$PWD/lib
+ export LIBGL_DRIVERS_DIR=$PWD/lib
+ git bisect start \
+ 6491e9593d5cbc5644eb02593a2f562447efdcbb 71acbb54f49089b03d3498b6f88c1681d3f649ac \
+ -- src/mesa/drivers/dri/intel src/mesa/drivers/dri/i965/
+ git bisect run /path/to/tracecheck.py \
+ --precision-threshold 8.0 \
+ --build /path/to/build-script.sh \
+ --gl-renderer '.*Mesa.*Intel.*' \
+ --retrace=/path/to/glretrace \
+ -c /path/to/reference/snapshots/ \
+ topogun-1.06-orc-84k.trace
+
+The trace-check.py script will skip automatically when there are build
+failures.
+
+The `--gl-renderer` option will also cause a commit to be skipped if the
+`GL_RENDERER` is unexpected (e.g., when a software renderer or another OpenGL
+driver is unintentionally loaded due to a missing symbol in the DRI driver, or
+another runtime fault).
+
+
+## Side by side retracing ##
+
+In order to determine which draw call a regression first manifests one could
+generate snapshots for every draw call, using the `-S` option. That is, however,
+very inefficient for big traces with many draw calls.
+
+A faster approach is to run both the bad and a good OpenGL driver side-by-side.
+The latter can be either a previously known good build of the OpenGL driver, or a
+reference software renderer.
+
+This can be achieved with retracediff.py script, which invokes glretrace with
+different environments, allowing to choose the desired OpenGL driver by
+manipulating variables such as `LD_LIBRARY_PATH`, `LIBGL_DRIVERS_DIR`, or
+`TRACE_LIBGL`.
+
+For example, on Linux:
+
+ ./scripts/retracediff.py \
+ --ref-env LD_LIBRARY_PATH=/path/to/reference/OpenGL/implementation \
+ --retrace /path/to/glretrace \
+ --diff-prefix=/path/to/output/diffs \
+ application.trace
+
+Or on Windows:
+
+ python scripts\retracediff.py --retrace \path\to\glretrace.exe --ref-env TRACE_LIBGL=\path\to\reference\opengl32.dll application.trace
+
+
+# Advanced GUI usage #
+
+qapitrace has rudimentary support for replaying traces on a remote
+target device. This can be useful, for example, when developing for an
+embedded system. The primary GUI will run on the local host, while any
+replays will be performed on the target device.
+
+In order to target a remote device, use the command-line:
+
+ qapitrace --remote-target <HOST> <trace-file>
+
+In order for this to work, the following must be available in the
+system configuration:
+
+1. It must be possible for the current user to initiate an ssh session
+ that has access to the target's window system. The command to be
+ exectuted by qapitrace will be:
+
+ ssh <HOST> glretrace
+
+ For example, if the target device is using the X window system, one
+ can test whether an ssh session has access to the target X server
+ with:
+
+ ssh <HOST> xdpyinfo
+
+ If this command fails with something like "cannot open display"
+ then the user will have to configure the target to set the DISPLAY
+ environment variable, (for example, setting DISPLAY=:0 in the
+ .bashrc file on the target or similar).
+
+ Also, note that if the ssh session requires a custom username, then
+ this must be configured on the host side so that ssh can be
+ initiated without a username.
+
+ For example, if you normally connect with `ssh user@192.168.0.2`
+ you could configure ~/.ssh/config on the host with a block such as:
+
+ Host target
+ HostName 192.168.0.2
+ User user
+
+ And after this you should be able to connect with `ssh target` so
+ that you can also use `qapitrace --remote-target target`.
+
+2. The target host must have a functional glretrace binary available
+
+3. The target host must have access to <trace-file> at the same path
+ in the filesystem as the <trace-file> path on the host system being
+ passed to the qapitrace command line.
diff --git a/docs/VMWX_map_buffer_debug.txt b/docs/VMWX_map_buffer_debug.txt
new file mode 100644
index 00000000..254e08d3
--- /dev/null
+++ b/docs/VMWX_map_buffer_debug.txt
@@ -0,0 +1,116 @@
+Name
+
+ VMWX_map_buffer_debug
+
+Name Strings
+
+ GL_VMWX_map_buffer_debug
+
+Contact
+
+ Jose Fonseca, VMware (jfonseca 'at' vmware.com)
+
+IP Status
+
+ No known IP claims.
+
+Status
+
+ Implemented by Apitrace
+
+Version
+
+ Last Modified Date: December 14, 2014
+ Version: 1
+
+Number
+
+ TBD.
+
+Dependencies
+
+ GL_ARB_buffer_storage is required.
+
+Overview
+
+ This extension provides a mechanism for the application to notify OpenGL
+ debugging tools that it modified ranges of persistent buffer mappings,
+ without explicitly flushing buffer ranges.
+
+New Procedures and Functions
+
+ void NotifyMappedBufferRangeVMWX(const void * start, sizeiptr length);
+
+New Tokens
+
+ Accepted in the <flags> parameter of BufferStorage:
+
+ MAP_NOTIFY_EXPLICIT_BIT_VMWX 0x80000000
+
+ Accepted as part of the <access> parameter to MapBufferRange and
+ MapNamedBufferRange:
+
+ MAP_NOTIFY_EXPLICIT_BIT_VMWX 0x80000000
+
+Additions to Chapter 6 of the OpenGL Core Profile Specification, Version 4.3,
+"Buffer Objects"
+
+ Modify Section 6.2, "Creating and Modifying Buffer Object Data Stores"
+
+ Add to the bulleted list describing flags that modify buffer storage
+ flags, p.57.
+
+ * MAP_NOTIFY_EXPLICIT_BIT_VMWX indicates that the application will
+ notify whenever discrete subranges of coherent mappings are
+ notified.
+
+ This flag may only be used in conjunction with MAP_PERSISTENT_BIT.
+
+ Modify Section 6.3, "Mapping and Unmapping Buffer Data"
+
+ Add to the bulleted list describing flags that modify buffer mappings,
+ p.62.
+
+ * MAP_NOTIFY_EXPLICIT_BIT_VMWX indicates that discrete subranges of the
+ mapping will be notified explicitly when modified.
+
+ When this flag is set, modifications to each subrange must be
+ explicitly flushed by calling NotifyMappedBufferRangeVMWX.
+
+ This flag may only be used in conjunction with MAP_PERSISTENT_BIT.
+
+ If this bit is set, the value of BUFFER_STORAGE_FLAGS for the buffer
+ being mapped must include MAP_NOTIFY_EXPLICIT_BIT_VMWX.
+
+Issues
+
+ 1) Why is this extension necessary?
+
+ It is true that an application may be friendly towards OpenGL debugging
+ tools that intercept calls by ensuring that MAP_PERSISTENT_BIT is always
+ set with MAP_FLUSH_EXPLICIT_BIT, and never with MAP_COHERENT_BIT. But
+ this restricts/deviates from intended behavior. This extensions provides
+ a mechanism for applications to notify debugging tools without affecting
+ behavior.
+
+
+ 2) Why the new MAP_NOTIFY_EXPLICIT_BIT_VMWX token?
+
+ To be future-proof.
+
+ In order to record complete traces, OpenGL tracing tools may choose to
+ mask out support for coherent mappings by failing BufferStorage calls with
+ OUT_OF_MEMORY when MAP_COHERENT_BIT is set without
+ MAP_NOTIFY_EXPLICIT_BIT_VMWX; or use techniques to approximately detect
+ writes to coherent mappings if the application calls MapBufferRange with
+ MAP_COHERENT_BIT and MAP_NOTIFY_EXPLICIT_BIT_VMWX.
+
+ It is therefore crucial that applications that want to explicitily notify
+ modified subranges with calls NotifyMappedBufferRangeVMWX set the
+ MAP_NOTIFY_EXPLICIT_BIT_VMWX bit both on BufferStorage and MapBufferRange
+ calls, to opt-out of further interference from debugging tools.
+
+
+Revision History
+
+ Version 1, 2014/12/14 - Initial version
diff --git a/gui/.gitignore b/gui/.gitignore
index a0052ede..cd437b3f 100644
--- a/gui/.gitignore
+++ b/gui/.gitignore
@@ -1,3 +1,6 @@
+moc_*.cpp
qapitrace.qrc.depends
+qapitrace_automoc.cpp
+qrc_qapitrace.cpp
qrc_qapitrace.cxx
ui_*.h
diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt
index ad13475e..b74e3ece 100644
--- a/gui/CMakeLists.txt
+++ b/gui/CMakeLists.txt
@@ -1,7 +1,31 @@
-# Include the cmake file needed to use qt4
-include( ${QT_USE_FILE} )
+# CMake will throw a cryptic message if an user unwittingly invokes it from
+# this directory.
+if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+ message (FATAL_ERROR
+ "qapitrace must be built from the top source directory.\n"
+ "Read docs/INSTALL.markdown for detailed build instructions."
+ )
+endif ()
+
+add_definitions (-DQT_FORCE_ASSERTS)
+
+if (APPLE)
+ # Recent builds of Qt no longer support i386 architecture
+ set (CMAKE_OSX_ARCHITECTURES "x86_64")
+endif()
+
+add_library (qubjson STATIC
+ qubjson.cpp
+)
+
+add_gtest (qubjson_test qubjson_test.cpp)
+target_link_libraries (qubjson_test qubjson)
set(qapitrace_SRCS
+ androiddevicedialog.cpp
+ androidfiledialog.cpp
+ androidretracer.cpp
+ androidutils.cpp
apisurface.cpp
apitrace.cpp
apicalldelegate.cpp
@@ -27,6 +51,7 @@ set(qapitrace_SRCS
traceprocess.cpp
trimprocess.cpp
vertexdatainterpreter.cpp
+ leaktracethread.cpp
graphing/frameaxiswidget.cpp
graphing/graphwidget.cpp
graphing/graphaxiswidget.cpp
@@ -37,11 +62,11 @@ set(qapitrace_SRCS
graphing/timeaxiswidget.cpp
)
-qt4_automoc(${qapitrace_SRCS})
-
-qt4_add_resources(qapitrace_SRCS qapitrace.qrc)
+qt5_add_resources(qapitrace_SRCS qapitrace.qrc)
set(qapitrace_UIS
+ ui/androidfiledialog.ui
+ ui/androiddevicedialog.ui
ui/argumentseditor.ui
ui/imageviewer.ui
ui/jumpwidget.ui
@@ -55,47 +80,56 @@ set(qapitrace_UIS
ui/shaderssourcewidget.ui
)
-QT4_WRAP_UI(qapitrace_UIS_H ${qapitrace_UIS})
+set (CMAKE_AUTOMOC ON)
+# Silence `Note: No relevant classes found. No output generated.`
+set (CMAKE_AUTOMOC_MOC_OPTIONS "-nn")
+
+QT5_WRAP_UI(qapitrace_UIS_H ${qapitrace_UIS})
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
#add_app_icon(qapitrace_SRCS ../icons/hi*-qapitrace.png)
-link_directories(${LINK_DIRECTORIES} ${QJSON_LIBRARY_DIRS})
include_directories(
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_SOURCE_DIR}
- ${QJSON_INCLUDE_DIR}
- ${QT_INCLUDES}
+ ${CMAKE_SOURCE_DIR} # for image/*
)
-if (WIN32)
- # Use Windows subsystem (i.e., no console).
- set (qapitrace_SUBSYSTEM "WIN32")
-endif ()
+add_executable (qapitrace ${qapitrace_SRCS} ${qapitrace_UIS_H})
-add_executable(qapitrace ${qapitrace_SUBSYSTEM} ${qapitrace_SRCS} ${qapitrace_UIS_H})
+# Avoid qt5_use_modules. See also:
+# - https://bugreports.qt.io/browse/QTBUG-39457
+# - http://doc.qt.io/qt-5/cmake-manual.html
+# - http://www.kdab.com/using-cmake-with-qt-5/
+if (Qt5Core_VERSION_STRING VERSION_LESS 5.2.0)
+ qt5_use_modules (qubjson Widgets)
+ qt5_use_modules (qubjson_test Widgets)
+ qt5_use_modules (qapitrace Widgets WebKitWidgets)
+else ()
+ target_link_libraries (qubjson Qt5::Widgets)
+ target_link_libraries (qubjson_test Qt5::Widgets)
+ target_link_libraries (qapitrace Qt5::Widgets Qt5::WebKitWidgets)
+endif ()
target_link_libraries (qapitrace
+ qubjson
image
common
${ZLIB_LIBRARIES}
${SNAPPY_LIBRARIES}
- ${QJSON_LIBRARIES}
- ${QT_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
-if (APPLE)
- # Recent builds of Qt no longer support i386 architecture
- set_target_properties (qapitrace PROPERTIES OSX_ARCHITECTURES x86_64)
-endif ()
-if (MSVC)
- # When the Windows subsystem is chosen by default MSVC expects WinMain()
- # entry point, but we rather use plain old main() everywhere.
- set_target_properties (qapitrace PROPERTIES LINK_FLAGS "/ENTRY:mainCRTStartup")
+if (WIN32 AND NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
+ # Use Windows subsystem (i.e., no console).
+ set_target_properties (qapitrace PROPERTIES CMAKE_WIN32_EXECUTABLE TRUE)
+ if (MSVC)
+ # When the Windows subsystem is chosen by default MSVC expects WinMain()
+ # entry point, but we rather use plain old main() everywhere.
+ set_target_properties (qapitrace PROPERTIES LINK_FLAGS "/ENTRY:mainCRTStartup")
+ endif ()
endif ()
########### install files ###############
install (TARGETS qapitrace RUNTIME DESTINATION bin)
+install_pdb (qapitrace RUNTIME DESTINATION bin)
#install (FILES qapitrace.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
diff --git a/gui/androiddevicedialog.cpp b/gui/androiddevicedialog.cpp
new file mode 100644
index 00000000..8c524fc2
--- /dev/null
+++ b/gui/androiddevicedialog.cpp
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "androiddevicedialog.h"
+#include "ui_androiddevicedialog.h"
+
+#include <QMessageBox>
+#include <QPainter>
+#include <QProcess>
+#include <QSettings>
+#include <QStyledItemDelegate>
+#include <QToolTip>
+
+// yeah, writing tree models is fun!
+class AndroidDeviceModelNode
+{
+public:
+ AndroidDeviceModelNode(AndroidDeviceModelNode *parent, const AndroidDeviceInfo &info, const QString &incompatibleReason = QString())
+ : m_parent(parent), m_info(info), m_incompatibleReason(incompatibleReason)
+ {
+ if (m_parent)
+ m_parent->m_children.append(this);
+ }
+
+ AndroidDeviceModelNode(AndroidDeviceModelNode *parent, const QString &displayName)
+ : m_parent(parent), m_displayName(displayName)
+ {
+ if (m_parent)
+ m_parent->m_children.append(this);
+ }
+
+ ~AndroidDeviceModelNode()
+ {
+ if (m_parent)
+ m_parent->m_children.removeOne(this);
+ QList<AndroidDeviceModelNode *> children = m_children;
+ qDeleteAll(children);
+ }
+
+ AndroidDeviceModelNode *parent() const
+ {
+ return m_parent;
+ }
+
+ QList<AndroidDeviceModelNode *> children() const
+ {
+ return m_children;
+ }
+
+ AndroidDeviceInfo deviceInfo() const
+ {
+ return m_info;
+ }
+
+ QString displayName() const
+ {
+ return m_displayName;
+ }
+
+ QString incompatibleReason() const
+ {
+ return m_incompatibleReason;
+ }
+
+private:
+ AndroidDeviceModelNode *m_parent;
+ AndroidDeviceInfo m_info;
+ QString m_incompatibleReason;
+ QString m_displayName;
+ QList<AndroidDeviceModelNode *> m_children;
+};
+
+class AndroidDeviceModelDelegate : public QStyledItemDelegate
+{
+public:
+ AndroidDeviceModelDelegate(QObject * parent = 0)
+ : QStyledItemDelegate(parent)
+ {
+
+ }
+
+ ~AndroidDeviceModelDelegate()
+ {
+ }
+
+ QString getProductModel(const QString &device) const
+ {
+ if (m_serialNumberToDeviceName.contains(device))
+ return m_serialNumberToDeviceName.value(device);
+ // workaround for '????????????' serial numbers
+ QStringList arguments = AndroidDeviceInfo::adbSelector(device);
+ arguments << QLatin1String("shell") << QLatin1String("getprop")
+ << QLatin1String("ro.product.model");
+
+ QProcess adbProc;
+ adbProc.start(AndroidDeviceInfo::adbPath(), arguments);
+ if (!adbProc.waitForFinished(10000)) {
+ adbProc.kill();
+ return device;
+ }
+ QString model = QString::fromLocal8Bit(adbProc.readAll().trimmed());
+ if (model.isEmpty())
+ return device;
+ if (!device.startsWith(QLatin1String("????")))
+ m_serialNumberToDeviceName.insert(device, model);
+ return model;
+ }
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption(&opt, index);
+ painter->save();
+
+ AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(index.internalPointer());
+ AndroidDeviceInfo device = node->deviceInfo();
+
+ painter->setPen(Qt::NoPen);
+
+ // Paint Background
+ QPalette palette = opt.palette; // we always draw enabled
+ palette.setCurrentColorGroup(QPalette::Active);
+ bool selected = opt.state & QStyle::State_Selected;
+ QColor backgroundColor = selected ? palette.highlight().color()
+ : palette.background().color();
+ painter->setBrush(backgroundColor);
+
+ painter->drawRect(0, opt.rect.top(), opt.rect.width() + opt.rect.left(), opt.rect.height());
+
+ QColor textColor;
+ // Set Text Color
+ if (opt.state & QStyle::State_Selected)
+ textColor = palette.highlightedText().color();
+ else
+ textColor = palette.text().color();
+ painter->setPen(textColor);
+
+ if (!node->displayName().isEmpty()) { // Title
+ // We have a top level node
+ QFont font = opt.font;
+ font.setPointSizeF(font.pointSizeF() * 1.2);
+ font.setBold(true);
+
+ QFontMetrics fm(font);
+ painter->setFont(font);
+ int top = (opt.rect.bottom() + opt.rect.top() - fm.height()) / 2 + fm.ascent();
+ painter->drawText(6, top, node->displayName());
+ } else {
+ QIcon icon(QLatin1String(":/resources/android.png"));
+ int size = opt.rect.bottom() - opt.rect.top() - 12;
+ QPixmap pixmap = icon.pixmap(size, size);
+ painter->drawPixmap(6 + (size - pixmap.width()) / 2, opt.rect.top() + 6 + (size - pixmap.width()) / 2, pixmap);
+
+ QFontMetrics fm(opt.font);
+ // TopLeft
+ QString topLeft = device.serialNumber;
+ if (device.type == AndroidDeviceInfo::Hardware)
+ topLeft = getProductModel(device.serialNumber);
+ painter->drawText(size + 12, 2 + opt.rect.top() + fm.ascent(), topLeft);
+
+ QString topRight = device.serialNumber;
+ // topRight
+ if (device.type == AndroidDeviceInfo::Hardware) // otherwise it's not very informative
+ painter->drawText(opt.rect.right() - fm.width(topRight) - 6 , 2 + opt.rect.top() + fm.ascent(), topRight);
+
+ // Directory
+ QColor mix;
+ mix.setRgbF(0.7 * textColor.redF() + 0.3 * backgroundColor.redF(),
+ 0.7 * textColor.greenF() + 0.3 * backgroundColor.greenF(),
+ 0.7 * textColor.blueF() + 0.3 * backgroundColor.blueF());
+ painter->setPen(mix);
+
+ QString lineText;
+ if (node->incompatibleReason().isEmpty())
+ lineText = device.serialNumber;
+ else
+ lineText = node->incompatibleReason();
+ painter->drawText(size + 12, opt.rect.top() + fm.ascent() + fm.height() + 6, lineText);
+ }
+
+ // Separator lines
+ painter->setPen(QColor::fromRgb(150,150,150));
+ painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
+ painter->restore();
+ }
+
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption(&opt, index);
+
+ QFontMetrics fm(option.font);
+ QSize s;
+ s.setWidth(option.rect.width());
+ s.setHeight(fm.height() * 2 + 10);
+ return s;
+ }
+private:
+ mutable QHash<QString, QString> m_serialNumberToDeviceName;
+
+};
+
+class AndroidDeviceModel : public QAbstractItemModel
+{
+public:
+ AndroidDeviceModel();
+ QModelIndex index(int row, int column,
+ const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &child) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ AndroidDeviceInfo device(QModelIndex index);
+ void setDevices(const QVector<AndroidDeviceInfo> &devices);
+
+ QModelIndex indexFor(const QString &serial);
+private:
+ AndroidDeviceModelNode *m_root;
+};
+
+bool androidDevicesLessThan(const AndroidDeviceInfo &dev1, const AndroidDeviceInfo &dev2)
+{
+ // shamelessly stolen from qtcreator :)
+ if (dev1.serialNumber.contains(QLatin1String("????")) != dev2.serialNumber.contains(QLatin1String("????")))
+ return !dev1.serialNumber.contains(QLatin1String("????"));
+ if (dev1.type != dev2.type)
+ return dev1.type == AndroidDeviceInfo::Hardware;
+
+ return dev1.serialNumber < dev2.serialNumber;
+}
+
+/////////////////
+// AndroidDeviceModel
+/////////////////
+AndroidDeviceModel::AndroidDeviceModel()
+ : m_root(0)
+{
+}
+
+QModelIndex AndroidDeviceModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (column != 0)
+ return QModelIndex();
+
+ if (!m_root)
+ return QModelIndex();
+
+ if (!parent.isValid()) {
+ if (row < 0 || row >= m_root->children().count())
+ return QModelIndex();
+ return createIndex(row, column, m_root->children().at(row));
+ }
+
+ AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(parent.internalPointer());
+ if (row < node->children().count())
+ return createIndex(row, column, node->children().at(row));
+
+ return QModelIndex();
+}
+
+QModelIndex AndroidDeviceModel::parent(const QModelIndex &child) const
+{
+ if (!child.isValid())
+ return QModelIndex();
+ if (!m_root)
+ return QModelIndex();
+ AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(child.internalPointer());
+ if (node == m_root)
+ return QModelIndex();
+ AndroidDeviceModelNode *parent = node->parent();
+
+ if (parent == m_root)
+ return QModelIndex();
+
+ AndroidDeviceModelNode *grandParent = parent->parent();
+ return createIndex(grandParent->children().indexOf(parent), 0, parent);
+}
+
+int AndroidDeviceModel::rowCount(const QModelIndex &parent) const
+{
+ if (!m_root)
+ return 0;
+ if (!parent.isValid())
+ return m_root->children().count();
+ AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(parent.internalPointer());
+ return node->children().count();
+}
+
+int AndroidDeviceModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return 1;
+}
+
+QVariant AndroidDeviceModel::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(index.internalPointer());
+ if (!node)
+ return QVariant();
+ return node->deviceInfo().serialNumber;
+}
+
+Qt::ItemFlags AndroidDeviceModel::flags(const QModelIndex &index) const
+{
+ AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(index.internalPointer());
+ if (node)
+ if (node->displayName().isEmpty() && node->incompatibleReason().isEmpty())
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+
+ return Qt::NoItemFlags;
+}
+
+AndroidDeviceInfo AndroidDeviceModel::device(QModelIndex index)
+{
+ AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(index.internalPointer());
+ if (!node)
+ return AndroidDeviceInfo();
+ return node->deviceInfo();
+}
+
+void AndroidDeviceModel::setDevices(const QVector<AndroidDeviceInfo> &devices)
+{
+ beginResetModel();
+ delete m_root;
+ m_root = new AndroidDeviceModelNode(0, QString());
+
+ AndroidDeviceModelNode *compatibleDevices = new AndroidDeviceModelNode(m_root, AndroidDeviceDialog::tr("Compatible devices"));
+ AndroidDeviceModelNode *incompatibleDevices = 0; // created on demand
+ foreach (const AndroidDeviceInfo &device, devices) {
+ QString error;
+ if (device.state == AndroidDeviceInfo::UnAuthorizedState) {
+ error = AndroidDeviceDialog::tr("Unauthorized. Please check the confirmation dialog on your device %1.")
+ .arg(device.serialNumber);
+ }else if (device.state == AndroidDeviceInfo::OfflineState) {
+ error = AndroidDeviceDialog::tr("Offline. Please check the state of your device %1.")
+ .arg(device.serialNumber);
+ } else {
+ new AndroidDeviceModelNode(compatibleDevices, device);
+ continue;
+ }
+ if (!incompatibleDevices)
+ incompatibleDevices = new AndroidDeviceModelNode(m_root, AndroidDeviceDialog::tr("Incompatible devices"));
+ new AndroidDeviceModelNode(incompatibleDevices, device, error);
+ }
+ endResetModel();
+}
+
+QModelIndex AndroidDeviceModel::indexFor(const QString &serial)
+{
+ foreach (AndroidDeviceModelNode *topLevelNode, m_root->children()) {
+ QList<AndroidDeviceModelNode *> deviceNodes = topLevelNode->children();
+ for (int i = 0; i < deviceNodes.size(); ++i) {
+ if (deviceNodes.at(i)->deviceInfo().serialNumber == serial)
+ return createIndex(i, 0, deviceNodes.at(i));
+ }
+ }
+ return QModelIndex();
+}
+
+/////////////////
+// AndroidDeviceDialog
+/////////////////
+
+static inline QString msgConnect()
+{
+ return AndroidDeviceDialog::tr("<p>Connect an Android device via USB and activate developer mode on it. "
+ "Some devices require the installation of a USB driver.</p>");
+
+}
+
+static inline QString msgAdbListDevices()
+{
+ return AndroidDeviceDialog::tr("<p>The adb tool in the Android SDK lists all connected devices if run via &quot;adb devices&quot;.</p>");
+}
+
+AndroidDeviceDialog::AndroidDeviceDialog(QWidget *parent) :
+ QDialog(parent),
+ m_model(new AndroidDeviceModel()),
+ m_ui(new Ui::AndroidDeviceDialog)
+{
+ m_ui->setupUi(this);
+ m_ui->deviceView->setModel(m_model);
+ m_ui->deviceView->setItemDelegate(new AndroidDeviceModelDelegate(m_ui->deviceView));
+ m_ui->deviceView->setHeaderHidden(true);
+ m_ui->deviceView->setRootIsDecorated(false);
+ m_ui->deviceView->setUniformRowHeights(true);
+ m_ui->deviceView->setExpandsOnDoubleClick(false);
+
+ m_ui->defaultDeviceCheckBox->setText(tr("Always use this device for this session"));
+
+ m_ui->noDeviceFoundLabel->setText(QLatin1String("<p align=\"center\"><span style=\" font-size:16pt;\">")
+ + tr("No Device Found") + QLatin1String("</span></p><br/>")
+ + msgConnect() + QLatin1String("<br/>")
+ + msgAdbListDevices());
+ connect(m_ui->missingLabel, SIGNAL(linkActivated(QString)),
+ this, SLOT(showHelp()));
+
+ connect(m_ui->refreshDevicesButton, SIGNAL(clicked()),
+ this, SLOT(refreshDeviceList()));
+
+ connect(m_ui->deviceView, SIGNAL(doubleClicked(QModelIndex)),
+ this, SLOT(accept()));
+
+ refreshDeviceList();
+}
+
+AndroidDeviceDialog::~AndroidDeviceDialog()
+{
+ delete m_ui;
+}
+
+AndroidDeviceInfo AndroidDeviceDialog::device()
+{
+ if (result() == QDialog::Accepted)
+ return m_model->device(m_ui->deviceView->currentIndex());
+ return AndroidDeviceInfo();
+}
+
+void AndroidDeviceDialog::accept()
+{
+ QDialog::accept();
+}
+
+bool AndroidDeviceDialog::saveDeviceSelection()
+{
+ return m_ui->defaultDeviceCheckBox->isChecked();
+}
+
+void AndroidDeviceDialog::refreshDeviceList()
+{
+ QString serialNumber;
+ QModelIndex currentIndex = m_ui->deviceView->currentIndex();
+ if (currentIndex.isValid())
+ serialNumber = m_model->device(currentIndex).serialNumber;
+
+ QVector<AndroidDeviceInfo> devices;
+ foreach (const AndroidDeviceInfo &info, connectedDevices())
+ if (info.type == AndroidDeviceInfo::Hardware)
+ devices << info;
+
+ m_model->setDevices(devices);
+
+ m_ui->deviceView->expand(m_model->index(0, 0));
+ if (m_model->rowCount() > 1) // we have a incompatible device node
+ m_ui->deviceView->expand(m_model->index(1, 0));
+
+ // Smartly select a index
+ QModelIndex newIndex;
+ if (!serialNumber.isEmpty())
+ newIndex = m_model->indexFor(serialNumber);
+
+ if (!newIndex.isValid() && !devices.isEmpty())
+ newIndex = m_model->indexFor(devices.first().serialNumber);
+
+ m_ui->deviceView->setCurrentIndex(newIndex);
+
+ m_ui->stackedWidget->setCurrentIndex(devices.isEmpty() ? 1 : 0);
+}
+
+
+// Does not work.
+void AndroidDeviceDialog::clickedOnView(const QModelIndex &idx)
+{
+ if (idx.isValid()) {
+ AndroidDeviceModelNode *node = static_cast<AndroidDeviceModelNode *>(idx.internalPointer());
+ if (!node->displayName().isEmpty()) {
+ if (m_ui->deviceView->isExpanded(idx))
+ m_ui->deviceView->collapse(idx);
+ else
+ m_ui->deviceView->expand(idx);
+ }
+ }
+}
+
+void AndroidDeviceDialog::showHelp()
+{
+ QPoint pos = m_ui->missingLabel->pos();
+ pos = m_ui->missingLabel->parentWidget()->mapToGlobal(pos);
+ QToolTip::showText(pos, msgConnect() + msgAdbListDevices(), this);
+}
+
+QVector<AndroidDeviceInfo> AndroidDeviceDialog::connectedDevices(QString *error)
+{
+ // shamelessly stolen from qtcreator :)
+ // Well, not exactly shamelessly, because is more or leass my work though :)
+ QVector<AndroidDeviceInfo> devices;
+ QProcess adbProc;
+ QString adbPath = AndroidDeviceInfo::adbPath();
+ adbProc.start(adbPath, QStringList() << QLatin1String("devices"));
+ if (!adbProc.waitForFinished(10000)) {
+ adbProc.kill();
+ if (error)
+ *error = tr("Could not run: %1").arg(adbPath + QLatin1String(" devices"));
+ return devices;
+ }
+ QList<QByteArray> adbDevs = adbProc.readAll().trimmed().split('\n');
+ if (adbDevs.empty())
+ return devices;
+
+ while (adbDevs.first().startsWith("* daemon"))
+ adbDevs.removeFirst(); // remove the daemon logs
+ adbDevs.removeFirst(); // remove "List of devices attached" header line
+
+ // workaround for '????????????' serial numbers:
+ // can use "adb -d" when only one usb device attached
+ foreach (const QByteArray &device, adbDevs) {
+ const QString serialNo = QString::fromLatin1(device.left(device.indexOf('\t')).trimmed());
+ const QString deviceType = QString::fromLatin1(device.mid(device.indexOf('\t'))).trimmed();
+ AndroidDeviceInfo dev;
+ dev.serialNumber = serialNo;
+ dev.type = serialNo.startsWith(QLatin1String("emulator")) ? AndroidDeviceInfo::Emulator : AndroidDeviceInfo::Hardware;
+ if (deviceType == QLatin1String("unauthorized"))
+ dev.state = AndroidDeviceInfo::UnAuthorizedState;
+ else if (deviceType == QLatin1String("offline"))
+ dev.state = AndroidDeviceInfo::OfflineState;
+ else
+ dev.state = AndroidDeviceInfo::OkState;
+ devices.push_back(dev);
+ }
+
+ std::sort(devices.begin(), devices.end(), androidDevicesLessThan);
+ if (devices.isEmpty() && error)
+ *error = tr("No devices found in output of: %1").arg(adbPath + QLatin1String(" devices"));
+ return devices;
+}
diff --git a/gui/androiddevicedialog.h b/gui/androiddevicedialog.h
new file mode 100644
index 00000000..0b994c6a
--- /dev/null
+++ b/gui/androiddevicedialog.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "androidutils.h"
+
+#include <QVector>
+#include <QDialog>
+
+class AndroidDeviceModel;
+namespace Ui { class AndroidDeviceDialog; }
+
+class AndroidDeviceDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit AndroidDeviceDialog(QWidget *parent = 0);
+ ~AndroidDeviceDialog();
+
+ AndroidDeviceInfo device();
+ void accept();
+ bool saveDeviceSelection();
+
+private slots:
+ void refreshDeviceList();
+ void clickedOnView(const QModelIndex &idx);
+ void showHelp();
+
+private:
+ QVector<AndroidDeviceInfo> connectedDevices(QString *error = 0);
+
+private:
+ AndroidDeviceModel *m_model;
+ Ui::AndroidDeviceDialog *m_ui;
+};
+
diff --git a/gui/androidfiledialog.cpp b/gui/androidfiledialog.cpp
new file mode 100644
index 00000000..e3c1479a
--- /dev/null
+++ b/gui/androidfiledialog.cpp
@@ -0,0 +1,279 @@
+#include "androidfiledialog.h"
+#include "androidutils.h"
+
+#include "ui_androidfiledialog.h"
+
+#include <QAbstractTableModel>
+#include <QApplication>
+#include <QFileInfo>
+
+typedef QLatin1String _;
+
+static bool androidFileLessThan(const AndroidUtils::FileInfo &file1, const AndroidUtils::FileInfo &file2)
+{
+ if (file1.type != file2.type)
+ return file1.type == AndroidUtils::FileInfo::Directory;
+ return file1.name < file2.name;
+}
+
+const int FileInfoRole = Qt::UserRole + 1;
+
+static QString humanSize(double size)
+{
+ QStringList list;
+ list << " KB" << " MB" << " GB";
+
+ QStringListIterator i(list);
+ QString unit("bytes");
+
+ while(size >= 1024.0 && i.hasNext())
+ {
+ unit = i.next();
+ size /= 1024.0;
+ }
+
+ return QString::number(size, 'f', 2) + unit;
+}
+
+class AndroidFileDialogModel : public QAbstractTableModel
+{
+public:
+ AndroidFileDialogModel(QObject * parent = 0)
+ : QAbstractTableModel(parent)
+ {}
+
+ void setDir(const QString &dir)
+ {
+ m_fileList = m_androidUtils.ls(dir + _("/"));
+ setFilterSuffix(m_suffix);
+ }
+
+ void setFilterSuffix(const QString &suffix)
+ {
+ m_suffix = suffix;
+ beginResetModel();
+ if (!m_suffix.isEmpty()) {
+ AndroidUtils::FileInfoList::iterator it = m_fileList.begin();
+ while(it != m_fileList.end()) {
+ if (it->type == AndroidUtils::FileInfo::File &&
+ !it->name.endsWith(m_suffix)) {
+ it = m_fileList.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ }
+ std::sort(m_fileList.begin(), m_fileList.end(), androidFileLessThan);
+ endResetModel();
+ }
+
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
+ {
+ if (!index.isValid() || index.row() >= m_fileList.size())
+ return QVariant();
+
+ QVariant ret;
+ switch (role) {
+ case Qt::DisplayRole:
+ switch (index.column()) {
+ case 0:
+ ret = m_fileList.at(index.row()).name;
+ break;
+ case 1:
+ {
+ const AndroidUtils::FileInfo &file = m_fileList.at(index.row());
+ if (file.type == AndroidUtils::FileInfo::File)
+ ret = humanSize(file.size);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case Qt::DecorationRole:
+ if (index.column() == 0) {
+ if (m_fileList.at(index.row()).type == AndroidUtils::FileInfo::File)
+ ret = qApp->style()->standardIcon(QStyle::SP_FileIcon);
+ else
+ ret = qApp->style()->standardIcon(QStyle::SP_DirIcon);
+ }
+ break;
+
+ case Qt::TextAlignmentRole:
+ ret = int(index.column() == 1 ? Qt::AlignRight : Qt::AlignLeft) | Qt::AlignVCenter;
+ break;
+
+ case FileInfoRole:
+ ret = QVariant::fromValue(m_fileList.at(index.row()));
+ break;
+ default:
+ break;
+ }
+ return ret;
+ }
+ virtual QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const {
+ if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
+ return QVariant();
+
+ QVariant ret;
+ switch (section) {
+ case 0:
+ ret = tr("Name");
+ break;
+ case 1:
+ ret = tr("Size");
+ break;
+ }
+ return ret;
+ }
+
+ virtual int columnCount(const QModelIndex &parent = QModelIndex()) const
+ {
+ return 2;
+ }
+
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const
+ {
+ if (parent.isValid())
+ return 0;
+ return m_fileList.size();
+ }
+
+private:
+ AndroidUtils m_androidUtils;
+ QString m_suffix;
+ AndroidUtils::FileInfoList m_fileList;
+};
+
+AndroidFileDialog::AndroidFileDialog(Mode mode, QWidget *parent)
+ : QDialog(parent),
+ m_ui(new Ui::AndroidFileDialog),
+ m_model(new AndroidFileDialogModel(this)),
+ m_mode(mode)
+{
+ m_ui->setupUi(this);
+ m_ui->pathComboBox->setModel(&m_pathModel);
+ m_ui->filesView->setModel(m_model);
+ m_ui->upButton->setIcon(qApp->style()->standardIcon(QStyle::SP_ArrowUp));
+ m_ui->buttonBox->setStandardButtons(QDialogButtonBox::StandardButton(m_mode) | QDialogButtonBox::Cancel);
+ connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(accept()));
+ connect(m_ui->upButton, SIGNAL(clicked()), SLOT(upFolder()));
+ connect(m_ui->pathComboBox, SIGNAL(activated(QString)), SLOT(setDir(QString)));
+ QHeaderView *hv = m_ui->filesView->horizontalHeader();
+ hv->setSectionResizeMode(0, QHeaderView::Stretch);
+ hv->setSectionResizeMode(1, QHeaderView::ResizeToContents);
+ connect(m_ui->filesView, SIGNAL(activated(QModelIndex)), SLOT(itemActivated(QModelIndex)));
+}
+
+AndroidFileDialog::~AndroidFileDialog()
+{
+ delete m_model;
+}
+
+void AndroidFileDialog::setInitialPath(const QString &path)
+{
+ AndroidUtils::FileInfoList files = AndroidUtils().ls(path);
+ if (files.size() == 1 && files.at(0).type == AndroidUtils::FileInfo::File) {
+ QFileInfo fi(path);
+ m_ui->fileLineEdit->setText(fi.fileName());
+ setDir(fi.absolutePath());
+ } else {
+ if (files.isEmpty() && m_mode == SaveFile) {
+ QFileInfo fi(path);
+ m_ui->fileLineEdit->setText(fi.fileName());
+ setDir(fi.absolutePath());
+ } else {
+ m_ui->fileLineEdit->setText(QString());
+ setDir(path);
+ }
+ }
+}
+
+void AndroidFileDialog::setSuffix(const QString &suffix)
+{
+ m_model->setFilterSuffix(suffix);
+}
+
+QString AndroidFileDialog::filePath() const
+{
+ return m_dir + _("/") + m_ui->fileLineEdit->text();
+}
+
+QString AndroidFileDialog::getOpenFileName(QWidget *parent, const QString &caption, const QString &path, const QString &filter)
+{
+ AndroidFileDialog d(OpenFile, parent);
+ d.setWindowTitle(caption);
+ d.setSuffix(filter);
+ d.setInitialPath(path);
+ if (d.exec() == QDialog::Accepted)
+ return d.filePath();
+ return QString();
+}
+
+QString AndroidFileDialog::getSaveFileName(QWidget *parent, const QString &caption, const QString &path, const QString &filter)
+{
+ AndroidFileDialog d(SaveFile, parent);
+ d.setWindowTitle(caption);
+ d.setSuffix(filter);
+ d.setInitialPath(path);
+ if (d.exec() == QDialog::Accepted)
+ return d.filePath();
+ return QString();
+}
+
+void AndroidFileDialog::accept()
+{
+ if (m_mode == SaveFile) {
+ QDialog::accept();
+ return;
+ }
+ AndroidUtils::FileInfoList files = AndroidUtils().ls(filePath());
+ if (files.size() == 1 && files.at(0).type == AndroidUtils::FileInfo::File)
+ QDialog::accept();
+}
+
+void AndroidFileDialog::upFolder()
+{
+ setDir(QFileInfo(m_dir).absolutePath());
+}
+
+void AndroidFileDialog::itemActivated(QModelIndex index)
+{
+ QVariant file = index.data(FileInfoRole);
+ if (file.isNull())
+ return;
+ AndroidUtils::FileInfo f = file.value<AndroidUtils::FileInfo>();
+ if (f.type == AndroidUtils::FileInfo::Directory) {
+ setDir(m_dir + _("/") + f.name);
+ } else {
+ m_ui->fileLineEdit->setText(f.name);
+ accept();
+ }
+}
+
+void AndroidFileDialog::setDir(const QString &dir)
+{
+ m_dir = dir;
+ while (m_dir.endsWith(QLatin1Char('/')))
+ m_dir.chop(1);
+
+ if (m_dir.isEmpty())
+ m_dir = _("/");
+
+ QStringList paths;
+ QString dirname = m_dir;
+ paths << dirname;
+ while (dirname != _("/")) {
+ dirname = QFileInfo(dirname).absolutePath();
+ paths << dirname;
+ }
+
+ m_pathModel.setStringList(paths);
+ m_ui->pathComboBox->setCurrentIndex(0);
+ m_ui->upButton->setEnabled(paths.size() > 1);
+ m_model->setDir(dir);
+}
+
+Q_DECLARE_METATYPE(AndroidUtils::FileInfo);
diff --git a/gui/androidfiledialog.h b/gui/androidfiledialog.h
new file mode 100644
index 00000000..ac626ef0
--- /dev/null
+++ b/gui/androidfiledialog.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QStringListModel>
+#include <QModelIndex>
+
+class AndroidFileDialogModel;
+
+namespace Ui { class AndroidFileDialog; }
+
+class AndroidFileDialog : public QDialog
+{
+ Q_OBJECT
+ enum Mode {
+ OpenFile = QDialogButtonBox::Open,
+ SaveFile = QDialogButtonBox::Save
+ };
+
+public:
+ explicit AndroidFileDialog(Mode mode, QWidget *parent = 0);
+ ~AndroidFileDialog();
+
+ void setInitialPath(const QString &path);
+ void setSuffix(const QString &suffix);
+ QString filePath() const;
+ void setMode(Mode mode);
+
+ static QString getOpenFileName(QWidget *parent = 0, const QString &caption = QString(), const QString &path = QString(), const QString &suffix = QString());
+ static QString getSaveFileName(QWidget *parent = 0, const QString &caption = QString(), const QString &path = QString(), const QString &filter = QString());
+
+private slots:
+ virtual void accept();
+ void upFolder();
+ void itemActivated(QModelIndex index);
+ void setDir(const QString &dir);
+
+private:
+ QString m_dir;
+ QStringListModel m_pathModel;
+ Ui::AndroidFileDialog *m_ui;
+ AndroidFileDialogModel *m_model;
+ Mode m_mode;
+};
+
diff --git a/gui/androidretracer.cpp b/gui/androidretracer.cpp
new file mode 100644
index 00000000..de70606d
--- /dev/null
+++ b/gui/androidretracer.cpp
@@ -0,0 +1,326 @@
+#include "androidretracer.h"
+
+#include "androiddevicedialog.h"
+
+#include "thumbnail.h"
+
+#include "image/image.hpp"
+#include "trace_profiler.hpp"
+
+#include <QHostAddress>
+#include <QSettings>
+#include <QTime>
+#include <QBuffer>
+
+#include "qubjson.h"
+
+typedef QLatin1String _;
+
+static QLatin1String packageName("apitrace.github.io.eglretrace");
+static QLatin1String activityName("/.RetraceActivity");
+
+AndroidRetracer::AndroidRetracer(QObject *parent)
+ : Retracer(parent),
+ m_stdoutPort(52341),
+ m_stderrPort(52342)
+{
+ connect(&m_androidUtils, SIGNAL(statusMessage(QString)),
+ SIGNAL(statusMessage(QString)));
+}
+
+void AndroidRetracer::setAndroidFileName(const QString &fileName)
+{
+ m_androdiFileName = fileName;
+}
+
+static int extractPidFromChunk(const QByteArray &chunk, int from)
+{
+ int pos1 = chunk.indexOf(' ', from);
+ if (pos1 == -1)
+ return -1;
+ while (chunk[pos1] == ' ')
+ ++pos1;
+ int pos3 = chunk.indexOf(' ', pos1);
+ int pid = chunk.mid(pos1, pos3 - pos1).toInt();
+ return pid;
+}
+
+static int extractPid(const QByteArray &psOutput)
+{
+ static const QByteArray needle("apitrace.github.io.eglretrace\r");
+ const int to = psOutput.indexOf(needle);
+ if (to == -1)
+ return -1;
+ const int from = psOutput.lastIndexOf('\n', to);
+ if (from == -1)
+ return -1;
+ return extractPidFromChunk(psOutput, from);
+}
+
+static QByteArray readLine(QTcpSocket &sock)
+{
+ while (!sock.canReadLine() && sock.waitForReadyRead());
+ if (sock.state() != QAbstractSocket::ConnectedState)
+ return QByteArray();
+ return sock.readLine();
+}
+
+static bool read(QTcpSocket &sock, char *ptr, qint64 sz)
+{
+ do {
+ qint64 readBytes = sock.read(ptr, sz);
+ ptr += readBytes;
+ sz -= readBytes;
+ } while(sz && sock.waitForReadyRead());
+ return sz == 0;
+}
+
+void AndroidRetracer::run()
+{
+ m_androidUtils.reloadAdb();
+ QString errorStr;
+ bool setupRet;
+ QMetaObject::invokeMethod(this, "setup", Qt::BlockingQueuedConnection,
+ Q_RETURN_ARG(bool, setupRet),
+ Q_ARG(QString *, &errorStr));
+
+ if (!setupRet) {
+ emit finished(errorStr);
+ return;
+ }
+
+ if (!m_androidUtils.runAdb(QStringList() << _("shell") << _("am") << _("start") << _("-n") << packageName + activityName)) {
+ emit finished(tr("Can't start apitrace application"));
+ return;
+ }
+ QByteArray which;
+ if (!m_androidUtils.runAdb(QStringList() << _("shell") << _("readlink") << _("$(which ps)") , &which)) {
+ emit finished(tr("Can't start adb"));
+ return;
+ }
+
+ bool isBusyBox = which.startsWith("busybox");
+ QStringList psArgs;
+ psArgs << _("shell") << _("ps");
+ if (isBusyBox)
+ psArgs << _("-w");
+
+ qint64 processPID;
+ bool wasStarted = false;
+ QTime startTime;
+ startTime.start();
+
+ QTcpSocket stdoutSocket;
+ QTcpSocket stderrSocket;
+
+ ImageHash thumbnails;
+
+ QVariantMap parsedJson;
+ trace::Profile* profile = isProfiling() ? new trace::Profile() : NULL;
+
+ QList<ApiTraceError> errors;
+ QRegExp regexp("(^\\d+): +(\\b\\w+\\b): ([^\\r\\n]+)[\\r\\n]*$");
+
+ QString msg = QLatin1String("Replay finished!");
+ QByteArray ubjsonBuffer;
+ QByteArray outputBuffer;
+ bool keepGoing = true;
+ while(keepGoing) {
+ if (!wasStarted || startTime.elapsed() > 1000) {
+ QByteArray psOut;
+ m_androidUtils.runAdb(psArgs, &psOut);
+ processPID = extractPid(psOut);
+ if (wasStarted)
+ startTime.restart();
+ }
+
+ if (processPID == -1) {
+ if (wasStarted) {
+ break;
+ } else {
+ if (startTime.elapsed() > 3000) { // wait 3 seconds to start
+ emit finished(tr("Unable to start retrace on device."));
+ return;
+ }
+ }
+ msleep(100);
+ continue;
+ }
+
+ // we have a valid pid, it means the application started
+ if (!wasStarted) {
+ // connect the sockets
+ int tries = 0;
+ do {
+ stdoutSocket.connectToHost(QHostAddress::LocalHost, m_stdoutPort);
+ } while (!stdoutSocket.waitForConnected(100) && ++tries < 10);
+ if (stdoutSocket.state() != QAbstractSocket::ConnectedState) {
+ emit finished(tr("Can't connect to stdout socket."));
+ return;
+ }
+
+ // Android doesn't suport GPU and PPD profiling (at leats not on my devices)
+ //setProfiling(false, isProfilingCpu(), false);
+
+ QString args = (retraceArguments() << m_androdiFileName).join(" ") + _("\n");
+ stdoutSocket.write(args.toUtf8());
+ if (!stdoutSocket.waitForBytesWritten()) {
+ emit finished(tr("Can't send params."));
+ return;
+ }
+
+
+ stderrSocket.connectToHost(QHostAddress::LocalHost, m_stderrPort);
+ stderrSocket.waitForConnected(100);
+ if (stderrSocket.state() != QAbstractSocket::ConnectedState) {
+ emit finished(tr("Can't connect to stderr socket."));
+ return;
+ }
+ wasStarted = true;
+ }
+
+ // We are going to read both channels at the same time
+
+ // read stdout channel
+ if (stdoutSocket.waitForReadyRead(100)) {
+ if (captureState())
+ ubjsonBuffer.append(stdoutSocket.readAll());
+ else if (captureThumbnails()) {
+ // read one image
+ image::PNMInfo info;
+ QByteArray header;
+ int headerLines = 3; // assume no optional comment line
+ for (int headerLine = 0; headerLine < headerLines; ++headerLine) {
+ QByteArray line = readLine(stdoutSocket);
+ if (line.isEmpty()) {
+ keepGoing = false;
+ break;
+ }
+ header += line;
+ // if header actually contains optional comment line, ...
+ if (headerLine == 1 && line[0] == '#') {
+ ++headerLines;
+ }
+ }
+
+ const char *headerEnd = image::readPNMHeader(header.constData(), header.size(), info);
+
+ // if invalid PNM header was encountered, ...
+ if (headerEnd == NULL ||
+ info.channelType != image::TYPE_UNORM8) {
+ qDebug() << "error: invalid snapshot stream encountered";
+ keepGoing = false;
+ break;
+ }
+
+ unsigned channels = info.channels;
+ unsigned width = info.width;
+ unsigned height = info.height;
+
+ // qDebug() << "channels: " << channels << ", width: " << width << ", height: " << height";
+
+ QImage snapshot = QImage(width, height, channels == 1 ? QImage::Format_Mono : QImage::Format_RGB888);
+
+ int rowBytes = channels * width;
+ for (int y = 0; y < height; ++y) {
+ unsigned char *scanLine = snapshot.scanLine(y);
+ if (!read(stdoutSocket, (char *) scanLine, rowBytes)) {
+ keepGoing = false;
+ break;
+ }
+ }
+
+ QImage thumb = thumbnail(snapshot);
+ thumbnails.insert(info.commentNumber, thumb);
+ } else if (isProfiling()) {
+ QByteArray line = readLine(stdoutSocket);
+ if (line.isEmpty()) {
+ keepGoing = false;
+ break;
+ }
+ line.append('\0');
+ trace::Profiler::parseLine(line.constData(), profile);
+ } else {
+ outputBuffer.append(stdoutSocket.readAll());
+ }
+ }
+
+ // read stderr channel
+ if (stderrSocket.waitForReadyRead(5) && stderrSocket.canReadLine()) {
+ QString line = stderrSocket.readLine();
+ if (regexp.indexIn(line) != -1) {
+ ApiTraceError error;
+ error.callIndex = regexp.cap(1).toInt();
+ error.type = regexp.cap(2);
+ error.message = regexp.cap(3);
+ errors.append(error);
+ } else if (!errors.isEmpty()) {
+ // Probably a multiligne message
+ ApiTraceError &previous = errors.last();
+ if (line.endsWith("\n")) {
+ line.chop(1);
+ }
+ previous.message.append('\n');
+ previous.message.append(line);
+ }
+ }
+ }
+
+ if (outputBuffer.size() < 80)
+ msg = outputBuffer;
+
+ if (captureState()) {
+ QBuffer io(&ubjsonBuffer);
+ io.open(QIODevice::ReadOnly);
+
+ parsedJson = decodeUBJSONObject(&io).toMap();
+ ApiTraceState *state = new ApiTraceState(parsedJson);
+ emit foundState(state);
+ }
+
+ if (captureThumbnails() && !thumbnails.isEmpty()) {
+ emit foundThumbnails(thumbnails);
+ }
+
+ if (isProfiling() && profile) {
+ emit foundProfile(profile);
+ }
+
+ if (!errors.isEmpty()) {
+ emit retraceErrors(errors);
+ }
+
+ emit finished(msg);
+}
+
+bool AndroidRetracer::setup(QString *error)
+{
+ m_androidUtils.reloadAdb();
+ if (m_androidUtils.serialNumber().isEmpty()) {
+ *error = tr("No device selected");
+ return false;
+ }
+
+ // forward adbPorts
+ QSettings s;
+ s.beginGroup(_("android"));
+ m_stdoutPort = s.value(_("stdoutPort"), m_stdoutPort).toInt();
+ m_stderrPort = s.value(_("stderrPort"), m_stderrPort).toInt();
+ s.endGroup();
+
+ if (!m_androidUtils.runAdb(QStringList(_("forward"))
+ << QString::fromLatin1("tcp:%1").arg(m_stdoutPort)
+ << _("localabstract:apitrace.github.io.eglretrace.stdout"))) {
+ *error = tr("Can't forward ports");
+ return false;
+ }
+
+ if (!m_androidUtils.runAdb(QStringList(_("forward"))
+ << QString::fromLatin1("tcp:%1").arg(m_stderrPort)
+ << _("localabstract:apitrace.github.io.eglretrace.stderr"))) {
+ *error = tr("Can't forward ports");
+ return false;
+ }
+
+ return true;
+}
diff --git a/gui/androidretracer.h b/gui/androidretracer.h
new file mode 100644
index 00000000..f2c758e5
--- /dev/null
+++ b/gui/androidretracer.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <QAtomicInt>
+#include <QTcpSocket>
+
+#include "androidutils.h"
+#include "retracer.h"
+
+class AndroidRetracer : public Retracer
+{
+ Q_OBJECT
+public:
+ AndroidRetracer(QObject *parent);
+
+ void setAndroidFileName(const QString &fileName);
+
+signals:
+ void statusMessage(const QString &message);
+
+protected:
+ void run();
+
+private slots:
+ bool setup(QString *error);
+
+private:
+ QString m_androdiFileName;
+ QString m_serialNumber;
+ AndroidUtils m_androidUtils;
+ int m_stdoutPort;
+ int m_stderrPort;
+};
+
diff --git a/gui/androidutils.cpp b/gui/androidutils.cpp
new file mode 100644
index 00000000..ac0ca263
--- /dev/null
+++ b/gui/androidutils.cpp
@@ -0,0 +1,185 @@
+#include "androidutils.h"
+#include "androiddevicedialog.h"
+
+#include <QCoreApplication>
+#include <QByteArray>
+#include <QFileInfo>
+#include <QProcess>
+#include <QSettings>
+#include <QStringList>
+
+typedef QLatin1String _;
+
+static QString s_androidSerialNumber;
+
+QStringList AndroidDeviceInfo::adbSelector(const QString &serialNumber)
+{
+ if (serialNumber.startsWith(_("????")))
+ return QStringList() << _("-d");
+ return QStringList() << _("-s") << serialNumber;
+}
+
+QString AndroidDeviceInfo::adbPath()
+{
+ QSettings s;
+ s.beginGroup(_("android"));
+ return s.value(_("adbPath"), _("adb")).toString();
+}
+
+AndroidUtils::FileInfo::FileInfo()
+{
+ type = File;
+ size = 0;
+}
+
+AndroidUtils::AndroidUtils()
+{
+ m_wait = 30000;
+ reloadAdb();
+}
+
+void AndroidUtils::reloadAdb()
+{
+ m_adbPath = AndroidDeviceInfo::adbPath();
+}
+
+QString AndroidUtils::serialNumber() const
+{
+ if (m_serialNumber.isEmpty())
+ m_serialNumber = s_androidSerialNumber;
+
+ if (m_serialNumber.isEmpty()) {
+ AndroidDeviceDialog ad;
+ if (ad.exec() != QDialog::Accepted)
+ return QString();
+
+ m_serialNumber = ad.device().serialNumber;
+ if (ad.saveDeviceSelection())
+ s_androidSerialNumber = m_serialNumber;
+ }
+ return m_serialNumber;
+}
+
+bool AndroidUtils::runAdb(const QStringList &params, QByteArray *output) const
+{
+ QProcess adbProcess;
+ adbProcess.start(m_adbPath, AndroidDeviceInfo::adbSelector(serialNumber()) << params);
+ if (!output)
+ connect(&adbProcess, SIGNAL(readyReadStandardError()), SLOT(processReadyRead()));
+
+ if (!adbProcess.waitForStarted())
+ return false;
+
+ if (!adbProcess.waitForFinished(m_wait > INT_MAX ? -1 : m_wait))
+ return false;
+
+ if (output)
+ *output = adbProcess.readAll();
+ return true;
+}
+
+AndroidUtils::FileInfoList AndroidUtils::ls(const QString &path) const
+{
+ m_wait = 10000;
+ FileInfoList ret;
+ QByteArray lsOutput;
+ runAdb(QStringList(_("shell")) << _("ls") << _("-l") << path, &lsOutput);
+ foreach (const QByteArray &line, lsOutput.split('\n')) {
+ if (line.isEmpty() || line[10] != ' ')
+ continue;
+
+ int pos = line.indexOf(':');
+ if (pos == -1)
+ continue;
+ pos += 3;
+ if (pos >= line.size())
+ continue;
+
+ FileInfo f;
+ // Assume all links are directories
+ f.type = (line[0] == 'd' || line[0] == 'l') ? FileInfo::Directory : FileInfo::File;
+ f.name = line.mid(pos).trimmed();
+ if (f.type == FileInfo::File) {
+ pos = line.lastIndexOf('-', pos);
+ if (pos < 4)
+ continue;
+ pos = line.lastIndexOf('-', pos -1);
+ if (pos < 3)
+ continue;
+ pos = line.lastIndexOf(' ', pos -1);
+ if (pos < 2)
+ continue;
+ int startPos = line.lastIndexOf(' ', pos -1);
+ if (startPos == -1)
+ continue;
+ f.size = line.mid(startPos, pos - startPos).trimmed().toLongLong();
+ } else if (line[0] == 'l') {
+ // Fix links
+ pos = f.name.indexOf(_("->"));
+ if (pos < 2)
+ continue;
+ f.name = f.name.left(pos - 1).trimmed();
+ }
+ ret << f;
+ }
+ return ret;
+}
+
+bool AndroidUtils::sameFile(const QString &localPath, const QString &devicePath)
+{
+ QFileInfo fi(localPath);
+ QList<FileInfo> deviceFiles = ls(devicePath);
+ return fi.exists() && (deviceFiles.size() == 1) && (deviceFiles.first().size == fi.size());
+}
+
+bool AndroidUtils::updateFile(const QString &localPath, const QString &devicePath, UpdateType updateType)
+{
+ if (sameFile(localPath, devicePath))
+ return true;
+
+ QFileInfo fi(localPath);
+ QList<FileInfo> deviceFiles = ls(devicePath);
+
+ switch (updateType) {
+ case PushLocalToDevice:
+ if (!fi.exists())
+ return false;
+
+ m_wait = std::min(fi.size() / 1024, qint64(30000));
+ if (!runAdb(QStringList()<< _("push") << _("-p") << localPath << devicePath))
+ return false;
+
+ deviceFiles = ls(devicePath);
+
+ if (deviceFiles.size() != 1 || deviceFiles.first().size != fi.size())
+ return false; // pushing to device failed
+ break;
+
+ case PullFromDeviceToLocal:
+ if (deviceFiles.size() != 1)
+ return false;
+
+ m_wait = std::min(deviceFiles.at(0).size / 1024, qint64(30000));
+ if (!runAdb(QStringList()<< _("pull") << _("-p") << devicePath << localPath))
+ return false;
+
+ fi = QFileInfo(localPath);
+ if (!fi.exists() || deviceFiles.first().size != fi.size())
+ return false; // pulling from device failed
+ break;
+ }
+ return true;
+}
+
+void AndroidUtils::processReadyRead()
+{
+ QProcess *proc = qobject_cast<QProcess *>(QObject::sender());
+ if (proc) {
+ QByteArray stdOutErr = proc->readAllStandardError();
+ foreach (const QByteArray &line, stdOutErr.split('\r')) {
+ QString msg(line.trimmed());
+ if (!msg.isEmpty())
+ emit statusMessage(msg);
+ }
+ }
+}
diff --git a/gui/androidutils.h b/gui/androidutils.h
new file mode 100644
index 00000000..60c8abea
--- /dev/null
+++ b/gui/androidutils.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include <QList>
+#include <QObject>
+#include <QString>
+
+class QByteArray;
+class QStringList;
+
+
+struct AndroidDeviceInfo
+{
+ QString serialNumber;
+ enum State { OkState, UnAuthorizedState, OfflineState };
+ State state;
+ bool unauthorized;
+ enum AndroidDeviceType { Hardware, Emulator };
+ AndroidDeviceType type;
+
+ static QStringList adbSelector(const QString &serialNumber);
+ static QString adbPath();
+};
+
+class AndroidUtils : public QObject
+{
+ Q_OBJECT
+public:
+ struct FileInfo
+ {
+ FileInfo();
+
+ enum Type {
+ File,
+ Directory
+ };
+ Type type;
+ QString name;
+ qint64 size;
+ };
+
+ typedef QList<FileInfo> FileInfoList;
+
+ enum UpdateType {
+ PushLocalToDevice,
+ PullFromDeviceToLocal
+ };
+
+public:
+ AndroidUtils();
+
+ void reloadAdb();
+
+ QString serialNumber() const;
+
+ bool runAdb(const QStringList &params, QByteArray *output = 0) const;
+ FileInfoList ls(const QString &path) const;
+
+ bool sameFile(const QString &localPath, const QString &devicePath);
+ bool updateFile(const QString &localPath, const QString &devicePath, UpdateType updateType);
+
+signals:
+ void statusMessage(const QString &message);
+
+private slots:
+ void processReadyRead();
+
+private:
+ QString m_adbPath;
+ mutable qint64 m_wait;
+ mutable QString m_serialNumber;
+};
diff --git a/gui/apicalldelegate.cpp b/gui/apicalldelegate.cpp
index 9ad9f24a..d52e2d10 100644
--- a/gui/apicalldelegate.cpp
+++ b/gui/apicalldelegate.cpp
@@ -43,6 +43,8 @@ void ApiCallDelegate::paint(QPainter *painter,
if (!thumbnail.isNull()) {
painter->drawImage(offset, thumbnail);
offset += QPoint(textSize.height() + thumbnail.width(), option.rect.height()/2 - textSize.height()/2);
+ } else {
+ frame->missingThumbnail();
}
}
@@ -54,6 +56,13 @@ void ApiCallDelegate::paint(QPainter *painter,
}
if (event->type() == ApiTraceEvent::Call) {
ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
+ const QImage & thumbnail = call->thumbnail();
+ if (!thumbnail.isNull()) {
+ painter->drawImage(offset, thumbnail);
+ offset += QPoint(textSize.height() + thumbnail.width(), option.rect.height()/2 - textSize.height()/2);
+ } else if (call->flags() & trace::CALL_FLAG_RENDER) {
+ call->missingThumbnail();
+ }
if (call->hasError()) {
QPixmap px = m_errorEmblem.pixmap(textSize.height(),
textSize.height());
@@ -101,6 +110,15 @@ QSize ApiCallDelegate::sizeHint(const QStyleOptionViewItem &option,
size.setHeight(thumbnail.height());
}
}
+ } else if (event->type() == ApiTraceEvent::Call) {
+ ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
+ const QImage & thumbnail = call->thumbnail();
+ if (!thumbnail.isNull()) {
+ size.rwidth() += thumbnail.width();
+ if (size.height() < thumbnail.height()) {
+ size.setHeight(thumbnail.height());
+ }
+ }
}
return size;
diff --git a/gui/apicalldelegate.h b/gui/apicalldelegate.h
index 18c8b33a..c4379586 100644
--- a/gui/apicalldelegate.h
+++ b/gui/apicalldelegate.h
@@ -1,5 +1,4 @@
-#ifndef APICALLDELEGATE_H
-#define APICALLDELEGATE_H
+#pragma once
#include <QStyledItemDelegate>
@@ -20,5 +19,3 @@ private:
QIcon m_editEmblem;
QIcon m_errorEmblem;
};
-
-#endif
diff --git a/gui/apisurface.cpp b/gui/apisurface.cpp
index 22de5f0b..4f0a9173 100644
--- a/gui/apisurface.cpp
+++ b/gui/apisurface.cpp
@@ -25,29 +25,29 @@ void ApiSurface::setSize(const QSize &size)
struct ByteArrayBuf : public std::streambuf
{
- ByteArrayBuf(QByteArray & a)
+ ByteArrayBuf(const QByteArray & a)
{
- setg(a.data(), a.data(), a.data() + a.size());
+ setg((char *)a.data(), (char *)a.data(), (char *)a.data() + a.size());
}
};
-void ApiSurface::contentsFromBase64(const QByteArray &base64)
+void ApiSurface::setData(const QByteArray &data)
{
- m_base64Data = base64;
+ m_data = data;
/*
* We need to do the conversion to create the thumbnail
*/
- image::Image *image = imageFromBase64(base64);
+ image::Image *image = imageFromData(data);
Q_ASSERT(image);
QImage img = qimageFromRawImage(image);
m_thumb = thumbnail(img);
delete image;
}
-QByteArray ApiSurface::base64Data() const
+QByteArray ApiSurface::data() const
{
- return m_base64Data;
+ return m_data;
}
QImage ApiSurface::thumb() const
@@ -107,9 +107,8 @@ void ApiFramebuffer::setType(const QString &str)
}
image::Image *
-ApiSurface::imageFromBase64(const QByteArray &base64)
+ApiSurface::imageFromData(const QByteArray &dataArray)
{
- QByteArray dataArray = QByteArray::fromBase64(base64);
image::Image *image;
/*
diff --git a/gui/apisurface.h b/gui/apisurface.h
index 19fbce31..de5f531d 100644
--- a/gui/apisurface.h
+++ b/gui/apisurface.h
@@ -1,5 +1,4 @@
-#ifndef APISURFACE_H
-#define APISURFACE_H
+#pragma once
#include <QImage>
#include <QSize>
@@ -23,12 +22,12 @@ public:
QString formatName() const;
void setFormatName(const QString &str);
- void contentsFromBase64(const QByteArray &base64);
+ void setData(const QByteArray &data);
- QByteArray base64Data() const;
+ QByteArray data() const;
QImage thumb() const;
- static image::Image *imageFromBase64(const QByteArray &data);
+ static image::Image *imageFromData(const QByteArray &data);
static QImage qimageFromRawImage(const image::Image *img,
float lowerValue = 0.0f,
float upperValue = 1.0f,
@@ -37,7 +36,7 @@ public:
private:
QSize m_size;
- QByteArray m_base64Data;
+ QByteArray m_data;
QImage m_thumb;
int m_depth;
QString m_formatName;
@@ -68,5 +67,3 @@ private:
QString m_type;
};
-
-#endif
diff --git a/gui/apitrace.cpp b/gui/apitrace.cpp
index 3f840eee..18556173 100644
--- a/gui/apitrace.cpp
+++ b/gui/apitrace.cpp
@@ -4,6 +4,7 @@
#include "saverthread.h"
#include <QDebug>
+#include <QFileInfo>
#include <QDir>
#include <QThread>
@@ -44,6 +45,8 @@ ApiTrace::ApiTrace()
this, SIGNAL(foundCallIndex(ApiTraceCall*)));
+ connect(m_loader, SIGNAL(parseProblem(const QString&)),
+ this, SIGNAL(problemLoadingTrace(const QString&)));
connect(m_loader, SIGNAL(startedParsing()),
this, SIGNAL(startedLoadingTrace()));
connect(m_loader, SIGNAL(parsed(int)),
@@ -173,11 +176,13 @@ ApiTraceState ApiTrace::defaultState() const
void ApiTrace::callEdited(ApiTraceCall *call)
{
if (!m_editedCalls.contains(call)) {
- //lets generate a temp filename
+ // Lets generate a temp filename
+ QFileInfo fileInfo(m_fileName);
QString tempPath = QDir::tempPath();
- m_tempFileName = QString::fromLatin1("%1/%2.edited")
- .arg(tempPath)
- .arg(m_fileName);
+ m_tempFileName = QDir::tempPath();
+ m_tempFileName += QDir::separator();
+ m_tempFileName += fileInfo.fileName();
+ m_tempFileName += QString::fromLatin1(".edited");
}
m_editedCalls.insert(call);
m_needsSaving = true;
@@ -276,18 +281,19 @@ void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame,
if (!m_queuedErrors.isEmpty()) {
QList< QPair<ApiTraceFrame*, ApiTraceError> >::iterator itr;
- for (itr = m_queuedErrors.begin(); itr != m_queuedErrors.end();
- ++itr) {
+ itr = m_queuedErrors.begin();
+ while (itr != m_queuedErrors.end()) {
const ApiTraceError &error = (*itr).second;
if ((*itr).first == frame) {
ApiTraceCall *call = frame->callWithIndex(error.callIndex);
if (!call) {
+ ++itr;
continue;
}
call->setError(error.message);
- m_queuedErrors.erase(itr);
+ itr = m_queuedErrors.erase(itr);
if (call->hasError()) {
m_errors.insert(call);
@@ -295,6 +301,8 @@ void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame,
m_errors.remove(call);
}
emit changed(call);
+ } else {
+ ++itr;
}
}
}
@@ -459,22 +467,24 @@ int ApiTrace::callInFrame(int callIdx) const
void ApiTrace::setCallError(const ApiTraceError &error)
{
int frameIdx = callInFrame(error.callIndex);
- ApiTraceFrame *frame = 0;
-
if (frameIdx < 0) {
return;
}
- frame = m_frames[frameIdx];
+ ApiTraceFrame *frame = 0;
+ frame = m_frames[frameIdx];
if (frame->isLoaded()) {
ApiTraceCall *call = frame->callWithIndex(error.callIndex);
- call->setError(error.message);
- if (call->hasError()) {
- m_errors.insert(call);
- } else {
- m_errors.remove(call);
+ // call might be null if the error is in a filtered call
+ if (call) {
+ call->setError(error.message);
+ if (call->hasError()) {
+ m_errors.insert(call);
+ } else {
+ m_errors.remove(call);
+ }
+ emit changed(call);
}
- emit changed(call);
} else {
loadFrame(frame);
m_queuedErrors.append(qMakePair(frame, error));
@@ -486,21 +496,80 @@ bool ApiTrace::isFrameLoading(ApiTraceFrame *frame) const
return m_loadingFrames.contains(frame);
}
-void ApiTrace::bindThumbnailsToFrames(const QList<QImage> &thumbnails)
+void ApiTrace::bindThumbnails(const ImageHash &thumbnails)
{
- QList<ApiTraceFrame *> frames = m_frames;
+ QHashIterator<int, QImage> i(thumbnails);
- QList<QImage>::const_iterator thumbnail = thumbnails.begin();
+ while (i.hasNext()) {
+ i.next();
- foreach (ApiTraceFrame *frame, frames) {
- if (thumbnail != thumbnails.end()) {
- frame->setThumbnail(*thumbnail);
+ if (!m_thumbnails.contains(i.key())) {
+ int callIndex = i.key();
+ const QImage &thumbnail = i.value();
- ++thumbnail;
+ m_thumbnails.insert(callIndex, thumbnail);
- emit changed(frame);
+ // find the frame associated with the call index
+ int frameIndex = 0;
+ while (frameAt(frameIndex)->lastCallIndex() < callIndex) {
+ ++frameIndex;
+ }
+
+ ApiTraceFrame *frame = frameAt(frameIndex);
+
+ // if the call was actually for a frame, ...
+ if (callIndex == frame->lastCallIndex()) {
+ frame->setThumbnail(thumbnail);
+
+ emit changed(frame);
+ } else {
+ ApiTraceCall *call = frame->callWithIndex(callIndex);
+ if (call) {
+ call->setThumbnail(thumbnail);
+
+ emit changed(call);
+ }
+ }
}
}
}
+void ApiTrace::missingThumbnail(ApiTraceFrame *frame)
+{
+ missingThumbnail(frame->lastCallIndex());
+}
+
+void ApiTrace::missingThumbnail(ApiTraceCall *call)
+{
+ missingThumbnail(call->index());
+}
+
+void ApiTrace::missingThumbnail(int callIdx)
+{
+ // technically, the contain() test is redundant, since this is a set;
+ // however, it enables debugging techniques to confirm correct behavior
+ if (!m_missingThumbnails.contains(callIdx)) {
+ //qDebug() << QLatin1String("debug: new missing thumbnail: ") << callIdx;
+ m_missingThumbnails.insert(callIdx);
+ }
+}
+
+bool ApiTrace::isMissingThumbnails() const
+{
+ return !m_missingThumbnails.isEmpty();
+}
+void ApiTrace::resetMissingThumbnails()
+{
+ m_missingThumbnails.clear();
+}
+
+void ApiTrace::iterateMissingThumbnails(void *object, ThumbnailCallback cb)
+{
+ //qDebug() << QLatin1String("debug: count of missing thumbnail list") << m_missingThumbnails.count();
+ foreach (int thumbnailIndex, m_missingThumbnails) {
+ //qDebug() << QLatin1String("debug: iterate missing thumbnail list") << thumbnailIndex;
+ (*cb)(object, thumbnailIndex);
+ }
+}
+
#include "apitrace.moc"
diff --git a/gui/apitrace.h b/gui/apitrace.h
index 22bedec2..d7259924 100644
--- a/gui/apitrace.h
+++ b/gui/apitrace.h
@@ -1,5 +1,4 @@
-#ifndef APITRACE_H
-#define APITRACE_H
+#pragma once
#include "apitracecall.h"
@@ -12,6 +11,9 @@ class TraceLoader;
class SaverThread;
class QThread;
+typedef void (*ThumbnailCallback)(void *object, int thumbnailIdx);
+typedef QHash<int, QImage> ImageHash;
+
class ApiTrace : public QObject
{
Q_OBJECT
@@ -77,6 +79,14 @@ public:
trace::API api() const;
+ void missingThumbnail(ApiTraceFrame* frame);
+ void missingThumbnail(ApiTraceCall* call);
+
+ bool isMissingThumbnails() const;
+ void resetMissingThumbnails();
+
+ void iterateMissingThumbnails(void *object, ThumbnailCallback cb);
+
public slots:
void setFileName(const QString &name);
void save();
@@ -95,11 +105,12 @@ public slots:
void findCallIndex(int index);
void setCallError(const ApiTraceError &error);
- void bindThumbnailsToFrames(const QList<QImage> &thumbnails);
+ void bindThumbnails(const ImageHash &thumbnails);
signals:
void loadTrace(const QString &name);
void requestFrame(ApiTraceFrame *frame);
+ void problemLoadingTrace(const QString &message);
void startedLoadingTrace();
void loaded(int percent);
void finishedLoadingTrace();
@@ -141,6 +152,8 @@ private slots:
private:
int callInFrame(int callIdx) const;
bool isFrameLoading(ApiTraceFrame *frame) const;
+
+ void missingThumbnail(int callIdx);
private:
QString m_fileName;
QString m_tempFileName;
@@ -159,6 +172,8 @@ private:
QSet<ApiTraceCall*> m_errors;
QList< QPair<ApiTraceFrame*, ApiTraceError> > m_queuedErrors;
QSet<ApiTraceFrame*> m_loadingFrames;
-};
-#endif
+ QSet<int> m_missingThumbnails;
+
+ ImageHash m_thumbnails;
+};
diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp
index a746cdd2..8ae03d0e 100644
--- a/gui/apitracecall.cpp
+++ b/gui/apitracecall.cpp
@@ -185,24 +185,17 @@ void VariantVisitor::visit(trace::Double *node)
void VariantVisitor::visit(trace::String *node)
{
- m_variant = QVariant(QString::fromStdString(node->value));
+ m_variant = QVariant(QString::fromLatin1(node->value));
}
-void VariantVisitor::visit(trace::Enum *e)
+void VariantVisitor::visit(trace::WString *node)
{
- ApiTraceEnumSignature *sig = 0;
-
- if (m_loader) {
- sig = m_loader->enumSignature(e->sig->id);
- }
- if (!sig) {
- sig = new ApiTraceEnumSignature(e->sig);
- if (m_loader) {
- m_loader->addEnumSignature(e->sig->id, sig);
- }
- }
+ m_variant = QVariant(QString::fromWCharArray(node->value));
+}
- m_variant = QVariant::fromValue(ApiEnum(sig, e->value));
+void VariantVisitor::visit(trace::Enum *e)
+{
+ m_variant = QVariant::fromValue(ApiEnum(e->sig, e->value));
}
void VariantVisitor::visit(trace::Bitmask *bitmask)
@@ -237,42 +230,24 @@ void VariantVisitor::visit(trace::Repr *repr)
repr->humanValue->visit(*this);
}
-ApiTraceEnumSignature::ApiTraceEnumSignature(const trace::EnumSig *sig)
-{
- for (const trace::EnumValue *it = sig->values;
- it != sig->values + sig->num_values; ++it) {
- QPair<QString, signed long long> pair;
-
- pair.first = QString::fromStdString(it->name);
- pair.second = it->value;
-
- m_names.append(pair);
- }
-}
-
-QString ApiTraceEnumSignature::name(signed long long value) const
-{
- for (ValueList::const_iterator it = m_names.begin();
- it != m_names.end(); ++it) {
- if (value == it->second) {
- return it->first;
- }
- }
- return QString::fromLatin1("%1").arg(value);
-}
-
-ApiEnum::ApiEnum(ApiTraceEnumSignature *sig, signed long long value)
+ApiEnum::ApiEnum(const trace::EnumSig *sig, signed long long value)
: m_sig(sig), m_value(value)
{
+ Q_ASSERT(m_sig);
}
QString ApiEnum::toString() const
{
- if (m_sig) {
- return m_sig->name(m_value);
+ Q_ASSERT(m_sig);
+
+ for (const trace::EnumValue *it = m_sig->values;
+ it != m_sig->values + m_sig->num_values; ++it) {
+ if (m_value == it->value) {
+ return QString::fromLatin1(it->name);
+ }
}
- Q_ASSERT(!"should never happen");
- return QString();
+
+ return QString::fromLatin1("%1").arg(m_value);
}
QVariant ApiEnum::value() const
@@ -284,15 +259,6 @@ QVariant ApiEnum::value() const
return QVariant();
}
-QString ApiEnum::name() const
-{
- if (m_sig) {
- return m_sig->name(m_value);
- }
- Q_ASSERT(!"should never happen");
- return QString();
-}
-
unsigned long long ApiBitmask::value() const
{
return m_value;
@@ -348,7 +314,7 @@ void ApiBitmask::init(const trace::Bitmask *bitmask)
it != bitmask->sig->flags + bitmask->sig->num_flags; ++it) {
QPair<QString, unsigned long long> pair;
- pair.first = QString::fromStdString(it->name);
+ pair.first = QString::fromLatin1(it->name);
pair.second = it->value;
m_sig.append(pair);
@@ -411,11 +377,11 @@ void ApiStruct::init(const trace::Struct *s)
if (!s)
return;
- m_sig.name = QString::fromStdString(s->sig->name);
+ m_sig.name = QString::fromLatin1(s->sig->name);
for (unsigned i = 0; i < s->sig->num_members; ++i) {
- VariantVisitor vis(0);
+ VariantVisitor vis;
m_sig.memberNames.append(
- QString::fromStdString(s->sig->member_names[i]));
+ QString::fromLatin1(s->sig->member_names[i]));
s->members[i]->visit(vis);
m_members.append(vis.variant());
}
@@ -458,7 +424,7 @@ void ApiArray::init(const trace::Array *arr)
m_array.reserve(arr->values.size());
for (int i = 0; i < arr->values.size(); ++i) {
- VariantVisitor vis(0);
+ VariantVisitor vis;
arr->values[i]->visit(vis);
m_array.append(vis.variant());
@@ -470,6 +436,34 @@ ApiTraceState::ApiTraceState()
{
}
+static ApiTexture getTextureFrom(QVariantMap const &image, QString label)
+{
+ QSize size(image[QLatin1String("__width__")].toInt(),
+ image[QLatin1String("__height__")].toInt());
+ QString cls = image[QLatin1String("__class__")].toString();
+ int depth =
+ image[QLatin1String("__depth__")].toInt();
+ QString formatName =
+ image[QLatin1String("__format__")].toString();
+
+ QByteArray dataArray =
+ image[QLatin1String("__data__")].toByteArray();
+
+ QString userLabel =
+ image[QLatin1String("__label__")].toString();
+ if (!userLabel.isEmpty()) {
+ label += QString(", \"%1\"").arg(userLabel);
+ }
+
+ ApiTexture tex;
+ tex.setSize(size);
+ tex.setDepth(depth);
+ tex.setFormatName(formatName);
+ tex.setLabel(label);
+ tex.setData(dataArray);
+ return tex;
+}
+
ApiTraceState::ApiTraceState(const QVariantMap &parsedJson)
{
m_parameters = parsedJson[QLatin1String("parameters")].toMap();
@@ -487,29 +481,14 @@ ApiTraceState::ApiTraceState(const QVariantMap &parsedJson)
m_uniforms = parsedJson[QLatin1String("uniforms")].toMap();
- QVariantMap textures =
- parsedJson[QLatin1String("textures")].toMap();
- for (itr = textures.constBegin(); itr != textures.constEnd(); ++itr) {
- QVariantMap image = itr.value().toMap();
- QSize size(image[QLatin1String("__width__")].toInt(),
- image[QLatin1String("__height__")].toInt());
- QString cls = image[QLatin1String("__class__")].toString();
- int depth =
- image[QLatin1String("__depth__")].toInt();
- QString formatName =
- image[QLatin1String("__format__")].toString();
+ m_buffers = parsedJson[QLatin1String("buffers")].toMap();
- QByteArray dataArray =
- image[QLatin1String("__data__")].toByteArray();
-
- ApiTexture tex;
- tex.setSize(size);
- tex.setDepth(depth);
- tex.setFormatName(formatName);
- tex.setLabel(itr.key());
- tex.contentsFromBase64(dataArray);
-
- m_textures.append(tex);
+ {
+ QVariantMap textures =
+ parsedJson[QLatin1String("textures")].toMap();
+ for (itr = textures.constBegin(); itr != textures.constEnd(); ++itr) {
+ m_textures.append(getTextureFrom(itr.value().toMap(), itr.key()));
+ }
}
QVariantMap fbos =
@@ -525,12 +504,19 @@ ApiTraceState::ApiTraceState(const QVariantMap &parsedJson)
QByteArray dataArray =
buffer[QLatin1String("__data__")].toByteArray();
+ QString label = itr.key();
+ QString userLabel =
+ buffer[QLatin1String("__label__")].toString();
+ if (!userLabel.isEmpty()) {
+ label += QString(", \"%1\"").arg(userLabel);
+ }
+
ApiFramebuffer fbo;
fbo.setSize(size);
fbo.setDepth(depth);
fbo.setFormatName(formatName);
- fbo.setType(itr.key());
- fbo.contentsFromBase64(dataArray);
+ fbo.setType(label);
+ fbo.setData(dataArray);
m_framebuffers.append(fbo);
}
}
@@ -550,6 +536,11 @@ const QVariantMap & ApiTraceState::uniforms() const
return m_uniforms;
}
+const QVariantMap & ApiTraceState::buffers() const
+{
+ return m_buffers;
+}
+
bool ApiTraceState::isEmpty() const
{
return m_parameters.isEmpty() &&
@@ -607,8 +598,7 @@ void ApiTraceCallSignature::setHelpUrl(const QUrl &url)
ApiTraceEvent::ApiTraceEvent()
: m_type(ApiTraceEvent::None),
- m_hasBinaryData(false),
- m_binaryDataIndex(0),
+ m_binaryDataIndex(-1),
m_state(0),
m_staticText(0)
{
@@ -616,11 +606,11 @@ ApiTraceEvent::ApiTraceEvent()
ApiTraceEvent::ApiTraceEvent(Type t)
: m_type(t),
- m_hasBinaryData(false),
- m_binaryDataIndex(0),
+ m_binaryDataIndex(-1),
m_state(0),
m_staticText(0)
{
+ Q_ASSERT(m_type == t);
}
ApiTraceEvent::~ApiTraceEvent()
@@ -629,15 +619,6 @@ ApiTraceEvent::~ApiTraceEvent()
delete m_staticText;
}
-QVariantMap ApiTraceEvent::stateParameters() const
-{
- if (m_state) {
- return m_state->parameters();
- } else {
- return QVariantMap();
- }
-}
-
ApiTraceState *ApiTraceEvent::state() const
{
return m_state;
@@ -648,6 +629,16 @@ void ApiTraceEvent::setState(ApiTraceState *state)
m_state = state;
}
+void ApiTraceEvent::setThumbnail(const QImage & thumbnail)
+{
+ m_thumbnail = thumbnail;
+}
+
+const QImage & ApiTraceEvent::thumbnail() const
+{
+ return m_thumbnail;
+}
+
ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame,
TraceLoader *loader,
const trace::Call *call)
@@ -683,28 +674,27 @@ ApiTraceCall::loadData(TraceLoader *loader,
m_signature = loader->signature(call->sig->id);
if (!m_signature) {
- QString name = QString::fromStdString(call->sig->name);
+ QString name = QString::fromLatin1(call->sig->name);
QStringList argNames;
argNames.reserve(call->sig->num_args);
for (int i = 0; i < call->sig->num_args; ++i) {
- argNames += QString::fromStdString(call->sig->arg_names[i]);
+ argNames += QString::fromLatin1(call->sig->arg_names[i]);
}
m_signature = new ApiTraceCallSignature(name, argNames);
loader->addSignature(call->sig->id, m_signature);
}
if (call->ret) {
- VariantVisitor retVisitor(loader);
+ VariantVisitor retVisitor;
call->ret->visit(retVisitor);
m_returnValue = retVisitor.variant();
}
m_argValues.reserve(call->args.size());
for (int i = 0; i < call->args.size(); ++i) {
if (call->args[i].value) {
- VariantVisitor argVisitor(loader);
+ VariantVisitor argVisitor;
call->args[i].value->visit(argVisitor);
m_argValues.append(argVisitor.variant());
if (m_argValues[i].type() == QVariant::ByteArray) {
- m_hasBinaryData = true;
m_binaryDataIndex = i;
}
} else {
@@ -910,11 +900,12 @@ QUrl ApiTraceCall::helpUrl() const
bool ApiTraceCall::hasBinaryData() const
{
- return m_hasBinaryData;
+ return m_binaryDataIndex >= 0;
}
int ApiTraceCall::binaryDataIndex() const
{
+ Q_ASSERT(hasBinaryData());
return m_binaryDataIndex;
}
@@ -1117,6 +1108,11 @@ bool ApiTraceCall::contains(const QString &str,
return txt.contains(str, sensitivity);
}
+void ApiTraceCall::missingThumbnail()
+{
+ m_parentFrame->parentTrace()->missingThumbnail(this);
+}
+
ApiTraceFrame::ApiTraceFrame(ApiTrace *parentTrace)
: ApiTraceEvent(ApiTraceEvent::Frame),
@@ -1317,12 +1313,7 @@ unsigned ApiTraceFrame::lastCallIndex() const
}
}
-void ApiTraceFrame::setThumbnail(const QImage & thumbnail)
-{
- m_thumbnail = thumbnail;
-}
-
-const QImage & ApiTraceFrame::thumbnail() const
+void ApiTraceFrame::missingThumbnail()
{
- return m_thumbnail;
+ m_parentTrace->missingThumbnail(this);
}
diff --git a/gui/apitracecall.h b/gui/apitracecall.h
index 46ead63e..7ff03400 100644
--- a/gui/apitracecall.h
+++ b/gui/apitracecall.h
@@ -1,5 +1,4 @@
-#ifndef APITRACECALL_H
-#define APITRACECALL_H
+#pragma once
#include "apisurface.h"
@@ -17,9 +16,6 @@ class TraceLoader;
class VariantVisitor : public trace::Visitor
{
public:
- VariantVisitor(TraceLoader *loader)
- : m_loader(loader)
- {}
virtual void visit(trace::Null *);
virtual void visit(trace::Bool *node);
virtual void visit(trace::SInt *node);
@@ -27,6 +23,7 @@ public:
virtual void visit(trace::Float *node);
virtual void visit(trace::Double *node);
virtual void visit(trace::String *node);
+ virtual void visit(trace::WString *node);
virtual void visit(trace::Enum *e);
virtual void visit(trace::Bitmask *bitmask);
virtual void visit(trace::Struct *str);
@@ -40,7 +37,6 @@ public:
return m_variant;
}
private:
- TraceLoader *m_loader;
QVariant m_variant;
};
@@ -52,29 +48,16 @@ struct ApiTraceError
QString message;
};
-class ApiTraceEnumSignature
-{
-public:
- ApiTraceEnumSignature(const trace::EnumSig *sig);
-
- QString name(signed long long value) const;
-
-private:
- typedef QList<QPair<QString, signed long long> > ValueList;
- ValueList m_names;
-};
-
class ApiEnum
{
public:
- ApiEnum(ApiTraceEnumSignature *sig=0, signed long long value = 0);
+ ApiEnum(const trace::EnumSig *sig=0, signed long long value = 0);
QString toString() const;
QVariant value() const;
- QString name() const;
private:
- ApiTraceEnumSignature *m_sig;
+ const trace::EnumSig *m_sig;
signed long long m_value;
};
Q_DECLARE_METATYPE(ApiEnum);
@@ -165,6 +148,7 @@ public:
const QVariantMap & parameters() const;
const QMap<QString, QString> & shaderSources() const;
const QVariantMap & uniforms() const;
+ const QVariantMap & buffers() const;
const QList<ApiTexture> & textures() const;
const QList<ApiFramebuffer> & framebuffers() const;
@@ -173,6 +157,7 @@ private:
QVariantMap m_parameters;
QMap<QString, QString> m_shaderSources;
QVariantMap m_uniforms;
+ QVariantMap m_buffers;
QList<ApiTexture> m_textures;
QList<ApiFramebuffer> m_framebuffers;
};
@@ -225,7 +210,6 @@ public:
virtual int callIndex(ApiTraceCall *call) const = 0;
virtual ApiTraceEvent *eventAtRow(int row) const = 0;
- QVariantMap stateParameters() const;
ApiTraceState *state() const;
void setState(ApiTraceState *state);
bool hasState() const
@@ -233,13 +217,19 @@ public:
return m_state && !m_state->isEmpty();
}
+ void setThumbnail(const QImage & thumbnail);
+ const QImage & thumbnail() const;
+
+ virtual void missingThumbnail() = 0;
+
protected:
int m_type : 4;
- mutable bool m_hasBinaryData;
mutable int m_binaryDataIndex:8;
ApiTraceState *m_state;
mutable QStaticText *m_staticText;
+
+ QImage m_thumbnail;
};
Q_DECLARE_METATYPE(ApiTraceEvent*);
@@ -297,6 +287,9 @@ public:
QString backtrace() const;
void setBacktrace(QString backtrace);
+
+ void missingThumbnail();
+
private:
void loadData(TraceLoader *loader,
const trace::Call *tcall);
@@ -363,8 +356,7 @@ public:
void setLastCallIndex(unsigned index);
unsigned lastCallIndex() const;
- void setThumbnail(const QImage & thumbnail);
- const QImage & thumbnail() const;
+ void missingThumbnail();
private:
ApiTrace *m_parentTrace;
@@ -374,9 +366,5 @@ private:
bool m_loaded;
unsigned m_callsToLoad;
unsigned m_lastCallIndex;
- QImage m_thumbnail;
};
Q_DECLARE_METATYPE(ApiTraceFrame*);
-
-
-#endif
diff --git a/gui/apitracefilter.h b/gui/apitracefilter.h
index 35f627df..b9cd75d5 100644
--- a/gui/apitracefilter.h
+++ b/gui/apitracefilter.h
@@ -1,5 +1,4 @@
-#ifndef APITRACEFILTER_H
-#define APITRACEFILTER_H
+#pragma once
#include <QRegExp>
#include <QSortFilterProxyModel>
@@ -40,5 +39,3 @@ private:
FilterOptions m_filters;
QRegExp m_customRegexp;
};
-
-#endif
diff --git a/gui/apitracemodel.cpp b/gui/apitracemodel.cpp
index fb339677..51908dea 100644
--- a/gui/apitracemodel.cpp
+++ b/gui/apitracemodel.cpp
@@ -384,7 +384,6 @@ void ApiTraceModel::fetchMore(const QModelIndex &parent)
ApiTraceEvent *event = item(parent);
if (event && event->type() == ApiTraceEvent::Frame) {
ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
- QModelIndex index = createIndex(frame->number, 0, frame);
Q_ASSERT(!frame->isLoaded());
m_loadingFrames.insert(frame);
diff --git a/gui/apitracemodel.h b/gui/apitracemodel.h
index e7354aa6..76876c20 100644
--- a/gui/apitracemodel.h
+++ b/gui/apitracemodel.h
@@ -1,5 +1,4 @@
-#ifndef APITRACEMODEL_H
-#define APITRACEMODEL_H
+#pragma once
#include <QAbstractItemModel>
@@ -67,5 +66,3 @@ private:
ApiTrace *m_trace;
QSet<ApiTraceFrame*> m_loadingFrames;
};
-
-#endif
diff --git a/gui/argumentseditor.h b/gui/argumentseditor.h
index 73cd4580..148b3ff6 100644
--- a/gui/argumentseditor.h
+++ b/gui/argumentseditor.h
@@ -1,5 +1,4 @@
-#ifndef ARGUMENTSEDITOR_H
-#define ARGUMENTSEDITOR_H
+#pragma once
#include "apitracecall.h"
#include "ui_argumentseditor.h"
@@ -182,5 +181,3 @@ private:
ApiTraceCall *m_call;
};
-
-#endif
diff --git a/gui/calldurationgraph.h b/gui/calldurationgraph.h
index 0c7e8c91..be6fe45e 100644
--- a/gui/calldurationgraph.h
+++ b/gui/calldurationgraph.h
@@ -1,5 +1,4 @@
-#ifndef CALLDURATIONGRAPH_H
-#define CALLDURATIONGRAPH_H
+#pragma once
#include "graphing/graphwidget.h"
#include "trace_profiler.hpp"
@@ -170,4 +169,3 @@ private:
SelectionState* m_selectionState;
};
-#endif
diff --git a/gui/glsledit.cpp b/gui/glsledit.cpp
index b73f0980..8cd7f022 100644
--- a/gui/glsledit.cpp
+++ b/gui/glsledit.cpp
@@ -29,7 +29,7 @@
#include "glsledit.h"
-#include <QtGui>
+#include <QtWidgets>
class GLSLBlockData: public QTextBlockUserData
{
diff --git a/gui/graphing/frameaxiswidget.h b/gui/graphing/frameaxiswidget.h
index 59fdc162..4b2c4cbb 100644
--- a/gui/graphing/frameaxiswidget.h
+++ b/gui/graphing/frameaxiswidget.h
@@ -1,5 +1,4 @@
-#ifndef FRAMEAXISWIDGET_H
-#define FRAMEAXISWIDGET_H
+#pragma once
#include "graphaxiswidget.h"
@@ -30,5 +29,3 @@ public:
protected:
FrameDataProvider* m_data;
};
-
-#endif
diff --git a/gui/graphing/graphaxiswidget.h b/gui/graphing/graphaxiswidget.h
index 6ae00800..a8d1c01a 100644
--- a/gui/graphing/graphaxiswidget.h
+++ b/gui/graphing/graphaxiswidget.h
@@ -1,5 +1,4 @@
-#ifndef GRAPHAXISWIDGET_H
-#define GRAPHAXISWIDGET_H
+#pragma once
#include "graphing.h"
@@ -69,5 +68,3 @@ protected:
QPoint m_mousePressPosition;
qint64 m_mousePressValue;
};
-
-#endif
diff --git a/gui/graphing/graphing.h b/gui/graphing/graphing.h
index 35b4a913..f97df8b3 100644
--- a/gui/graphing/graphing.h
+++ b/gui/graphing/graphing.h
@@ -1,5 +1,4 @@
-#ifndef GRAPHING_H
-#define GRAPHING_H
+#pragma once
#include <QString>
@@ -44,5 +43,3 @@ public:
/* Set pointer to selection state */
virtual void setSelectionState(SelectionState* state) = 0;
};
-
-#endif
diff --git a/gui/graphing/graphlabelwidget.h b/gui/graphing/graphlabelwidget.h
index 49c0cd49..050dc40d 100644
--- a/gui/graphing/graphlabelwidget.h
+++ b/gui/graphing/graphlabelwidget.h
@@ -1,5 +1,4 @@
-#ifndef GRAPHLABELWIDGET_H
-#define GRAPHLABELWIDGET_H
+#pragma once
#include <QWidget>
#include <QPainter>
@@ -38,5 +37,3 @@ protected:
int m_flags;
QString m_text;
};
-
-#endif
diff --git a/gui/graphing/graphview.h b/gui/graphing/graphview.h
index 6b881d4e..94328b69 100644
--- a/gui/graphing/graphview.h
+++ b/gui/graphing/graphview.h
@@ -1,5 +1,4 @@
-#ifndef GRAPHVIEW_H
-#define GRAPHVIEW_H
+#pragma once
#include "graphing.h"
@@ -89,5 +88,3 @@ protected:
qint64 m_graphTop;
} m_previous;
};
-
-#endif
diff --git a/gui/graphing/graphwidget.h b/gui/graphing/graphwidget.h
index 16b77868..17cb4651 100644
--- a/gui/graphing/graphwidget.h
+++ b/gui/graphing/graphwidget.h
@@ -1,5 +1,4 @@
-#ifndef GRAPHWIDGET_H
-#define GRAPHWIDGET_H
+#pragma once
#include "graphview.h"
#include "graphaxiswidget.h"
@@ -108,5 +107,3 @@ protected:
qint64 m_verticalEnd;
Qt::ScrollBarPolicy m_verticalScrollbarPolicy;
};
-
-#endif
diff --git a/gui/graphing/heatmapverticalaxiswidget.h b/gui/graphing/heatmapverticalaxiswidget.h
index ca64adb4..9a21c25b 100644
--- a/gui/graphing/heatmapverticalaxiswidget.h
+++ b/gui/graphing/heatmapverticalaxiswidget.h
@@ -1,5 +1,4 @@
-#ifndef HEATMAPVERTICALAXISWIDGET_H
-#define HEATMAPVERTICALAXISWIDGET_H
+#pragma once
#include "heatmapview.h"
#include "graphaxiswidget.h"
@@ -20,5 +19,3 @@ protected:
int m_rowHeight;
HeatmapDataProvider* m_data;
};
-
-#endif
diff --git a/gui/graphing/heatmapview.h b/gui/graphing/heatmapview.h
index 781c9a7a..86d8848d 100644
--- a/gui/graphing/heatmapview.h
+++ b/gui/graphing/heatmapview.h
@@ -1,5 +1,4 @@
-#ifndef HEATMAPVIEW_H
-#define HEATMAPVIEW_H
+#pragma once
#include "graphview.h"
@@ -120,5 +119,3 @@ protected:
int m_rowHeight;
HeatmapDataProvider* m_data;
};
-
-#endif
diff --git a/gui/graphing/histogramview.h b/gui/graphing/histogramview.h
index 563d664b..ae89f7b1 100644
--- a/gui/graphing/histogramview.h
+++ b/gui/graphing/histogramview.h
@@ -1,5 +1,4 @@
-#ifndef HISTOGRAMVIEW_H
-#define HISTOGRAMVIEW_H
+#pragma once
#include "graphview.h"
@@ -37,5 +36,3 @@ protected:
GraphDataProvider* m_data;
};
-
-#endif
diff --git a/gui/graphing/timeaxiswidget.h b/gui/graphing/timeaxiswidget.h
index 836651cb..7f79a399 100644
--- a/gui/graphing/timeaxiswidget.h
+++ b/gui/graphing/timeaxiswidget.h
@@ -1,5 +1,4 @@
-#ifndef TIMEAXISWIDGET_H
-#define TIMEAXISWIDGET_H
+#pragma once
#include "graphaxiswidget.h"
@@ -12,5 +11,3 @@ public:
virtual void paintEvent(QPaintEvent *e);
};
-
-#endif
diff --git a/gui/imageviewer.cpp b/gui/imageviewer.cpp
index 4c3f2bdc..6953c009 100644
--- a/gui/imageviewer.cpp
+++ b/gui/imageviewer.cpp
@@ -61,10 +61,10 @@ ImageViewer::~ImageViewer()
delete m_image;
}
-void ImageViewer::setBase64Data(const QByteArray &base64)
+void ImageViewer::setData(const QByteArray &data)
{
delete m_image;
- m_image = ApiSurface::imageFromBase64(base64);
+ m_image = ApiSurface::imageFromData(data);
m_convertedImage = ApiSurface::qimageFromRawImage(m_image);
m_pixelWidget->setSurface(m_convertedImage);
updateGeometry();
@@ -126,6 +126,10 @@ QString createPixelLabel(image::Image *img, int x, int y)
unsigned char *pixelLocation = 0;
T *pixel;
+ if (x < 0 || y < 0 || x >= img->width || y >= img->height) {
+ return QString::fromLatin1("(Out of bounds)");
+ }
+
pixelLocation = img->pixels + img->stride() * y;
pixelLocation += x * img->bytesPerPixel;
pixel = ((T*)pixelLocation);
diff --git a/gui/imageviewer.h b/gui/imageviewer.h
index ce5d9bdd..7cb2eb52 100644
--- a/gui/imageviewer.h
+++ b/gui/imageviewer.h
@@ -1,5 +1,4 @@
-#ifndef IMAGEVIEWER_H
-#define IMAGEVIEWER_H
+#pragma once
#include "ui_imageviewer.h"
#include <QDialog>
@@ -18,7 +17,7 @@ public:
ImageViewer(QWidget *parent = 0);
~ImageViewer();
- void setBase64Data(const QByteArray &base64);
+ void setData(const QByteArray &data);
QSize sizeHint() const;
@@ -35,6 +34,3 @@ private:
QImage m_convertedImage;
PixelWidget *m_pixelWidget;
};
-
-
-#endif
diff --git a/gui/jumpwidget.h b/gui/jumpwidget.h
index 5f71c002..8fec83f4 100644
--- a/gui/jumpwidget.h
+++ b/gui/jumpwidget.h
@@ -1,5 +1,4 @@
-#ifndef JUMPWIDGET_H
-#define JUMPWIDGET_H
+#pragma once
#include "ui_jumpwidget.h"
#include <QWidget>
@@ -27,5 +26,3 @@ protected:
private:
Ui_JumpWidget m_ui;
};
-
-#endif
diff --git a/gui/leaktracethread.cpp b/gui/leaktracethread.cpp
new file mode 100644
index 00000000..a5b1e346
--- /dev/null
+++ b/gui/leaktracethread.cpp
@@ -0,0 +1,82 @@
+#include "leaktracethread.h"
+
+#include "apitracecall.h"
+
+#include <QDebug>
+#include <QProcess>
+
+void LeakTraceThread::run()
+{
+ QString msg = QLatin1String("Replay finished!");
+
+ /*
+ * Construct command line
+ */
+
+ QString prog = "apitrace";
+ QStringList arguments;
+ arguments << "leaks";
+ arguments << filename;
+
+ /*
+ * Start the process.
+ */
+
+ {
+ QDebug debug(QtDebugMsg);
+ debug << "Running:";
+ debug << prog;
+ foreach (const QString &argument, arguments) {
+ debug << argument;
+ }
+ }
+
+ QProcess process;
+
+ process.start(prog, arguments, QIODevice::ReadOnly);
+ if (!process.waitForStarted(-1)) {
+ return;
+ }
+
+ /*
+ * Wait for process termination
+ */
+
+ process.waitForFinished(-1);
+
+ if (process.exitStatus() != QProcess::NormalExit) {
+ msg = QLatin1String("Process crashed");
+ } else if (process.exitCode() != 0) {
+ msg = QLatin1String("Process exited with non zero exit code");
+ }
+
+ /*
+ * Parse errors.
+ */
+
+ QList<ApiTraceError> errors;
+ process.setReadChannel(QProcess::StandardError);
+ QRegExp regexp("(^\\d+): +(\\b\\w+\\b): ([^\\r\\n]+)[\\r\\n]*$");
+ while (!process.atEnd()) {
+ QString line = process.readLine();
+ qDebug() << line;
+ if (regexp.indexIn(line) != -1) {
+ qDebug() << "error";
+ ApiTraceError error;
+ error.callIndex = regexp.cap(1).toInt();
+ error.type = regexp.cap(2);
+ error.message = regexp.cap(3);
+ errors.append(error);
+ } else {
+ qDebug() << line;
+ }
+ }
+
+ /*
+ * Emit signals
+ */
+
+ error = !errors.empty();
+ emit leakTraceErrors(errors);
+}
+
diff --git a/gui/leaktracethread.h b/gui/leaktracethread.h
new file mode 100644
index 00000000..cbc16ea0
--- /dev/null
+++ b/gui/leaktracethread.h
@@ -0,0 +1,35 @@
+
+#pragma once
+
+#include <QThread>
+#include <QString>
+#include <QList>
+
+struct ApiTraceError;
+
+class LeakTraceThread: public QThread{
+
+ Q_OBJECT
+
+ public:
+
+ LeakTraceThread(QString _filename):filename(_filename){}
+
+
+ bool hasError()const {return error;}
+ signals:
+
+ void leakTraceErrors(const QList<ApiTraceError> &errors);
+
+ protected:
+
+ virtual void run();
+
+ private:
+
+ QString filename;
+
+ bool error=false;
+};
+
+
diff --git a/gui/main.cpp b/gui/main.cpp
index b98bce60..d8f40656 100644
--- a/gui/main.cpp
+++ b/gui/main.cpp
@@ -18,7 +18,7 @@ Q_DECLARE_METATYPE(QVector<ApiTraceCall*>);
Q_DECLARE_METATYPE(Qt::CaseSensitivity);
Q_DECLARE_METATYPE(ApiTrace::SearchResult);
Q_DECLARE_METATYPE(ApiTrace::SearchRequest);
-Q_DECLARE_METATYPE(QList<QImage>);
+Q_DECLARE_METATYPE(ImageHash);
static void usage(void)
{
@@ -30,7 +30,6 @@ static void usage(void)
int main(int argc, char **argv)
{
- QApplication::setGraphicsSystem("raster");
QApplication app(argc, argv);
qRegisterMetaType<QList<ApiTraceFrame*> >();
@@ -39,7 +38,7 @@ int main(int argc, char **argv)
qRegisterMetaType<Qt::CaseSensitivity>();
qRegisterMetaType<ApiTrace::SearchResult>();
qRegisterMetaType<ApiTrace::SearchRequest>();
- qRegisterMetaType<QList<QImage> >();
+ qRegisterMetaType<ImageHash>();
#ifndef Q_OS_WIN
os::String currentProcess = os::getProcessName();
diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp
index f10434d1..129e634d 100644
--- a/gui/mainwindow.cpp
+++ b/gui/mainwindow.cpp
@@ -17,10 +17,14 @@
#include "traceprocess.h"
#include "trimprocess.h"
#include "thumbnail.h"
+#include "androidretracer.h"
+#include "androidfiledialog.h"
#include "ui_retracerdialog.h"
#include "ui_profilereplaydialog.h"
#include "vertexdatainterpreter.h"
#include "trace_profiler.hpp"
+#include "image/image.hpp"
+#include "leaktracethread.h"
#include <QAction>
#include <QApplication>
@@ -32,16 +36,18 @@
#include <QLineEdit>
#include <QMessageBox>
#include <QProgressBar>
+#include <QSettings>
#include <QToolBar>
#include <QUrl>
#include <QVBoxLayout>
#include <QWebPage>
#include <QWebView>
+typedef QLatin1String _;
MainWindow::MainWindow()
: QMainWindow(),
- m_api(trace::API_GL),
+ m_api(trace::API_UNKNOWN),
m_initalCallNum(-1),
m_selectedEvent(0),
m_stateEvent(0),
@@ -97,6 +103,94 @@ void MainWindow::openTrace()
}
}
+void MainWindow::saveTrace()
+{
+ QString localFile = m_trace->fileName();
+
+ QString fileName =
+ QFileDialog::getSaveFileName(
+ this,
+ tr("Save Trace As"),
+ QFileInfo(localFile).fileName(),
+ tr("Trace Files (*.trace);;All Files (*)"));
+
+ if (!fileName.isEmpty()) {
+ QFile::copy(localFile, fileName);
+ }
+}
+
+void MainWindow::pullTrace()
+{
+ QString androidFile = AndroidFileDialog::getOpenFileName(this, tr("Open trace file"), _("/sdcard"), _(".trace"));
+ if (androidFile.isEmpty())
+ return;
+
+ QString localFile =
+ QFileDialog::getSaveFileName(
+ this,
+ tr("Open Trace"),
+ QDir::homePath() + _("/") + QFileInfo(androidFile).fileName(),
+ tr("Trace Files (*.trace)"));
+
+ if (localFile.isEmpty())
+ return;
+
+ AndroidUtils au;
+ connect(&au, SIGNAL(statusMessage(QString)), statusBar(), SLOT(showMessage(QString)));
+ if (au.updateFile(localFile, androidFile, AndroidUtils::PullFromDeviceToLocal)) {
+ m_androidFilePath = androidFile;
+ linkLocalAndroidTrace(localFile, androidFile);
+ newTraceFile(localFile);
+ m_ui.actionRetraceOnAndroid->setChecked(true);
+ } else {
+ QMessageBox::warning(this, tr("Error"),
+ tr("Pulling '%1' for Android device failed.").arg(androidFile));
+ }
+}
+
+void MainWindow::pushTrace()
+{
+ QString localFile = m_trace->fileName();
+ QString androidFile = AndroidFileDialog::getSaveFileName(this, tr("Save trace file"), _("/sdcard/") + QFileInfo(localFile).fileName(), _(".trace"));
+ if (androidFile.isEmpty())
+ return;
+ AndroidUtils au;
+ connect(&au, SIGNAL(statusMessage(QString)), statusBar(), SLOT(showMessage(QString)));
+ if (au.updateFile(localFile, androidFile, AndroidUtils::PushLocalToDevice)) {
+ m_androidFilePath = androidFile;
+ linkLocalAndroidTrace(localFile, androidFile);
+ } else {
+ QMessageBox::warning(this, tr("Error"),
+ tr("Pushing '%1' to Android device failed.\n"
+ "Make usre you have enough space on device.").arg(localFile));
+ }
+ statusBar()->showMessage(QString());
+}
+
+void MainWindow::linkTrace()
+{
+ QString localFile = m_trace->fileName();
+ QString androidFile = AndroidFileDialog::getOpenFileName(this, tr("Link trace file %1").arg(localFile),
+ _("/sdcard/") + QFileInfo(localFile).fileName(),
+ _(".trace"));
+ if (androidFile.isEmpty())
+ return;
+ m_androidFilePath = androidFile;
+ linkLocalAndroidTrace(localFile, androidFile);
+}
+
+void MainWindow::retraceOnAndroid(bool android)
+{
+ delete m_retracer;
+ if (android) {
+ m_retracer = new AndroidRetracer(this);
+ m_androidFilePath = linkedAndroidTrace(m_trace->fileName());
+ } else {
+ m_retracer = new Retracer(this);
+ }
+ initRetraceConnections();
+}
+
void MainWindow::loadTrace(const QString &fileName, int callNum)
{
if (!QFile::exists(fileName)) {
@@ -216,7 +310,7 @@ void MainWindow::replayStart()
m_retracer->setCoreProfile(
dlgUi.coreProfileCB->isChecked());
- m_retracer->setProfiling(false, false, false);
+ m_retracer->setProfiling(false, false, false, false);
replayTrace(false, false);
}
@@ -236,12 +330,17 @@ void MainWindow::replayProfile()
QDialog dlg;
Ui_ProfileReplayDialog dlgUi;
dlgUi.setupUi(&dlg);
+ if (m_ui.actionRetraceOnAndroid->isChecked()) {
+ dlgUi.gpuTimesCB->setChecked(false);
+ dlgUi.pixelsDrawnCB->setChecked(false);
+ }
if (dlg.exec() == QDialog::Accepted) {
m_retracer->setProfiling(
dlgUi.gpuTimesCB->isChecked(),
dlgUi.cpuTimesCB->isChecked(),
- dlgUi.pixelsDrawnCB->isChecked());
+ dlgUi.pixelsDrawnCB->isChecked(),
+ dlgUi.memoryUsageCB->isChecked());
replayTrace(false, false);
}
@@ -255,7 +354,10 @@ void MainWindow::replayStop()
void MainWindow::newTraceFile(const QString &fileName)
{
- qDebug()<< "Loading : " <<fileName;
+ if (m_ui.actionRetraceOnAndroid->isChecked())
+ m_androidFilePath = linkedAndroidTrace(fileName);
+
+ qDebug()<< "Loading:" << fileName;
m_progressBar->setValue(0);
m_trace->setFileName(fileName);
@@ -297,6 +399,15 @@ void MainWindow::replayError(const QString &message)
this, tr("Replay Failed"), message);
}
+void MainWindow::loadError(const QString &message)
+{
+ m_progressBar->hide();
+ statusBar()->showMessage(
+ tr("Load unsuccessful."), 2000);
+ QMessageBox::warning(
+ this, tr("Load Failed"), message);
+}
+
void MainWindow::startedLoadingTrace()
{
Q_ASSERT(m_trace);
@@ -322,6 +433,9 @@ void MainWindow::finishedLoadingTrace()
} else {
m_trace->finishedParsing();
}
+ m_ui.actionPushTrace->setEnabled(m_api == trace::API_EGL);
+ m_ui.actionLinkTrace->setEnabled(m_api == trace::API_EGL);
+ m_ui.actionRetraceOnAndroid->setEnabled(m_api == trace::API_EGL);
}
void MainWindow::replayTrace(bool dumpState, bool dumpThumbnails)
@@ -330,6 +444,48 @@ void MainWindow::replayTrace(bool dumpState, bool dumpThumbnails)
return;
}
+ if (m_ui.actionRetraceOnAndroid->isChecked()) {
+ if (m_androidFilePath.isEmpty()) {
+ QMessageBox::information(this, tr("Info"), tr("Current opened file is not linked with any file on the Android device."));
+ linkTrace();
+ if (m_androidFilePath.isEmpty())
+ return;
+ }
+ // make sure both trace files (local & android) are the same
+ AndroidUtils au;
+ if (!au.sameFile(m_trace->fileName(), m_androidFilePath)) {
+ QMessageBox msgBox;
+ msgBox.setText("Local file is different from the Android file.\nWhat do you want to do?");
+ msgBox.setDetailedText(tr("Chossing:\n"
+ " - \"Update Android\" will push the local file to the device (replacing it).\n"
+ " - \"Update local\" will pull the device file to local (replacing it)."));
+ QAbstractButton *updateAndroid =
+ msgBox.addButton(tr("Update Android"), QMessageBox::ActionRole);
+ QAbstractButton *updateLocal =
+ msgBox.addButton(tr("Update local"), QMessageBox::ActionRole);
+ msgBox.addButton(QMessageBox::Cancel);
+ msgBox.exec();
+ if (msgBox.clickedButton() == updateAndroid) {
+ statusBar()->showMessage(tr("Please wait, pushing the file to device might take long time ..."));
+ if (!au.updateFile(m_trace->fileName(), m_androidFilePath, AndroidUtils::PushLocalToDevice)) {
+ QMessageBox::warning(this, tr("Error"),
+ tr("Pushing '%1' to Android device failed.\n"
+ "Make usre you have enough space on device.").arg(m_trace->fileName()));
+ }
+ } else if (msgBox.clickedButton() == updateLocal) {
+ statusBar()->showMessage(tr("Please wait, pulling the file from device might take long time ..."));
+ if (!au.updateFile(m_trace->fileName(), m_androidFilePath, AndroidUtils::PullFromDeviceToLocal)) {
+ QMessageBox::warning(this, tr("Error"),
+ tr("Pulling '%1' for Android device failed.").arg(m_androidFilePath));
+ }
+ } else {
+ return;
+ }
+ statusBar()->showMessage(QString());
+ }
+ static_cast<AndroidRetracer *>(m_retracer)->setAndroidFileName(m_androidFilePath);
+ }
+
m_retracer->setFileName(m_trace->fileName());
m_retracer->setAPI(m_api);
m_retracer->setCaptureState(dumpState);
@@ -353,6 +509,11 @@ void MainWindow::replayTrace(bool dumpState, bool dumpThumbnails)
}
m_retracer->setCaptureAtCallNumber(index);
}
+ if (m_trace->isMissingThumbnails()) {
+ m_retracer->resetThumbnailsToCapture();
+ m_trace->iterateMissingThumbnails(this, this->thumbnailCallback);
+ m_trace->resetMissingThumbnails();
+ }
m_retracer->start();
m_ui.actionStop->setEnabled(true);
@@ -484,8 +645,9 @@ variantListToItems(const QVector<QVariant> &lst,
const QVector<QVariant> &defaultLst,
QList<QTreeWidgetItem *> &items)
{
+ int width = QString::number(lst.count()).length();
for (int i = 0; i < lst.count(); ++i) {
- QString key = QString::number(i);
+ QString key = QString::number(i).rightJustified(width, ' ');
QVariant var = lst[i];
QVariant defaultVar;
@@ -500,23 +662,42 @@ variantListToItems(const QVector<QVariant> &lst,
}
}
-static bool
-isVariantDeep(const QVariant &var)
+// Get the depth (dimensionality) of the variant:
+//
+// It will return:
+// 0: scalar
+// 1: vector (up to 4 elems)
+// 2: matrix (up to 4x4 elements)
+// 3: array
+// 4: map, etc.
+static unsigned
+getVariantDepth(const QVariant &var)
{
if (var.type() == QVariant::List) {
QVector<QVariant> lst = var.toList().toVector();
+ unsigned maxDepth = 0;
for (int i = 0; i < lst.count(); ++i) {
- if (isVariantDeep(lst[i])) {
- return true;
+ unsigned elemDepth = getVariantDepth(lst[i]);
+ if (elemDepth > maxDepth) {
+ if (elemDepth >= 4) {
+ return elemDepth;
+ }
+ maxDepth = elemDepth;
+ }
+ }
+ if (lst.count() > 1) {
+ if (lst.count() > 4) {
+ return 3;
}
+ maxDepth += 1;
}
- return false;
+ return maxDepth;
} else if (var.type() == QVariant::Map) {
- return true;
+ return 4;
} else if (var.type() == QVariant::Hash) {
- return true;
+ return 4;
} else {
- return false;
+ return 0;
}
}
@@ -530,7 +711,7 @@ variantToItem(const QString &key, const QVariant &var,
QString val;
- bool deep = isVariantDeep(var);
+ bool deep = getVariantDepth(var) >= 3;
if (!deep) {
variantToString(var, val);
}
@@ -579,12 +760,42 @@ static void addSurfaceItem(const ApiSurface &surface,
.arg(width)
.arg(height);
+ QString toolTip;
+ toolTip += QString::fromLatin1("label = %1\n").arg(label);
+ toolTip += QString::fromLatin1("format = %1\n").arg(surface.formatName());
+ toolTip += QString::fromLatin1("width = %1\n").arg(width);
+ toolTip += QString::fromLatin1("height = %1\n").arg(height);
+ item->setToolTip(0, toolTip);
+ item->setToolTip(1, toolTip);
+
//item->setText(1, descr);
QLabel *l = new QLabel(descr, tree);
l->setWordWrap(true);
tree->setItemWidget(item, 1, l);
- item->setData(0, Qt::UserRole, surface.base64Data());
+ item->setData(0, Qt::UserRole, surface.data());
+}
+
+void MainWindow::addSurface(const ApiTexture &image, QTreeWidgetItem *parent) {
+ addSurfaceItem(image, image.label(), parent, m_ui.surfacesTreeWidget);
+}
+
+void MainWindow::addSurface(const ApiFramebuffer &fbo, QTreeWidgetItem *parent) {
+ addSurfaceItem(fbo, fbo.type(), parent, m_ui.surfacesTreeWidget);
+}
+
+template <typename Surface>
+void MainWindow::addSurfaces(const QList<Surface> &surfaces, const char *label) {
+ if (!surfaces.isEmpty()) {
+ QTreeWidgetItem *imageItem = new QTreeWidgetItem(m_ui.surfacesTreeWidget);
+ imageItem->setText(0, tr(label));
+ if (surfaces.count() <= 6) {
+ imageItem->setExpanded(true);
+ }
+ for (int i = 0; i < surfaces.count(); ++i) {
+ addSurface(surfaces[i], imageItem);
+ }
+ }
}
void MainWindow::fillStateForFrame()
@@ -624,6 +835,11 @@ void MainWindow::fillStateForFrame()
variantMapToItems(state.uniforms(), QVariantMap(), uniformsItems);
m_ui.uniformsTreeWidget->insertTopLevelItems(0, uniformsItems);
+ m_ui.buffersTreeWidget->clear();
+ QList<QTreeWidgetItem *> buffersItems;
+ variantMapToItems(state.buffers(), QVariantMap(), buffersItems);
+ m_ui.buffersTreeWidget->insertTopLevelItems(0, buffersItems);
+
const QList<ApiTexture> &textures =
state.textures();
const QList<ApiFramebuffer> &fbos =
@@ -634,38 +850,8 @@ void MainWindow::fillStateForFrame()
m_ui.surfacesTab->setDisabled(false);
} else {
m_ui.surfacesTreeWidget->setIconSize(QSize(THUMBNAIL_SIZE, THUMBNAIL_SIZE));
- if (!textures.isEmpty()) {
- QTreeWidgetItem *textureItem =
- new QTreeWidgetItem(m_ui.surfacesTreeWidget);
- textureItem->setText(0, tr("Textures"));
- if (textures.count() <= 6) {
- textureItem->setExpanded(true);
- }
-
- for (int i = 0; i < textures.count(); ++i) {
- const ApiTexture &texture =
- textures[i];
- addSurfaceItem(texture, texture.label(),
- textureItem,
- m_ui.surfacesTreeWidget);
- }
- }
- if (!fbos.isEmpty()) {
- QTreeWidgetItem *fboItem =
- new QTreeWidgetItem(m_ui.surfacesTreeWidget);
- fboItem->setText(0, tr("Framebuffers"));
- if (fbos.count() <= 6) {
- fboItem->setExpanded(true);
- }
-
- for (int i = 0; i < fbos.count(); ++i) {
- const ApiFramebuffer &fbo =
- fbos[i];
- addSurfaceItem(fbo, fbo.type(),
- fboItem,
- m_ui.surfacesTreeWidget);
- }
- }
+ addSurfaces(textures, "Textures");
+ addSurfaces(fbos, "Framebuffers");
m_ui.surfacesTab->setEnabled(true);
}
m_ui.stateDock->show();
@@ -679,6 +865,27 @@ void MainWindow::showSettings()
dialog.exec();
}
+void MainWindow::leakTrace()
+{
+ LeakTraceThread *t=new LeakTraceThread(m_trace->fileName());
+
+ connect (t,SIGNAL(finished()),this,SLOT(leakTraceFinished()));
+
+ connect (t,SIGNAL(leakTraceErrors(const QList<ApiTraceError> &)),
+ this,SLOT(slotRetraceErrors(const QList<ApiTraceError>&)));
+
+ t->start();
+}
+
+void MainWindow::leakTraceFinished(){
+
+ LeakTraceThread *t = qobject_cast<LeakTraceThread*>(sender());
+
+ m_ui.errorsDock->setVisible(t->hasError());
+
+ delete t;
+}
+
void MainWindow::openHelp(const QUrl &url)
{
QDesktopServices::openUrl(url);
@@ -734,8 +941,8 @@ void MainWindow::showSelectedSurface()
viewer->setAttribute(Qt::WA_DeleteOnClose, true);
- QByteArray base64Data = var.value<QByteArray>();
- viewer->setBase64Data(base64Data);
+ QByteArray data = var.value<QByteArray>();
+ viewer->setData(data);
viewer->show();
viewer->raise();
@@ -817,6 +1024,8 @@ void MainWindow::initObjects()
void MainWindow::initConnections()
{
+ connect(m_trace, SIGNAL(problemLoadingTrace(const QString&)),
+ this, SLOT(loadError(const QString&)));
connect(m_trace, SIGNAL(startedLoadingTrace()),
this, SLOT(startedLoadingTrace()));
connect(m_trace, SIGNAL(loaded(int)),
@@ -838,21 +1047,13 @@ void MainWindow::initConnections()
connect(m_trace, SIGNAL(foundCallIndex(ApiTraceCall*)),
this, SLOT(slotJumpToResult(ApiTraceCall*)));
- connect(m_retracer, SIGNAL(finished(const QString&)),
- this, SLOT(replayFinished(const QString&)));
- connect(m_retracer, SIGNAL(error(const QString&)),
- this, SLOT(replayError(const QString&)));
- connect(m_retracer, SIGNAL(foundState(ApiTraceState*)),
- this, SLOT(replayStateFound(ApiTraceState*)));
- connect(m_retracer, SIGNAL(foundProfile(trace::Profile*)),
- this, SLOT(replayProfileFound(trace::Profile*)));
- connect(m_retracer, SIGNAL(foundThumbnails(const QList<QImage>&)),
- this, SLOT(replayThumbnailsFound(const QList<QImage>&)));
- connect(m_retracer, SIGNAL(retraceErrors(const QList<ApiTraceError>&)),
- this, SLOT(slotRetraceErrors(const QList<ApiTraceError>&)));
+ initRetraceConnections();
+
connect(m_ui.vertexInterpretButton, SIGNAL(clicked()),
m_vdataInterpreter, SLOT(interpretData()));
+ connect(m_ui.bufferExportButton, SIGNAL(clicked()),
+ this, SLOT(exportBufferData()));
connect(m_ui.vertexTypeCB, SIGNAL(currentIndexChanged(const QString&)),
m_vdataInterpreter, SLOT(setTypeFromString(const QString&)));
connect(m_ui.vertexStrideSB, SIGNAL(valueChanged(int)),
@@ -867,6 +1068,16 @@ void MainWindow::initConnections()
this, SLOT(createTrace()));
connect(m_ui.actionOpen, SIGNAL(triggered()),
this, SLOT(openTrace()));
+ connect(m_ui.actionSave, SIGNAL(triggered()),
+ this, SLOT(saveTrace()));
+ connect(m_ui.actionPullTrace, SIGNAL(triggered()),
+ this, SLOT(pullTrace()));
+ connect(m_ui.actionPushTrace, SIGNAL(triggered()),
+ this, SLOT(pushTrace()));
+ connect(m_ui.actionLinkTrace, SIGNAL(triggered()),
+ this, SLOT(linkTrace()));
+ connect(m_ui.actionRetraceOnAndroid, SIGNAL(toggled(bool)),
+ this, SLOT(retraceOnAndroid(bool)));
connect(m_ui.actionQuit, SIGNAL(triggered()),
this, SLOT(close()));
@@ -893,6 +1104,8 @@ void MainWindow::initConnections()
this, SLOT(showThumbnails()));
connect(m_ui.actionOptions, SIGNAL(triggered()),
this, SLOT(showSettings()));
+ connect(m_ui.actionLeakTrace,SIGNAL(triggered()),
+ this, SLOT(leakTrace()));
connect(m_ui.callView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(callItemSelected(const QModelIndex &)));
@@ -948,9 +1161,31 @@ void MainWindow::initConnections()
this, SLOT(slotJumpTo(int)));
}
+void MainWindow::initRetraceConnections()
+{
+ connect(m_retracer, SIGNAL(finished(const QString&)),
+ this, SLOT(replayFinished(const QString&)));
+ connect(m_retracer, SIGNAL(error(const QString&)),
+ this, SLOT(replayError(const QString&)));
+ connect(m_retracer, SIGNAL(foundState(ApiTraceState*)),
+ this, SLOT(replayStateFound(ApiTraceState*)));
+ connect(m_retracer, SIGNAL(foundProfile(trace::Profile*)),
+ this, SLOT(replayProfileFound(trace::Profile*)));
+ connect(m_retracer, SIGNAL(foundThumbnails(const ImageHash&)),
+ this, SLOT(replayThumbnailsFound(const ImageHash&)));
+ connect(m_retracer, SIGNAL(retraceErrors(const QList<ApiTraceError>&)),
+ this, SLOT(slotRetraceErrors(const QList<ApiTraceError>&)));
+}
+
void MainWindow::updateActionsState(bool traceLoaded, bool stopped)
{
+ m_ui.actionPushTrace->setEnabled(false);
+ m_ui.actionLinkTrace->setEnabled(false);
+ m_ui.actionRetraceOnAndroid->setEnabled(false);
if (traceLoaded) {
+ /* File */
+ m_ui.actionSave ->setEnabled(true);
+
/* Edit */
m_ui.actionFind ->setEnabled(true);
m_ui.actionGo ->setEnabled(true);
@@ -973,6 +1208,9 @@ void MainWindow::updateActionsState(bool traceLoaded, bool stopped)
m_ui.actionTrim ->setEnabled(true);
}
else {
+ /* File */
+ m_ui.actionSave ->setEnabled(false);
+
/* Edit */
m_ui.actionFind ->setEnabled(false);
m_ui.actionGo ->setEnabled(false);
@@ -1017,10 +1255,10 @@ void MainWindow::replayStateFound(ApiTraceState *state)
m_nonDefaultsLookupEvent = 0;
}
-void MainWindow::replayThumbnailsFound(const QList<QImage> &thumbnails)
+void MainWindow::replayThumbnailsFound(const ImageHash &thumbnails)
{
m_ui.callView->setUniformRowHeights(false);
- m_trace->bindThumbnailsToFrames(thumbnails);
+ m_trace->bindThumbnails(thumbnails);
}
void MainWindow::slotGoTo()
@@ -1075,8 +1313,11 @@ void MainWindow::slotSearchNext(const QString &str,
ApiTraceCall *call = currentCall();
ApiTraceFrame *frame = currentFrame();
- Q_ASSERT(call || frame);
if (!frame) {
+ // Trace is still loading.
+ if (!call) {
+ return;
+ }
frame = call->parentFrame();
}
Q_ASSERT(frame);
@@ -1090,8 +1331,11 @@ void MainWindow::slotSearchPrev(const QString &str,
ApiTraceCall *call = currentCall();
ApiTraceFrame *frame = currentFrame();
- Q_ASSERT(call || frame);
if (!frame) {
+ // Trace is still loading.
+ if (!call) {
+ return;
+ }
frame = call->parentFrame();
}
Q_ASSERT(frame);
@@ -1270,22 +1514,31 @@ void MainWindow::saveSelectedSurface()
}
QVariant var = item->data(0, Qt::UserRole);
+ if (!var.isValid()) {
+ return;
+ }
+
QImage img = var.value<QImage>();
+ if (img.isNull()) {
+ image::Image *traceImage = ApiSurface::imageFromData(var.value<QByteArray>());
+ img = ApiSurface::qimageFromRawImage(traceImage);
+ delete traceImage;
+ }
+ if (img.isNull()) {
+ statusBar()->showMessage( "Failed to save image", 5000);
+ return;
+ }
QString imageIndex;
- if (selectedCall()) {
+ ApiTraceCall *call = selectedCall();
+ if (call) {
imageIndex = tr("_call_%1")
- .arg(selectedCall()->index());
- } else if (selectedFrame()) {
- ApiTraceCall *firstCall =
- static_cast<ApiTraceCall *>(selectedFrame()->eventAtRow(0));
- if (firstCall) {
- imageIndex = tr("_frame_%1")
- .arg(firstCall->index());
- } else {
- qDebug()<<"unknown frame number";
+ .arg(call->index());
+ } else {
+ ApiTraceFrame *frame = selectedFrame();
+ if (frame) {
imageIndex = tr("_frame_%1")
- .arg(firstCall->index());
+ .arg(frame->number);
}
}
@@ -1311,8 +1564,50 @@ void MainWindow::saveSelectedSurface()
.arg(parentIndex)
.arg(childIndex);
//qDebug()<<"save "<<fileName;
- img.save(fileName, "PNG");
- statusBar()->showMessage( tr("Saved '%1'").arg(fileName), 5000);
+ if (img.save(fileName, "PNG")) {
+ statusBar()->showMessage( tr("Saved '%1'").arg(fileName), 5000);
+ } else {
+ statusBar()->showMessage( tr("Failed to save '%1'").arg(fileName), 5000);
+ }
+}
+
+void MainWindow::exportBufferData()
+{
+ QByteArray data = m_vdataInterpreter->data();
+ if (data.isEmpty())
+ return;
+
+ QString bufferIndex;
+ ApiTraceCall *call = selectedCall();
+ if (call) {
+ bufferIndex = tr("_call_%1").arg(call->index());
+ } else {
+ ApiTraceFrame *frame = selectedFrame();
+ if (frame) {
+ bufferIndex = tr("_frame_%1")
+ .arg(frame->number);
+ }
+ }
+
+ QString filename =
+ tr("%1%2_buffer.raw")
+ .arg(m_trace->fileName())
+ .arg(bufferIndex);
+
+ QFile file(filename);
+ if (!file.open(QIODevice::WriteOnly)) {
+ statusBar()->showMessage("Failed to save buffer data", 5000);
+ return;
+ }
+
+ if (file.write(data) == -1) {
+ statusBar()->showMessage("Failed to save buffer data", 5000);
+ return;
+ }
+
+ file.close();
+
+ statusBar()->showMessage( tr("Saved buffer to '%1'").arg(filename), 5000);
}
void MainWindow::loadProgess(int percent)
@@ -1411,7 +1706,25 @@ ApiTraceCall * MainWindow::currentCall() const
}
return call;
+}
+
+void MainWindow::linkLocalAndroidTrace(const QString &localFile, const QString &deviceFile)
+{
+ QSettings s;
+ s.beginGroup(_("android"));
+ QVariantMap map = s.value(_("links")).toMap();
+ map[localFile] = deviceFile;
+ s.setValue(_("links"), map);
+ s.endGroup();
+}
+
+QString MainWindow::linkedAndroidTrace(const QString &localFile)
+{
+ QSettings s;
+ s.beginGroup(_("android"));
+ QVariantMap map = s.value(_("links")).toMap();
+ return map[localFile].toString();
}
void MainWindow::slotFoundFrameStart(ApiTraceFrame *frame)
@@ -1472,4 +1785,11 @@ void MainWindow::slotJumpToResult(ApiTraceCall *call)
}
}
+void MainWindow::thumbnailCallback(void *object, int thumbnailIdx)
+{
+ //qDebug() << QLatin1String("debug: transfer from trace to retracer thumbnail index: ") << thumbnailIdx;
+ MainWindow *mySelf = (MainWindow *) object;
+ mySelf->m_retracer->addThumbnailToCapture(thumbnailIdx);
+}
+
#include "mainwindow.moc"
diff --git a/gui/mainwindow.h b/gui/mainwindow.h
index 4d1358ce..8740ab76 100644
--- a/gui/mainwindow.h
+++ b/gui/mainwindow.h
@@ -1,5 +1,4 @@
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
+#pragma once
#include "ui_mainwindow.h"
@@ -52,14 +51,20 @@ private slots:
void callItemActivated(const QModelIndex &index);
void createTrace();
void openTrace();
+ void saveTrace();
+ void pullTrace();
+ void pushTrace();
+ void linkTrace();
+ void retraceOnAndroid(bool android);
void replayStart();
void replayProfile();
void replayStop();
void replayFinished(const QString &message);
void replayStateFound(ApiTraceState *state);
void replayProfileFound(trace::Profile *state);
- void replayThumbnailsFound(const QList<QImage> &thumbnails);
+ void replayThumbnailsFound(const ImageHash &thumbnails);
void replayError(const QString &msg);
+ void loadError(const QString &msg);
void startedLoadingTrace();
void loadProgess(int percent);
void finishedLoadingTrace();
@@ -67,10 +72,13 @@ private slots:
void showThumbnails();
void trim();
void showSettings();
+ void leakTrace();
+ void leakTraceFinished();
void openHelp(const QUrl &url);
void showSurfacesMenu(const QPoint &pos);
void showSelectedSurface();
void saveSelectedSurface();
+ void exportBufferData();
void slotGoTo();
void slotJumpTo(int callNum);
void createdTrace(const QString &path);
@@ -96,13 +104,15 @@ private slots:
void slotFoundFrameStart(ApiTraceFrame *frame);
void slotFoundFrameEnd(ApiTraceFrame *frame);
void slotJumpToResult(ApiTraceCall *call);
+ void replayTrace(bool dumpState, bool dumpThumbnails);
private:
void initObjects();
void initConnections();
+ void initRetraceConnections();
+
void updateActionsState(bool traceLoaded, bool stopped = true);
void newTraceFile(const QString &fileName);
- void replayTrace(bool dumpState, bool dumpThumbnails);
void trimEvent();
void fillStateForFrame();
@@ -115,6 +125,15 @@ private:
ApiTraceFrame *currentFrame() const;
ApiTraceCall *currentCall() const;
+ static void thumbnailCallback(void *object, int thumbnailIdx);
+
+ void linkLocalAndroidTrace(const QString &localFile, const QString &deviceFile);
+ QString linkedAndroidTrace(const QString &localFile);
+ void addSurface(const ApiTexture &image, QTreeWidgetItem *parent);
+ void addSurface(const ApiFramebuffer &image, QTreeWidgetItem *parent);
+ template <typename Surface>
+ void addSurfaces(const QList<Surface> &images, const char *label);
+
protected:
virtual void closeEvent(QCloseEvent * event);
@@ -153,7 +172,5 @@ private:
ApiTraceEvent *m_nonDefaultsLookupEvent;
ProfileDialog* m_profileDialog;
+ QString m_androidFilePath;
};
-
-
-#endif
diff --git a/gui/pixelwidget.h b/gui/pixelwidget.h
index 837dde40..6d92a84e 100644
--- a/gui/pixelwidget.h
+++ b/gui/pixelwidget.h
@@ -44,8 +44,7 @@
**
****************************************************************************/
-#ifndef PIXELWIDGET_H
-#define PIXELWIDGET_H
+#pragma once
#include <qwidget.h>
#include <qpixmap.h>
@@ -111,5 +110,3 @@ private:
QSize m_initialSize;
QColor m_currentColor;
};
-
-#endif // PIXELWIDGET_H
diff --git a/gui/profiledialog.cpp b/gui/profiledialog.cpp
index a9892cf0..9d80d3f3 100644
--- a/gui/profiledialog.cpp
+++ b/gui/profiledialog.cpp
@@ -223,7 +223,7 @@ void ProfileDialog::setProfile(trace::Profile* profile)
m_table->setModel(model);
m_table->update(QModelIndex());
m_table->sortByColumn(2, Qt::DescendingOrder);
- m_table->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+ m_table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_table->resizeColumnsToContents();
/* Reset selection */
diff --git a/gui/profiledialog.h b/gui/profiledialog.h
index 862d068b..b6c3f163 100644
--- a/gui/profiledialog.h
+++ b/gui/profiledialog.h
@@ -1,5 +1,4 @@
-#ifndef PROFILEDIALOG_H
-#define PROFILEDIALOG_H
+#pragma once
#include "ui_profiledialog.h"
#include <QDialog>
@@ -27,5 +26,3 @@ signals:
private:
trace::Profile *m_profile;
};
-
-#endif
diff --git a/gui/profileheatmap.h b/gui/profileheatmap.h
index e50ea263..548917bd 100644
--- a/gui/profileheatmap.h
+++ b/gui/profileheatmap.h
@@ -1,5 +1,4 @@
-#ifndef PROFILEHEATMAP_H
-#define PROFILEHEATMAP_H
+#pragma once
#include "graphing/heatmapview.h"
#include "profiling.h"
@@ -417,12 +416,12 @@ public:
text = QString::fromStdString(call.name);
text += QString("\nCall: %1").arg(call.no);
- text += QString("\nCPU Start: %1").arg(Profiling::getTimeString(call.cpuStart));
- text += QString("\nCPU Duration: %1").arg(Profiling::getTimeString(call.cpuDuration));
+ text += QString("\nCPU Start: %1").arg(Profiling::getTimeString(call.cpuStart, 1e3));
+ text += QString("\nCPU Duration: %1").arg(Profiling::getTimeString(call.cpuDuration, 1e3));
if (call.pixels >= 0) {
- text += QString("\nGPU Start: %1").arg(Profiling::getTimeString(call.gpuStart));
- text += QString("\nGPU Duration: %1").arg(Profiling::getTimeString(call.gpuDuration));
+ text += QString("\nGPU Start: %1").arg(Profiling::getTimeString(call.gpuStart, 1e3));
+ text += QString("\nGPU Duration: %1").arg(Profiling::getTimeString(call.gpuDuration, 1e3));
text += QString("\nPixels Drawn: %1").arg(QLocale::system().toString((qlonglong)call.pixels));
}
@@ -466,5 +465,3 @@ protected:
std::vector<int> m_rowPrograms;
SelectionState* m_selectionState;
};
-
-#endif
diff --git a/gui/profiletablemodel.h b/gui/profiletablemodel.h
index da175503..e2288b42 100644
--- a/gui/profiletablemodel.h
+++ b/gui/profiletablemodel.h
@@ -1,5 +1,4 @@
-#ifndef PROFILETABLEMODEL_H
-#define PROFILETABLEMODEL_H
+#pragma once
#include <QAbstractTableModel>
#include "trace_profiler.hpp"
@@ -67,4 +66,3 @@ private:
Qt::SortOrder m_sortOrder;
};
-#endif // PROFILEMODEL_H
diff --git a/gui/profiling.h b/gui/profiling.h
index a5b12660..6d4ef806 100644
--- a/gui/profiling.h
+++ b/gui/profiling.h
@@ -1,5 +1,4 @@
-#ifndef PROFILING_H
-#define PROFILING_H
+#pragma once
#include <QString>
#include <QLocale>
@@ -124,5 +123,3 @@ public:
}
}
};
-
-#endif
diff --git a/gui/qapitrace.qrc b/gui/qapitrace.qrc
index fe002f1b..89df6a86 100644
--- a/gui/qapitrace.qrc
+++ b/gui/qapitrace.qrc
@@ -1,23 +1,25 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
- <file>resources/application-exit.png</file>
- <file>resources/dialog-close.png</file>
- <file>resources/dialog-information.png</file>
- <file>resources/document-edit.png</file>
- <file>resources/document-new.png</file>
- <file>resources/document-open.png</file>
- <file>resources/edit-find.png</file>
- <file>resources/edit-undo.png</file>
- <file>resources/emblem-locked.png</file>
- <file>resources/go-bottom.png</file>
- <file>resources/go-down-search.png</file>
- <file>resources/go-jump.png</file>
- <file>resources/go-top.png</file>
- <file>resources/go-up-search.png</file>
- <file>resources/media-playback-start.png</file>
- <file>resources/media-playback-stop.png</file>
- <file>resources/media-record.png</file>
- <file>resources/script-error.png</file>
- <file>resources/glreference.tsv</file>
-</qresource>
+<RCC>
+ <qresource prefix="/">
+ <file>resources/application-exit.png</file>
+ <file>resources/dialog-close.png</file>
+ <file>resources/dialog-information.png</file>
+ <file>resources/document-edit.png</file>
+ <file>resources/document-new.png</file>
+ <file>resources/document-open.png</file>
+ <file>resources/edit-find.png</file>
+ <file>resources/edit-undo.png</file>
+ <file>resources/emblem-locked.png</file>
+ <file>resources/go-bottom.png</file>
+ <file>resources/go-down-search.png</file>
+ <file>resources/go-jump.png</file>
+ <file>resources/go-top.png</file>
+ <file>resources/go-up-search.png</file>
+ <file>resources/media-playback-start.png</file>
+ <file>resources/media-playback-stop.png</file>
+ <file>resources/media-record.png</file>
+ <file>resources/script-error.png</file>
+ <file>resources/glreference.tsv</file>
+ <file>resources/android.png</file>
+ <file>resources/android-setup.png</file>
+ </qresource>
</RCC>
diff --git a/gui/qubjson.cpp b/gui/qubjson.cpp
new file mode 100644
index 00000000..2d4138dc
--- /dev/null
+++ b/gui/qubjson.cpp
@@ -0,0 +1,298 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "qubjson.h"
+
+#include <QDebug>
+#include <QVariant>
+#include <QDataStream>
+
+#include "ubjson.hpp"
+
+
+using namespace ubjson;
+
+
+static Marker
+readMarker(QDataStream &stream)
+{
+ if (stream.atEnd()) {
+ return MARKER_EOF;
+ }
+ quint8 byte;
+ stream >> byte;
+ return static_cast<Marker>(byte);
+}
+
+
+static int8_t
+readInt8(QDataStream &stream)
+{
+ qint8 i;
+ stream >> i;
+ return i;
+}
+
+static uint8_t
+readUInt8(QDataStream &stream)
+{
+ quint8 u;
+ stream >> u;
+ return u;
+}
+
+static int16_t
+readInt16(QDataStream &stream)
+{
+ qint16 i;
+ stream >> i;
+ return i;
+}
+
+static int32_t
+readInt32(QDataStream &stream)
+{
+ qint32 i;
+ stream >> i;
+ return i;
+}
+
+static int64_t
+readInt64(QDataStream &stream)
+{
+ qint64 i;
+ stream >> i;
+ return i;
+}
+
+static float
+readFloat32(QDataStream &stream)
+{
+ float f;
+ stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
+ stream >> f;
+ return f;
+}
+
+static double
+readFloat64(QDataStream &stream)
+{
+ double f;
+ stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
+ stream >> f;
+ return f;
+}
+
+
+static int
+readSize(QDataStream &stream, Marker type)
+{
+ switch (type) {
+ case MARKER_INT8: {
+ int8_t size = readInt8(stream);
+ Q_ASSERT(size >= 0);
+ return size;
+ }
+ case MARKER_UINT8:
+ return readUInt8(stream);
+ case MARKER_INT16: {
+ int16_t size = readInt16(stream);
+ Q_ASSERT(size >= 0);
+ return size;
+ }
+ case MARKER_INT32: {
+ int32_t size = readInt32(stream);
+ Q_ASSERT(size >= 0);
+ return size;
+ }
+ case MARKER_INT64: {
+ int64_t size = readInt64(stream);
+ Q_ASSERT(size >= 0);
+ Q_ASSERT_X(size <= INT_MAX, "qubjson::readSize", "size too large (https://github.com/apitrace/apitrace/issues/343)");
+ return size;
+ }
+ default:
+ Q_UNIMPLEMENTED();
+ case MARKER_EOF:
+ return 0;
+ }
+}
+
+
+static QString
+readChar(QDataStream &stream)
+{
+ qint8 c;
+ stream >> c;
+ Q_ASSERT(c >= 0);
+ return QChar(c);
+}
+
+
+static int
+readSize(QDataStream &stream)
+{
+ Marker type = readMarker(stream);
+ return readSize(stream, type);
+}
+
+
+static QString
+readString(QDataStream &stream, int size)
+{
+ char *buf = new char [size];
+ stream.readRawData(buf, size);
+ QString str = QString::fromUtf8(buf, size);
+ delete [] buf;
+ return str;
+}
+
+
+static QString
+readString(QDataStream &stream)
+{
+ int size = readSize(stream);
+ return readString(stream, size);
+}
+
+
+static QVariant
+readVariant(QDataStream &stream, Marker type);
+
+
+static QVariant
+readArray(QDataStream &stream)
+{
+ Marker marker = readMarker(stream);
+ if (marker == MARKER_TYPE) {
+ Marker type = readMarker(stream);
+ Q_ASSERT(type == MARKER_UINT8);
+ Q_UNUSED(type);
+ marker = readMarker(stream);
+ Q_ASSERT(marker == MARKER_COUNT);
+ int count = readSize(stream);
+ QByteArray array(count, Qt::Uninitialized);
+ int read = stream.readRawData(array.data(), count);
+ Q_ASSERT(read == count);
+ Q_UNUSED(read);
+ return array;
+ } else if (marker == MARKER_COUNT) {
+ int count = readSize(stream);
+ QVariantList array;
+ for (int i = 0; i < count; ++i) {
+ marker = readMarker(stream);
+ QVariant value = readVariant(stream, marker);
+ array.append(value);
+ }
+ return array;
+ } else {
+ QVariantList array;
+ while (marker != MARKER_ARRAY_END &&
+ marker != MARKER_EOF) {
+ QVariant value = readVariant(stream, marker);
+ array.append(value);
+ marker = readMarker(stream);
+ }
+ return array;
+ }
+}
+
+
+static QVariantMap
+readObject(QDataStream &stream)
+{
+ QVariantMap object;
+ Marker marker = readMarker(stream);
+ while (marker != MARKER_OBJECT_END &&
+ marker != MARKER_EOF) {
+ int nameSize = readSize(stream, marker);
+ QString name = readString(stream, nameSize);
+ marker = readMarker(stream);
+ QVariant value = readVariant(stream, marker);
+ object[name] = value;
+ marker = readMarker(stream);
+ }
+ return object;
+}
+
+
+static QVariant
+readVariant(QDataStream &stream, Marker type)
+{
+ switch (type) {
+ case MARKER_NULL:
+ return QVariant();
+ case MARKER_NOOP:
+ return QVariant();
+ case MARKER_TRUE:
+ return true;
+ case MARKER_FALSE:
+ return false;
+ case MARKER_INT8:
+ return readInt8(stream);
+ case MARKER_UINT8:
+ return readUInt8(stream);
+ case MARKER_INT16:
+ return readInt16(stream);
+ case MARKER_INT32:
+ return readInt32(stream);
+ case MARKER_INT64:
+ return (qlonglong)readInt64(stream);
+ case MARKER_FLOAT32:
+ return readFloat32(stream);
+ case MARKER_FLOAT64:
+ return readFloat64(stream);
+ case MARKER_HIGH_PRECISION:
+ Q_UNIMPLEMENTED();
+ return QVariant();
+ case MARKER_CHAR:
+ return readChar(stream);
+ case MARKER_STRING:
+ return readString(stream);
+ case MARKER_ARRAY_BEGIN:
+ return readArray(stream);
+ case MARKER_OBJECT_BEGIN:
+ return readObject(stream);
+ case MARKER_ARRAY_END:
+ case MARKER_OBJECT_END:
+ case MARKER_TYPE:
+ case MARKER_COUNT:
+ default:
+ Q_ASSERT(0);
+ case MARKER_EOF:
+ return QVariant();
+ }
+}
+
+
+QVariant decodeUBJSONObject(QIODevice *io)
+{
+ QDataStream stream(io);
+ stream.setByteOrder(QDataStream::BigEndian);
+ Marker marker = readMarker(stream);
+ return readVariant(stream, marker);
+}
+
diff --git a/gui/qubjson.h b/gui/qubjson.h
new file mode 100644
index 00000000..7ca043d4
--- /dev/null
+++ b/gui/qubjson.h
@@ -0,0 +1,34 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+
+#include <QVariantMap>
+
+class QIODevice;
+
+QVariant decodeUBJSONObject(QIODevice *io);
diff --git a/gui/qubjson_test.cpp b/gui/qubjson_test.cpp
new file mode 100644
index 00000000..1d075ea7
--- /dev/null
+++ b/gui/qubjson_test.cpp
@@ -0,0 +1,161 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "qubjson.h"
+
+#include <QDebug>
+#include <QBuffer>
+
+#include "gtest/gtest.h"
+
+
+static inline std::ostream &
+operator << (std::ostream &os, const QVariant &var)
+{
+ QString buf;
+ QDebug debug(&buf);
+ debug << var;
+ os << buf.trimmed().toLocal8Bit().constData();
+ return os;
+}
+
+
+static ::testing::AssertionResult
+check(const char *buf_expr, const char *exp_expr, QByteArray & bytearray, const QVariant & expected)
+{
+ QBuffer buffer(&bytearray);
+ buffer.open(QIODevice::ReadOnly);
+
+ QVariant actual = decodeUBJSONObject(&buffer);
+
+ if (!buffer.atEnd()) {
+ return ::testing::AssertionFailure() << "Trailing bytes";
+ }
+
+ if (actual != expected) {
+ return ::testing::AssertionFailure() << "Expected " << expected << " but got " << actual;
+ }
+
+ return ::testing::AssertionSuccess();
+}
+
+
+#define BYTEARRAY(...) { __VA_ARGS__ }
+
+#define CHECK( x , y ) \
+ { \
+ static const unsigned char X[] = x; \
+ QByteArray bytearray((const char *)X, sizeof X); \
+ EXPECT_PRED_FORMAT2(check, bytearray, y); \
+ }
+
+
+TEST(qubjson, null) {
+ CHECK(BYTEARRAY('Z'), QVariant());
+}
+
+
+TEST(qubjson, boolean) {
+ CHECK(BYTEARRAY('T'), true);
+ CHECK(BYTEARRAY('F'), false);
+}
+
+
+TEST(qubjson, integral) {
+ CHECK(BYTEARRAY('i', 0x00), +0x00);
+ CHECK(BYTEARRAY('i', 0x7f), +0x7f);
+ CHECK(BYTEARRAY('i', 0x80), -0x80);
+ CHECK(BYTEARRAY('U', 0x00), +0x00);
+ CHECK(BYTEARRAY('U', 0x80), +0x80);
+ CHECK(BYTEARRAY('U', 0xff), +0xff);
+ CHECK(BYTEARRAY('I', 0x01, 0x23), +0x0123);
+ CHECK(BYTEARRAY('I', 0x80, 0x00), -0x8000);
+ CHECK(BYTEARRAY('l', 0x01, 0x23, 0x45, 0x67), +0x01234567);
+ CHECK(BYTEARRAY('l', 0x80, 0x00, 0x00, 0x00), -0x7fffffff - 1); // -0x80000000 causes signed warnings
+ CHECK(BYTEARRAY('L', 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF), qlonglong(+0x0123456789ABCDEFLL));
+ CHECK(BYTEARRAY('L', 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), qlonglong(-0x8000000000000000LL));
+}
+
+
+TEST(qubjson, float) {
+ CHECK(BYTEARRAY('d', 0x3f, 0x80, 0x00, 0x00), 1.0f);
+ CHECK(BYTEARRAY('d', 0x00, 0x00, 0x00, 0x01), 1.40129846e-45f);
+ CHECK(BYTEARRAY('d', 0xff, 0x7f, 0xff, 0xff), -3.4028234e38f);
+
+ CHECK(BYTEARRAY('D', 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 1.0);
+ CHECK(BYTEARRAY('D', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01), 4.9406564584124654e-324);
+ CHECK(BYTEARRAY('D', 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), -1.7976931348623157e308);
+}
+
+
+TEST(qubjson, string) {
+ CHECK(BYTEARRAY('C', 'A'), "A");
+
+ CHECK(BYTEARRAY('S', 'U', 0), "");
+ CHECK(BYTEARRAY('S', 'U', 5, 'A', 'B', 'C', 'D', 'E'), "ABCDE");
+}
+
+
+TEST(qubjson, array) {
+ QVariantList list;
+ CHECK(BYTEARRAY('[', ']'), list);
+ list.append(1);
+ CHECK(BYTEARRAY('[', 'i', 1, ']'), list);
+ CHECK(BYTEARRAY('[', '#', 'i', 1, 'i', 1), list);
+ list.append(2);
+ CHECK(BYTEARRAY('[', 'U', 1, 'i', 2, ']'), list);
+ CHECK(BYTEARRAY('[', '#', 'U', 2, 'i', 1, 'i', 2), list);
+}
+
+
+TEST(qubjson, object) {
+ QVariantMap map;
+ CHECK(BYTEARRAY('{', '}'), map);
+ map["A"] = 1;
+ CHECK(BYTEARRAY('{', 'U', 1, 'A', 'i', 1, '}'), map);
+ map["B"] = 2;
+ CHECK(BYTEARRAY('{', 'U', 1, 'A', 'i', 1, 'U', 1, 'B', 'i', 2, '}'), map);
+}
+
+
+TEST(qubjson, binary_data) {
+ CHECK(BYTEARRAY('[', '$', 'U', '#', 'U', 0), QByteArray());
+ CHECK(BYTEARRAY('[', '$', 'U', '#', 'U', 1, 'A'), QByteArray("A"));
+ CHECK(BYTEARRAY('[', '$', 'U', '#', 'U', 2, 'A', 'B'), QByteArray("AB"));
+ CHECK(BYTEARRAY('[', '$', 'U', '#', 'U', 3, 'A', 'B', 'C'), QByteArray("ABC"));
+}
+
+
+int
+main(int argc, char **argv)
+{
+#if defined(_MSC_VER) && !defined(NDEBUG)
+ return 0;
+#else
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+#endif
+}
diff --git a/gui/resources/android-setup.png b/gui/resources/android-setup.png
new file mode 100644
index 00000000..c2ae8235
--- /dev/null
+++ b/gui/resources/android-setup.png
Binary files differ
diff --git a/gui/resources/android.png b/gui/resources/android.png
new file mode 100644
index 00000000..359047df
--- /dev/null
+++ b/gui/resources/android.png
Binary files differ
diff --git a/gui/resources/glreference-man.sh b/gui/resources/glreference-man.sh
index 20bdaa6a..abf9a134 100755
--- a/gui/resources/glreference-man.sh
+++ b/gui/resources/glreference-man.sh
@@ -1,8 +1,8 @@
-#!/bin/sh
+#!/bin/bash
# Script to extract reference URLS for functions documented in OpenGL man pages
-wget -N -r -np http://www.opengl.org/sdk/docs/{man,man2,man3,man4}/
+wget -N -r -np https://www.opengl.org/sdk/docs/{man,man2,man3,man4}/
-find www.opengl.org -type f -name '*.xml' \
-| xargs grep -o '<b class="fsfunc">[^<]*</b>' \
-| sed -e 's/<[^>]*>//g' -e 's@^\(.*\):\(.*\)$@\2\thttp://\1@'
+find www.opengl.org -type f -name '*.xml' -o -name '*.xhtml' \
+| xargs grep -o '<\(b\|strong\) class="fsfunc">[^<]*</\1>' \
+| sed -e 's/<[^>]*>//g' -e 's@^\(.*\):\(.*\)$@\2\thttps://\1@'
diff --git a/gui/resources/glreference-registry.sh b/gui/resources/glreference-registry.sh
index 76b5dbe4..1c0cbe4f 100755
--- a/gui/resources/glreference-registry.sh
+++ b/gui/resources/glreference-registry.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
# Script to extract reference URLs for functions documented in OpenGL ARB specs
extract_urls () {
@@ -13,8 +13,8 @@ extract_functions () {
| sed -e '/^[A-Z]/s/^/gl/'
}
-extract_urls http://www.opengl.org/registry/ \
-| grep '^http://www\.opengl\.org/registry/specs/\w\+/.*\.txt$' \
+extract_urls https://www.opengl.org/registry/ \
+| grep '^https://www\.opengl\.org/registry/specs/\w\+/.*\.txt$' \
| sort -u \
| while read URL
do
diff --git a/gui/resources/glreference.tsv b/gui/resources/glreference.tsv
index 76cba730..8f69f4d6 100644
--- a/gui/resources/glreference.tsv
+++ b/gui/resources/glreference.tsv
@@ -1,3270 +1,3270 @@
-glAccum http://www.opengl.org/sdk/docs/man/xhtml/glAccum.xml
-glAccumxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glActiveProgramEXT http://www.opengl.org/registry/specs/EXT/separate_shader_objects.txt
-glActiveShaderProgram http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glActiveShaderProgram http://www.opengl.org/sdk/docs/man4/xhtml/glActiveShaderProgram.xml
-glActiveStencilFaceEXT http://www.opengl.org/registry/specs/EXT/stencil_two_side.txt
-glActiveTexture http://www.opengl.org/sdk/docs/man/xhtml/glActiveTexture.xml
-glActiveTexture http://www.opengl.org/sdk/docs/man3/xhtml/glActiveTexture.xml
-glActiveTexture http://www.opengl.org/sdk/docs/man4/xhtml/glActiveTexture.xml
-glActiveVaryingNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glAlphaFunc http://www.opengl.org/sdk/docs/man/xhtml/glAlphaFunc.xml
-glAlphaFuncxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glApplyTextureEXT http://www.opengl.org/registry/specs/EXT/light_texture.txt
-glAreProgramsResidentNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glAreTexturesResident http://www.opengl.org/sdk/docs/man/xhtml/glAreTexturesResident.xml
-glAreTexturesResidentEXT http://www.opengl.org/registry/specs/EXT/texture_object.txt
-glArrayElement http://www.opengl.org/sdk/docs/man/xhtml/glArrayElement.xml
-glArrayElementEXT http://www.opengl.org/registry/specs/EXT/vertex_array.txt
-glArrayObjectATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glAsyncMarkerSGIX http://www.opengl.org/registry/specs/SGIX/async.txt
-glAttachObjectARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glAttachShader http://www.opengl.org/sdk/docs/man/xhtml/glAttachShader.xml
-glAttachShader http://www.opengl.org/sdk/docs/man3/xhtml/glAttachShader.xml
-glAttachShader http://www.opengl.org/sdk/docs/man4/xhtml/glAttachShader.xml
-glBegin http://www.opengl.org/sdk/docs/man/xhtml/glBegin.xml
-glBeginConditionalRender http://www.opengl.org/sdk/docs/man3/xhtml/glBeginConditionalRender.xml
-glBeginConditionalRender http://www.opengl.org/sdk/docs/man4/xhtml/glBeginConditionalRender.xml
-glBeginConditionalRenderNV http://www.opengl.org/registry/specs/NV/conditional_render.txt
-glBeginOcclusionQueryNV http://www.opengl.org/registry/specs/NV/occlusion_query.txt
-glBeginPerfMonitorAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glBeginQuery http://www.opengl.org/sdk/docs/man/xhtml/glBeginQuery.xml
-glBeginQuery http://www.opengl.org/sdk/docs/man3/xhtml/glBeginQuery.xml
-glBeginQuery http://www.opengl.org/sdk/docs/man4/xhtml/glBeginQuery.xml
-glBeginQueryARB http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-glBeginQueryIndexed http://www.opengl.org/registry/specs/ARB/transform_feedback3.txt
-glBeginQueryIndexed http://www.opengl.org/sdk/docs/man4/xhtml/glBeginQueryIndexed.xml
-glBeginSceneEXT http://www.opengl.org/registry/specs/EXT/scene_marker.txt
-glBeginTransformFeedback http://www.opengl.org/sdk/docs/man3/xhtml/glBeginTransformFeedback.xml
-glBeginTransformFeedback http://www.opengl.org/sdk/docs/man4/xhtml/glBeginTransformFeedback.xml
-glBeginTransformFeedbackEXT http://www.opengl.org/registry/specs/EXT/transform_feedback.txt
-glBeginTransformFeedbackNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glBeginVideoCaptureNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glBindArraySetEXT http://www.opengl.org/registry/specs/EXT/vertex_array_set.alt.txt
-glBindArraySetEXT http://www.opengl.org/registry/specs/EXT/vertex_array_set.txt
-glBindAttribLocation http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocation.xml
-glBindAttribLocation http://www.opengl.org/sdk/docs/man3/xhtml/glBindAttribLocation.xml
-glBindAttribLocation http://www.opengl.org/sdk/docs/man4/xhtml/glBindAttribLocation.xml
-glBindAttribLocationARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glBindBuffer http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml
-glBindBuffer http://www.opengl.org/sdk/docs/man3/xhtml/glBindBuffer.xml
-glBindBuffer http://www.opengl.org/sdk/docs/man4/xhtml/glBindBuffer.xml
-glBindBufferARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glBindBufferBase http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glBindBufferBase http://www.opengl.org/sdk/docs/man3/xhtml/glBindBufferBase.xml
-glBindBufferBase http://www.opengl.org/sdk/docs/man4/xhtml/glBindBufferBase.xml
-glBindBufferBaseEXT http://www.opengl.org/registry/specs/EXT/transform_feedback.txt
-glBindBufferBaseNV http://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
-glBindBufferBaseNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glBindBufferOffsetEXT http://www.opengl.org/registry/specs/EXT/transform_feedback.txt
-glBindBufferOffsetNV http://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
-glBindBufferOffsetNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glBindBufferRange http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glBindBufferRange http://www.opengl.org/sdk/docs/man3/xhtml/glBindBufferRange.xml
-glBindBufferRange http://www.opengl.org/sdk/docs/man4/xhtml/glBindBufferRange.xml
-glBindBufferRangeEXT http://www.opengl.org/registry/specs/EXT/transform_feedback.txt
-glBindBufferRangeNV http://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
-glBindBufferRangeNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glBindFragDataLocation http://www.opengl.org/sdk/docs/man3/xhtml/glBindFragDataLocation.xml
-glBindFragDataLocation http://www.opengl.org/sdk/docs/man4/xhtml/glBindFragDataLocation.xml
-glBindFragDataLocationEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glBindFragDataLocationIndexed http://www.opengl.org/registry/specs/ARB/blend_func_extended.txt
-glBindFragDataLocationIndexed http://www.opengl.org/sdk/docs/man3/xhtml/glBindFragDataLocationIndexed.xml
-glBindFragDataLocationIndexed http://www.opengl.org/sdk/docs/man4/xhtml/glBindFragDataLocationIndexed.xml
-glBindFramebuffer http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glBindFramebuffer http://www.opengl.org/sdk/docs/man3/xhtml/glBindFramebuffer.xml
-glBindFramebuffer http://www.opengl.org/sdk/docs/man4/xhtml/glBindFramebuffer.xml
-glBindFramebufferEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glBindImageTexture http://www.opengl.org/registry/specs/ARB/shader_image_load_store.txt
-glBindImageTextureEXT http://www.opengl.org/registry/specs/EXT/shader_image_load_store.txt
-glBindMultiTextureEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glBindProgramARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glBindProgramARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glBindProgramNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glBindProgramPipeline http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glBindProgramPipeline http://www.opengl.org/sdk/docs/man4/xhtml/glBindProgramPipeline.xml
-glBindRenderbuffer http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glBindRenderbuffer http://www.opengl.org/sdk/docs/man3/xhtml/glBindRenderbuffer.xml
-glBindRenderbuffer http://www.opengl.org/sdk/docs/man4/xhtml/glBindRenderbuffer.xml
-glBindRenderbufferEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glBindSampler http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glBindSampler http://www.opengl.org/sdk/docs/man3/xhtml/glBindSampler.xml
-glBindSampler http://www.opengl.org/sdk/docs/man4/xhtml/glBindSampler.xml
-glBindSwapBarrierSGIX http://www.opengl.org/registry/specs/SGIX/swap_barrier.txt
-glBindTexture http://www.opengl.org/sdk/docs/man/xhtml/glBindTexture.xml
-glBindTexture http://www.opengl.org/sdk/docs/man3/xhtml/glBindTexture.xml
-glBindTexture http://www.opengl.org/sdk/docs/man4/xhtml/glBindTexture.xml
-glBindTextureEXT http://www.opengl.org/registry/specs/EXT/texture_object.txt
-glBindTransformFeedback http://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
-glBindTransformFeedback http://www.opengl.org/sdk/docs/man4/xhtml/glBindTransformFeedback.xml
-glBindTransformFeedbackNV http://www.opengl.org/registry/specs/NV/transform_feedback2.txt
-glBindVertexArray http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
-glBindVertexArray http://www.opengl.org/sdk/docs/man3/xhtml/glBindVertexArray.xml
-glBindVertexArray http://www.opengl.org/sdk/docs/man4/xhtml/glBindVertexArray.xml
-glBindVertexArrayAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_array_object.txt
-glBindVideoCaptureStreamBufferNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glBindVideoCaptureStreamTextureNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glBinormalPointerEXT http://www.opengl.org/registry/specs/EXT/coordinate_frame.txt
-glBitmap http://www.opengl.org/sdk/docs/man/xhtml/glBitmap.xml
-glBitmapxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glBlendColor http://www.opengl.org/sdk/docs/man/xhtml/glBlendColor.xml
-glBlendColor http://www.opengl.org/sdk/docs/man3/xhtml/glBlendColor.xml
-glBlendColor http://www.opengl.org/sdk/docs/man4/xhtml/glBlendColor.xml
-glBlendColorEXT http://www.opengl.org/registry/specs/EXT/blend_color.txt
-glBlendColorxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glBlendEquation http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquation.xml
-glBlendEquation http://www.opengl.org/sdk/docs/man3/xhtml/glBlendEquation.xml
-glBlendEquation http://www.opengl.org/sdk/docs/man4/xhtml/glBlendEquation.xml
-glBlendEquationEXT http://www.opengl.org/registry/specs/EXT/blend_minmax.txt
-glBlendEquationIndexedAMD http://www.opengl.org/registry/specs/AMD/draw_buffers_blend.txt
-glBlendEquationSeparate http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml
-glBlendEquationSeparate http://www.opengl.org/sdk/docs/man3/xhtml/glBlendEquationSeparate.xml
-glBlendEquationSeparate http://www.opengl.org/sdk/docs/man4/xhtml/glBlendEquationSeparate.xml
-glBlendEquationSeparateEXT http://www.opengl.org/registry/specs/EXT/blend_equation_separate.txt
-glBlendEquationSeparateIndexedAMD http://www.opengl.org/registry/specs/AMD/draw_buffers_blend.txt
-glBlendEquationSeparatei http://www.opengl.org/sdk/docs/man4/xhtml/glBlendEquationSeparate.xml
-glBlendEquationSeparateiARB http://www.opengl.org/registry/specs/ARB/draw_buffers_blend.txt
-glBlendEquationi http://www.opengl.org/sdk/docs/man4/xhtml/glBlendEquation.xml
-glBlendEquationiARB http://www.opengl.org/registry/specs/ARB/draw_buffers_blend.txt
-glBlendFunc http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml
-glBlendFunc http://www.opengl.org/sdk/docs/man3/xhtml/glBlendFunc.xml
-glBlendFunc http://www.opengl.org/sdk/docs/man4/xhtml/glBlendFunc.xml
-glBlendFuncIndexedAMD http://www.opengl.org/registry/specs/AMD/draw_buffers_blend.txt
-glBlendFuncSeparate http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml
-glBlendFuncSeparate http://www.opengl.org/sdk/docs/man3/xhtml/glBlendFuncSeparate.xml
-glBlendFuncSeparate http://www.opengl.org/sdk/docs/man4/xhtml/glBlendFuncSeparate.xml
-glBlendFuncSeparateEXT http://www.opengl.org/registry/specs/EXT/blend_func_separate.txt
-glBlendFuncSeparateIndexedAMD http://www.opengl.org/registry/specs/AMD/draw_buffers_blend.txt
-glBlendFuncSeparatei http://www.opengl.org/sdk/docs/man4/xhtml/glBlendFuncSeparate.xml
-glBlendFuncSeparateiARB http://www.opengl.org/registry/specs/ARB/draw_buffers_blend.txt
-glBlendFunci http://www.opengl.org/sdk/docs/man4/xhtml/glBlendFunc.xml
-glBlendFunciARB http://www.opengl.org/registry/specs/ARB/draw_buffers_blend.txt
-glBlitFramebuffer http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glBlitFramebuffer http://www.opengl.org/sdk/docs/man3/xhtml/glBlitFramebuffer.xml
-glBlitFramebuffer http://www.opengl.org/sdk/docs/man4/xhtml/glBlitFramebuffer.xml
-glBlitFramebufferEXT http://www.opengl.org/registry/specs/EXT/framebuffer_blit.txt
-glBufferAddressRangeNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glBufferData http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml
-glBufferData http://www.opengl.org/sdk/docs/man3/xhtml/glBufferData.xml
-glBufferData http://www.opengl.org/sdk/docs/man4/xhtml/glBufferData.xml
-glBufferDataARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glBufferParameteriAPPLE http://www.opengl.org/registry/specs/APPLE/flush_buffer_range.txt
-glBufferSubData http://www.opengl.org/sdk/docs/man/xhtml/glBufferSubData.xml
-glBufferSubData http://www.opengl.org/sdk/docs/man3/xhtml/glBufferSubData.xml
-glBufferSubData http://www.opengl.org/sdk/docs/man4/xhtml/glBufferSubData.xml
-glBufferSubDataARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glCallList http://www.opengl.org/sdk/docs/man/xhtml/glCallList.xml
-glCallLists http://www.opengl.org/sdk/docs/man/xhtml/glCallLists.xml
-glCheckFramebufferStatus http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glCheckFramebufferStatus http://www.opengl.org/sdk/docs/man3/xhtml/glCheckFramebufferStatus.xml
-glCheckFramebufferStatus http://www.opengl.org/sdk/docs/man4/xhtml/glCheckFramebufferStatus.xml
-glCheckFramebufferStatusEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glCheckNamedFramebufferStatusEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glClampColor http://www.opengl.org/sdk/docs/man3/xhtml/glClampColor.xml
-glClampColor http://www.opengl.org/sdk/docs/man4/xhtml/glClampColor.xml
-glClampColorARB http://www.opengl.org/registry/specs/ARB/color_buffer_float.txt
-glClear http://www.opengl.org/sdk/docs/man/xhtml/glClear.xml
-glClear http://www.opengl.org/sdk/docs/man3/xhtml/glClear.xml
-glClear http://www.opengl.org/sdk/docs/man4/xhtml/glClear.xml
-glClearAccum http://www.opengl.org/sdk/docs/man/xhtml/glClearAccum.xml
-glClearAccumxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glClearBufferfi http://www.opengl.org/sdk/docs/man3/xhtml/glClearBuffer.xml
-glClearBufferfi http://www.opengl.org/sdk/docs/man4/xhtml/glClearBuffer.xml
-glClearBufferfv http://www.opengl.org/sdk/docs/man3/xhtml/glClearBuffer.xml
-glClearBufferfv http://www.opengl.org/sdk/docs/man4/xhtml/glClearBuffer.xml
-glClearBufferiv http://www.opengl.org/sdk/docs/man3/xhtml/glClearBuffer.xml
-glClearBufferiv http://www.opengl.org/sdk/docs/man4/xhtml/glClearBuffer.xml
-glClearBufferuiv http://www.opengl.org/sdk/docs/man3/xhtml/glClearBuffer.xml
-glClearBufferuiv http://www.opengl.org/sdk/docs/man4/xhtml/glClearBuffer.xml
-glClearColor http://www.opengl.org/sdk/docs/man/xhtml/glClearColor.xml
-glClearColor http://www.opengl.org/sdk/docs/man3/xhtml/glClearColor.xml
-glClearColor http://www.opengl.org/sdk/docs/man4/xhtml/glClearColor.xml
-glClearColorxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glClearDepth http://www.opengl.org/sdk/docs/man/xhtml/glClearDepth.xml
-glClearDepth http://www.opengl.org/sdk/docs/man3/xhtml/glClearDepth.xml
-glClearDepth http://www.opengl.org/sdk/docs/man4/xhtml/glClearDepth.xml
-glClearDepthdNV http://www.opengl.org/registry/specs/NV/depth_buffer_float.txt
-glClearDepthf http://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
-glClearDepthf http://www.opengl.org/sdk/docs/man4/xhtml/glClearDepth.xml
-glClearDepthfOES http://www.opengl.org/registry/specs/OES/OES_single_precision.txt
-glClearDepthxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glClearIndex http://www.opengl.org/sdk/docs/man/xhtml/glClearIndex.xml
-glClearStencil http://www.opengl.org/sdk/docs/man/xhtml/glClearStencil.xml
-glClearStencil http://www.opengl.org/sdk/docs/man3/xhtml/glClearStencil.xml
-glClearStencil http://www.opengl.org/sdk/docs/man4/xhtml/glClearStencil.xml
-glClientActiveTexture http://www.opengl.org/sdk/docs/man/xhtml/glClientActiveTexture.xml
-glClientActiveVertexStream http://www.opengl.org/registry/specs/ATI/vertex_streams.txt
-glClientAttribDefaultEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glClientWaitSync http://www.opengl.org/registry/specs/ARB/sync.txt
-glClientWaitSync http://www.opengl.org/sdk/docs/man3/xhtml/glClientWaitSync.xml
-glClientWaitSync http://www.opengl.org/sdk/docs/man4/xhtml/glClientWaitSync.xml
-glClipPlane http://www.opengl.org/sdk/docs/man/xhtml/glClipPlane.xml
-glClipPlanefOES http://www.opengl.org/registry/specs/OES/OES_single_precision.txt
-glClipPlanexOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glColor3b http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3bv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3d http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3dv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3f http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3fVertex3fSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glColor3fVertex3fvSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glColor3fv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glColor3hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glColor3i http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3iv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3s http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3sv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3ub http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3ubv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3ui http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3uiv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3us http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor3usv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4b http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4bv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4d http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4dv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4f http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4fNormal3fVertex3fSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glColor4fNormal3fVertex3fvSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glColor4fv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glColor4hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glColor4i http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4iv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4s http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4sv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4ub http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4ubVertex2fSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glColor4ubVertex2fvSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glColor4ubVertex3fSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glColor4ubVertex3fvSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glColor4ubv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4ui http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4uiv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4us http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColor4usv http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
-glColorFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glColorMask http://www.opengl.org/sdk/docs/man/xhtml/glColorMask.xml
-glColorMask http://www.opengl.org/sdk/docs/man3/xhtml/glColorMask.xml
-glColorMask http://www.opengl.org/sdk/docs/man4/xhtml/glColorMask.xml
-glColorMaskIndexedEXT http://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
-glColorMaski http://www.opengl.org/sdk/docs/man4/xhtml/glColorMask.xml
-glColorMaterial http://www.opengl.org/sdk/docs/man/xhtml/glColorMaterial.xml
-glColorP3ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glColorP3uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glColorP4ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glColorP4uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glColorPointer http://www.opengl.org/sdk/docs/man/xhtml/glColorPointer.xml
-glColorPointerEXT http://www.opengl.org/registry/specs/EXT/vertex_array.txt
-glColorPointervINTEL http://www.opengl.org/registry/specs/INTEL/parallel_arrays.txt
-glColorSubTable http://www.opengl.org/sdk/docs/man/xhtml/glColorSubTable.xml
-glColorSubTableEXT http://www.opengl.org/registry/specs/EXT/color_subtable.txt
-glColorSubTableEXT http://www.opengl.org/registry/specs/EXT/paletted_texture.txt
-glColorTable http://www.opengl.org/sdk/docs/man/xhtml/glColorTable.xml
-glColorTableEXT http://www.opengl.org/registry/specs/EXT/paletted_texture.txt
-glColorTableParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glColorTableParameter.xml
-glColorTableParameterfvSGI http://www.opengl.org/registry/specs/SGI/color_table.txt
-glColorTableParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glColorTableParameter.xml
-glColorTableParameterivSGI http://www.opengl.org/registry/specs/SGI/color_table.txt
-glColorTableSGI http://www.opengl.org/registry/specs/SGI/color_table.txt
-glCombinerInputNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glCombinerOutputNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glCombinerParameterfNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glCombinerParameterfvNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glCombinerParameteriNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glCombinerParameterivNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glCombinerStageParameterfvNV http://www.opengl.org/registry/specs/NV/register_combiners2.txt
-glCompileShader http://www.opengl.org/sdk/docs/man/xhtml/glCompileShader.xml
-glCompileShader http://www.opengl.org/sdk/docs/man3/xhtml/glCompileShader.xml
-glCompileShader http://www.opengl.org/sdk/docs/man4/xhtml/glCompileShader.xml
-glCompileShaderARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glCompileShaderIncludeARB http://www.opengl.org/registry/specs/ARB/shading_language_include.txt
-glCompressedMultiTexImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedMultiTexImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedMultiTexImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedMultiTexSubImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedMultiTexSubImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedMultiTexSubImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedTexImage1D http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage1D.xml
-glCompressedTexImage1D http://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexImage1D.xml
-glCompressedTexImage1D http://www.opengl.org/sdk/docs/man4/xhtml/glCompressedTexImage1D.xml
-glCompressedTexImage1DARB http://www.opengl.org/registry/specs/ARB/texture_compression.txt
-glCompressedTexImage2D http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage2D.xml
-glCompressedTexImage2D http://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexImage2D.xml
-glCompressedTexImage2D http://www.opengl.org/sdk/docs/man4/xhtml/glCompressedTexImage2D.xml
-glCompressedTexImage2DARB http://www.opengl.org/registry/specs/ARB/texture_compression.txt
-glCompressedTexImage3D http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage3D.xml
-glCompressedTexImage3D http://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexImage3D.xml
-glCompressedTexImage3D http://www.opengl.org/sdk/docs/man4/xhtml/glCompressedTexImage3D.xml
-glCompressedTexImage3DARB http://www.opengl.org/registry/specs/ARB/texture_compression.txt
-glCompressedTexSubImage1D http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage1D.xml
-glCompressedTexSubImage1D http://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexSubImage1D.xml
-glCompressedTexSubImage1D http://www.opengl.org/sdk/docs/man4/xhtml/glCompressedTexSubImage1D.xml
-glCompressedTexSubImage1DARB http://www.opengl.org/registry/specs/ARB/texture_compression.txt
-glCompressedTexSubImage2D http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage2D.xml
-glCompressedTexSubImage2D http://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexSubImage2D.xml
-glCompressedTexSubImage2D http://www.opengl.org/sdk/docs/man4/xhtml/glCompressedTexSubImage2D.xml
-glCompressedTexSubImage2DARB http://www.opengl.org/registry/specs/ARB/texture_compression.txt
-glCompressedTexSubImage3D http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage3D.xml
-glCompressedTexSubImage3D http://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexSubImage3D.xml
-glCompressedTexSubImage3D http://www.opengl.org/sdk/docs/man4/xhtml/glCompressedTexSubImage3D.xml
-glCompressedTexSubImage3DARB http://www.opengl.org/registry/specs/ARB/texture_compression.txt
-glCompressedTextureImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedTextureImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedTextureImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedTextureSubImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedTextureSubImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCompressedTextureSubImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glConvolutionFilter1D http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter1D.xml
-glConvolutionFilter1DEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glConvolutionFilter2D http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter2D.xml
-glConvolutionFilter2DEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glConvolutionParameterf http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml
-glConvolutionParameterfEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glConvolutionParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml
-glConvolutionParameterfvEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glConvolutionParameteri http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml
-glConvolutionParameteriEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glConvolutionParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml
-glConvolutionParameterivEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glCopyBufferSubData http://www.opengl.org/registry/specs/ARB/copy_buffer.txt
-glCopyBufferSubData http://www.opengl.org/sdk/docs/man3/xhtml/glCopyBufferSubData.xml
-glCopyBufferSubData http://www.opengl.org/sdk/docs/man4/xhtml/glCopyBufferSubData.xml
-glCopyColorSubTable http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorSubTable.xml
-glCopyColorSubTableEXT http://www.opengl.org/registry/specs/EXT/color_subtable.txt
-glCopyColorTable http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorTable.xml
-glCopyColorTableSGI http://www.opengl.org/registry/specs/SGI/color_table.txt
-glCopyConvolutionFilter1D http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter1D.xml
-glCopyConvolutionFilter1DEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glCopyConvolutionFilter2D http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter2D.xml
-glCopyConvolutionFilter2DEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glCopyImageSubDataNV http://www.opengl.org/registry/specs/NV/copy_image.txt
-glCopyMultiTexImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCopyMultiTexImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCopyMultiTexSubImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCopyMultiTexSubImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCopyMultiTexSubImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCopyPathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glCopyPixels http://www.opengl.org/sdk/docs/man/xhtml/glCopyPixels.xml
-glCopyTexImage1D http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage1D.xml
-glCopyTexImage1D http://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexImage1D.xml
-glCopyTexImage1D http://www.opengl.org/sdk/docs/man4/xhtml/glCopyTexImage1D.xml
-glCopyTexImage1DEXT http://www.opengl.org/registry/specs/EXT/copy_texture.txt
-glCopyTexImage2D http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage2D.xml
-glCopyTexImage2D http://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexImage2D.xml
-glCopyTexImage2D http://www.opengl.org/sdk/docs/man4/xhtml/glCopyTexImage2D.xml
-glCopyTexImage2DEXT http://www.opengl.org/registry/specs/EXT/copy_texture.txt
-glCopyTexSubImage1D http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage1D.xml
-glCopyTexSubImage1D http://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexSubImage1D.xml
-glCopyTexSubImage1D http://www.opengl.org/sdk/docs/man4/xhtml/glCopyTexSubImage1D.xml
-glCopyTexSubImage1DEXT http://www.opengl.org/registry/specs/EXT/copy_texture.txt
-glCopyTexSubImage2D http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage2D.xml
-glCopyTexSubImage2D http://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexSubImage2D.xml
-glCopyTexSubImage2D http://www.opengl.org/sdk/docs/man4/xhtml/glCopyTexSubImage2D.xml
-glCopyTexSubImage2DEXT http://www.opengl.org/registry/specs/EXT/copy_texture.txt
-glCopyTexSubImage3D http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage3D.xml
-glCopyTexSubImage3D http://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexSubImage3D.xml
-glCopyTexSubImage3D http://www.opengl.org/sdk/docs/man4/xhtml/glCopyTexSubImage3D.xml
-glCopyTexSubImage3DEXT http://www.opengl.org/registry/specs/EXT/copy_texture.txt
-glCopyTextureImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCopyTextureImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCopyTextureSubImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCopyTextureSubImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCopyTextureSubImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glCoverFillPathInstancedNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glCoverFillPathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glCoverStrokePathInstancedNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glCoverStrokePathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glCreateProgram http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgram.xml
-glCreateProgram http://www.opengl.org/sdk/docs/man3/xhtml/glCreateProgram.xml
-glCreateProgram http://www.opengl.org/sdk/docs/man4/xhtml/glCreateProgram.xml
-glCreateProgramObjectARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glCreateShader http://www.opengl.org/sdk/docs/man/xhtml/glCreateShader.xml
-glCreateShader http://www.opengl.org/sdk/docs/man3/xhtml/glCreateShader.xml
-glCreateShader http://www.opengl.org/sdk/docs/man4/xhtml/glCreateShader.xml
-glCreateShaderObjectARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glCreateShaderProgramEXT http://www.opengl.org/registry/specs/EXT/separate_shader_objects.txt
-glCreateShaderProgramv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glCreateShaderProgramv http://www.opengl.org/sdk/docs/man4/xhtml/glCreateShaderProgram.xml
-glCreateSyncFromCLeventARB http://www.opengl.org/registry/specs/ARB/cl_event.txt
-glCullFace http://www.opengl.org/sdk/docs/man/xhtml/glCullFace.xml
-glCullFace http://www.opengl.org/sdk/docs/man3/xhtml/glCullFace.xml
-glCullFace http://www.opengl.org/sdk/docs/man4/xhtml/glCullFace.xml
-glCurrentPaletteMatrixARB http://www.opengl.org/registry/specs/ARB/matrix_palette.txt
-glDECLARE_HANDLE http://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
-glDECLARE_HANDLE http://www.opengl.org/registry/specs/NV/present_video.txt
-glDebugMessageCallbackAMD http://www.opengl.org/registry/specs/AMD/debug_output.txt
-glDebugMessageCallbackARB http://www.opengl.org/registry/specs/ARB/debug_output.txt
-glDebugMessageControlARB http://www.opengl.org/registry/specs/ARB/debug_output.txt
-glDebugMessageEnableAMD http://www.opengl.org/registry/specs/AMD/debug_output.txt
-glDebugMessageInsertAMD http://www.opengl.org/registry/specs/AMD/debug_output.txt
-glDebugMessageInsertARB http://www.opengl.org/registry/specs/ARB/debug_output.txt
-glDeleteArraySetsEXT http://www.opengl.org/registry/specs/EXT/vertex_array_set.alt.txt
-glDeleteArraySetsEXT http://www.opengl.org/registry/specs/EXT/vertex_array_set.txt
-glDeleteAsyncMarkersSGIX http://www.opengl.org/registry/specs/SGIX/async.txt
-glDeleteBuffers http://www.opengl.org/sdk/docs/man/xhtml/glDeleteBuffers.xml
-glDeleteBuffers http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteBuffers.xml
-glDeleteBuffers http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteBuffers.xml
-glDeleteBuffersARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glDeleteFencesAPPLE http://www.opengl.org/registry/specs/APPLE/fence.txt
-glDeleteFencesNV http://www.opengl.org/registry/specs/NV/fence.txt
-glDeleteFramebuffers http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glDeleteFramebuffers http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteFramebuffers.xml
-glDeleteFramebuffers http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteFramebuffers.xml
-glDeleteFramebuffersEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glDeleteLists http://www.opengl.org/sdk/docs/man/xhtml/glDeleteLists.xml
-glDeleteNamedStringARB http://www.opengl.org/registry/specs/ARB/shading_language_include.txt
-glDeleteNamesAMD http://www.opengl.org/registry/specs/AMD/name_gen_delete.txt
-glDeleteObjectARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glDeleteOcclusionQueriesNV http://www.opengl.org/registry/specs/NV/occlusion_query.txt
-glDeletePathsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glDeletePerfMonitorsAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glDeleteProgram http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgram.xml
-glDeleteProgram http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteProgram.xml
-glDeleteProgram http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteProgram.xml
-glDeleteProgramPipelines http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glDeleteProgramPipelines http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteProgramPipelines.xml
-glDeleteProgramsARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glDeleteProgramsARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glDeleteProgramsNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glDeleteQueries http://www.opengl.org/sdk/docs/man/xhtml/glDeleteQueries.xml
-glDeleteQueries http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteQueries.xml
-glDeleteQueries http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteQueries.xml
-glDeleteQueriesARB http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-glDeleteRenderbuffers http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glDeleteRenderbuffers http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteRenderbuffers.xml
-glDeleteRenderbuffers http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteRenderbuffers.xml
-glDeleteRenderbuffersEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glDeleteSamplers http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glDeleteSamplers http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteSamplers.xml
-glDeleteSamplers http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteSamplers.xml
-glDeleteShader http://www.opengl.org/sdk/docs/man/xhtml/glDeleteShader.xml
-glDeleteShader http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteShader.xml
-glDeleteShader http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteShader.xml
-glDeleteSync http://www.opengl.org/registry/specs/ARB/sync.txt
-glDeleteSync http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteSync.xml
-glDeleteSync http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteSync.xml
-glDeleteTextures http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTextures.xml
-glDeleteTextures http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteTextures.xml
-glDeleteTextures http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteTextures.xml
-glDeleteTexturesEXT http://www.opengl.org/registry/specs/EXT/texture_object.txt
-glDeleteTransformFeedbacks http://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
-glDeleteTransformFeedbacks http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteTransformFeedbacks.xml
-glDeleteTransformFeedbacksNV http://www.opengl.org/registry/specs/NV/transform_feedback2.txt
-glDeleteVertexArrays http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
-glDeleteVertexArrays http://www.opengl.org/sdk/docs/man3/xhtml/glDeleteVertexArrays.xml
-glDeleteVertexArrays http://www.opengl.org/sdk/docs/man4/xhtml/glDeleteVertexArrays.xml
-glDeleteVertexArraysAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_array_object.txt
-glDepthBoundsEXT http://www.opengl.org/registry/specs/EXT/depth_bounds_test.txt
-glDepthBoundsdNV http://www.opengl.org/registry/specs/NV/depth_buffer_float.txt
-glDepthFunc http://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml
-glDepthFunc http://www.opengl.org/sdk/docs/man3/xhtml/glDepthFunc.xml
-glDepthFunc http://www.opengl.org/sdk/docs/man4/xhtml/glDepthFunc.xml
-glDepthMask http://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml
-glDepthMask http://www.opengl.org/sdk/docs/man3/xhtml/glDepthMask.xml
-glDepthMask http://www.opengl.org/sdk/docs/man4/xhtml/glDepthMask.xml
-glDepthRange http://www.opengl.org/sdk/docs/man/xhtml/glDepthRange.xml
-glDepthRange http://www.opengl.org/sdk/docs/man3/xhtml/glDepthRange.xml
-glDepthRange http://www.opengl.org/sdk/docs/man4/xhtml/glDepthRange.xml
-glDepthRangeArrayv http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glDepthRangeArrayv http://www.opengl.org/sdk/docs/man4/xhtml/glDepthRangeArray.xml
-glDepthRangeIndexed http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glDepthRangeIndexed http://www.opengl.org/sdk/docs/man4/xhtml/glDepthRangeIndexed.xml
-glDepthRangedNV http://www.opengl.org/registry/specs/NV/depth_buffer_float.txt
-glDepthRangef http://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
-glDepthRangef http://www.opengl.org/sdk/docs/man4/xhtml/glDepthRange.xml
-glDepthRangefOES http://www.opengl.org/registry/specs/OES/OES_single_precision.txt
-glDepthRangexOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glDetachObjectARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glDetachShader http://www.opengl.org/sdk/docs/man/xhtml/glDetachShader.xml
-glDetachShader http://www.opengl.org/sdk/docs/man3/xhtml/glDetachShader.xml
-glDetachShader http://www.opengl.org/sdk/docs/man4/xhtml/glDetachShader.xml
-glDetailTexFuncSGIS http://www.opengl.org/registry/specs/SGIS/detail_texture.txt
-glDisable http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
-glDisable http://www.opengl.org/sdk/docs/man3/xhtml/glEnable.xml
-glDisable http://www.opengl.org/sdk/docs/man4/xhtml/glEnable.xml
-glDisableClientState http://www.opengl.org/sdk/docs/man/xhtml/glEnableClientState.xml
-glDisableClientStateIndexedEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glDisableClientStateiEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glDisableIndexedEXT http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glDisableIndexedEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glDisableIndexedEXT http://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
-glDisableVertexArrayAttribEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glDisableVertexArrayEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glDisableVertexAttribAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
-glDisableVertexAttribArray http://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml
-glDisableVertexAttribArray http://www.opengl.org/sdk/docs/man3/xhtml/glEnableVertexAttribArray.xml
-glDisableVertexAttribArray http://www.opengl.org/sdk/docs/man4/xhtml/glEnableVertexAttribArray.xml
-glDisableVertexAttribArrayARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glDisableVertexAttribArrayARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glDisablei http://www.opengl.org/sdk/docs/man3/xhtml/glEnable.xml
-glDisablei http://www.opengl.org/sdk/docs/man4/xhtml/glEnable.xml
-glDrawArrays http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml
-glDrawArrays http://www.opengl.org/sdk/docs/man3/xhtml/glDrawArrays.xml
-glDrawArrays http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArrays.xml
-glDrawArraysEXT http://www.opengl.org/registry/specs/EXT/vertex_array.txt
-glDrawArraysIndirect http://www.opengl.org/registry/specs/ARB/draw_indirect.txt
-glDrawArraysIndirect http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArraysIndirect.xml
-glDrawArraysInstanced http://www.opengl.org/sdk/docs/man3/xhtml/glDrawArraysInstanced.xml
-glDrawArraysInstanced http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArraysInstanced.xml
-glDrawArraysInstancedARB http://www.opengl.org/registry/specs/ARB/draw_instanced.txt
-glDrawArraysInstancedBaseInstance http://www.opengl.org/registry/specs/ARB/base_instance.txt
-glDrawArraysInstancedEXT http://www.opengl.org/registry/specs/EXT/draw_instanced.txt
-glDrawBuffer http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffer.xml
-glDrawBuffer http://www.opengl.org/sdk/docs/man3/xhtml/glDrawBuffer.xml
-glDrawBuffer http://www.opengl.org/sdk/docs/man4/xhtml/glDrawBuffer.xml
-glDrawBuffers http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffers.xml
-glDrawBuffers http://www.opengl.org/sdk/docs/man3/xhtml/glDrawBuffers.xml
-glDrawBuffers http://www.opengl.org/sdk/docs/man4/xhtml/glDrawBuffers.xml
-glDrawBuffersARB http://www.opengl.org/registry/specs/ARB/draw_buffers.txt
-glDrawBuffersATI http://www.opengl.org/registry/specs/ATI/draw_buffers.txt
-glDrawElementArrayAPPLE http://www.opengl.org/registry/specs/APPLE/element_array.txt
-glDrawElementArrayATI http://www.opengl.org/registry/specs/ATI/element_array.txt
-glDrawElements http://www.opengl.org/sdk/docs/man/xhtml/glDrawElements.xml
-glDrawElements http://www.opengl.org/sdk/docs/man3/xhtml/glDrawElements.xml
-glDrawElements http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElements.xml
-glDrawElementsBaseVertex http://www.opengl.org/registry/specs/ARB/draw_elements_base_vertex.txt
-glDrawElementsBaseVertex http://www.opengl.org/sdk/docs/man3/xhtml/glDrawElementsBaseVertex.xml
-glDrawElementsBaseVertex http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElementsBaseVertex.xml
-glDrawElementsIndirect http://www.opengl.org/registry/specs/ARB/draw_indirect.txt
-glDrawElementsIndirect http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElementsIndirect.xml
-glDrawElementsInstanced http://www.opengl.org/sdk/docs/man3/xhtml/glDrawElementsInstanced.xml
-glDrawElementsInstanced http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElementsInstanced.xml
-glDrawElementsInstancedARB http://www.opengl.org/registry/specs/ARB/draw_instanced.txt
-glDrawElementsInstancedBaseInstance http://www.opengl.org/registry/specs/ARB/base_instance.txt
-glDrawElementsInstancedBaseVertex http://www.opengl.org/registry/specs/ARB/draw_elements_base_vertex.txt
-glDrawElementsInstancedBaseVertex http://www.opengl.org/sdk/docs/man3/xhtml/glDrawElementsInstancedBaseVertex.xml
-glDrawElementsInstancedBaseVertex http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElementsInstancedBaseVertex.xml
-glDrawElementsInstancedBaseVertexBaseInstance http://www.opengl.org/registry/specs/ARB/base_instance.txt
-glDrawElementsInstancedEXT http://www.opengl.org/registry/specs/EXT/draw_instanced.txt
-glDrawMeshArraysSUN http://www.opengl.org/registry/specs/SUN/mesh_array.txt
-glDrawPixels http://www.opengl.org/sdk/docs/man/xhtml/glDrawPixels.xml
-glDrawRangeElementArrayAPPLE http://www.opengl.org/registry/specs/APPLE/element_array.txt
-glDrawRangeElementArrayATI http://www.opengl.org/registry/specs/ATI/element_array.txt
-glDrawRangeElements http://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElements.xml
-glDrawRangeElements http://www.opengl.org/sdk/docs/man3/xhtml/glDrawRangeElements.xml
-glDrawRangeElements http://www.opengl.org/sdk/docs/man4/xhtml/glDrawRangeElements.xml
-glDrawRangeElementsBaseVertex http://www.opengl.org/registry/specs/ARB/draw_elements_base_vertex.txt
-glDrawRangeElementsBaseVertex http://www.opengl.org/sdk/docs/man3/xhtml/glDrawRangeElementsBaseVertex.xml
-glDrawRangeElementsBaseVertex http://www.opengl.org/sdk/docs/man4/xhtml/glDrawRangeElementsBaseVertex.xml
-glDrawTransformFeedback http://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
-glDrawTransformFeedback http://www.opengl.org/sdk/docs/man4/xhtml/glDrawTransformFeedback.xml
-glDrawTransformFeedbackInstanced http://www.opengl.org/registry/specs/ARB/transform_feedback_instanced.txt
-glDrawTransformFeedbackNV http://www.opengl.org/registry/specs/NV/transform_feedback2.txt
-glDrawTransformFeedbackStream http://www.opengl.org/registry/specs/ARB/transform_feedback3.txt
-glDrawTransformFeedbackStream http://www.opengl.org/sdk/docs/man4/xhtml/glDrawTransformFeedbackStream.xml
-glDrawTransformFeedbackStreamInstanced http://www.opengl.org/registry/specs/ARB/transform_feedback_instanced.txt
-glEdgeFlag http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlag.xml
-glEdgeFlagFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glEdgeFlagPointer http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlagPointer.xml
-glEdgeFlagPointerEXT http://www.opengl.org/registry/specs/EXT/vertex_array.txt
-glEdgeFlagv http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlag.xml
-glElementPointerAPPLE http://www.opengl.org/registry/specs/APPLE/element_array.txt
-glElementPointerATI http://www.opengl.org/registry/specs/ATI/element_array.txt
-glEnable http://www.opengl.org/registry/specs/SGIX/instruments.txt
-glEnable http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
-glEnable http://www.opengl.org/sdk/docs/man3/xhtml/glEnable.xml
-glEnable http://www.opengl.org/sdk/docs/man4/xhtml/glEnable.xml
-glEnableClientState http://www.opengl.org/sdk/docs/man/xhtml/glEnableClientState.xml
-glEnableClientStateIndexedEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glEnableClientStateiEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glEnableIndexedEXT http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glEnableIndexedEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glEnableIndexedEXT http://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
-glEnableVertexArrayAttribEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glEnableVertexArrayEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glEnableVertexAttribAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
-glEnableVertexAttribArray http://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml
-glEnableVertexAttribArray http://www.opengl.org/sdk/docs/man3/xhtml/glEnableVertexAttribArray.xml
-glEnableVertexAttribArray http://www.opengl.org/sdk/docs/man4/xhtml/glEnableVertexAttribArray.xml
-glEnableVertexAttribArrayARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glEnableVertexAttribArrayARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glEnablei http://www.opengl.org/sdk/docs/man3/xhtml/glEnable.xml
-glEnablei http://www.opengl.org/sdk/docs/man4/xhtml/glEnable.xml
-glEnd http://www.opengl.org/sdk/docs/man/xhtml/glBegin.xml
-glEndConditionalRender http://www.opengl.org/sdk/docs/man3/xhtml/glBeginConditionalRender.xml
-glEndConditionalRender http://www.opengl.org/sdk/docs/man4/xhtml/glBeginConditionalRender.xml
-glEndConditionalRenderNV http://www.opengl.org/registry/specs/NV/conditional_render.txt
-glEndList http://www.opengl.org/sdk/docs/man/xhtml/glNewList.xml
-glEndOcclusionQueryNV http://www.opengl.org/registry/specs/NV/occlusion_query.txt
-glEndPerfMonitorAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glEndQuery http://www.opengl.org/sdk/docs/man/xhtml/glBeginQuery.xml
-glEndQuery http://www.opengl.org/sdk/docs/man3/xhtml/glBeginQuery.xml
-glEndQuery http://www.opengl.org/sdk/docs/man4/xhtml/glBeginQuery.xml
-glEndQueryARB http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-glEndQueryIndexed http://www.opengl.org/registry/specs/ARB/transform_feedback3.txt
-glEndQueryIndexed http://www.opengl.org/sdk/docs/man4/xhtml/glBeginQueryIndexed.xml
-glEndSceneEXT http://www.opengl.org/registry/specs/EXT/scene_marker.txt
-glEndTransformFeedback http://www.opengl.org/sdk/docs/man3/xhtml/glBeginTransformFeedback.xml
-glEndTransformFeedback http://www.opengl.org/sdk/docs/man4/xhtml/glBeginTransformFeedback.xml
-glEndTransformFeedbackEXT http://www.opengl.org/registry/specs/EXT/transform_feedback.txt
-glEndTransformFeedbackNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glEndVideoCaptureNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glEvalCoord1d http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
-glEvalCoord1dv http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
-glEvalCoord1f http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
-glEvalCoord1fv http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
-glEvalCoord2d http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
-glEvalCoord2dv http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
-glEvalCoord2f http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
-glEvalCoord2fv http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
-glEvalMapsNV http://www.opengl.org/registry/specs/NV/evaluators.txt
-glEvalMesh1 http://www.opengl.org/sdk/docs/man/xhtml/glEvalMesh.xml
-glEvalMesh2 http://www.opengl.org/sdk/docs/man/xhtml/glEvalMesh.xml
-glEvalPoint1 http://www.opengl.org/sdk/docs/man/xhtml/glEvalPoint.xml
-glEvalPoint2 http://www.opengl.org/sdk/docs/man/xhtml/glEvalPoint.xml
-glExecuteProgramNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glFeedbackBuffer http://www.opengl.org/sdk/docs/man/xhtml/glFeedbackBuffer.xml
-glFeedbackBufferxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glFenceSync http://www.opengl.org/registry/specs/ARB/sync.txt
-glFenceSync http://www.opengl.org/sdk/docs/man3/xhtml/glFenceSync.xml
-glFenceSync http://www.opengl.org/sdk/docs/man4/xhtml/glFenceSync.xml
-glFinalCombinerInputNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glFinish http://www.opengl.org/sdk/docs/man/xhtml/glFinish.xml
-glFinish http://www.opengl.org/sdk/docs/man3/xhtml/glFinish.xml
-glFinish http://www.opengl.org/sdk/docs/man4/xhtml/glFinish.xml
-glFinishAsyncSGIX http://www.opengl.org/registry/specs/SGIX/async.txt
-glFinishFenceAPPLE http://www.opengl.org/registry/specs/APPLE/fence.txt
-glFinishFenceNV http://www.opengl.org/registry/specs/NV/fence.txt
-glFinishObjectAPPLE http://www.opengl.org/registry/specs/APPLE/fence.txt
-glFinishTextureSUNX http://www.opengl.org/registry/specs/SUNX/constant_data.txt
-glFlush http://www.opengl.org/sdk/docs/man/xhtml/glFlush.xml
-glFlush http://www.opengl.org/sdk/docs/man3/xhtml/glFlush.xml
-glFlush http://www.opengl.org/sdk/docs/man4/xhtml/glFlush.xml
-glFlushMappedBufferRange http://www.opengl.org/registry/specs/ARB/map_buffer_range.txt
-glFlushMappedBufferRange http://www.opengl.org/sdk/docs/man3/xhtml/glFlushMappedBufferRange.xml
-glFlushMappedBufferRange http://www.opengl.org/sdk/docs/man4/xhtml/glFlushMappedBufferRange.xml
-glFlushMappedBufferRangeAPPLE http://www.opengl.org/registry/specs/APPLE/flush_buffer_range.txt
-glFlushMappedNamedBufferRangeEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glFlushPixelDataRangeNV http://www.opengl.org/registry/specs/NV/pixel_data_range.txt
-glFlushRasterSGIX http://www.opengl.org/registry/specs/SGIX/flush_raster.txt
-glFlushStaticDataIBM http://www.opengl.org/registry/specs/IBM/static_data.txt
-glFlushVertexArrayRangeAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_array_range.txt
-glFlushVertexArrayRangeNV http://www.opengl.org/registry/specs/NV/vertex_array_range.txt
-glFogCoordFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glFogCoordPointer http://www.opengl.org/sdk/docs/man/xhtml/glFogCoordPointer.xml
-glFogCoordPointerEXT http://www.opengl.org/registry/specs/EXT/fog_coord.txt
-glFogCoordd http://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml
-glFogCoorddv http://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml
-glFogCoordf http://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml
-glFogCoordfv http://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml
-glFogCoordhNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glFogCoordhvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glFogFuncSGIS http://www.opengl.org/registry/specs/SGIS/fog_func.txt
-glFogf http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml
-glFogfv http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml
-glFogi http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml
-glFogiv http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml
-glFragmentColorMaterialEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentColorMaterialSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentLightModelfEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentLightModelfSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentLightModelfvEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentLightModelfvSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentLightModeliEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentLightModeliSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentLightModelivEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentLightModelivSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentLightfEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentLightfSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentLightfvEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentLightfvSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentLightiEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentLightiSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentLightivEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentLightivSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentMaterialfEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentMaterialfSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentMaterialfvEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentMaterialfvSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentMaterialiEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentMaterialiSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFragmentMaterialivEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glFragmentMaterialivSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glFrameTerminatorGREMEDY http://www.opengl.org/registry/specs/GREMEDY/frame_terminator.txt
-glFrameZoomSGIX http://www.opengl.org/registry/specs/SGIX/framezoom.txt
-glFramebufferDrawBufferEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glFramebufferDrawBuffersEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glFramebufferReadBufferEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glFramebufferRenderbuffer http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glFramebufferRenderbuffer http://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferRenderbuffer.xml
-glFramebufferRenderbuffer http://www.opengl.org/sdk/docs/man4/xhtml/glFramebufferRenderbuffer.xml
-glFramebufferRenderbufferEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glFramebufferTexture http://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTexture.xml
-glFramebufferTexture http://www.opengl.org/sdk/docs/man4/xhtml/glFramebufferTexture.xml
-glFramebufferTexture1D http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glFramebufferTexture1D http://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTexture.xml
-glFramebufferTexture1D http://www.opengl.org/sdk/docs/man4/xhtml/glFramebufferTexture.xml
-glFramebufferTexture1DEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glFramebufferTexture2D http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glFramebufferTexture2D http://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTexture.xml
-glFramebufferTexture2D http://www.opengl.org/sdk/docs/man4/xhtml/glFramebufferTexture.xml
-glFramebufferTexture2DEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glFramebufferTexture3D http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glFramebufferTexture3D http://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTexture.xml
-glFramebufferTexture3D http://www.opengl.org/sdk/docs/man4/xhtml/glFramebufferTexture.xml
-glFramebufferTexture3DEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glFramebufferTextureARB http://www.opengl.org/registry/specs/ARB/geometry_shader4.txt
-glFramebufferTextureEXT http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
-glFramebufferTextureEXT http://www.opengl.org/registry/specs/NV/geometry_program4.txt
-glFramebufferTextureFaceARB http://www.opengl.org/registry/specs/ARB/geometry_shader4.txt
-glFramebufferTextureFaceEXT http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
-glFramebufferTextureFaceEXT http://www.opengl.org/registry/specs/NV/geometry_program4.txt
-glFramebufferTextureLayer http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glFramebufferTextureLayer http://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTextureLayer.xml
-glFramebufferTextureLayer http://www.opengl.org/sdk/docs/man4/xhtml/glFramebufferTextureLayer.xml
-glFramebufferTextureLayerARB http://www.opengl.org/registry/specs/ARB/geometry_shader4.txt
-glFramebufferTextureLayerEXT http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
-glFramebufferTextureLayerEXT http://www.opengl.org/registry/specs/EXT/texture_array.txt
-glFramebufferTextureLayerEXT http://www.opengl.org/registry/specs/NV/geometry_program4.txt
-glFreeObjectBufferATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glFrontFace http://www.opengl.org/sdk/docs/man/xhtml/glFrontFace.xml
-glFrontFace http://www.opengl.org/sdk/docs/man3/xhtml/glFrontFace.xml
-glFrontFace http://www.opengl.org/sdk/docs/man4/xhtml/glFrontFace.xml
-glFrustum http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml
-glFrustumfOES http://www.opengl.org/registry/specs/OES/OES_single_precision.txt
-glFrustumxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGenArraySetsEXT http://www.opengl.org/registry/specs/EXT/vertex_array_set.txt
-glGenAsyncMarkersSGIX http://www.opengl.org/registry/specs/SGIX/async.txt
-glGenBuffers http://www.opengl.org/sdk/docs/man/xhtml/glGenBuffers.xml
-glGenBuffers http://www.opengl.org/sdk/docs/man3/xhtml/glGenBuffers.xml
-glGenBuffers http://www.opengl.org/sdk/docs/man4/xhtml/glGenBuffers.xml
-glGenBuffersARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glGenFencesAPPLE http://www.opengl.org/registry/specs/APPLE/fence.txt
-glGenFencesNV http://www.opengl.org/registry/specs/NV/fence.txt
-glGenFramebuffers http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glGenFramebuffers http://www.opengl.org/sdk/docs/man3/xhtml/glGenFramebuffers.xml
-glGenFramebuffers http://www.opengl.org/sdk/docs/man4/xhtml/glGenFramebuffers.xml
-glGenFramebuffersEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glGenLists http://www.opengl.org/sdk/docs/man/xhtml/glGenLists.xml
-glGenNamesAMD http://www.opengl.org/registry/specs/AMD/name_gen_delete.txt
-glGenOcclusionQueriesNV http://www.opengl.org/registry/specs/NV/occlusion_query.txt
-glGenPathsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGenPerfMonitorsAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glGenProgramPipelines http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glGenProgramPipelines http://www.opengl.org/sdk/docs/man4/xhtml/glGenProgramPipelines.xml
-glGenProgramsARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glGenProgramsARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGenProgramsNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGenQueries http://www.opengl.org/sdk/docs/man/xhtml/glGenQueries.xml
-glGenQueries http://www.opengl.org/sdk/docs/man3/xhtml/glGenQueries.xml
-glGenQueries http://www.opengl.org/sdk/docs/man4/xhtml/glGenQueries.xml
-glGenQueriesARB http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-glGenRenderbuffers http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glGenRenderbuffers http://www.opengl.org/sdk/docs/man3/xhtml/glGenRenderbuffers.xml
-glGenRenderbuffers http://www.opengl.org/sdk/docs/man4/xhtml/glGenRenderbuffers.xml
-glGenRenderbuffersEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glGenSamplers http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glGenSamplers http://www.opengl.org/sdk/docs/man3/xhtml/glGenSamplers.xml
-glGenSamplers http://www.opengl.org/sdk/docs/man4/xhtml/glGenSamplers.xml
-glGenTextures http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml
-glGenTextures http://www.opengl.org/sdk/docs/man3/xhtml/glGenTextures.xml
-glGenTextures http://www.opengl.org/sdk/docs/man4/xhtml/glGenTextures.xml
-glGenTexturesEXT http://www.opengl.org/registry/specs/EXT/texture_object.txt
-glGenTransformFeedbacks http://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
-glGenTransformFeedbacks http://www.opengl.org/sdk/docs/man4/xhtml/glGenTransformFeedbacks.xml
-glGenTransformFeedbacksNV http://www.opengl.org/registry/specs/NV/transform_feedback2.txt
-glGenVertexArrays http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
-glGenVertexArrays http://www.opengl.org/sdk/docs/man3/xhtml/glGenVertexArrays.xml
-glGenVertexArrays http://www.opengl.org/sdk/docs/man4/xhtml/glGenVertexArrays.xml
-glGenVertexArraysAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_array_object.txt
-glGenerateMipmap http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glGenerateMipmap http://www.opengl.org/sdk/docs/man3/xhtml/glGenerateMipmap.xml
-glGenerateMipmap http://www.opengl.org/sdk/docs/man4/xhtml/glGenerateMipmap.xml
-glGenerateMipmapEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glGenerateMultiTexMipmapEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGenerateTextureMipmapEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetActiveAttrib http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttrib.xml
-glGetActiveAttrib http://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveAttrib.xml
-glGetActiveAttrib http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveAttrib.xml
-glGetActiveAttribARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glGetActiveSubroutineName http://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
-glGetActiveSubroutineName http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveSubroutineName.xml
-glGetActiveSubroutineUniformName http://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
-glGetActiveSubroutineUniformName http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveSubroutineUniformName.xml
-glGetActiveSubroutineUniformiv http://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
-glGetActiveSubroutineUniformiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveSubroutineUniform.xml
-glGetActiveUniform http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml
-glGetActiveUniform http://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniform.xml
-glGetActiveUniform http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveUniform.xml
-glGetActiveUniformARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetActiveUniformBlockName http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glGetActiveUniformBlockName http://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniformBlockName.xml
-glGetActiveUniformBlockName http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveUniformBlockName.xml
-glGetActiveUniformBlockiv http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glGetActiveUniformBlockiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniformBlock.xml
-glGetActiveUniformBlockiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveUniformBlock.xml
-glGetActiveUniformName http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glGetActiveUniformName http://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniformName.xml
-glGetActiveUniformName http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveUniformName.xml
-glGetActiveUniformsiv http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glGetActiveUniformsiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniformsiv.xml
-glGetActiveUniformsiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetActiveUniformsiv.xml
-glGetActiveVaryingNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glGetArrayObjectfvATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glGetArrayObjectivATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glGetAttachedObjectsARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetAttachedShaders http://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedShaders.xml
-glGetAttachedShaders http://www.opengl.org/sdk/docs/man3/xhtml/glGetAttachedShaders.xml
-glGetAttachedShaders http://www.opengl.org/sdk/docs/man4/xhtml/glGetAttachedShaders.xml
-glGetAttribLocation http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml
-glGetAttribLocation http://www.opengl.org/sdk/docs/man3/xhtml/glGetAttribLocation.xml
-glGetAttribLocation http://www.opengl.org/sdk/docs/man4/xhtml/glGetAttribLocation.xml
-glGetAttribLocationARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glGetBooleanIndexedvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetBooleanIndexedvEXT http://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
-glGetBooleanIndexedvEXT http://www.opengl.org/registry/specs/EXT/transform_feedback.txt
-glGetBooleanIndexedvEXT http://www.opengl.org/registry/specs/NV/explicit_multisample.txt
-glGetBooleanIndexedvEXT http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glGetBooleani_v http://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
-glGetBooleani_v http://www.opengl.org/sdk/docs/man4/xhtml/glGet.xml
-glGetBooleanv http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
-glGetBooleanv http://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
-glGetBooleanv http://www.opengl.org/sdk/docs/man4/xhtml/glGet.xml
-glGetBufferParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteriv.xml
-glGetBufferParameteriv http://www.opengl.org/sdk/docs/man3/xhtml/glGetBufferParameter.xml
-glGetBufferParameteriv http://www.opengl.org/sdk/docs/man4/xhtml/glGetBufferParameter.xml
-glGetBufferParameterivARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glGetBufferParameterui64vNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glGetBufferPointerv http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferPointerv.xml
-glGetBufferPointerv http://www.opengl.org/sdk/docs/man3/xhtml/glGetBufferPointerv.xml
-glGetBufferPointerv http://www.opengl.org/sdk/docs/man4/xhtml/glGetBufferPointerv.xml
-glGetBufferPointervARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glGetBufferSubData http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferSubData.xml
-glGetBufferSubData http://www.opengl.org/sdk/docs/man3/xhtml/glGetBufferSubData.xml
-glGetBufferSubData http://www.opengl.org/sdk/docs/man4/xhtml/glGetBufferSubData.xml
-glGetBufferSubDataARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glGetClipPlane http://www.opengl.org/sdk/docs/man/xhtml/glGetClipPlane.xml
-glGetClipPlanefOES http://www.opengl.org/registry/specs/OES/OES_single_precision.txt
-glGetClipPlanexOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetColorTable http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTable.xml
-glGetColorTableEXT http://www.opengl.org/registry/specs/EXT/paletted_texture.txt
-glGetColorTableParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTableParameter.xml
-glGetColorTableParameterfvEXT http://www.opengl.org/registry/specs/EXT/paletted_texture.txt
-glGetColorTableParameterfvSGI http://www.opengl.org/registry/specs/SGI/color_table.txt
-glGetColorTableParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTableParameter.xml
-glGetColorTableParameterivEXT http://www.opengl.org/registry/specs/EXT/paletted_texture.txt
-glGetColorTableParameterivSGI http://www.opengl.org/registry/specs/SGI/color_table.txt
-glGetColorTableSGI http://www.opengl.org/registry/specs/SGI/color_table.txt
-glGetCombinerInputParameterfvNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glGetCombinerInputParameterivNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glGetCombinerOutputParameterfvNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glGetCombinerOutputParameterivNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glGetCombinerStageParameterfvNV http://www.opengl.org/registry/specs/NV/register_combiners2.txt
-glGetCompressedMultiTexImageEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetCompressedTexImage http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml
-glGetCompressedTexImage http://www.opengl.org/sdk/docs/man3/xhtml/glGetCompressedTexImage.xml
-glGetCompressedTexImage http://www.opengl.org/sdk/docs/man4/xhtml/glGetCompressedTexImage.xml
-glGetCompressedTexImageARB http://www.opengl.org/registry/specs/ARB/texture_compression.txt
-glGetCompressedTextureImageEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetConvolutionFilter http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionFilter.xml
-glGetConvolutionFilterEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glGetConvolutionParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionParameter.xml
-glGetConvolutionParameterfvEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glGetConvolutionParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionParameter.xml
-glGetConvolutionParameterivEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glGetConvolutionParameterxvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetDebugMessageLogAMD http://www.opengl.org/registry/specs/AMD/debug_output.txt
-glGetDebugMessageLogARB http://www.opengl.org/registry/specs/ARB/debug_output.txt
-glGetDetailTexFuncSGIS http://www.opengl.org/registry/specs/SGIS/detail_texture.txt
-glGetDoubleIndexedvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetDoublei_v http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glGetDoublei_vEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetDoublev http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
-glGetDoublev http://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
-glGetDoublev http://www.opengl.org/sdk/docs/man4/xhtml/glGet.xml
-glGetError http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml
-glGetError http://www.opengl.org/sdk/docs/man3/xhtml/glGetError.xml
-glGetError http://www.opengl.org/sdk/docs/man4/xhtml/glGetError.xml
-glGetFenceivNV http://www.opengl.org/registry/specs/NV/fence.txt
-glGetFinalCombinerInputParameterfvNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glGetFinalCombinerInputParameterivNV http://www.opengl.org/registry/specs/NV/register_combiners.txt
-glGetFixedvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetFloatIndexedvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetFloati_v http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glGetFloati_vEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetFloatv http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
-glGetFloatv http://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
-glGetFloatv http://www.opengl.org/sdk/docs/man4/xhtml/glGet.xml
-glGetFogFuncSGIS http://www.opengl.org/registry/specs/SGIS/fog_func.txt
-glGetFragDataIndex http://www.opengl.org/registry/specs/ARB/blend_func_extended.txt
-glGetFragDataIndex http://www.opengl.org/sdk/docs/man3/xhtml/glGetFragDataIndex.xml
-glGetFragDataIndex http://www.opengl.org/sdk/docs/man4/xhtml/glGetFragDataIndex.xml
-glGetFragDataLocation http://www.opengl.org/sdk/docs/man3/xhtml/glGetFragDataLocation.xml
-glGetFragDataLocation http://www.opengl.org/sdk/docs/man4/xhtml/glGetFragDataLocation.xml
-glGetFragDataLocationEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glGetFragmentLightfvEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glGetFragmentLightfvSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glGetFragmentLightivEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glGetFragmentLightivSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glGetFragmentMaterialfvEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glGetFragmentMaterialfvSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glGetFragmentMaterialivEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glGetFragmentMaterialivSGIX http://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
-glGetFramebufferAttachmentParameter http://www.opengl.org/sdk/docs/man3/xhtml/glGetFramebufferAttachmentParameter.xml
-glGetFramebufferAttachmentParameter http://www.opengl.org/sdk/docs/man4/xhtml/glGetFramebufferAttachmentParameter.xml
-glGetFramebufferAttachmentParameteriv http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glGetFramebufferAttachmentParameterivEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glGetFramebufferParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetGraphicsResetStatusARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetHandleARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetHistogram http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogram.xml
-glGetHistogramEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glGetHistogramParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogramParameter.xml
-glGetHistogramParameterfvEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glGetHistogramParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogramParameter.xml
-glGetHistogramParameterivEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glGetHistogramParameterxvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetImageTransformParameterfvHP http://www.opengl.org/registry/specs/HP/image_transform.txt
-glGetImageTransformParameterivHP http://www.opengl.org/registry/specs/HP/image_transform.txt
-glGetInfoLogARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetInstrumentsSGIX http://www.opengl.org/registry/specs/SGIX/instruments.txt
-glGetInteger64i_v http://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
-glGetInteger64i_v http://www.opengl.org/sdk/docs/man4/xhtml/glGet.xml
-glGetInteger64v http://www.opengl.org/registry/specs/ARB/sync.txt
-glGetInteger64v http://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
-glGetInteger64v http://www.opengl.org/sdk/docs/man4/xhtml/glGet.xml
-glGetIntegerIndexedivEXT http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glGetIntegerIndexedvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetIntegerIndexedvEXT http://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
-glGetIntegerIndexedvEXT http://www.opengl.org/registry/specs/EXT/transform_feedback.txt
-glGetIntegerIndexedvEXT http://www.opengl.org/registry/specs/NV/explicit_multisample.txt
-glGetIntegerIndexedvEXT http://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
-glGetIntegerIndexedvEXT http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glGetIntegeri_v http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glGetIntegeri_v http://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
-glGetIntegeri_v http://www.opengl.org/sdk/docs/man4/xhtml/glGet.xml
-glGetIntegerui64i_vNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glGetIntegerui64vNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glGetIntegerv http://www.opengl.org/registry/specs/SGIX/instruments.txt
-glGetIntegerv http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
-glGetIntegerv http://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
-glGetIntegerv http://www.opengl.org/sdk/docs/man4/xhtml/glGet.xml
-glGetInternalformativ http://www.opengl.org/registry/specs/ARB/internalformat_query.txt
-glGetLightfv http://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml
-glGetLightiv http://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml
-glGetLightxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetListParameterfvSGIX http://www.opengl.org/registry/specs/SGIX/list_priority.txt
-glGetListParameterivSGIX http://www.opengl.org/registry/specs/SGIX/list_priority.txt
-glGetMapAttribParameterfvNV http://www.opengl.org/registry/specs/NV/evaluators.txt
-glGetMapAttribParameterivNV http://www.opengl.org/registry/specs/NV/evaluators.txt
-glGetMapControlPointsNV http://www.opengl.org/registry/specs/NV/evaluators.txt
-glGetMapParameterfvNV http://www.opengl.org/registry/specs/NV/evaluators.txt
-glGetMapParameterivNV http://www.opengl.org/registry/specs/NV/evaluators.txt
-glGetMapdv http://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml
-glGetMapfv http://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml
-glGetMapiv http://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml
-glGetMapxvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetMaterialfv http://www.opengl.org/sdk/docs/man/xhtml/glGetMaterial.xml
-glGetMaterialiv http://www.opengl.org/sdk/docs/man/xhtml/glGetMaterial.xml
-glGetMaterialxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetMinmax http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmax.xml
-glGetMinmaxEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glGetMinmaxParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmaxParameter.xml
-glGetMinmaxParameterfvEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glGetMinmaxParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmaxParameter.xml
-glGetMinmaxParameterivEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glGetMultiTexEnvfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexEnvivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexGendvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexGenfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexGenivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexImageEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexLevelParameterfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexLevelParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexParameterIivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexParameterIuivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexParameterfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultiTexParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetMultisamplefv http://www.opengl.org/registry/specs/ARB/texture_multisample.txt
-glGetMultisamplefv http://www.opengl.org/sdk/docs/man3/xhtml/glGetMultisample.xml
-glGetMultisamplefv http://www.opengl.org/sdk/docs/man4/xhtml/glGetMultisample.xml
-glGetMultisamplefvNV http://www.opengl.org/registry/specs/NV/explicit_multisample.txt
-glGetNamedBufferParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedBufferParameterui64vNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glGetNamedBufferPointervEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedBufferSubDataEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedFramebufferAttachmentParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedProgramLocalParameterIivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedProgramLocalParameterIuivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedProgramLocalParameterdvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedProgramLocalParameterfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedProgramStringEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedProgramivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedRenderbufferParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetNamedStringARB http://www.opengl.org/registry/specs/ARB/shading_language_include.txt
-glGetNamedStringivARB http://www.opengl.org/registry/specs/ARB/shading_language_include.txt
-glGetObjectBufferfvATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glGetObjectBufferivATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glGetObjectParameterfvARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetObjectParameterivAPPLE http://www.opengl.org/registry/specs/APPLE/object_purgeable.txt
-glGetObjectParameterivARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetOcclusionQueryivNV http://www.opengl.org/registry/specs/NV/occlusion_query.txt
-glGetOcclusionQueryuivNV http://www.opengl.org/registry/specs/NV/occlusion_query.txt
-glGetPathColorGenfvNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathColorGenivNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathCommandsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathCoordsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathDashArrayNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathLengthNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathMetricRangeNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathMetricsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathParameterfvNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathParameterivNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathSpacingNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathTexGenfvNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPathTexGenivNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glGetPerfMonitorCounterDataAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glGetPerfMonitorCounterInfoAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glGetPerfMonitorCounterStringAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glGetPerfMonitorCountersAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glGetPerfMonitorGroupStringAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glGetPerfMonitorGroupsAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glGetPixelMapfv http://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml
-glGetPixelMapuiv http://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml
-glGetPixelMapusv http://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml
-glGetPixelTransformParameterfvEXT http://www.opengl.org/registry/specs/EXT/pixel_transform.txt
-glGetPixelTransformParameterivEXT http://www.opengl.org/registry/specs/EXT/pixel_transform.txt
-glGetPointerIndexedvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetPointeri_vEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetPointerv http://www.opengl.org/registry/specs/ARB/debug_output.txt
-glGetPointerv http://www.opengl.org/sdk/docs/man/xhtml/glGetPointerv.xml
-glGetPointervEXT http://www.opengl.org/registry/specs/EXT/vertex_array.txt
-glGetPointervEXT http://www.opengl.org/registry/specs/SGIX/instruments.txt
-glGetPolygonStipple http://www.opengl.org/sdk/docs/man/xhtml/glGetPolygonStipple.xml
-glGetProgramBinary http://www.opengl.org/registry/specs/ARB/get_program_binary.txt
-glGetProgramBinary http://www.opengl.org/sdk/docs/man4/xhtml/glGetProgramBinary.xml
-glGetProgramEnvParameterIivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glGetProgramEnvParameterIuivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glGetProgramEnvParameterdvARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glGetProgramEnvParameterdvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetProgramEnvParameterfvARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glGetProgramEnvParameterfvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetProgramInfoLog http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramInfoLog.xml
-glGetProgramInfoLog http://www.opengl.org/sdk/docs/man3/xhtml/glGetProgramInfoLog.xml
-glGetProgramInfoLog http://www.opengl.org/sdk/docs/man4/xhtml/glGetProgramInfoLog.xml
-glGetProgramLocalParameterIivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glGetProgramLocalParameterIuivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glGetProgramLocalParameterdvARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glGetProgramLocalParameterdvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetProgramLocalParameterdvARB http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glGetProgramLocalParameterfvARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glGetProgramLocalParameterfvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetProgramLocalParameterfvARB http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glGetProgramNamedParameterdvNV http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glGetProgramNamedParameterfvNV http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glGetProgramParameterdvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGetProgramParameterfvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGetProgramPipelineInfoLog http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glGetProgramPipelineInfoLog http://www.opengl.org/sdk/docs/man4/xhtml/glGetProgramPipelineInfoLog.xml
-glGetProgramPipelineiv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glGetProgramPipelineiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetProgramPipeline.xml
-glGetProgramStageiv http://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
-glGetProgramStageiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetProgramStage.xml
-glGetProgramStringARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glGetProgramStringARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetProgramStringNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGetProgramiv http://www.opengl.org/sdk/docs/man/xhtml/glGetProgram.xml
-glGetProgramiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetProgram.xml
-glGetProgramiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetProgram.xml
-glGetProgramivARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glGetProgramivARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetProgramivNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGetQueryIndexediv http://www.opengl.org/registry/specs/ARB/transform_feedback3.txt
-glGetQueryIndexediv http://www.opengl.org/sdk/docs/man4/xhtml/glGetQueryIndexed.xml
-glGetQueryObjecti64v http://www.opengl.org/registry/specs/ARB/timer_query.txt
-glGetQueryObjecti64v http://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryObject.xml
-glGetQueryObjecti64v http://www.opengl.org/sdk/docs/man4/xhtml/glGetQueryObject.xml
-glGetQueryObjecti64vEXT http://www.opengl.org/registry/specs/EXT/timer_query.txt
-glGetQueryObjectiv http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObject.xml
-glGetQueryObjectiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryObject.xml
-glGetQueryObjectiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetQueryObject.xml
-glGetQueryObjectivARB http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-glGetQueryObjectui64v http://www.opengl.org/registry/specs/ARB/timer_query.txt
-glGetQueryObjectui64v http://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryObject.xml
-glGetQueryObjectui64v http://www.opengl.org/sdk/docs/man4/xhtml/glGetQueryObject.xml
-glGetQueryObjectui64vEXT http://www.opengl.org/registry/specs/EXT/timer_query.txt
-glGetQueryObjectuiv http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObject.xml
-glGetQueryObjectuiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryObject.xml
-glGetQueryObjectuiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetQueryObject.xml
-glGetQueryObjectuivARB http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-glGetQueryiv http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryiv.xml
-glGetQueryiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryiv.xml
-glGetQueryiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetQueryiv.xml
-glGetQueryivARB http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-glGetRenderbufferParameteriv http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glGetRenderbufferParameteriv http://www.opengl.org/sdk/docs/man3/xhtml/glGetRenderbufferParameter.xml
-glGetRenderbufferParameteriv http://www.opengl.org/sdk/docs/man4/xhtml/glGetRenderbufferParameter.xml
-glGetRenderbufferParameterivEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glGetSamplerParameterIiv http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glGetSamplerParameterIuiv http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glGetSamplerParameterfv http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glGetSamplerParameterfv http://www.opengl.org/sdk/docs/man3/xhtml/glGetSamplerParameter.xml
-glGetSamplerParameterfv http://www.opengl.org/sdk/docs/man4/xhtml/glGetSamplerParameter.xml
-glGetSamplerParameteriv http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glGetSamplerParameteriv http://www.opengl.org/sdk/docs/man3/xhtml/glGetSamplerParameter.xml
-glGetSamplerParameteriv http://www.opengl.org/sdk/docs/man4/xhtml/glGetSamplerParameter.xml
-glGetSeparableFilter http://www.opengl.org/sdk/docs/man/xhtml/glGetSeparableFilter.xml
-glGetSeparableFilterEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glGetShaderInfoLog http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderInfoLog.xml
-glGetShaderInfoLog http://www.opengl.org/sdk/docs/man3/xhtml/glGetShaderInfoLog.xml
-glGetShaderInfoLog http://www.opengl.org/sdk/docs/man4/xhtml/glGetShaderInfoLog.xml
-glGetShaderPrecisionFormat http://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
-glGetShaderPrecisionFormat http://www.opengl.org/sdk/docs/man4/xhtml/glGetShaderPrecisionFormat.xml
-glGetShaderSource http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSource.xml
-glGetShaderSource http://www.opengl.org/sdk/docs/man3/xhtml/glGetShaderSource.xml
-glGetShaderSource http://www.opengl.org/sdk/docs/man4/xhtml/glGetShaderSource.xml
-glGetShaderSourceARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetShaderiv http://www.opengl.org/sdk/docs/man/xhtml/glGetShader.xml
-glGetShaderiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetShader.xml
-glGetShaderiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetShader.xml
-glGetSharpenTexFuncSGIS http://www.opengl.org/registry/specs/SGIS/sharpen_texture.txt
-glGetString http://www.opengl.org/sdk/docs/man/xhtml/glGetString.xml
-glGetString http://www.opengl.org/sdk/docs/man3/xhtml/glGetString.xml
-glGetString http://www.opengl.org/sdk/docs/man4/xhtml/glGetString.xml
-glGetStringi http://www.opengl.org/sdk/docs/man3/xhtml/glGetString.xml
-glGetStringi http://www.opengl.org/sdk/docs/man4/xhtml/glGetString.xml
-glGetSubroutineIndex http://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
-glGetSubroutineIndex http://www.opengl.org/sdk/docs/man4/xhtml/glGetSubroutineIndex.xml
-glGetSubroutineUniformLocation http://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
-glGetSubroutineUniformLocation http://www.opengl.org/sdk/docs/man4/xhtml/glGetSubroutineUniformLocation.xml
-glGetSynciv http://www.opengl.org/registry/specs/ARB/sync.txt
-glGetSynciv http://www.opengl.org/sdk/docs/man3/xhtml/glGetSync.xml
-glGetSynciv http://www.opengl.org/sdk/docs/man4/xhtml/glGetSync.xml
-glGetTexEnvfv http://www.opengl.org/sdk/docs/man/xhtml/glGetTexEnv.xml
-glGetTexEnviv http://www.opengl.org/sdk/docs/man/xhtml/glGetTexEnv.xml
-glGetTexEnvxvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetTexFilterFuncSGIS http://www.opengl.org/registry/specs/SGIS/texture_filter4.txt
-glGetTexGendv http://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml
-glGetTexGenfv http://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml
-glGetTexGeniv http://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml
-glGetTexGenxvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetTexImage http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml
-glGetTexImage http://www.opengl.org/sdk/docs/man3/xhtml/glGetTexImage.xml
-glGetTexImage http://www.opengl.org/sdk/docs/man4/xhtml/glGetTexImage.xml
-glGetTexLevelParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glGetTexLevelParameter.xml
-glGetTexLevelParameterfv http://www.opengl.org/sdk/docs/man3/xhtml/glGetTexLevelParameter.xml
-glGetTexLevelParameterfv http://www.opengl.org/sdk/docs/man4/xhtml/glGetTexLevelParameter.xml
-glGetTexLevelParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glGetTexLevelParameter.xml
-glGetTexLevelParameteriv http://www.opengl.org/sdk/docs/man3/xhtml/glGetTexLevelParameter.xml
-glGetTexLevelParameteriv http://www.opengl.org/sdk/docs/man4/xhtml/glGetTexLevelParameter.xml
-glGetTexLevelParameterxvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetTexParameterPointervAPPLE http://www.opengl.org/registry/specs/APPLE/texture_range.txt
-glGetTexParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameter.xml
-glGetTexParameterfv http://www.opengl.org/sdk/docs/man3/xhtml/glGetTexParameter.xml
-glGetTexParameterfv http://www.opengl.org/sdk/docs/man4/xhtml/glGetTexParameter.xml
-glGetTexParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameter.xml
-glGetTexParameteriv http://www.opengl.org/sdk/docs/man3/xhtml/glGetTexParameter.xml
-glGetTexParameteriv http://www.opengl.org/sdk/docs/man4/xhtml/glGetTexParameter.xml
-glGetTexParameterxvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glGetTextureImageEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetTextureLevelParameterfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetTextureLevelParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetTextureParameterIivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetTextureParameterIuivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetTextureParameterfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetTextureParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetTrackMatrixivNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGetTransformFeedbackVarying http://www.opengl.org/sdk/docs/man3/xhtml/glGetTransformFeedbackVarying.xml
-glGetTransformFeedbackVarying http://www.opengl.org/sdk/docs/man4/xhtml/glGetTransformFeedbackVarying.xml
-glGetTransformFeedbackVaryingEXT http://www.opengl.org/registry/specs/EXT/transform_feedback.txt
-glGetTransformFeedbackVaryingNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glGetUniformBlockIndex http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glGetUniformBlockIndex http://www.opengl.org/sdk/docs/man3/xhtml/glGetUniformBlockIndex.xml
-glGetUniformBlockIndex http://www.opengl.org/sdk/docs/man4/xhtml/glGetUniformBlockIndex.xml
-glGetUniformBufferSizeEXT http://www.opengl.org/registry/specs/EXT/bindable_uniform.txt
-glGetUniformIndices http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glGetUniformIndices http://www.opengl.org/sdk/docs/man3/xhtml/glGetUniformIndices.xml
-glGetUniformIndices http://www.opengl.org/sdk/docs/man4/xhtml/glGetUniformIndices.xml
-glGetUniformLocation http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocation.xml
-glGetUniformLocation http://www.opengl.org/sdk/docs/man3/xhtml/glGetUniformLocation.xml
-glGetUniformLocation http://www.opengl.org/sdk/docs/man4/xhtml/glGetUniformLocation.xml
-glGetUniformLocationARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetUniformOffsetEXT http://www.opengl.org/registry/specs/EXT/bindable_uniform.txt
-glGetUniformSubroutineuiv http://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
-glGetUniformSubroutineuiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetUniformSubroutine.xml
-glGetUniformdv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glGetUniformfv http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml
-glGetUniformfv http://www.opengl.org/sdk/docs/man3/xhtml/glGetUniform.xml
-glGetUniformfv http://www.opengl.org/sdk/docs/man4/xhtml/glGetUniform.xml
-glGetUniformfvARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetUniformi64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glGetUniformiv http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml
-glGetUniformiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetUniform.xml
-glGetUniformiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetUniform.xml
-glGetUniformivARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glGetUniformui64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glGetUniformui64vNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glGetUniformuivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glGetVariantArrayObjectfvATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glGetVariantArrayObjectivATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glGetVaryingLocationNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glGetVertexArrayIntegeri_vEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetVertexArrayIntegervEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetVertexArrayPointeri_vEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetVertexArrayPointervEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glGetVertexAttribArrayObjectfvATI http://www.opengl.org/registry/specs/ATI/vertex_attrib_array_object.txt
-glGetVertexAttribArrayObjectivATI http://www.opengl.org/registry/specs/ATI/vertex_attrib_array_object.txt
-glGetVertexAttribIiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribIiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribIivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glGetVertexAttribIivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glGetVertexAttribIuiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribIuiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribIuivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glGetVertexAttribIuivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glGetVertexAttribLdv http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glGetVertexAttribLdv http://www.opengl.org/sdk/docs/man4/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribLdvEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glGetVertexAttribLi64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glGetVertexAttribLui64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glGetVertexAttribPointerv http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribPointerv.xml
-glGetVertexAttribPointerv http://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttribPointerv.xml
-glGetVertexAttribPointerv http://www.opengl.org/sdk/docs/man4/xhtml/glGetVertexAttribPointerv.xml
-glGetVertexAttribPointervARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetVertexAttribPointervARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glGetVertexAttribPointervNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGetVertexAttribdv http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribdv http://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribdv http://www.opengl.org/sdk/docs/man4/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribdvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetVertexAttribdvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glGetVertexAttribdvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGetVertexAttribfv http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribfv http://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribfv http://www.opengl.org/sdk/docs/man4/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribfvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetVertexAttribfvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glGetVertexAttribfvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGetVertexAttribiv http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribiv http://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribiv http://www.opengl.org/sdk/docs/man4/xhtml/glGetVertexAttrib.xml
-glGetVertexAttribivARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glGetVertexAttribivARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glGetVertexAttribivNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glGetVideoCaptureivNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glGetVideoi64vNV http://www.opengl.org/registry/specs/NV/present_video.txt
-glGetVideoivNV http://www.opengl.org/registry/specs/NV/present_video.txt
-glGetVideoui64vNV http://www.opengl.org/registry/specs/NV/present_video.txt
-glGetVideouivNV http://www.opengl.org/registry/specs/NV/present_video.txt
-glGetnColorTableARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnCompressedTexImageARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnConvolutionFilterARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnHistogramARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnMapdvARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnMapfvARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnMapivARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnMinmaxARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnPixelMapfvARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnPixelMapuivARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnPixelMapusvARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnPolygonStippleARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnSeparableFilterARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnTexImageARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnUniformdvARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnUniformfvARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnUniformivARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGetnUniformuivARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glGlobalAlphaFactorbSUN http://www.opengl.org/registry/specs/SUN/global_alpha.txt
-glGlobalAlphaFactordSUN http://www.opengl.org/registry/specs/SUN/global_alpha.txt
-glGlobalAlphaFactorfSUN http://www.opengl.org/registry/specs/SUN/global_alpha.txt
-glGlobalAlphaFactoriSUN http://www.opengl.org/registry/specs/SUN/global_alpha.txt
-glGlobalAlphaFactorsSUN http://www.opengl.org/registry/specs/SUN/global_alpha.txt
-glGlobalAlphaFactorubSUN http://www.opengl.org/registry/specs/SUN/global_alpha.txt
-glGlobalAlphaFactoruiSUN http://www.opengl.org/registry/specs/SUN/global_alpha.txt
-glGlobalAlphaFactorusSUN http://www.opengl.org/registry/specs/SUN/global_alpha.txt
-glHint http://www.opengl.org/sdk/docs/man/xhtml/glHint.xml
-glHint http://www.opengl.org/sdk/docs/man3/xhtml/glHint.xml
-glHint http://www.opengl.org/sdk/docs/man4/xhtml/glHint.xml
-glHistogram http://www.opengl.org/sdk/docs/man/xhtml/glHistogram.xml
-glHistogramEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glImageTransformParameterfHP http://www.opengl.org/registry/specs/HP/image_transform.txt
-glImageTransformParameterfvHP http://www.opengl.org/registry/specs/HP/image_transform.txt
-glImageTransformParameteriHP http://www.opengl.org/registry/specs/HP/image_transform.txt
-glImageTransformParameterivHP http://www.opengl.org/registry/specs/HP/image_transform.txt
-glImportSyncEXT http://www.opengl.org/registry/specs/EXT/x11_sync_object.txt
-glIndexFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glIndexMask http://www.opengl.org/sdk/docs/man/xhtml/glIndexMask.xml
-glIndexPointer http://www.opengl.org/sdk/docs/man/xhtml/glIndexPointer.xml
-glIndexPointerEXT http://www.opengl.org/registry/specs/EXT/vertex_array.txt
-glIndexd http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glIndexdv http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glIndexf http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glIndexfv http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glIndexi http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glIndexiv http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glIndexs http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glIndexsv http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glIndexub http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glIndexubv http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
-glInitNames http://www.opengl.org/sdk/docs/man/xhtml/glInitNames.xml
-glInstrumentsBufferSGIX http://www.opengl.org/registry/specs/SGIX/instruments.txt
-glInterleavedArrays http://www.opengl.org/sdk/docs/man/xhtml/glInterleavedArrays.xml
-glInterpolatePathsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glIsArraySetEXT http://www.opengl.org/registry/specs/EXT/vertex_array_set.txt
-glIsAsyncMarkerSGIX http://www.opengl.org/registry/specs/SGIX/async.txt
-glIsBuffer http://www.opengl.org/sdk/docs/man/xhtml/glIsBuffer.xml
-glIsBuffer http://www.opengl.org/sdk/docs/man3/xhtml/glIsBuffer.xml
-glIsBuffer http://www.opengl.org/sdk/docs/man4/xhtml/glIsBuffer.xml
-glIsBufferARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glIsBufferResidentNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glIsEnabled http://www.opengl.org/sdk/docs/man/xhtml/glIsEnabled.xml
-glIsEnabled http://www.opengl.org/sdk/docs/man3/xhtml/glIsEnabled.xml
-glIsEnabled http://www.opengl.org/sdk/docs/man4/xhtml/glIsEnabled.xml
-glIsEnabledIndexedEXT http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glIsEnabledIndexedEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glIsEnabledIndexedEXT http://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
-glIsFenceAPPLE http://www.opengl.org/registry/specs/APPLE/fence.txt
-glIsFenceNV http://www.opengl.org/registry/specs/NV/fence.txt
-glIsFramebuffer http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glIsFramebuffer http://www.opengl.org/sdk/docs/man3/xhtml/glIsFramebuffer.xml
-glIsFramebuffer http://www.opengl.org/sdk/docs/man4/xhtml/glIsFramebuffer.xml
-glIsFramebufferEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glIsList http://www.opengl.org/sdk/docs/man/xhtml/glIsList.xml
-glIsNameAMD http://www.opengl.org/registry/specs/AMD/name_gen_delete.txt
-glIsNamedBufferResidentNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glIsNamedStringARB http://www.opengl.org/registry/specs/ARB/shading_language_include.txt
-glIsObjectBufferATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glIsOcclusionQueryNV http://www.opengl.org/registry/specs/NV/occlusion_query.txt
-glIsPathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glIsPointInFillPathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glIsPointInStrokePathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glIsProgram http://www.opengl.org/sdk/docs/man/xhtml/glIsProgram.xml
-glIsProgram http://www.opengl.org/sdk/docs/man3/xhtml/glIsProgram.xml
-glIsProgram http://www.opengl.org/sdk/docs/man4/xhtml/glIsProgram.xml
-glIsProgramARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glIsProgramARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glIsProgramNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glIsProgramPipeline http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glIsProgramPipeline http://www.opengl.org/sdk/docs/man4/xhtml/glIsProgramPipeline.xml
-glIsQuery http://www.opengl.org/sdk/docs/man/xhtml/glIsQuery.xml
-glIsQuery http://www.opengl.org/sdk/docs/man3/xhtml/glIsQuery.xml
-glIsQuery http://www.opengl.org/sdk/docs/man4/xhtml/glIsQuery.xml
-glIsQueryARB http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-glIsRenderbuffer http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glIsRenderbuffer http://www.opengl.org/sdk/docs/man3/xhtml/glIsRenderbuffer.xml
-glIsRenderbuffer http://www.opengl.org/sdk/docs/man4/xhtml/glIsRenderbuffer.xml
-glIsRenderbufferEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glIsSampler http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glIsSampler http://www.opengl.org/sdk/docs/man3/xhtml/glIsSampler.xml
-glIsSampler http://www.opengl.org/sdk/docs/man4/xhtml/glIsSampler.xml
-glIsShader http://www.opengl.org/sdk/docs/man/xhtml/glIsShader.xml
-glIsShader http://www.opengl.org/sdk/docs/man3/xhtml/glIsShader.xml
-glIsShader http://www.opengl.org/sdk/docs/man4/xhtml/glIsShader.xml
-glIsSync http://www.opengl.org/registry/specs/ARB/sync.txt
-glIsSync http://www.opengl.org/sdk/docs/man3/xhtml/glIsSync.xml
-glIsSync http://www.opengl.org/sdk/docs/man4/xhtml/glIsSync.xml
-glIsTexture http://www.opengl.org/sdk/docs/man/xhtml/glIsTexture.xml
-glIsTexture http://www.opengl.org/sdk/docs/man3/xhtml/glIsTexture.xml
-glIsTexture http://www.opengl.org/sdk/docs/man4/xhtml/glIsTexture.xml
-glIsTextureEXT http://www.opengl.org/registry/specs/EXT/texture_object.txt
-glIsTransformFeedback http://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
-glIsTransformFeedback http://www.opengl.org/sdk/docs/man4/xhtml/glIsTransformFeedback.xml
-glIsTransformFeedbackNV http://www.opengl.org/registry/specs/NV/transform_feedback2.txt
-glIsVertexArray http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
-glIsVertexArray http://www.opengl.org/sdk/docs/man3/xhtml/glIsVertexArray.xml
-glIsVertexArray http://www.opengl.org/sdk/docs/man4/xhtml/glIsVertexArray.xml
-glIsVertexArrayAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_array_object.txt
-glIsVertexAttribEnabledAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
-glJoinSwapGroupSGIX http://www.opengl.org/registry/specs/SGIX/swap_group.txt
-glLightEnviEXT http://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
-glLightModelf http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
-glLightModelfv http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
-glLightModeli http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
-glLightModeliv http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
-glLightf http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml
-glLightfv http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml
-glLighti http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml
-glLightiv http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml
-glLineStipple http://www.opengl.org/sdk/docs/man/xhtml/glLineStipple.xml
-glLineWidth http://www.opengl.org/sdk/docs/man/xhtml/glLineWidth.xml
-glLineWidth http://www.opengl.org/sdk/docs/man3/xhtml/glLineWidth.xml
-glLineWidth http://www.opengl.org/sdk/docs/man4/xhtml/glLineWidth.xml
-glLineWidthxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glLinkProgram http://www.opengl.org/sdk/docs/man/xhtml/glLinkProgram.xml
-glLinkProgram http://www.opengl.org/sdk/docs/man3/xhtml/glLinkProgram.xml
-glLinkProgram http://www.opengl.org/sdk/docs/man4/xhtml/glLinkProgram.xml
-glLinkProgramARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glListBase http://www.opengl.org/sdk/docs/man/xhtml/glListBase.xml
-glListParameterfSGIX http://www.opengl.org/registry/specs/SGIX/list_priority.txt
-glListParameterfvSGIX http://www.opengl.org/registry/specs/SGIX/list_priority.txt
-glListParameteriSGIX http://www.opengl.org/registry/specs/SGIX/list_priority.txt
-glListParameterivSGIX http://www.opengl.org/registry/specs/SGIX/list_priority.txt
-glLoadIdentity http://www.opengl.org/sdk/docs/man/xhtml/glLoadIdentity.xml
-glLoadMatrixd http://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml
-glLoadMatrixf http://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml
-glLoadMatrixxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glLoadName http://www.opengl.org/sdk/docs/man/xhtml/glLoadName.xml
-glLoadProgramNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glLoadTransposeMatrixd http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrix.xml
-glLoadTransposeMatrixf http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrix.xml
-glLoadTransposeMatrixxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glLogicOp http://www.opengl.org/sdk/docs/man/xhtml/glLogicOp.xml
-glLogicOp http://www.opengl.org/sdk/docs/man3/xhtml/glLogicOp.xml
-glLogicOp http://www.opengl.org/sdk/docs/man4/xhtml/glLogicOp.xml
-glMakeBufferNonResidentNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glMakeBufferResidentNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glMakeNamedBufferNonResidentNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glMakeNamedBufferResidentNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glMap1d http://www.opengl.org/sdk/docs/man/xhtml/glMap1.xml
-glMap1f http://www.opengl.org/sdk/docs/man/xhtml/glMap1.xml
-glMap1xOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glMap2d http://www.opengl.org/sdk/docs/man/xhtml/glMap2.xml
-glMap2f http://www.opengl.org/sdk/docs/man/xhtml/glMap2.xml
-glMap2xOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glMapBuffer http://www.opengl.org/sdk/docs/man/xhtml/glMapBuffer.xml
-glMapBuffer http://www.opengl.org/sdk/docs/man3/xhtml/glMapBuffer.xml
-glMapBuffer http://www.opengl.org/sdk/docs/man4/xhtml/glMapBuffer.xml
-glMapBufferRange http://www.opengl.org/sdk/docs/man3/xhtml/glMapBufferRange.xml
-glMapBufferRange http://www.opengl.org/sdk/docs/man4/xhtml/glMapBufferRange.xml
-glMapControlPointsNV http://www.opengl.org/registry/specs/NV/evaluators.txt
-glMapGrid1d http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml
-glMapGrid1f http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml
-glMapGrid1xOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glMapGrid2d http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml
-glMapGrid2f http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml
-glMapGrid2xOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glMapNamedBufferEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMapParameterfvNV http://www.opengl.org/registry/specs/NV/evaluators.txt
-glMapParameterivNV http://www.opengl.org/registry/specs/NV/evaluators.txt
-glMapVertexAttrib1dAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
-glMapVertexAttrib1fAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
-glMapVertexAttrib2dAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
-glMapVertexAttrib2fAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
-glMaterialf http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml
-glMaterialfv http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml
-glMateriali http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml
-glMaterialiv http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml
-glMatrixFrustumEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixIndexPointerARB http://www.opengl.org/registry/specs/ARB/matrix_palette.txt
-glMatrixLoadIdentityEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixLoadTransposedEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixLoadTransposefEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixLoaddEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixLoadfEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixMode http://www.opengl.org/sdk/docs/man/xhtml/glMatrixMode.xml
-glMatrixMultTransposedEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixMultTransposefEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixMultdEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixMultfEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixOrthoEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixPopEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixPushEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixRotatedEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixRotatefEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixScaledEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixScalefEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixTranslatedEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMatrixTranslatefEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMemoryBarrier http://www.opengl.org/registry/specs/ARB/shader_image_load_store.txt
-glMemoryBarrierEXT http://www.opengl.org/registry/specs/EXT/shader_image_load_store.txt
-glMinSampleShading http://www.opengl.org/sdk/docs/man4/xhtml/glMinSampleShading.xml
-glMinSampleShadingARB http://www.opengl.org/registry/specs/ARB/sample_shading.txt
-glMinmax http://www.opengl.org/sdk/docs/man/xhtml/glMinmax.xml
-glMinmaxEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glMultMatrixd http://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml
-glMultMatrixf http://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml
-glMultMatrixxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glMultTransposeMatrixd http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrix.xml
-glMultTransposeMatrixf http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrix.xml
-glMultTransposeMatrixxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glMultiDrawArrays http://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawArrays.xml
-glMultiDrawArrays http://www.opengl.org/sdk/docs/man3/xhtml/glMultiDrawArrays.xml
-glMultiDrawArrays http://www.opengl.org/sdk/docs/man4/xhtml/glMultiDrawArrays.xml
-glMultiDrawArraysEXT http://www.opengl.org/registry/specs/EXT/multi_draw_arrays.txt
-glMultiDrawArraysIndirectAMD http://www.opengl.org/registry/specs/AMD/multi_draw_indirect.txt
-glMultiDrawElementArrayAPPLE http://www.opengl.org/registry/specs/APPLE/element_array.txt
-glMultiDrawElements http://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawElements.xml
-glMultiDrawElements http://www.opengl.org/sdk/docs/man3/xhtml/glMultiDrawElements.xml
-glMultiDrawElements http://www.opengl.org/sdk/docs/man4/xhtml/glMultiDrawElements.xml
-glMultiDrawElementsBaseVertex http://www.opengl.org/registry/specs/ARB/draw_elements_base_vertex.txt
-glMultiDrawElementsBaseVertex http://www.opengl.org/sdk/docs/man3/xhtml/glMultiDrawElementsBaseVertex.xml
-glMultiDrawElementsBaseVertex http://www.opengl.org/sdk/docs/man4/xhtml/glMultiDrawElementsBaseVertex.xml
-glMultiDrawElementsEXT http://www.opengl.org/registry/specs/EXT/multi_draw_arrays.txt
-glMultiDrawElementsIndirectAMD http://www.opengl.org/registry/specs/AMD/multi_draw_indirect.txt
-glMultiDrawRangeElementArrayAPPLE http://www.opengl.org/registry/specs/APPLE/element_array.txt
-glMultiModeDrawArraysIBM http://www.opengl.org/registry/specs/IBM/multimode_draw_arrays.txt
-glMultiModeDrawElementsIBM http://www.opengl.org/registry/specs/IBM/multimode_draw_arrays.txt
-glMultiTexBufferEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexCoord1d http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord1dv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord1f http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord1fv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord1hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glMultiTexCoord1hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glMultiTexCoord1i http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord1iv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord1s http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord1sv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord2d http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord2dv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord2f http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord2fv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord2hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glMultiTexCoord2hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glMultiTexCoord2i http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord2iv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord2s http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord2sv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord3d http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord3dv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord3f http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord3fv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord3hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glMultiTexCoord3hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glMultiTexCoord3i http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord3iv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord3s http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord3sv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord4d http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord4dv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord4f http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord4fv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord4hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glMultiTexCoord4hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glMultiTexCoord4i http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord4iv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord4s http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoord4sv http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
-glMultiTexCoordP1ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glMultiTexCoordP1uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glMultiTexCoordP2ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glMultiTexCoordP2uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glMultiTexCoordP3ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glMultiTexCoordP3uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glMultiTexCoordP4ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glMultiTexCoordP4uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glMultiTexCoordPointerEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexEnvfEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexEnvfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexEnviEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexEnvivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexGendEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexGendvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexGenfEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexGenfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexGeniEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexGenivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexParameterIivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexParameterIuivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexParameterfEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexParameterfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexParameteriEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexRenderbufferEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexSubImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexSubImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glMultiTexSubImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedBufferDataEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedBufferSubDataEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedCopyBufferSubDataEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedFramebufferRenderbufferEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedFramebufferTexture1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedFramebufferTexture2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedFramebufferTexture3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedFramebufferTextureEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedFramebufferTextureFaceEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedFramebufferTextureLayerEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParameter4dEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParameter4dvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParameter4fEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParameter4fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParameterI4iEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParameterI4ivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParameterI4uiEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParameterI4uivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParameters4fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParametersI4ivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramLocalParametersI4uivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedProgramStringEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedRenderbufferStorageEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedRenderbufferStorageMultisampleCoverageEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedRenderbufferStorageMultisampleEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glNamedStringARB http://www.opengl.org/registry/specs/ARB/shading_language_include.txt
-glNewList http://www.opengl.org/sdk/docs/man/xhtml/glNewList.xml
-glNewObjectBufferATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glNormal3b http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormal3bv http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormal3d http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormal3dv http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormal3f http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormal3fVertex3fSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glNormal3fVertex3fvSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glNormal3fv http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormal3hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glNormal3hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glNormal3i http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormal3iv http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormal3s http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormal3sv http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
-glNormalFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glNormalP3ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glNormalP3uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glNormalPointer http://www.opengl.org/sdk/docs/man/xhtml/glNormalPointer.xml
-glNormalPointerEXT http://www.opengl.org/registry/specs/EXT/vertex_array.txt
-glNormalPointervINTEL http://www.opengl.org/registry/specs/INTEL/parallel_arrays.txt
-glObjectPurgeableAPPLE http://www.opengl.org/registry/specs/APPLE/object_purgeable.txt
-glObjectUnpurgeableAPPLE http://www.opengl.org/registry/specs/APPLE/object_purgeable.txt
-glOrtho http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml
-glOrthofOES http://www.opengl.org/registry/specs/OES/OES_single_precision.txt
-glOrthoxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glPassThrough http://www.opengl.org/sdk/docs/man/xhtml/glPassThrough.xml
-glPassThroughxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glPatchParameterfv http://www.opengl.org/registry/specs/ARB/tessellation_shader.txt
-glPatchParameterfv http://www.opengl.org/sdk/docs/man4/xhtml/glPatchParameter.xml
-glPatchParameteri http://www.opengl.org/registry/specs/ARB/tessellation_shader.txt
-glPatchParameteri http://www.opengl.org/sdk/docs/man4/xhtml/glPatchParameter.xml
-glPathColorGenNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathCommandsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathCoordsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathCoverDepthFuncNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathDashArrayNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathFogGenNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathGlyphRangeNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathGlyphsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathParameterfNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathParameterfvNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathParameteriNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathParameterivNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathStencilDepthOffsetNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathStencilFuncNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathStringNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathSubCommandsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathSubCoordsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPathTexGenNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPauseTransformFeedback http://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
-glPauseTransformFeedback http://www.opengl.org/sdk/docs/man4/xhtml/glPauseTransformFeedback.xml
-glPauseTransformFeedbackNV http://www.opengl.org/registry/specs/NV/transform_feedback2.txt
-glPixelDataRangeNV http://www.opengl.org/registry/specs/NV/pixel_data_range.txt
-glPixelMapfv http://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml
-glPixelMapuiv http://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml
-glPixelMapusv http://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml
-glPixelStoref http://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml
-glPixelStoref http://www.opengl.org/sdk/docs/man3/xhtml/glPixelStore.xml
-glPixelStoref http://www.opengl.org/sdk/docs/man4/xhtml/glPixelStore.xml
-glPixelStorei http://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml
-glPixelStorei http://www.opengl.org/sdk/docs/man3/xhtml/glPixelStore.xml
-glPixelStorei http://www.opengl.org/sdk/docs/man4/xhtml/glPixelStore.xml
-glPixelTexGenSGIX http://www.opengl.org/registry/specs/SGIX/sgix_pixel_texture.txt
-glPixelTransferf http://www.opengl.org/sdk/docs/man/xhtml/glPixelTransfer.xml
-glPixelTransferi http://www.opengl.org/sdk/docs/man/xhtml/glPixelTransfer.xml
-glPixelTransferxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glPixelTransformParameterfEXT http://www.opengl.org/registry/specs/EXT/pixel_transform.txt
-glPixelTransformParameterfvEXT http://www.opengl.org/registry/specs/EXT/pixel_transform.txt
-glPixelTransformParameteriEXT http://www.opengl.org/registry/specs/EXT/pixel_transform.txt
-glPixelTransformParameterivEXT http://www.opengl.org/registry/specs/EXT/pixel_transform.txt
-glPixelZoom http://www.opengl.org/sdk/docs/man/xhtml/glPixelZoom.xml
-glPixelZoomxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glPointAlongPathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glPointParameterf http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml
-glPointParameterf http://www.opengl.org/sdk/docs/man3/xhtml/glPointParameter.xml
-glPointParameterf http://www.opengl.org/sdk/docs/man4/xhtml/glPointParameter.xml
-glPointParameterfARB http://www.opengl.org/registry/specs/ARB/point_parameters.txt
-glPointParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml
-glPointParameterfv http://www.opengl.org/sdk/docs/man3/xhtml/glPointParameter.xml
-glPointParameterfv http://www.opengl.org/sdk/docs/man4/xhtml/glPointParameter.xml
-glPointParameterfvARB http://www.opengl.org/registry/specs/ARB/point_parameters.txt
-glPointParameteri http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml
-glPointParameteri http://www.opengl.org/sdk/docs/man3/xhtml/glPointParameter.xml
-glPointParameteri http://www.opengl.org/sdk/docs/man4/xhtml/glPointParameter.xml
-glPointParameteriNV http://www.opengl.org/registry/specs/NV/point_sprite.txt
-glPointParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml
-glPointParameteriv http://www.opengl.org/sdk/docs/man3/xhtml/glPointParameter.xml
-glPointParameteriv http://www.opengl.org/sdk/docs/man4/xhtml/glPointParameter.xml
-glPointParameterivNV http://www.opengl.org/registry/specs/NV/point_sprite.txt
-glPointParameterxvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glPointSize http://www.opengl.org/sdk/docs/man/xhtml/glPointSize.xml
-glPointSize http://www.opengl.org/sdk/docs/man3/xhtml/glPointSize.xml
-glPointSize http://www.opengl.org/sdk/docs/man4/xhtml/glPointSize.xml
-glPointSizexOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glPollAsyncSGIX http://www.opengl.org/registry/specs/SGIX/async.txt
-glPollInstrumentsSGIX http://www.opengl.org/registry/specs/SGIX/instruments.txt
-glPolygonMode http://www.opengl.org/sdk/docs/man/xhtml/glPolygonMode.xml
-glPolygonMode http://www.opengl.org/sdk/docs/man3/xhtml/glPolygonMode.xml
-glPolygonMode http://www.opengl.org/sdk/docs/man4/xhtml/glPolygonMode.xml
-glPolygonOffset http://www.opengl.org/sdk/docs/man/xhtml/glPolygonOffset.xml
-glPolygonOffset http://www.opengl.org/sdk/docs/man3/xhtml/glPolygonOffset.xml
-glPolygonOffset http://www.opengl.org/sdk/docs/man4/xhtml/glPolygonOffset.xml
-glPolygonOffsetEXT http://www.opengl.org/registry/specs/EXT/polygon_offset.txt
-glPolygonOffsetxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glPolygonStipple http://www.opengl.org/sdk/docs/man/xhtml/glPolygonStipple.xml
-glPopAttrib http://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml
-glPopClientAttrib http://www.opengl.org/sdk/docs/man/xhtml/glPushClientAttrib.xml
-glPopMatrix http://www.opengl.org/sdk/docs/man/xhtml/glPushMatrix.xml
-glPopName http://www.opengl.org/sdk/docs/man/xhtml/glPushName.xml
-glPresentFrameDualFillNV http://www.opengl.org/registry/specs/NV/present_video.txt
-glPresentFrameKeyedNV http://www.opengl.org/registry/specs/NV/present_video.txt
-glPrimitiveRestartIndex http://www.opengl.org/sdk/docs/man3/xhtml/glPrimitiveRestartIndex.xml
-glPrimitiveRestartIndex http://www.opengl.org/sdk/docs/man4/xhtml/glPrimitiveRestartIndex.xml
-glPrimitiveRestartIndexNV http://www.opengl.org/registry/specs/NV/primitive_restart.txt
-glPrimitiveRestartNV http://www.opengl.org/registry/specs/NV/primitive_restart.txt
-glPrioritizeTextures http://www.opengl.org/sdk/docs/man/xhtml/glPrioritizeTextures.xml
-glPrioritizeTexturesEXT http://www.opengl.org/registry/specs/EXT/texture_object.txt
-glPrioritizeTexturesxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glProgramBinary http://www.opengl.org/registry/specs/ARB/get_program_binary.txt
-glProgramBinary http://www.opengl.org/sdk/docs/man4/xhtml/glProgramBinary.xml
-glProgramBufferParametersIivNV http://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
-glProgramBufferParametersIuivNV http://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
-glProgramBufferParametersfvNV http://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
-glProgramEnvParameter4dARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glProgramEnvParameter4dARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glProgramEnvParameter4dvARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glProgramEnvParameter4dvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glProgramEnvParameter4fARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glProgramEnvParameter4fARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glProgramEnvParameter4fvARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glProgramEnvParameter4fvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glProgramEnvParameterI4iNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramEnvParameterI4ivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramEnvParameterI4uiNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramEnvParameterI4uivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramEnvParametersI4ivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramEnvParametersI4uivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramLocalParameter4dARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glProgramLocalParameter4dARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glProgramLocalParameter4dARB http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glProgramLocalParameter4dvARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glProgramLocalParameter4dvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glProgramLocalParameter4dvARB http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glProgramLocalParameter4fARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glProgramLocalParameter4fARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glProgramLocalParameter4fARB http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glProgramLocalParameter4fvARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glProgramLocalParameter4fvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glProgramLocalParameter4fvARB http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glProgramLocalParameterI4iNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramLocalParameterI4ivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramLocalParameterI4uiNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramLocalParameterI4uivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramLocalParametersI4ivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramLocalParametersI4uivNV http://www.opengl.org/registry/specs/NV/gpu_program4.txt
-glProgramNamedParameter4dNV http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glProgramNamedParameter4dvNV http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glProgramNamedParameter4fNV http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glProgramNamedParameter4fvNV http://www.opengl.org/registry/specs/NV/fragment_program.txt
-glProgramParameter4dNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glProgramParameter4dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glProgramParameter4fNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glProgramParameter4fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glProgramParameteri http://www.opengl.org/registry/specs/ARB/get_program_binary.txt
-glProgramParameteri http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramParameteri http://www.opengl.org/sdk/docs/man4/xhtml/glProgramParameter.xml
-glProgramParameteriARB http://www.opengl.org/registry/specs/ARB/geometry_shader4.txt
-glProgramParameteriEXT http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
-glProgramParameters4dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glProgramParameters4fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glProgramStringARB http://www.opengl.org/registry/specs/ARB/fragment_program.txt
-glProgramStringARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glProgramUniform1d http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform1dEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniform1dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform1dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniform1f http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform1f http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform1fEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform1fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform1fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform1fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform1i http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform1i http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform1i64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform1i64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform1iEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform1iv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform1iv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform1ivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform1ui http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform1ui http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform1ui64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform1ui64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform1uiEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform1uiv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform1uiv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform1uivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform2d http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform2dEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniform2dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform2dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniform2f http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform2f http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform2fEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform2fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform2fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform2fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform2i http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform2i http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform2i64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform2i64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform2iEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform2iv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform2iv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform2ivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform2ui http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform2ui http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform2ui64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform2ui64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform2uiEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform2uiv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform2uiv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform2uivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform3d http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform3dEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniform3dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform3dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniform3f http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform3f http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform3fEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform3fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform3fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform3fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform3i http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform3i http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform3i64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform3i64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform3iEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform3iv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform3iv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform3ivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform3ui http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform3ui http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform3ui64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform3ui64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform3uiEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform3uiv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform3uiv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform3uivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform4d http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform4dEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniform4dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform4dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniform4f http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform4f http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform4fEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform4fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform4fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform4fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform4i http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform4i http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform4i64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform4i64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform4iEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform4iv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform4iv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform4ivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform4ui http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform4ui http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform4ui64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform4ui64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glProgramUniform4uiEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniform4uiv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniform4uiv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniform4uivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformMatrix2dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix2dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniformMatrix2fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix2fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniformMatrix2fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformMatrix2x3dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix2x3dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniformMatrix2x3fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix2x3fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniformMatrix2x3fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformMatrix2x4dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix2x4dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniformMatrix2x4fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix2x4fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniformMatrix2x4fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformMatrix3dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix3dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniformMatrix3fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix3fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniformMatrix3fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformMatrix3x2dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix3x2dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniformMatrix3x2fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix3x2fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniformMatrix3x2fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformMatrix3x4dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix3x4dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniformMatrix3x4fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix3x4fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniformMatrix3x4fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformMatrix4dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix4dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniformMatrix4fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix4fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniformMatrix4fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformMatrix4x2dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix4x2dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniformMatrix4x2fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix4x2fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniformMatrix4x2fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformMatrix4x3dv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix4x3dvEXT http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glProgramUniformMatrix4x3fv http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glProgramUniformMatrix4x3fv http://www.opengl.org/sdk/docs/man4/xhtml/glProgramUniform.xml
-glProgramUniformMatrix4x3fvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glProgramUniformui64NV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glProgramUniformui64vNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glProgramVertexLimitNV http://www.opengl.org/registry/specs/NV/geometry_program4.txt
-glProvokingVertex http://www.opengl.org/registry/specs/ARB/provoking_vertex.txt
-glProvokingVertex http://www.opengl.org/sdk/docs/man3/xhtml/glProvokingVertex.xml
-glProvokingVertex http://www.opengl.org/sdk/docs/man4/xhtml/glProvokingVertex.xml
-glProvokingVertexEXT http://www.opengl.org/registry/specs/EXT/provoking_vertex.txt
-glPushAttrib http://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml
-glPushClientAttrib http://www.opengl.org/sdk/docs/man/xhtml/glPushClientAttrib.xml
-glPushClientAttribDefaultEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glPushMatrix http://www.opengl.org/sdk/docs/man/xhtml/glPushMatrix.xml
-glPushName http://www.opengl.org/sdk/docs/man/xhtml/glPushName.xml
-glQueryCounter http://www.opengl.org/registry/specs/ARB/timer_query.txt
-glQueryCounter http://www.opengl.org/sdk/docs/man3/xhtml/glQueryCounter.xml
-glQueryCounter http://www.opengl.org/sdk/docs/man4/xhtml/glQueryCounter.xml
-glQueryMatrixxOES http://www.opengl.org/registry/specs/OES/OES_query_matrix.txt
-glQueryMaxSwapBarriersSGIX http://www.opengl.org/registry/specs/SGIX/swap_barrier.txt
-glRasterPos2d http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos2dv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos2f http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos2fv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos2i http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos2iv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos2s http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos2sv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos3d http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos3dv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos3f http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos3fv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos3i http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos3iv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos3s http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos3sv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos4d http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos4dv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos4f http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos4fv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos4i http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos4iv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos4s http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glRasterPos4sv http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
-glReadBuffer http://www.opengl.org/sdk/docs/man/xhtml/glReadBuffer.xml
-glReadBuffer http://www.opengl.org/sdk/docs/man3/xhtml/glReadBuffer.xml
-glReadBuffer http://www.opengl.org/sdk/docs/man4/xhtml/glReadBuffer.xml
-glReadInstrumentsSGIX http://www.opengl.org/registry/specs/SGIX/instruments.txt
-glReadPixels http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml
-glReadPixels http://www.opengl.org/sdk/docs/man3/xhtml/glReadPixels.xml
-glReadPixels http://www.opengl.org/sdk/docs/man4/xhtml/glReadPixels.xml
-glReadnPixelsARB http://www.opengl.org/registry/specs/ARB/robustness.txt
-glRectd http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
-glRectdv http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
-glRectf http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
-glRectfv http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
-glRecti http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
-glRectiv http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
-glRects http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
-glRectsv http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
-glRectxOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glRectxvOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glReferencePlaneSGIX http://www.opengl.org/registry/specs/SGIX/reference_plane.txt
-glReleaseShaderCompiler http://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
-glReleaseShaderCompiler http://www.opengl.org/sdk/docs/man4/xhtml/glReleaseShaderCompiler.xml
-glRenderMode http://www.opengl.org/sdk/docs/man/xhtml/glRenderMode.xml
-glRenderbufferStorage http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glRenderbufferStorage http://www.opengl.org/sdk/docs/man3/xhtml/glRenderbufferStorage.xml
-glRenderbufferStorage http://www.opengl.org/sdk/docs/man4/xhtml/glRenderbufferStorage.xml
-glRenderbufferStorageEXT http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
-glRenderbufferStorageMultisample http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
-glRenderbufferStorageMultisample http://www.opengl.org/sdk/docs/man3/xhtml/glRenderbufferStorageMultisample.xml
-glRenderbufferStorageMultisample http://www.opengl.org/sdk/docs/man4/xhtml/glRenderbufferStorageMultisample.xml
-glRenderbufferStorageMultisampleCoverageNV http://www.opengl.org/registry/specs/NV/framebuffer_multisample_coverage.txt
-glRenderbufferStorageMultisampleEXT http://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt
-glReplacementCodePointerSUN http://www.opengl.org/registry/specs/SUN/triangle_list.txt
-glReplacementCodeubSUN http://www.opengl.org/registry/specs/SUN/triangle_list.txt
-glReplacementCodeubvSUN http://www.opengl.org/registry/specs/SUN/triangle_list.txt
-glReplacementCodeuiSUN http://www.opengl.org/registry/specs/SUN/triangle_list.txt
-glReplacementCodeuivSUN http://www.opengl.org/registry/specs/SUN/triangle_list.txt
-glReplacementCodeusSUN http://www.opengl.org/registry/specs/SUN/triangle_list.txt
-glReplacementCodeusvSUN http://www.opengl.org/registry/specs/SUN/triangle_list.txt
-glRequestResidentProgramsNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glResetHistogram http://www.opengl.org/sdk/docs/man/xhtml/glResetHistogram.xml
-glResetHistogramEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glResetMinmax http://www.opengl.org/sdk/docs/man/xhtml/glResetMinmax.xml
-glResetMinmaxEXT http://www.opengl.org/registry/specs/EXT/histogram.txt
-glResizeBuffersMESA http://www.opengl.org/registry/specs/MESA/resize_buffers.txt
-glResumeTransformFeedback http://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
-glResumeTransformFeedback http://www.opengl.org/sdk/docs/man4/xhtml/glResumeTransformFeedback.xml
-glResumeTransformFeedbackNV http://www.opengl.org/registry/specs/NV/transform_feedback2.txt
-glRotated http://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml
-glRotatef http://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml
-glRotatexOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glSampleCoverage http://www.opengl.org/sdk/docs/man/xhtml/glSampleCoverage.xml
-glSampleCoverage http://www.opengl.org/sdk/docs/man3/xhtml/glSampleCoverage.xml
-glSampleCoverage http://www.opengl.org/sdk/docs/man4/xhtml/glSampleCoverage.xml
-glSampleCoverageARB http://www.opengl.org/registry/specs/ARB/multisample.txt
-glSampleCoverageOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glSampleMaskEXT http://www.opengl.org/registry/specs/EXT/wgl_multisample.txt
-glSampleMaskIndexedNV http://www.opengl.org/registry/specs/NV/explicit_multisample.txt
-glSampleMaskSGIS http://www.opengl.org/registry/specs/SGIS/multisample.txt
-glSampleMaski http://www.opengl.org/registry/specs/ARB/texture_multisample.txt
-glSampleMaski http://www.opengl.org/sdk/docs/man3/xhtml/glSampleMaski.xml
-glSampleMaski http://www.opengl.org/sdk/docs/man4/xhtml/glSampleMaski.xml
-glSamplePatternEXT http://www.opengl.org/registry/specs/EXT/wgl_multisample.txt
-glSamplePatternSGIS http://www.opengl.org/registry/specs/SGIS/multisample.txt
-glSamplerParameterIiv http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glSamplerParameterIuiv http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glSamplerParameterf http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glSamplerParameterf http://www.opengl.org/sdk/docs/man3/xhtml/glSamplerParameter.xml
-glSamplerParameterf http://www.opengl.org/sdk/docs/man4/xhtml/glSamplerParameter.xml
-glSamplerParameterfv http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glSamplerParameterfv http://www.opengl.org/sdk/docs/man3/xhtml/glSamplerParameter.xml
-glSamplerParameterfv http://www.opengl.org/sdk/docs/man4/xhtml/glSamplerParameter.xml
-glSamplerParameteri http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glSamplerParameteri http://www.opengl.org/sdk/docs/man3/xhtml/glSamplerParameter.xml
-glSamplerParameteri http://www.opengl.org/sdk/docs/man4/xhtml/glSamplerParameter.xml
-glSamplerParameteriv http://www.opengl.org/registry/specs/ARB/sampler_objects.txt
-glSamplerParameteriv http://www.opengl.org/sdk/docs/man3/xhtml/glSamplerParameter.xml
-glSamplerParameteriv http://www.opengl.org/sdk/docs/man4/xhtml/glSamplerParameter.xml
-glScaled http://www.opengl.org/sdk/docs/man/xhtml/glScale.xml
-glScalef http://www.opengl.org/sdk/docs/man/xhtml/glScale.xml
-glScalexOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glScissor http://www.opengl.org/sdk/docs/man/xhtml/glScissor.xml
-glScissor http://www.opengl.org/sdk/docs/man3/xhtml/glScissor.xml
-glScissor http://www.opengl.org/sdk/docs/man4/xhtml/glScissor.xml
-glScissorArrayv http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glScissorArrayv http://www.opengl.org/sdk/docs/man4/xhtml/glScissorArray.xml
-glScissorIndexed http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glScissorIndexed http://www.opengl.org/sdk/docs/man4/xhtml/glScissorIndexed.xml
-glScissorIndexedv http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glScissorIndexedv http://www.opengl.org/sdk/docs/man4/xhtml/glScissorIndexed.xml
-glSecondaryColor3b http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3bv http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3d http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3dv http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3f http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3fv http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glSecondaryColor3hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glSecondaryColor3i http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3iv http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3s http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3sv http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3ub http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3ubv http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3ui http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3uiv http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3us http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColor3usv http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
-glSecondaryColorFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glSecondaryColorP3ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glSecondaryColorP3uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glSecondaryColorPointer http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColorPointer.xml
-glSecondaryColorPointerEXT http://www.opengl.org/registry/specs/EXT/secondary_color.txt
-glSelectBuffer http://www.opengl.org/sdk/docs/man/xhtml/glSelectBuffer.xml
-glSelectPerfMonitorCountersAMD http://www.opengl.org/registry/specs/AMD/performance_monitor.txt
-glSeparableFilter2D http://www.opengl.org/sdk/docs/man/xhtml/glSeparableFilter2D.xml
-glSeparableFilter2DEXT http://www.opengl.org/registry/specs/EXT/convolution.txt
-glSetFenceAPPLE http://www.opengl.org/registry/specs/APPLE/fence.txt
-glSetFenceNV http://www.opengl.org/registry/specs/NV/fence.txt
-glSetMultisamplefvAMD http://www.opengl.org/registry/specs/AMD/sample_positions.txt
-glShadeModel http://www.opengl.org/sdk/docs/man/xhtml/glShadeModel.xml
-glShaderBinary http://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
-glShaderBinary http://www.opengl.org/sdk/docs/man4/xhtml/glShaderBinary.xml
-glShaderSource http://www.opengl.org/sdk/docs/man/xhtml/glShaderSource.xml
-glShaderSource http://www.opengl.org/sdk/docs/man3/xhtml/glShaderSource.xml
-glShaderSource http://www.opengl.org/sdk/docs/man4/xhtml/glShaderSource.xml
-glShaderSourceARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glSharpenTexFuncSGIS http://www.opengl.org/registry/specs/SGIS/sharpen_texture.txt
-glSpriteParameterfSGIX http://www.opengl.org/registry/specs/SGIX/sprite.txt
-glSpriteParameterfvSGIX http://www.opengl.org/registry/specs/SGIX/sprite.txt
-glSpriteParameteriSGIX http://www.opengl.org/registry/specs/SGIX/sprite.txt
-glSpriteParameterivSGIX http://www.opengl.org/registry/specs/SGIX/sprite.txt
-glStartInstrumentsSGIX http://www.opengl.org/registry/specs/SGIX/instruments.txt
-glStencilClearTagEXT http://www.opengl.org/registry/specs/EXT/stencil_clear_tag.txt
-glStencilFillPathInstancedNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glStencilFillPathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glStencilFunc http://www.opengl.org/sdk/docs/man/xhtml/glStencilFunc.xml
-glStencilFunc http://www.opengl.org/sdk/docs/man3/xhtml/glStencilFunc.xml
-glStencilFunc http://www.opengl.org/sdk/docs/man4/xhtml/glStencilFunc.xml
-glStencilFuncSeparate http://www.opengl.org/sdk/docs/man/xhtml/glStencilFuncSeparate.xml
-glStencilFuncSeparate http://www.opengl.org/sdk/docs/man3/xhtml/glStencilFuncSeparate.xml
-glStencilFuncSeparate http://www.opengl.org/sdk/docs/man4/xhtml/glStencilFuncSeparate.xml
-glStencilMask http://www.opengl.org/sdk/docs/man/xhtml/glStencilMask.xml
-glStencilMask http://www.opengl.org/sdk/docs/man3/xhtml/glStencilMask.xml
-glStencilMask http://www.opengl.org/sdk/docs/man4/xhtml/glStencilMask.xml
-glStencilMaskSeparate http://www.opengl.org/sdk/docs/man/xhtml/glStencilMaskSeparate.xml
-glStencilMaskSeparate http://www.opengl.org/sdk/docs/man3/xhtml/glStencilMaskSeparate.xml
-glStencilMaskSeparate http://www.opengl.org/sdk/docs/man4/xhtml/glStencilMaskSeparate.xml
-glStencilOp http://www.opengl.org/sdk/docs/man/xhtml/glStencilOp.xml
-glStencilOp http://www.opengl.org/sdk/docs/man3/xhtml/glStencilOp.xml
-glStencilOp http://www.opengl.org/sdk/docs/man4/xhtml/glStencilOp.xml
-glStencilOpSeparate http://www.opengl.org/sdk/docs/man/xhtml/glStencilOpSeparate.xml
-glStencilOpSeparate http://www.opengl.org/sdk/docs/man3/xhtml/glStencilOpSeparate.xml
-glStencilOpSeparate http://www.opengl.org/sdk/docs/man4/xhtml/glStencilOpSeparate.xml
-glStencilStrokePathInstancedNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glStencilStrokePathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glStopInstrumentsSGIX http://www.opengl.org/registry/specs/SGIX/instruments.txt
-glStringMarkerGREMEDY http://www.opengl.org/registry/specs/GREMEDY/string_marker.txt
-glTagSampleBufferSGIX http://www.opengl.org/registry/specs/SGIX/tag_sample_buffer.txt
-glTangentPointerEXT http://www.opengl.org/registry/specs/EXT/coordinate_frame.txt
-glTbufferMask3DFX http://www.opengl.org/registry/specs/3DFX/tbuffer.txt
-glTessellationFactorAMD http://www.opengl.org/registry/specs/AMD/vertex_shader_tessellator.txt
-glTessellationModeAMD http://www.opengl.org/registry/specs/AMD/vertex_shader_tessellator.txt
-glTestFenceAPPLE http://www.opengl.org/registry/specs/APPLE/fence.txt
-glTestFenceNV http://www.opengl.org/registry/specs/NV/fence.txt
-glTestObjectAPPLE http://www.opengl.org/registry/specs/APPLE/fence.txt
-glTexBuffer http://www.opengl.org/sdk/docs/man3/xhtml/glTexBuffer.xml
-glTexBuffer http://www.opengl.org/sdk/docs/man4/xhtml/glTexBuffer.xml
-glTexBufferARB http://www.opengl.org/registry/specs/ARB/texture_buffer_object.txt
-glTexBufferEXT http://www.opengl.org/registry/specs/EXT/texture_buffer_object.txt
-glTexCoord1d http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord1dv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord1f http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord1fv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord1hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glTexCoord1hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glTexCoord1i http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord1iv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord1s http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord1sv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord2d http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord2dv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord2f http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord2fColor4ubVertex3fSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glTexCoord2fColor4ubVertex3fvSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glTexCoord2fVertex3fSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glTexCoord2fVertex3fvSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glTexCoord2fv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord2hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glTexCoord2hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glTexCoord2i http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord2iv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord2s http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord2sv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord3d http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord3dv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord3f http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord3fv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord3hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glTexCoord3hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glTexCoord3i http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord3iv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord3s http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord3sv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord4d http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord4dv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord4f http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord4fVertex4fSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glTexCoord4fVertex4fvSUN http://www.opengl.org/registry/specs/SUN/vertex.txt
-glTexCoord4fv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord4hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glTexCoord4hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glTexCoord4i http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord4iv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord4s http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoord4sv http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
-glTexCoordFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glTexCoordP1ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glTexCoordP1uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glTexCoordP2ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glTexCoordP2uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glTexCoordP3ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glTexCoordP3uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glTexCoordP4ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glTexCoordP4uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glTexCoordPointer http://www.opengl.org/sdk/docs/man/xhtml/glTexCoordPointer.xml
-glTexCoordPointerEXT http://www.opengl.org/registry/specs/EXT/vertex_array.txt
-glTexCoordPointervINTEL http://www.opengl.org/registry/specs/INTEL/parallel_arrays.txt
-glTexEnvf http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
-glTexEnvfv http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
-glTexEnvi http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
-glTexEnviv http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
-glTexFilterFuncSGIS http://www.opengl.org/registry/specs/SGIS/texture_filter4.txt
-glTexGend http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
-glTexGendv http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
-glTexGenf http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
-glTexGenfv http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
-glTexGeni http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
-glTexGeniv http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
-glTexImage1D http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml
-glTexImage1D http://www.opengl.org/sdk/docs/man3/xhtml/glTexImage1D.xml
-glTexImage1D http://www.opengl.org/sdk/docs/man4/xhtml/glTexImage1D.xml
-glTexImage2D http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml
-glTexImage2D http://www.opengl.org/sdk/docs/man3/xhtml/glTexImage2D.xml
-glTexImage2D http://www.opengl.org/sdk/docs/man4/xhtml/glTexImage2D.xml
-glTexImage2DMultisample http://www.opengl.org/registry/specs/ARB/texture_multisample.txt
-glTexImage2DMultisample http://www.opengl.org/sdk/docs/man3/xhtml/glTexImage2DMultisample.xml
-glTexImage2DMultisample http://www.opengl.org/sdk/docs/man4/xhtml/glTexImage2DMultisample.xml
-glTexImage2DMultisampleCoverageNV http://www.opengl.org/registry/specs/NV/texture_multisample.txt
-glTexImage3D http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml
-glTexImage3D http://www.opengl.org/sdk/docs/man3/xhtml/glTexImage3D.xml
-glTexImage3D http://www.opengl.org/sdk/docs/man4/xhtml/glTexImage3D.xml
-glTexImage3DEXT http://www.opengl.org/registry/specs/EXT/texture3D.txt
-glTexImage3DMultisample http://www.opengl.org/registry/specs/ARB/texture_multisample.txt
-glTexImage3DMultisample http://www.opengl.org/sdk/docs/man3/xhtml/glTexImage3DMultisample.xml
-glTexImage3DMultisample http://www.opengl.org/sdk/docs/man4/xhtml/glTexImage3DMultisample.xml
-glTexImage3DMultisampleCoverageNV http://www.opengl.org/registry/specs/NV/texture_multisample.txt
-glTexImage4DSGIS http://www.opengl.org/registry/specs/SGIS/texture4D.txt
-glTexParameterIiv http://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
-glTexParameterIiv http://www.opengl.org/sdk/docs/man4/xhtml/glTexParameter.xml
-glTexParameterIivEXT http://www.opengl.org/registry/specs/EXT/texture_integer.txt
-glTexParameterIuiv http://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
-glTexParameterIuiv http://www.opengl.org/sdk/docs/man4/xhtml/glTexParameter.xml
-glTexParameterIuivEXT http://www.opengl.org/registry/specs/EXT/texture_integer.txt
-glTexParameterf http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
-glTexParameterf http://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
-glTexParameterf http://www.opengl.org/sdk/docs/man4/xhtml/glTexParameter.xml
-glTexParameterfv http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
-glTexParameterfv http://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
-glTexParameterfv http://www.opengl.org/sdk/docs/man4/xhtml/glTexParameter.xml
-glTexParameteri http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
-glTexParameteri http://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
-glTexParameteri http://www.opengl.org/sdk/docs/man4/xhtml/glTexParameter.xml
-glTexParameteriv http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
-glTexParameteriv http://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
-glTexParameteriv http://www.opengl.org/sdk/docs/man4/xhtml/glTexParameter.xml
-glTexRenderbufferNV http://www.opengl.org/registry/specs/NV/explicit_multisample.txt
-glTexStorage1D http://www.opengl.org/registry/specs/ARB/texture_storage.txt
-glTexStorage2D http://www.opengl.org/registry/specs/ARB/texture_storage.txt
-glTexStorage3D http://www.opengl.org/registry/specs/ARB/texture_storage.txt
-glTexSubImage1D http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage1D.xml
-glTexSubImage1D http://www.opengl.org/sdk/docs/man3/xhtml/glTexSubImage1D.xml
-glTexSubImage1D http://www.opengl.org/sdk/docs/man4/xhtml/glTexSubImage1D.xml
-glTexSubImage1DEXT http://www.opengl.org/registry/specs/EXT/subtexture.txt
-glTexSubImage2D http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage2D.xml
-glTexSubImage2D http://www.opengl.org/sdk/docs/man3/xhtml/glTexSubImage2D.xml
-glTexSubImage2D http://www.opengl.org/sdk/docs/man4/xhtml/glTexSubImage2D.xml
-glTexSubImage2DEXT http://www.opengl.org/registry/specs/EXT/subtexture.txt
-glTexSubImage3D http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage3D.xml
-glTexSubImage3D http://www.opengl.org/sdk/docs/man3/xhtml/glTexSubImage3D.xml
-glTexSubImage3D http://www.opengl.org/sdk/docs/man4/xhtml/glTexSubImage3D.xml
-glTexSubImage3DEXT http://www.opengl.org/registry/specs/EXT/subtexture.txt
-glTexSubImage4DSGIS http://www.opengl.org/registry/specs/SGIS/texture4D.txt
-glTextureBarrierNV http://www.opengl.org/registry/specs/NV/texture_barrier.txt
-glTextureBufferEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureColorMaskSGIS http://www.opengl.org/registry/specs/SGIS/texture_color_mask.txt
-glTextureFogSGIX http://www.opengl.org/registry/specs/SGIX/fog_texture.txt
-glTextureImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureImage2DMultisampleCoverageNV http://www.opengl.org/registry/specs/NV/texture_multisample.txt
-glTextureImage2DMultisampleNV http://www.opengl.org/registry/specs/NV/texture_multisample.txt
-glTextureImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureImage3DMultisampleCoverageNV http://www.opengl.org/registry/specs/NV/texture_multisample.txt
-glTextureImage3DMultisampleNV http://www.opengl.org/registry/specs/NV/texture_multisample.txt
-glTextureLightEXT http://www.opengl.org/registry/specs/EXT/light_texture.txt
-glTextureMaterialEXT http://www.opengl.org/registry/specs/EXT/light_texture.txt
-glTextureNormalEXT http://www.opengl.org/registry/specs/EXT/texture_perturb_normal.txt
-glTextureParameterIivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureParameterIuivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureParameterfEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureParameterfvEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureParameteriEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureParameterivEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureRangeAPPLE http://www.opengl.org/registry/specs/APPLE/texture_range.txt
-glTextureRenderbufferEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureStorage1DEXT http://www.opengl.org/registry/specs/ARB/texture_storage.txt
-glTextureStorage2DEXT http://www.opengl.org/registry/specs/ARB/texture_storage.txt
-glTextureStorage3DEXT http://www.opengl.org/registry/specs/ARB/texture_storage.txt
-glTextureSubImage1DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureSubImage2DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTextureSubImage3DEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glTrackMatrixNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glTransformFeedbackAttribsNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glTransformFeedbackVaryings http://www.opengl.org/sdk/docs/man3/xhtml/glTransformFeedbackVaryings.xml
-glTransformFeedbackVaryings http://www.opengl.org/sdk/docs/man4/xhtml/glTransformFeedbackVaryings.xml
-glTransformFeedbackVaryingsEXT http://www.opengl.org/registry/specs/EXT/transform_feedback.txt
-glTransformFeedbackVaryingsNV http://www.opengl.org/registry/specs/NV/transform_feedback.txt
-glTransformPathNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glTranslated http://www.opengl.org/sdk/docs/man/xhtml/glTranslate.xml
-glTranslatef http://www.opengl.org/sdk/docs/man/xhtml/glTranslate.xml
-glTranslatexOES http://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
-glUniform1d http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniform1dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniform1f http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform1f http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform1f http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform1fARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform1fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform1fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform1fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform1fvARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform1i http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform1i http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform1i http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform1i64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform1i64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform1iARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform1iv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform1iv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform1iv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform1ivARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform1ui http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform1ui http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform1ui64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform1ui64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform1uiEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glUniform1uiv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform1uiv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform1uivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glUniform2d http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniform2dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniform2f http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform2f http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform2f http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform2fARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform2fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform2fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform2fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform2fvARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform2i http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform2i http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform2i http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform2i64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform2i64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform2iARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform2iv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform2iv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform2iv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform2ivARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform2ui http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform2ui http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform2ui64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform2ui64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform2uiEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glUniform2uiv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform2uiv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform2uivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glUniform3d http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniform3dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniform3f http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform3f http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform3f http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform3fARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform3fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform3fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform3fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform3fvARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform3i http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform3i http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform3i http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform3i64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform3i64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform3iARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform3iv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform3iv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform3iv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform3ivARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform3ui http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform3ui http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform3ui64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform3ui64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform3uiEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glUniform3uiv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform3uiv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform3uivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glUniform4d http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniform4dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniform4f http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform4f http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform4f http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform4fARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform4fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform4fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform4fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform4fvARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform4i http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform4i http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform4i http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform4i64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform4i64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform4iARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform4iv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniform4iv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform4iv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform4ivARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniform4ui http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform4ui http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform4ui64NV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform4ui64vNV http://www.opengl.org/registry/specs/NV/gpu_shader5.txt
-glUniform4uiEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glUniform4uiv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniform4uiv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniform4uivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glUniformBlockBinding http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
-glUniformBlockBinding http://www.opengl.org/sdk/docs/man3/xhtml/glUniformBlockBinding.xml
-glUniformBlockBinding http://www.opengl.org/sdk/docs/man4/xhtml/glUniformBlockBinding.xml
-glUniformBufferEXT http://www.opengl.org/registry/specs/EXT/bindable_uniform.txt
-glUniformMatrix2dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniformMatrix2fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniformMatrix2fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniformMatrix2fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniformMatrix2fvARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniformMatrix2x3dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniformMatrix2x3fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniformMatrix2x3fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniformMatrix2x3fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniformMatrix2x4dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniformMatrix2x4fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniformMatrix2x4fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniformMatrix2x4fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniformMatrix3dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniformMatrix3fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniformMatrix3fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniformMatrix3fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniformMatrix3fvARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniformMatrix3x2dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniformMatrix3x2fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniformMatrix3x2fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniformMatrix3x2fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniformMatrix3x4dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniformMatrix3x4fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniformMatrix3x4fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniformMatrix3x4fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniformMatrix4dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniformMatrix4fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniformMatrix4fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniformMatrix4fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniformMatrix4fvARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUniformMatrix4x2dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniformMatrix4x2fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniformMatrix4x2fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniformMatrix4x2fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniformMatrix4x3dv http://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
-glUniformMatrix4x3fv http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
-glUniformMatrix4x3fv http://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
-glUniformMatrix4x3fv http://www.opengl.org/sdk/docs/man4/xhtml/glUniform.xml
-glUniformSubroutinesuiv http://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
-glUniformSubroutinesuiv http://www.opengl.org/sdk/docs/man4/xhtml/glUniformSubroutines.xml
-glUniformui64NV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glUniformui64vNV http://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
-glUnmapBuffer http://www.opengl.org/sdk/docs/man/xhtml/glMapBuffer.xml
-glUnmapBuffer http://www.opengl.org/sdk/docs/man3/xhtml/glMapBuffer.xml
-glUnmapBuffer http://www.opengl.org/sdk/docs/man4/xhtml/glMapBuffer.xml
-glUnmapBufferARB http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-glUnmapNamedBufferEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glUnmapObjectBufferATI http://www.opengl.org/registry/specs/ATI/map_object_buffer.txt
-glUpdateObjectBufferATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glUseProgram http://www.opengl.org/sdk/docs/man/xhtml/glUseProgram.xml
-glUseProgram http://www.opengl.org/sdk/docs/man3/xhtml/glUseProgram.xml
-glUseProgram http://www.opengl.org/sdk/docs/man4/xhtml/glUseProgram.xml
-glUseProgramObjectARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glUseProgramStages http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glUseProgramStages http://www.opengl.org/sdk/docs/man4/xhtml/glUseProgramStages.xml
-glUseShaderProgramEXT http://www.opengl.org/registry/specs/EXT/separate_shader_objects.txt
-glValidateProgram http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml
-glValidateProgram http://www.opengl.org/sdk/docs/man3/xhtml/glValidateProgram.xml
-glValidateProgram http://www.opengl.org/sdk/docs/man4/xhtml/glValidateProgram.xml
-glValidateProgramARB http://www.opengl.org/registry/specs/ARB/shader_objects.txt
-glValidateProgramPipeline http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
-glValidateProgramPipeline http://www.opengl.org/sdk/docs/man4/xhtml/glValidateProgramPipeline.xml
-glVariantArrayObjectATI http://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
-glVertex2d http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex2dv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex2f http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex2fv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex2hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertex2hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertex2i http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex2iv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex2s http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex2sv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex3d http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex3dv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex3f http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex3fv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex3hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertex3hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertex3i http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex3iv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex3s http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex3sv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex4d http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex4dv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex4f http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex4fv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex4hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertex4hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertex4i http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex4iv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex4s http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertex4sv http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
-glVertexArrayColorOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayEdgeFlagOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayFogCoordOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayIndexOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayMultiTexCoordOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayNormalOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayParameteriAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_array_range.txt
-glVertexArrayRangeAPPLE http://www.opengl.org/registry/specs/APPLE/vertex_array_range.txt
-glVertexArrayRangeNV http://www.opengl.org/registry/specs/NV/vertex_array_range.txt
-glVertexArraySecondaryColorOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayTexCoordOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayVertexAttribIOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayVertexAttribLOffsetEXT http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexArrayVertexAttribLOffsetEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexArrayVertexAttribOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexArrayVertexOffsetEXT http://www.opengl.org/registry/specs/EXT/direct_state_access.txt
-glVertexAttrib1d http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib1d http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib1d http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib1dARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib1dARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib1dNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib1dv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib1dv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib1dv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib1dvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib1dvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib1dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib1f http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib1f http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib1f http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib1fARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib1fARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib1fNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib1fv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib1fv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib1fv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib1fvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib1fvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib1fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib1hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttrib1hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttrib1s http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib1s http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib1s http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib1sARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib1sARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib1sNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib1sv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib1sv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib1sv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib1svARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib1svARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib1svNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib2d http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib2d http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib2d http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib2dARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib2dARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib2dNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib2dv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib2dv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib2dv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib2dvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib2dvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib2dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib2f http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib2f http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib2f http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib2fARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib2fARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib2fNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib2fv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib2fv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib2fv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib2fvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib2fvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib2fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib2hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttrib2hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttrib2s http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib2s http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib2s http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib2sARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib2sARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib2sNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib2sv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib2sv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib2sv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib2svARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib2svARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib2svNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib3d http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib3d http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib3d http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib3dARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib3dARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib3dNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib3dv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib3dv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib3dv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib3dvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib3dvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib3dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib3f http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib3f http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib3f http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib3fARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib3fARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib3fNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib3fv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib3fv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib3fv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib3fvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib3fvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib3fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib3hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttrib3hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttrib3s http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib3s http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib3s http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib3sARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib3sARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib3sNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib3sv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib3sv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib3sv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib3svARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib3svARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib3svNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib4Nbv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nbv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nbv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4NbvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4NbvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4Niv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4Niv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4Niv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4NivARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4NivARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4Nsv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nsv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nsv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4NsvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4NsvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4Nub http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nub http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nub http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4NubARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4NubARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4Nubv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nubv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nubv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4NubvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4NubvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4Nuiv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nuiv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nuiv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4NuivARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4NuivARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4Nusv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nusv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4Nusv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4NusvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4NusvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4bv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4bv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4bv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4bvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4bvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4d http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4d http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4d http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4dARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4dARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4dNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib4dv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4dv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4dv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4dvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4dvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib4f http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4f http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4f http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4fARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4fARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4fNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib4fv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4fv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4fv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4fvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4fvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib4hNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttrib4hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttrib4iv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4iv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4iv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4ivARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4ivARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4s http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4s http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4s http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4sARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4sARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4sNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib4sv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4sv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4sv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4svARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4svARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4svNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib4ubNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib4ubv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4ubv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4ubv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4ubvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4ubvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4ubvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttrib4uiv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4uiv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4uiv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4uivARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4uivARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttrib4usv http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
-glVertexAttrib4usv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttrib4usv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttrib4usvARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttrib4usvARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttribArrayObjectATI http://www.opengl.org/registry/specs/ATI/vertex_attrib_array_object.txt
-glVertexAttribDivisor http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribDivisor.xml
-glVertexAttribDivisor http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttribDivisor.xml
-glVertexAttribDivisorARB http://www.opengl.org/registry/specs/ARB/instanced_arrays.txt
-glVertexAttribFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glVertexAttribI1i http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI1i http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI1iEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI1iEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI1iv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI1iv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI1ivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI1ivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI1ui http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI1ui http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI1uiEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI1uiEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI1uiv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI1uiv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI1uivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI1uivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI2i http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI2i http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI2iEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI2iEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI2iv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI2iv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI2ivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI2ivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI2ui http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI2ui http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI2uiEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI2uiEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI2uiv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI2uiv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI2uivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI2uivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI3i http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI3i http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI3iEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI3iEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI3iv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI3iv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI3ivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI3ivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI3ui http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI3ui http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI3uiEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI3uiEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI3uiv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI3uiv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI3uivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI3uivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI4bv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI4bv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI4bvEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI4bvEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI4i http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI4i http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI4iEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI4iEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI4iv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI4iv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI4ivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI4ivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI4sv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI4sv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI4svEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI4svEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI4ubv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI4ubv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI4ubvEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI4ubvEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI4ui http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI4ui http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI4uiEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI4uiEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI4uiv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI4uiv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI4uivEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI4uivEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribI4usv http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribI4usv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribI4usvEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribI4usvEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribIFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glVertexAttribIPointer http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribPointer.xml
-glVertexAttribIPointer http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttribPointer.xml
-glVertexAttribIPointerEXT http://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
-glVertexAttribIPointerEXT http://www.opengl.org/registry/specs/NV/vertex_program4.txt
-glVertexAttribL1d http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexAttribL1d http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribL1dEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexAttribL1dv http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexAttribL1dv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribL1dvEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexAttribL1i64NV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL1i64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL1ui64NV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL1ui64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL2d http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexAttribL2d http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribL2dEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexAttribL2dv http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexAttribL2dv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribL2dvEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexAttribL2i64NV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL2i64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL2ui64NV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL2ui64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL3d http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexAttribL3d http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribL3dEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexAttribL3dv http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexAttribL3dv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribL3dvEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexAttribL3i64NV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL3i64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL3ui64NV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL3ui64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL4d http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexAttribL4d http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribL4dEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexAttribL4dv http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexAttribL4dv http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribL4dvEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexAttribL4i64NV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL4i64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL4ui64NV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribL4ui64vNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribLFormatNV http://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
-glVertexAttribLPointer http://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
-glVertexAttribLPointer http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttribPointer.xml
-glVertexAttribLPointerEXT http://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
-glVertexAttribP1ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexAttribP1ui http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribP1ui http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribP1uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexAttribP2ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexAttribP2ui http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribP2ui http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribP2uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexAttribP3ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexAttribP3ui http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribP3ui http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribP3uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexAttribP4ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexAttribP4ui http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
-glVertexAttribP4ui http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttrib.xml
-glVertexAttribP4uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexAttribPointer http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribPointer.xml
-glVertexAttribPointer http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribPointer.xml
-glVertexAttribPointer http://www.opengl.org/sdk/docs/man4/xhtml/glVertexAttribPointer.xml
-glVertexAttribPointerARB http://www.opengl.org/registry/specs/ARB/vertex_program.txt
-glVertexAttribPointerARB http://www.opengl.org/registry/specs/ARB/vertex_shader.txt
-glVertexAttribPointerNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs1dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs1fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs1hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttribs1svNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs2dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs2fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs2hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttribs2svNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs3dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs3fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs3hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttribs3svNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs4dvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs4fvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs4hvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexAttribs4svNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexAttribs4ubvNV http://www.opengl.org/registry/specs/NV/vertex_program.txt
-glVertexBlendARB http://www.opengl.org/registry/specs/ARB/vertex_blend.txt
-glVertexFormatNV http://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
-glVertexP2ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexP2uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexP3ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexP3uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexP4ui http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexP4uiv http://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
-glVertexPointer http://www.opengl.org/sdk/docs/man/xhtml/glVertexPointer.xml
-glVertexPointerEXT http://www.opengl.org/registry/specs/EXT/vertex_array.txt
-glVertexPointervINTEL http://www.opengl.org/registry/specs/INTEL/parallel_arrays.txt
-glVertexWeighthNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVertexWeighthvNV http://www.opengl.org/registry/specs/NV/half_float.txt
-glVideoCaptureNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glViewport http://www.opengl.org/sdk/docs/man/xhtml/glViewport.xml
-glViewport http://www.opengl.org/sdk/docs/man3/xhtml/glViewport.xml
-glViewport http://www.opengl.org/sdk/docs/man4/xhtml/glViewport.xml
-glViewportArrayv http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glViewportArrayv http://www.opengl.org/sdk/docs/man4/xhtml/glViewportArray.xml
-glViewportIndexedf http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glViewportIndexedf http://www.opengl.org/sdk/docs/man4/xhtml/glViewportIndexed.xml
-glViewportIndexedfv http://www.opengl.org/registry/specs/ARB/viewport_array.txt
-glViewportIndexedfv http://www.opengl.org/sdk/docs/man4/xhtml/glViewportIndexed.xml
-glWaitSync http://www.opengl.org/registry/specs/ARB/sync.txt
-glWaitSync http://www.opengl.org/sdk/docs/man3/xhtml/glWaitSync.xml
-glWaitSync http://www.opengl.org/sdk/docs/man4/xhtml/glWaitSync.xml
-glWeightPathsNV http://www.opengl.org/registry/specs/NV/path_rendering.txt
-glWeightPointerARB http://www.opengl.org/registry/specs/ARB/vertex_blend.txt
-glWindowPos2d http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos2dARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos2dMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos2dv http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos2dvARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos2dvMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos2f http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos2fARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos2fMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos2fv http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos2fvARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos2fvMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos2i http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos2iARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos2iMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos2iv http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos2ivARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos2ivMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos2s http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos2sARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos2sMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos2sv http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos2svARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos2svMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos3d http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos3dARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos3dMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos3dv http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos3dvARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos3dvMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos3f http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos3fARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos3fMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos3fv http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos3fvARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos3fvMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos3i http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos3iARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos3iMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos3iv http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos3ivARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos3ivMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos3s http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos3sARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos3sMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos3sv http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
-glWindowPos3svARB http://www.opengl.org/registry/specs/ARB/window_pos.txt
-glWindowPos3svMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos4dMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos4dvMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos4fMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos4fvMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos4iMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos4ivMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos4sMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glWindowPos4svMESA http://www.opengl.org/registry/specs/MESA/window_pos.txt
-glXAssociateDMPbufferSGIX http://www.opengl.org/registry/specs/SGIX/dmbuffer.txt
-glXBindChannelToWindowSGIX http://www.opengl.org/registry/specs/SGIX/video_resize.txt
-glXBindHyperpipeSGIX http://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
-glXBindSwapBarrierNV http://www.opengl.org/registry/specs/NV/glx_swap_group.txt
-glXBindVideoCaptureDeviceNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glXBindVideoDeviceNV http://www.opengl.org/registry/specs/NV/present_video.txt
-glXBlitContextFramebufferAMD http://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
-glXChannelRectSGIX http://www.opengl.org/registry/specs/SGIX/video_resize.txt
-glXChannelRectSyncSGIX http://www.opengl.org/registry/specs/SGIX/video_resize.txt
-glXChooseFBConfig http://www.opengl.org/sdk/docs/man/xhtml/glXChooseFBConfig.xml
-glXChooseVisual http://www.opengl.org/sdk/docs/man/xhtml/glXChooseVisual.xml
-glXCopyContext http://www.opengl.org/sdk/docs/man/xhtml/glXCopyContext.xml
-glXCopySubBufferMESA http://www.opengl.org/registry/specs/MESA/copy_sub_buffer.txt
-glXCreateAssociatedContextAMD http://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
-glXCreateAssociatedContextAttribsAMD http://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
-glXCreateContext http://www.opengl.org/sdk/docs/man/xhtml/glXCreateContext.xml
-glXCreateContextAttribsARB http://www.opengl.org/registry/specs/ARB/glx_create_context.txt
-glXCreateContextWithConfigSGIX http://www.opengl.org/registry/specs/SGIX/fbconfig.txt
-glXCreateGLXPbufferSGIX http://www.opengl.org/registry/specs/SGIX/pbuffer.txt
-glXCreateGLXPixmap http://www.opengl.org/sdk/docs/man/xhtml/glXCreateGLXPixmap.xml
-glXCreateGLXPixmapMESA http://www.opengl.org/registry/specs/MESA/pixmap_colormap.txt
-glXCreateGLXPixmapWithConfigSGIX http://www.opengl.org/registry/specs/SGIX/fbconfig.txt
-glXCreateGLXVideoSourceSGIX http://www.opengl.org/registry/specs/SGIX/video_source.txt
-glXCreateNewContext http://www.opengl.org/sdk/docs/man/xhtml/glXCreateNewContext.xml
-glXCreatePbuffer http://www.opengl.org/sdk/docs/man/xhtml/glXCreatePbuffer.xml
-glXCreatePixmap http://www.opengl.org/sdk/docs/man/xhtml/glXCreatePixmap.xml
-glXCreateWindow http://www.opengl.org/sdk/docs/man/xhtml/glXCreateWindow.xml
-glXCushionSGI http://www.opengl.org/registry/specs/SGI/cushion.txt
-glXDeleteAssociatedContextAMD http://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
-glXDestroyContext http://www.opengl.org/sdk/docs/man/xhtml/glXDestroyContext.xml
-glXDestroyGLXPbufferSGIX http://www.opengl.org/registry/specs/SGIX/pbuffer.txt
-glXDestroyGLXPixmap http://www.opengl.org/sdk/docs/man/xhtml/glXDestroyGLXPixmap.xml
-glXDestroyGLXVideoSourceSGIX http://www.opengl.org/registry/specs/SGIX/video_source.txt
-glXDestroyHyperpipeConfigSGIX http://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
-glXDestroyPbuffer http://www.opengl.org/sdk/docs/man/xhtml/glXDestroyPbuffer.xml
-glXDestroyPixmap http://www.opengl.org/sdk/docs/man/xhtml/glXDestroyPixmap.xml
-glXDestroyWindow http://www.opengl.org/sdk/docs/man/xhtml/glXDestroyWindow.xml
-glXEnumerateVideoCaptureDevicesNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glXFreeContextEXT http://www.opengl.org/registry/specs/EXT/import_context.txt
-glXFreeContextEXT http://www.opengl.org/sdk/docs/man/xhtml/glXFreeContextEXT.xml
-glXGetAGPOffsetMESA http://www.opengl.org/registry/specs/MESA/agp_offset.txt
-glXGetClientString http://www.opengl.org/sdk/docs/man/xhtml/glXGetClientString.xml
-glXGetConfig http://www.opengl.org/sdk/docs/man/xhtml/glXGetConfig.xml
-glXGetContextGPUIDAMD http://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
-glXGetContextIDEXT http://www.opengl.org/registry/specs/EXT/import_context.txt
-glXGetContextIDEXT http://www.opengl.org/sdk/docs/man/xhtml/glXGetContextIDEXT.xml
-glXGetCurrentAssociatedContextAMD http://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
-glXGetCurrentContext http://www.opengl.org/sdk/docs/man/xhtml/glXGetCurrentContext.xml
-glXGetCurrentDisplay http://www.opengl.org/sdk/docs/man/xhtml/glXGetCurrentDisplay.xml
-glXGetCurrentDrawable http://www.opengl.org/sdk/docs/man/xhtml/glXGetCurrentDrawable.xml
-glXGetCurrentReadDrawable http://www.opengl.org/sdk/docs/man/xhtml/glXGetCurrentReadDrawable.xml
-glXGetCurrentReadDrawableSGI http://www.opengl.org/registry/specs/SGI/make_current_read.txt
-glXGetFBConfigAttrib http://www.opengl.org/sdk/docs/man/xhtml/glXGetFBConfigAttrib.xml
-glXGetFBConfigAttribSGIX http://www.opengl.org/registry/specs/SGIX/fbconfig.txt
-glXGetFBConfigFromVisualSGIX http://www.opengl.org/registry/specs/SGIX/fbconfig.txt
-glXGetFBConfigs http://www.opengl.org/sdk/docs/man/xhtml/glXGetFBConfigs.xml
-glXGetGPUIDsAMD http://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
-glXGetGPUInfoAMD http://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
-glXGetMscRateOML http://www.opengl.org/registry/specs/OML/glx_sync_control.txt
-glXGetProcAddress http://www.opengl.org/sdk/docs/man/xhtml/glXGetProcAddress.xml
-glXGetSelectedEvent http://www.opengl.org/sdk/docs/man/xhtml/glXGetSelectedEvent.xml
-glXGetSelectedEventSGIX http://www.opengl.org/registry/specs/SGIX/pbuffer.txt
-glXGetSyncValuesOML http://www.opengl.org/registry/specs/OML/glx_sync_control.txt
-glXGetTransparentIndexSUN http://www.opengl.org/registry/specs/SUN/get_transparent_index.txt
-glXGetVideoSyncSGI http://www.opengl.org/registry/specs/SGI/video_sync.txt
-glXGetVisualFromFBConfig http://www.opengl.org/sdk/docs/man/xhtml/glXGetVisualFromFBConfig.xml
-glXHyperpipeAttribSGIX http://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
-glXHyperpipeConfigSGIX http://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
-glXImportContextEXT http://www.opengl.org/registry/specs/EXT/import_context.txt
-glXImportContextEXT http://www.opengl.org/sdk/docs/man/xhtml/glXImportContextEXT.xml
-glXIsDirect http://www.opengl.org/sdk/docs/man/xhtml/glXIsDirect.xml
-glXJoinSwapGroupNV http://www.opengl.org/registry/specs/NV/glx_swap_group.txt
-glXLockVideoCaptureDeviceNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glXMakeAssociatedContextCurrentAMD http://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
-glXMakeContextCurrent http://www.opengl.org/sdk/docs/man/xhtml/glXMakeContextCurrent.xml
-glXMakeCurrent http://www.opengl.org/sdk/docs/man/xhtml/glXMakeCurrent.xml
-glXMakeCurrentReadSGI http://www.opengl.org/registry/specs/SGI/make_current_read.txt
-glXQueryChannelDeltasSGIX http://www.opengl.org/registry/specs/SGIX/video_resize.txt
-glXQueryChannelRectSGIX http://www.opengl.org/registry/specs/SGIX/video_resize.txt
-glXQueryContext http://www.opengl.org/sdk/docs/man/xhtml/glXQueryContext.xml
-glXQueryContextInfoEXT http://www.opengl.org/registry/specs/EXT/import_context.txt
-glXQueryContextInfoEXT http://www.opengl.org/sdk/docs/man/xhtml/glXQueryContextInfoEXT.xml
-glXQueryDrawable http://www.opengl.org/sdk/docs/man/xhtml/glXQueryDrawable.xml
-glXQueryExtension http://www.opengl.org/sdk/docs/man/xhtml/glXQueryExtension.xml
-glXQueryExtensionsString http://www.opengl.org/sdk/docs/man/xhtml/glXQueryExtensionsString.xml
-glXQueryFrameCountNV http://www.opengl.org/registry/specs/NV/glx_swap_group.txt
-glXQueryGLXPbufferSGIX http://www.opengl.org/registry/specs/SGIX/pbuffer.txt
-glXQueryHyperpipeAttribSGIX http://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
-glXQueryHyperpipeBestAttribSGIX http://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
-glXQueryMaxSwapGroupsNV http://www.opengl.org/registry/specs/NV/glx_swap_group.txt
-glXQueryServerString http://www.opengl.org/sdk/docs/man/xhtml/glXQueryServerString.xml
-glXQuerySwapGroupNV http://www.opengl.org/registry/specs/NV/glx_swap_group.txt
-glXQueryVersion http://www.opengl.org/sdk/docs/man/xhtml/glXQueryVersion.xml
-glXQueryVideoCaptureDeviceNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glXReleaseBuffersMESA http://www.opengl.org/registry/specs/MESA/release_buffers.txt
-glXReleaseVideoCaptureDeviceNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-glXResetFrameCountNV http://www.opengl.org/registry/specs/NV/glx_swap_group.txt
-glXSelectEvent http://www.opengl.org/sdk/docs/man/xhtml/glXSelectEvent.xml
-glXSelectEventSGIX http://www.opengl.org/registry/specs/SGIX/pbuffer.txt
-glXSet3DfxModeMESA http://www.opengl.org/registry/specs/MESA/set_3dfx_mode.txt
-glXSwapBuffers http://www.opengl.org/sdk/docs/man/xhtml/glXSwapBuffers.xml
-glXSwapBuffersMscOML http://www.opengl.org/registry/specs/OML/glx_sync_control.txt
-glXSwapIntervalEXT http://www.opengl.org/registry/specs/EXT/swap_control.txt
-glXSwapIntervalSGI http://www.opengl.org/registry/specs/SGI/swap_control.txt
-glXUseXFont http://www.opengl.org/sdk/docs/man/xhtml/glXUseXFont.xml
-glXWaitForMscOML http://www.opengl.org/registry/specs/OML/glx_sync_control.txt
-glXWaitForSbcOML http://www.opengl.org/registry/specs/OML/glx_sync_control.txt
-glXWaitGL http://www.opengl.org/sdk/docs/man/xhtml/glXWaitGL.xml
-glXWaitVideoSyncSGI http://www.opengl.org/registry/specs/SGI/video_sync.txt
-glXWaitX http://www.opengl.org/sdk/docs/man/xhtml/glXWaitX.xml
-gluBeginCurve http://www.opengl.org/sdk/docs/man/xhtml/gluBeginCurve.xml
-gluBeginPolygon http://www.opengl.org/sdk/docs/man/xhtml/gluBeginPolygon.xml
-gluBeginSurface http://www.opengl.org/sdk/docs/man/xhtml/gluBeginSurface.xml
-gluBeginTrim http://www.opengl.org/sdk/docs/man/xhtml/gluBeginTrim.xml
-gluBuild1DMipmapLevels http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmapLevels.xml
-gluBuild1DMipmaps http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmaps.xml
-gluBuild2DMipmapLevels http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmapLevels.xml
-gluBuild2DMipmaps http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmaps.xml
-gluBuild3DMipmapLevels http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmapLevels.xml
-gluBuild3DMipmaps http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmaps.xml
-gluCheckExtension http://www.opengl.org/sdk/docs/man/xhtml/gluCheckExtension.xml
-gluCylinder http://www.opengl.org/sdk/docs/man/xhtml/gluCylinder.xml
-gluDeleteNurbsRenderer http://www.opengl.org/sdk/docs/man/xhtml/gluDeleteNurbsRenderer.xml
-gluDeleteQuadric http://www.opengl.org/sdk/docs/man/xhtml/gluDeleteQuadric.xml
-gluDeleteTess http://www.opengl.org/sdk/docs/man/xhtml/gluDeleteTess.xml
-gluDisk http://www.opengl.org/sdk/docs/man/xhtml/gluDisk.xml
-gluEndCurve http://www.opengl.org/sdk/docs/man/xhtml/gluBeginCurve.xml
-gluEndPolygon http://www.opengl.org/sdk/docs/man/xhtml/gluBeginPolygon.xml
-gluEndSurface http://www.opengl.org/sdk/docs/man/xhtml/gluBeginSurface.xml
-gluEndTrim http://www.opengl.org/sdk/docs/man/xhtml/gluBeginTrim.xml
-gluErrorString http://www.opengl.org/sdk/docs/man/xhtml/gluErrorString.xml
-gluGetNurbsProperty http://www.opengl.org/sdk/docs/man/xhtml/gluGetNurbsProperty.xml
-gluGetString http://www.opengl.org/sdk/docs/man/xhtml/gluGetString.xml
-gluGetTessProperty http://www.opengl.org/sdk/docs/man/xhtml/gluGetTessProperty.xml
-gluLoadSamplingMatrices http://www.opengl.org/sdk/docs/man/xhtml/gluLoadSamplingMatrices.xml
-gluLookAt http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml
-gluNewNurbsRenderer http://www.opengl.org/sdk/docs/man/xhtml/gluNewNurbsRenderer.xml
-gluNewQuadric http://www.opengl.org/sdk/docs/man/xhtml/gluNewQuadric.xml
-gluNewTess http://www.opengl.org/sdk/docs/man/xhtml/gluNewTess.xml
-gluNextContour http://www.opengl.org/sdk/docs/man/xhtml/gluNextContour.xml
-gluNurbsCallback http://www.opengl.org/sdk/docs/man/xhtml/gluNurbsCallback.xml
-gluNurbsCallbackData http://www.opengl.org/sdk/docs/man/xhtml/gluNurbsCallbackData.xml
-gluNurbsCallbackDataEXT http://www.opengl.org/sdk/docs/man/xhtml/gluNurbsCallbackDataEXT.xml
-gluNurbsCurve http://www.opengl.org/sdk/docs/man/xhtml/gluNurbsCurve.xml
-gluNurbsProperty http://www.opengl.org/sdk/docs/man/xhtml/gluNurbsProperty.xml
-gluNurbsSurface http://www.opengl.org/sdk/docs/man/xhtml/gluNurbsSurface.xml
-gluOrtho2D http://www.opengl.org/sdk/docs/man/xhtml/gluOrtho2D.xml
-gluPartialDisk http://www.opengl.org/sdk/docs/man/xhtml/gluPartialDisk.xml
-gluPerspective http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml
-gluPickMatrix http://www.opengl.org/sdk/docs/man/xhtml/gluPickMatrix.xml
-gluProject http://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml
-gluPwlCurve http://www.opengl.org/sdk/docs/man/xhtml/gluPwlCurve.xml
-gluQuadricCallback http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricCallback.xml
-gluQuadricDrawStyle http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricDrawStyle.xml
-gluQuadricNormals http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricNormals.xml
-gluQuadricOrientation http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricOrientation.xml
-gluQuadricTexture http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricTexture.xml
-gluScaleImage http://www.opengl.org/sdk/docs/man/xhtml/gluScaleImage.xml
-gluSphere http://www.opengl.org/sdk/docs/man/xhtml/gluSphere.xml
-gluTessBeginContour http://www.opengl.org/sdk/docs/man/xhtml/gluTessBeginContour.xml
-gluTessBeginPolygon http://www.opengl.org/sdk/docs/man/xhtml/gluTessBeginPolygon.xml
-gluTessCallback http://www.opengl.org/sdk/docs/man/xhtml/gluTessCallback.xml
-gluTessEndContour http://www.opengl.org/sdk/docs/man/xhtml/gluTessBeginContour.xml
-gluTessEndPolygon http://www.opengl.org/sdk/docs/man/xhtml/gluTessEndPolygon.xml
-gluTessNormal http://www.opengl.org/sdk/docs/man/xhtml/gluTessNormal.xml
-gluTessProperty http://www.opengl.org/sdk/docs/man/xhtml/gluTessProperty.xml
-gluTessVertex http://www.opengl.org/sdk/docs/man/xhtml/gluTessVertex.xml
-gluTexFilterFuncSGI http://www.opengl.org/registry/specs/SGI/filter4_parameters.txt
-gluUnProject http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml
-gluUnProject4 http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject4.xml
-sizeof http://www.opengl.org/registry/specs/IBM/multimode_draw_arrays.txt
-wglAssociateImageBufferEventsI3D http://www.opengl.org/registry/specs/I3D/wgl_image_buffer.txt
-wglBeginFrameTrackingI3D http://www.opengl.org/registry/specs/I3D/wgl_swap_frame_usage.txt
-wglBindDisplayColorTableEXT http://www.opengl.org/registry/specs/EXT/wgl_display_color_table.txt
-wglBindSwapBarrierNV http://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
-wglBindVideoCaptureDeviceNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-wglBindVideoDeviceNV http://www.opengl.org/registry/specs/NV/present_video.txt
-wglBlitContextFramebufferAMD http://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
+glAccum https://www.opengl.org/sdk/docs/man/xhtml/glAccum.xml
+glAccumxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glActiveProgramEXT https://www.opengl.org/registry/specs/EXT/separate_shader_objects.txt
+glActiveShaderProgram https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glActiveShaderProgram https://www.opengl.org/sdk/docs/man4/html/glActiveShaderProgram.xhtml
+glActiveStencilFaceEXT https://www.opengl.org/registry/specs/EXT/stencil_two_side.txt
+glActiveTexture https://www.opengl.org/sdk/docs/man/xhtml/glActiveTexture.xml
+glActiveTexture https://www.opengl.org/sdk/docs/man3/xhtml/glActiveTexture.xml
+glActiveTexture https://www.opengl.org/sdk/docs/man4/html/glActiveTexture.xhtml
+glActiveVaryingNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glAlphaFunc https://www.opengl.org/sdk/docs/man/xhtml/glAlphaFunc.xml
+glAlphaFuncxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glApplyTextureEXT https://www.opengl.org/registry/specs/EXT/light_texture.txt
+glAreProgramsResidentNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glAreTexturesResident https://www.opengl.org/sdk/docs/man/xhtml/glAreTexturesResident.xml
+glAreTexturesResidentEXT https://www.opengl.org/registry/specs/EXT/texture_object.txt
+glArrayElement https://www.opengl.org/sdk/docs/man/xhtml/glArrayElement.xml
+glArrayElementEXT https://www.opengl.org/registry/specs/EXT/vertex_array.txt
+glArrayObjectATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glAsyncMarkerSGIX https://www.opengl.org/registry/specs/SGIX/async.txt
+glAttachObjectARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glAttachShader https://www.opengl.org/sdk/docs/man/xhtml/glAttachShader.xml
+glAttachShader https://www.opengl.org/sdk/docs/man3/xhtml/glAttachShader.xml
+glAttachShader https://www.opengl.org/sdk/docs/man4/html/glAttachShader.xhtml
+glBegin https://www.opengl.org/sdk/docs/man/xhtml/glBegin.xml
+glBeginConditionalRender https://www.opengl.org/sdk/docs/man3/xhtml/glBeginConditionalRender.xml
+glBeginConditionalRender https://www.opengl.org/sdk/docs/man4/html/glBeginConditionalRender.xhtml
+glBeginConditionalRenderNV https://www.opengl.org/registry/specs/NV/conditional_render.txt
+glBeginOcclusionQueryNV https://www.opengl.org/registry/specs/NV/occlusion_query.txt
+glBeginPerfMonitorAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glBeginQuery https://www.opengl.org/sdk/docs/man/xhtml/glBeginQuery.xml
+glBeginQuery https://www.opengl.org/sdk/docs/man3/xhtml/glBeginQuery.xml
+glBeginQuery https://www.opengl.org/sdk/docs/man4/html/glBeginQuery.xhtml
+glBeginQueryARB https://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+glBeginQueryIndexed https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt
+glBeginQueryIndexed https://www.opengl.org/sdk/docs/man4/html/glBeginQueryIndexed.xhtml
+glBeginSceneEXT https://www.opengl.org/registry/specs/EXT/scene_marker.txt
+glBeginTransformFeedback https://www.opengl.org/sdk/docs/man3/xhtml/glBeginTransformFeedback.xml
+glBeginTransformFeedback https://www.opengl.org/sdk/docs/man4/html/glBeginTransformFeedback.xhtml
+glBeginTransformFeedbackEXT https://www.opengl.org/registry/specs/EXT/transform_feedback.txt
+glBeginTransformFeedbackNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glBeginVideoCaptureNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glBindArraySetEXT https://www.opengl.org/registry/specs/EXT/vertex_array_set.alt.txt
+glBindArraySetEXT https://www.opengl.org/registry/specs/EXT/vertex_array_set.txt
+glBindAttribLocation https://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocation.xml
+glBindAttribLocation https://www.opengl.org/sdk/docs/man3/xhtml/glBindAttribLocation.xml
+glBindAttribLocation https://www.opengl.org/sdk/docs/man4/html/glBindAttribLocation.xhtml
+glBindAttribLocationARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glBindBuffer https://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml
+glBindBuffer https://www.opengl.org/sdk/docs/man3/xhtml/glBindBuffer.xml
+glBindBuffer https://www.opengl.org/sdk/docs/man4/html/glBindBuffer.xhtml
+glBindBufferARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glBindBufferBase https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glBindBufferBase https://www.opengl.org/sdk/docs/man3/xhtml/glBindBufferBase.xml
+glBindBufferBase https://www.opengl.org/sdk/docs/man4/html/glBindBufferBase.xhtml
+glBindBufferBaseEXT https://www.opengl.org/registry/specs/EXT/transform_feedback.txt
+glBindBufferBaseNV https://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
+glBindBufferBaseNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glBindBufferOffsetEXT https://www.opengl.org/registry/specs/EXT/transform_feedback.txt
+glBindBufferOffsetNV https://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
+glBindBufferOffsetNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glBindBufferRange https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glBindBufferRange https://www.opengl.org/sdk/docs/man3/xhtml/glBindBufferRange.xml
+glBindBufferRange https://www.opengl.org/sdk/docs/man4/html/glBindBufferRange.xhtml
+glBindBufferRangeEXT https://www.opengl.org/registry/specs/EXT/transform_feedback.txt
+glBindBufferRangeNV https://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
+glBindBufferRangeNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glBindFragDataLocation https://www.opengl.org/sdk/docs/man3/xhtml/glBindFragDataLocation.xml
+glBindFragDataLocation https://www.opengl.org/sdk/docs/man4/html/glBindFragDataLocation.xhtml
+glBindFragDataLocationEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glBindFragDataLocationIndexed https://www.opengl.org/registry/specs/ARB/blend_func_extended.txt
+glBindFragDataLocationIndexed https://www.opengl.org/sdk/docs/man3/xhtml/glBindFragDataLocationIndexed.xml
+glBindFragDataLocationIndexed https://www.opengl.org/sdk/docs/man4/html/glBindFragDataLocationIndexed.xhtml
+glBindFramebuffer https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glBindFramebuffer https://www.opengl.org/sdk/docs/man3/xhtml/glBindFramebuffer.xml
+glBindFramebuffer https://www.opengl.org/sdk/docs/man4/html/glBindFramebuffer.xhtml
+glBindFramebufferEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glBindImageTexture https://www.opengl.org/registry/specs/ARB/shader_image_load_store.txt
+glBindImageTextureEXT https://www.opengl.org/registry/specs/EXT/shader_image_load_store.txt
+glBindMultiTextureEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glBindProgramARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glBindProgramARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glBindProgramNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glBindProgramPipeline https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glBindProgramPipeline https://www.opengl.org/sdk/docs/man4/html/glBindProgramPipeline.xhtml
+glBindRenderbuffer https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glBindRenderbuffer https://www.opengl.org/sdk/docs/man3/xhtml/glBindRenderbuffer.xml
+glBindRenderbuffer https://www.opengl.org/sdk/docs/man4/html/glBindRenderbuffer.xhtml
+glBindRenderbufferEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glBindSampler https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glBindSampler https://www.opengl.org/sdk/docs/man3/xhtml/glBindSampler.xml
+glBindSampler https://www.opengl.org/sdk/docs/man4/html/glBindSampler.xhtml
+glBindSwapBarrierSGIX https://www.opengl.org/registry/specs/SGIX/swap_barrier.txt
+glBindTexture https://www.opengl.org/sdk/docs/man/xhtml/glBindTexture.xml
+glBindTexture https://www.opengl.org/sdk/docs/man3/xhtml/glBindTexture.xml
+glBindTexture https://www.opengl.org/sdk/docs/man4/html/glBindTexture.xhtml
+glBindTextureEXT https://www.opengl.org/registry/specs/EXT/texture_object.txt
+glBindTransformFeedback https://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
+glBindTransformFeedback https://www.opengl.org/sdk/docs/man4/html/glBindTransformFeedback.xhtml
+glBindTransformFeedbackNV https://www.opengl.org/registry/specs/NV/transform_feedback2.txt
+glBindVertexArray https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
+glBindVertexArray https://www.opengl.org/sdk/docs/man3/xhtml/glBindVertexArray.xml
+glBindVertexArray https://www.opengl.org/sdk/docs/man4/html/glBindVertexArray.xhtml
+glBindVertexArrayAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_array_object.txt
+glBindVideoCaptureStreamBufferNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glBindVideoCaptureStreamTextureNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glBinormalPointerEXT https://www.opengl.org/registry/specs/EXT/coordinate_frame.txt
+glBitmap https://www.opengl.org/sdk/docs/man/xhtml/glBitmap.xml
+glBitmapxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glBlendColor https://www.opengl.org/sdk/docs/man/xhtml/glBlendColor.xml
+glBlendColor https://www.opengl.org/sdk/docs/man3/xhtml/glBlendColor.xml
+glBlendColor https://www.opengl.org/sdk/docs/man4/html/glBlendColor.xhtml
+glBlendColorEXT https://www.opengl.org/registry/specs/EXT/blend_color.txt
+glBlendColorxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glBlendEquation https://www.opengl.org/sdk/docs/man/xhtml/glBlendEquation.xml
+glBlendEquation https://www.opengl.org/sdk/docs/man3/xhtml/glBlendEquation.xml
+glBlendEquation https://www.opengl.org/sdk/docs/man4/html/glBlendEquation.xhtml
+glBlendEquationEXT https://www.opengl.org/registry/specs/EXT/blend_minmax.txt
+glBlendEquationIndexedAMD https://www.opengl.org/registry/specs/AMD/draw_buffers_blend.txt
+glBlendEquationSeparate https://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml
+glBlendEquationSeparate https://www.opengl.org/sdk/docs/man3/xhtml/glBlendEquationSeparate.xml
+glBlendEquationSeparate https://www.opengl.org/sdk/docs/man4/html/glBlendEquationSeparate.xhtml
+glBlendEquationSeparateEXT https://www.opengl.org/registry/specs/EXT/blend_equation_separate.txt
+glBlendEquationSeparateIndexedAMD https://www.opengl.org/registry/specs/AMD/draw_buffers_blend.txt
+glBlendEquationSeparatei https://www.opengl.org/sdk/docs/man4/html/glBlendEquationSeparate.xhtml
+glBlendEquationSeparateiARB https://www.opengl.org/registry/specs/ARB/draw_buffers_blend.txt
+glBlendEquationi https://www.opengl.org/sdk/docs/man4/html/glBlendEquation.xhtml
+glBlendEquationiARB https://www.opengl.org/registry/specs/ARB/draw_buffers_blend.txt
+glBlendFunc https://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml
+glBlendFunc https://www.opengl.org/sdk/docs/man3/xhtml/glBlendFunc.xml
+glBlendFunc https://www.opengl.org/sdk/docs/man4/html/glBlendFunc.xhtml
+glBlendFuncIndexedAMD https://www.opengl.org/registry/specs/AMD/draw_buffers_blend.txt
+glBlendFuncSeparate https://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml
+glBlendFuncSeparate https://www.opengl.org/sdk/docs/man3/xhtml/glBlendFuncSeparate.xml
+glBlendFuncSeparate https://www.opengl.org/sdk/docs/man4/html/glBlendFuncSeparate.xhtml
+glBlendFuncSeparateEXT https://www.opengl.org/registry/specs/EXT/blend_func_separate.txt
+glBlendFuncSeparateIndexedAMD https://www.opengl.org/registry/specs/AMD/draw_buffers_blend.txt
+glBlendFuncSeparatei https://www.opengl.org/sdk/docs/man4/html/glBlendFuncSeparate.xhtml
+glBlendFuncSeparateiARB https://www.opengl.org/registry/specs/ARB/draw_buffers_blend.txt
+glBlendFunci https://www.opengl.org/sdk/docs/man4/html/glBlendFunc.xhtml
+glBlendFunciARB https://www.opengl.org/registry/specs/ARB/draw_buffers_blend.txt
+glBlitFramebuffer https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glBlitFramebuffer https://www.opengl.org/sdk/docs/man3/xhtml/glBlitFramebuffer.xml
+glBlitFramebuffer https://www.opengl.org/sdk/docs/man4/html/glBlitFramebuffer.xhtml
+glBlitFramebufferEXT https://www.opengl.org/registry/specs/EXT/framebuffer_blit.txt
+glBufferAddressRangeNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glBufferData https://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml
+glBufferData https://www.opengl.org/sdk/docs/man3/xhtml/glBufferData.xml
+glBufferData https://www.opengl.org/sdk/docs/man4/html/glBufferData.xhtml
+glBufferDataARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glBufferParameteriAPPLE https://www.opengl.org/registry/specs/APPLE/flush_buffer_range.txt
+glBufferSubData https://www.opengl.org/sdk/docs/man/xhtml/glBufferSubData.xml
+glBufferSubData https://www.opengl.org/sdk/docs/man3/xhtml/glBufferSubData.xml
+glBufferSubData https://www.opengl.org/sdk/docs/man4/html/glBufferSubData.xhtml
+glBufferSubDataARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glCallList https://www.opengl.org/sdk/docs/man/xhtml/glCallList.xml
+glCallLists https://www.opengl.org/sdk/docs/man/xhtml/glCallLists.xml
+glCheckFramebufferStatus https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glCheckFramebufferStatus https://www.opengl.org/sdk/docs/man3/xhtml/glCheckFramebufferStatus.xml
+glCheckFramebufferStatus https://www.opengl.org/sdk/docs/man4/html/glCheckFramebufferStatus.xhtml
+glCheckFramebufferStatusEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glCheckNamedFramebufferStatusEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glClampColor https://www.opengl.org/sdk/docs/man3/xhtml/glClampColor.xml
+glClampColor https://www.opengl.org/sdk/docs/man4/html/glClampColor.xhtml
+glClampColorARB https://www.opengl.org/registry/specs/ARB/color_buffer_float.txt
+glClear https://www.opengl.org/sdk/docs/man/xhtml/glClear.xml
+glClear https://www.opengl.org/sdk/docs/man3/xhtml/glClear.xml
+glClear https://www.opengl.org/sdk/docs/man4/html/glClear.xhtml
+glClearAccum https://www.opengl.org/sdk/docs/man/xhtml/glClearAccum.xml
+glClearAccumxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glClearBufferfi https://www.opengl.org/sdk/docs/man3/xhtml/glClearBuffer.xml
+glClearBufferfi https://www.opengl.org/sdk/docs/man4/html/glClearBuffer.xhtml
+glClearBufferfv https://www.opengl.org/sdk/docs/man3/xhtml/glClearBuffer.xml
+glClearBufferfv https://www.opengl.org/sdk/docs/man4/html/glClearBuffer.xhtml
+glClearBufferiv https://www.opengl.org/sdk/docs/man3/xhtml/glClearBuffer.xml
+glClearBufferiv https://www.opengl.org/sdk/docs/man4/html/glClearBuffer.xhtml
+glClearBufferuiv https://www.opengl.org/sdk/docs/man3/xhtml/glClearBuffer.xml
+glClearBufferuiv https://www.opengl.org/sdk/docs/man4/html/glClearBuffer.xhtml
+glClearColor https://www.opengl.org/sdk/docs/man/xhtml/glClearColor.xml
+glClearColor https://www.opengl.org/sdk/docs/man3/xhtml/glClearColor.xml
+glClearColor https://www.opengl.org/sdk/docs/man4/html/glClearColor.xhtml
+glClearColorxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glClearDepth https://www.opengl.org/sdk/docs/man/xhtml/glClearDepth.xml
+glClearDepth https://www.opengl.org/sdk/docs/man3/xhtml/glClearDepth.xml
+glClearDepth https://www.opengl.org/sdk/docs/man4/html/glClearDepth.xhtml
+glClearDepthdNV https://www.opengl.org/registry/specs/NV/depth_buffer_float.txt
+glClearDepthf https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
+glClearDepthf https://www.opengl.org/sdk/docs/man4/html/glClearDepth.xhtml
+glClearDepthfOES https://www.opengl.org/registry/specs/OES/OES_single_precision.txt
+glClearDepthxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glClearIndex https://www.opengl.org/sdk/docs/man/xhtml/glClearIndex.xml
+glClearStencil https://www.opengl.org/sdk/docs/man/xhtml/glClearStencil.xml
+glClearStencil https://www.opengl.org/sdk/docs/man3/xhtml/glClearStencil.xml
+glClearStencil https://www.opengl.org/sdk/docs/man4/html/glClearStencil.xhtml
+glClientActiveTexture https://www.opengl.org/sdk/docs/man/xhtml/glClientActiveTexture.xml
+glClientActiveVertexStream https://www.opengl.org/registry/specs/ATI/vertex_streams.txt
+glClientAttribDefaultEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glClientWaitSync https://www.opengl.org/registry/specs/ARB/sync.txt
+glClientWaitSync https://www.opengl.org/sdk/docs/man3/xhtml/glClientWaitSync.xml
+glClientWaitSync https://www.opengl.org/sdk/docs/man4/html/glClientWaitSync.xhtml
+glClipPlane https://www.opengl.org/sdk/docs/man/xhtml/glClipPlane.xml
+glClipPlanefOES https://www.opengl.org/registry/specs/OES/OES_single_precision.txt
+glClipPlanexOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glColor3b https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3bv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3d https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3dv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3f https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3fVertex3fSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glColor3fVertex3fvSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glColor3fv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glColor3hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glColor3i https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3iv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3s https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3sv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3ub https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3ubv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3ui https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3uiv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3us https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor3usv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4b https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4bv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4d https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4dv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4f https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4fNormal3fVertex3fSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glColor4fNormal3fVertex3fvSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glColor4fv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glColor4hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glColor4i https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4iv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4s https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4sv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4ub https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4ubVertex2fSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glColor4ubVertex2fvSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glColor4ubVertex3fSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glColor4ubVertex3fvSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glColor4ubv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4ui https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4uiv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4us https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColor4usv https://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
+glColorFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glColorMask https://www.opengl.org/sdk/docs/man/xhtml/glColorMask.xml
+glColorMask https://www.opengl.org/sdk/docs/man3/xhtml/glColorMask.xml
+glColorMask https://www.opengl.org/sdk/docs/man4/html/glColorMask.xhtml
+glColorMaskIndexedEXT https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
+glColorMaski https://www.opengl.org/sdk/docs/man4/html/glColorMask.xhtml
+glColorMaterial https://www.opengl.org/sdk/docs/man/xhtml/glColorMaterial.xml
+glColorP3ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glColorP3uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glColorP4ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glColorP4uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glColorPointer https://www.opengl.org/sdk/docs/man/xhtml/glColorPointer.xml
+glColorPointerEXT https://www.opengl.org/registry/specs/EXT/vertex_array.txt
+glColorPointervINTEL https://www.opengl.org/registry/specs/INTEL/parallel_arrays.txt
+glColorSubTable https://www.opengl.org/sdk/docs/man/xhtml/glColorSubTable.xml
+glColorSubTableEXT https://www.opengl.org/registry/specs/EXT/color_subtable.txt
+glColorSubTableEXT https://www.opengl.org/registry/specs/EXT/paletted_texture.txt
+glColorTable https://www.opengl.org/sdk/docs/man/xhtml/glColorTable.xml
+glColorTableEXT https://www.opengl.org/registry/specs/EXT/paletted_texture.txt
+glColorTableParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glColorTableParameter.xml
+glColorTableParameterfvSGI https://www.opengl.org/registry/specs/SGI/color_table.txt
+glColorTableParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glColorTableParameter.xml
+glColorTableParameterivSGI https://www.opengl.org/registry/specs/SGI/color_table.txt
+glColorTableSGI https://www.opengl.org/registry/specs/SGI/color_table.txt
+glCombinerInputNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glCombinerOutputNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glCombinerParameterfNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glCombinerParameterfvNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glCombinerParameteriNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glCombinerParameterivNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glCombinerStageParameterfvNV https://www.opengl.org/registry/specs/NV/register_combiners2.txt
+glCompileShader https://www.opengl.org/sdk/docs/man/xhtml/glCompileShader.xml
+glCompileShader https://www.opengl.org/sdk/docs/man3/xhtml/glCompileShader.xml
+glCompileShader https://www.opengl.org/sdk/docs/man4/html/glCompileShader.xhtml
+glCompileShaderARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glCompileShaderIncludeARB https://www.opengl.org/registry/specs/ARB/shading_language_include.txt
+glCompressedMultiTexImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedMultiTexImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedMultiTexImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedMultiTexSubImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedMultiTexSubImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedMultiTexSubImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedTexImage1D https://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage1D.xml
+glCompressedTexImage1D https://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexImage1D.xml
+glCompressedTexImage1D https://www.opengl.org/sdk/docs/man4/html/glCompressedTexImage1D.xhtml
+glCompressedTexImage1DARB https://www.opengl.org/registry/specs/ARB/texture_compression.txt
+glCompressedTexImage2D https://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage2D.xml
+glCompressedTexImage2D https://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexImage2D.xml
+glCompressedTexImage2D https://www.opengl.org/sdk/docs/man4/html/glCompressedTexImage2D.xhtml
+glCompressedTexImage2DARB https://www.opengl.org/registry/specs/ARB/texture_compression.txt
+glCompressedTexImage3D https://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage3D.xml
+glCompressedTexImage3D https://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexImage3D.xml
+glCompressedTexImage3D https://www.opengl.org/sdk/docs/man4/html/glCompressedTexImage3D.xhtml
+glCompressedTexImage3DARB https://www.opengl.org/registry/specs/ARB/texture_compression.txt
+glCompressedTexSubImage1D https://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage1D.xml
+glCompressedTexSubImage1D https://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexSubImage1D.xml
+glCompressedTexSubImage1D https://www.opengl.org/sdk/docs/man4/html/glCompressedTexSubImage1D.xhtml
+glCompressedTexSubImage1DARB https://www.opengl.org/registry/specs/ARB/texture_compression.txt
+glCompressedTexSubImage2D https://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage2D.xml
+glCompressedTexSubImage2D https://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexSubImage2D.xml
+glCompressedTexSubImage2D https://www.opengl.org/sdk/docs/man4/html/glCompressedTexSubImage2D.xhtml
+glCompressedTexSubImage2DARB https://www.opengl.org/registry/specs/ARB/texture_compression.txt
+glCompressedTexSubImage3D https://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage3D.xml
+glCompressedTexSubImage3D https://www.opengl.org/sdk/docs/man3/xhtml/glCompressedTexSubImage3D.xml
+glCompressedTexSubImage3D https://www.opengl.org/sdk/docs/man4/html/glCompressedTexSubImage3D.xhtml
+glCompressedTexSubImage3DARB https://www.opengl.org/registry/specs/ARB/texture_compression.txt
+glCompressedTextureImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedTextureImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedTextureImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedTextureSubImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedTextureSubImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCompressedTextureSubImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glConvolutionFilter1D https://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter1D.xml
+glConvolutionFilter1DEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glConvolutionFilter2D https://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter2D.xml
+glConvolutionFilter2DEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glConvolutionParameterf https://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml
+glConvolutionParameterfEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glConvolutionParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml
+glConvolutionParameterfvEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glConvolutionParameteri https://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml
+glConvolutionParameteriEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glConvolutionParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml
+glConvolutionParameterivEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glCopyBufferSubData https://www.opengl.org/registry/specs/ARB/copy_buffer.txt
+glCopyBufferSubData https://www.opengl.org/sdk/docs/man3/xhtml/glCopyBufferSubData.xml
+glCopyBufferSubData https://www.opengl.org/sdk/docs/man4/html/glCopyBufferSubData.xhtml
+glCopyColorSubTable https://www.opengl.org/sdk/docs/man/xhtml/glCopyColorSubTable.xml
+glCopyColorSubTableEXT https://www.opengl.org/registry/specs/EXT/color_subtable.txt
+glCopyColorTable https://www.opengl.org/sdk/docs/man/xhtml/glCopyColorTable.xml
+glCopyColorTableSGI https://www.opengl.org/registry/specs/SGI/color_table.txt
+glCopyConvolutionFilter1D https://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter1D.xml
+glCopyConvolutionFilter1DEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glCopyConvolutionFilter2D https://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter2D.xml
+glCopyConvolutionFilter2DEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glCopyImageSubDataNV https://www.opengl.org/registry/specs/NV/copy_image.txt
+glCopyMultiTexImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCopyMultiTexImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCopyMultiTexSubImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCopyMultiTexSubImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCopyMultiTexSubImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCopyPathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glCopyPixels https://www.opengl.org/sdk/docs/man/xhtml/glCopyPixels.xml
+glCopyTexImage1D https://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage1D.xml
+glCopyTexImage1D https://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexImage1D.xml
+glCopyTexImage1D https://www.opengl.org/sdk/docs/man4/html/glCopyTexImage1D.xhtml
+glCopyTexImage1DEXT https://www.opengl.org/registry/specs/EXT/copy_texture.txt
+glCopyTexImage2D https://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage2D.xml
+glCopyTexImage2D https://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexImage2D.xml
+glCopyTexImage2D https://www.opengl.org/sdk/docs/man4/html/glCopyTexImage2D.xhtml
+glCopyTexImage2DEXT https://www.opengl.org/registry/specs/EXT/copy_texture.txt
+glCopyTexSubImage1D https://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage1D.xml
+glCopyTexSubImage1D https://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexSubImage1D.xml
+glCopyTexSubImage1D https://www.opengl.org/sdk/docs/man4/html/glCopyTexSubImage1D.xhtml
+glCopyTexSubImage1DEXT https://www.opengl.org/registry/specs/EXT/copy_texture.txt
+glCopyTexSubImage2D https://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage2D.xml
+glCopyTexSubImage2D https://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexSubImage2D.xml
+glCopyTexSubImage2D https://www.opengl.org/sdk/docs/man4/html/glCopyTexSubImage2D.xhtml
+glCopyTexSubImage2DEXT https://www.opengl.org/registry/specs/EXT/copy_texture.txt
+glCopyTexSubImage3D https://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage3D.xml
+glCopyTexSubImage3D https://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexSubImage3D.xml
+glCopyTexSubImage3D https://www.opengl.org/sdk/docs/man4/html/glCopyTexSubImage3D.xhtml
+glCopyTexSubImage3DEXT https://www.opengl.org/registry/specs/EXT/copy_texture.txt
+glCopyTextureImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCopyTextureImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCopyTextureSubImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCopyTextureSubImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCopyTextureSubImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glCoverFillPathInstancedNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glCoverFillPathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glCoverStrokePathInstancedNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glCoverStrokePathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glCreateProgram https://www.opengl.org/sdk/docs/man/xhtml/glCreateProgram.xml
+glCreateProgram https://www.opengl.org/sdk/docs/man3/xhtml/glCreateProgram.xml
+glCreateProgram https://www.opengl.org/sdk/docs/man4/html/glCreateProgram.xhtml
+glCreateProgramObjectARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glCreateShader https://www.opengl.org/sdk/docs/man/xhtml/glCreateShader.xml
+glCreateShader https://www.opengl.org/sdk/docs/man3/xhtml/glCreateShader.xml
+glCreateShader https://www.opengl.org/sdk/docs/man4/html/glCreateShader.xhtml
+glCreateShaderObjectARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glCreateShaderProgramEXT https://www.opengl.org/registry/specs/EXT/separate_shader_objects.txt
+glCreateShaderProgramv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glCreateShaderProgramv https://www.opengl.org/sdk/docs/man4/html/glCreateShaderProgram.xhtml
+glCreateSyncFromCLeventARB https://www.opengl.org/registry/specs/ARB/cl_event.txt
+glCullFace https://www.opengl.org/sdk/docs/man/xhtml/glCullFace.xml
+glCullFace https://www.opengl.org/sdk/docs/man3/xhtml/glCullFace.xml
+glCullFace https://www.opengl.org/sdk/docs/man4/html/glCullFace.xhtml
+glCurrentPaletteMatrixARB https://www.opengl.org/registry/specs/ARB/matrix_palette.txt
+glDECLARE_HANDLE https://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
+glDECLARE_HANDLE https://www.opengl.org/registry/specs/NV/present_video.txt
+glDebugMessageCallbackAMD https://www.opengl.org/registry/specs/AMD/debug_output.txt
+glDebugMessageCallbackARB https://www.opengl.org/registry/specs/ARB/debug_output.txt
+glDebugMessageControlARB https://www.opengl.org/registry/specs/ARB/debug_output.txt
+glDebugMessageEnableAMD https://www.opengl.org/registry/specs/AMD/debug_output.txt
+glDebugMessageInsertAMD https://www.opengl.org/registry/specs/AMD/debug_output.txt
+glDebugMessageInsertARB https://www.opengl.org/registry/specs/ARB/debug_output.txt
+glDeleteArraySetsEXT https://www.opengl.org/registry/specs/EXT/vertex_array_set.alt.txt
+glDeleteArraySetsEXT https://www.opengl.org/registry/specs/EXT/vertex_array_set.txt
+glDeleteAsyncMarkersSGIX https://www.opengl.org/registry/specs/SGIX/async.txt
+glDeleteBuffers https://www.opengl.org/sdk/docs/man/xhtml/glDeleteBuffers.xml
+glDeleteBuffers https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteBuffers.xml
+glDeleteBuffers https://www.opengl.org/sdk/docs/man4/html/glDeleteBuffers.xhtml
+glDeleteBuffersARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glDeleteFencesAPPLE https://www.opengl.org/registry/specs/APPLE/fence.txt
+glDeleteFencesNV https://www.opengl.org/registry/specs/NV/fence.txt
+glDeleteFramebuffers https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glDeleteFramebuffers https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteFramebuffers.xml
+glDeleteFramebuffers https://www.opengl.org/sdk/docs/man4/html/glDeleteFramebuffers.xhtml
+glDeleteFramebuffersEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glDeleteLists https://www.opengl.org/sdk/docs/man/xhtml/glDeleteLists.xml
+glDeleteNamedStringARB https://www.opengl.org/registry/specs/ARB/shading_language_include.txt
+glDeleteNamesAMD https://www.opengl.org/registry/specs/AMD/name_gen_delete.txt
+glDeleteObjectARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glDeleteOcclusionQueriesNV https://www.opengl.org/registry/specs/NV/occlusion_query.txt
+glDeletePathsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glDeletePerfMonitorsAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glDeleteProgram https://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgram.xml
+glDeleteProgram https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteProgram.xml
+glDeleteProgram https://www.opengl.org/sdk/docs/man4/html/glDeleteProgram.xhtml
+glDeleteProgramPipelines https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glDeleteProgramPipelines https://www.opengl.org/sdk/docs/man4/html/glDeleteProgramPipelines.xhtml
+glDeleteProgramsARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glDeleteProgramsARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glDeleteProgramsNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glDeleteQueries https://www.opengl.org/sdk/docs/man/xhtml/glDeleteQueries.xml
+glDeleteQueries https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteQueries.xml
+glDeleteQueries https://www.opengl.org/sdk/docs/man4/html/glDeleteQueries.xhtml
+glDeleteQueriesARB https://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+glDeleteRenderbuffers https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glDeleteRenderbuffers https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteRenderbuffers.xml
+glDeleteRenderbuffers https://www.opengl.org/sdk/docs/man4/html/glDeleteRenderbuffers.xhtml
+glDeleteRenderbuffersEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glDeleteSamplers https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glDeleteSamplers https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteSamplers.xml
+glDeleteSamplers https://www.opengl.org/sdk/docs/man4/html/glDeleteSamplers.xhtml
+glDeleteShader https://www.opengl.org/sdk/docs/man/xhtml/glDeleteShader.xml
+glDeleteShader https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteShader.xml
+glDeleteShader https://www.opengl.org/sdk/docs/man4/html/glDeleteShader.xhtml
+glDeleteSync https://www.opengl.org/registry/specs/ARB/sync.txt
+glDeleteSync https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteSync.xml
+glDeleteSync https://www.opengl.org/sdk/docs/man4/html/glDeleteSync.xhtml
+glDeleteTextures https://www.opengl.org/sdk/docs/man/xhtml/glDeleteTextures.xml
+glDeleteTextures https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteTextures.xml
+glDeleteTextures https://www.opengl.org/sdk/docs/man4/html/glDeleteTextures.xhtml
+glDeleteTexturesEXT https://www.opengl.org/registry/specs/EXT/texture_object.txt
+glDeleteTransformFeedbacks https://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
+glDeleteTransformFeedbacks https://www.opengl.org/sdk/docs/man4/html/glDeleteTransformFeedbacks.xhtml
+glDeleteTransformFeedbacksNV https://www.opengl.org/registry/specs/NV/transform_feedback2.txt
+glDeleteVertexArrays https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
+glDeleteVertexArrays https://www.opengl.org/sdk/docs/man3/xhtml/glDeleteVertexArrays.xml
+glDeleteVertexArrays https://www.opengl.org/sdk/docs/man4/html/glDeleteVertexArrays.xhtml
+glDeleteVertexArraysAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_array_object.txt
+glDepthBoundsEXT https://www.opengl.org/registry/specs/EXT/depth_bounds_test.txt
+glDepthBoundsdNV https://www.opengl.org/registry/specs/NV/depth_buffer_float.txt
+glDepthFunc https://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml
+glDepthFunc https://www.opengl.org/sdk/docs/man3/xhtml/glDepthFunc.xml
+glDepthFunc https://www.opengl.org/sdk/docs/man4/html/glDepthFunc.xhtml
+glDepthMask https://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml
+glDepthMask https://www.opengl.org/sdk/docs/man3/xhtml/glDepthMask.xml
+glDepthMask https://www.opengl.org/sdk/docs/man4/html/glDepthMask.xhtml
+glDepthRange https://www.opengl.org/sdk/docs/man/xhtml/glDepthRange.xml
+glDepthRange https://www.opengl.org/sdk/docs/man3/xhtml/glDepthRange.xml
+glDepthRange https://www.opengl.org/sdk/docs/man4/html/glDepthRange.xhtml
+glDepthRangeArrayv https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glDepthRangeArrayv https://www.opengl.org/sdk/docs/man4/html/glDepthRangeArray.xhtml
+glDepthRangeIndexed https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glDepthRangeIndexed https://www.opengl.org/sdk/docs/man4/html/glDepthRangeIndexed.xhtml
+glDepthRangedNV https://www.opengl.org/registry/specs/NV/depth_buffer_float.txt
+glDepthRangef https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
+glDepthRangef https://www.opengl.org/sdk/docs/man4/html/glDepthRange.xhtml
+glDepthRangefOES https://www.opengl.org/registry/specs/OES/OES_single_precision.txt
+glDepthRangexOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glDetachObjectARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glDetachShader https://www.opengl.org/sdk/docs/man/xhtml/glDetachShader.xml
+glDetachShader https://www.opengl.org/sdk/docs/man3/xhtml/glDetachShader.xml
+glDetachShader https://www.opengl.org/sdk/docs/man4/html/glDetachShader.xhtml
+glDetailTexFuncSGIS https://www.opengl.org/registry/specs/SGIS/detail_texture.txt
+glDisable https://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
+glDisable https://www.opengl.org/sdk/docs/man3/xhtml/glEnable.xml
+glDisable https://www.opengl.org/sdk/docs/man4/html/glEnable.xhtml
+glDisableClientState https://www.opengl.org/sdk/docs/man/xhtml/glEnableClientState.xml
+glDisableClientStateIndexedEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glDisableClientStateiEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glDisableIndexedEXT https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glDisableIndexedEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glDisableIndexedEXT https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
+glDisableVertexArrayAttribEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glDisableVertexArrayEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glDisableVertexAttribAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
+glDisableVertexAttribArray https://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml
+glDisableVertexAttribArray https://www.opengl.org/sdk/docs/man3/xhtml/glEnableVertexAttribArray.xml
+glDisableVertexAttribArray https://www.opengl.org/sdk/docs/man4/html/glEnableVertexAttribArray.xhtml
+glDisableVertexAttribArrayARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glDisableVertexAttribArrayARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glDisablei https://www.opengl.org/sdk/docs/man3/xhtml/glEnable.xml
+glDisablei https://www.opengl.org/sdk/docs/man4/html/glEnable.xhtml
+glDrawArrays https://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml
+glDrawArrays https://www.opengl.org/sdk/docs/man3/xhtml/glDrawArrays.xml
+glDrawArrays https://www.opengl.org/sdk/docs/man4/html/glDrawArrays.xhtml
+glDrawArraysEXT https://www.opengl.org/registry/specs/EXT/vertex_array.txt
+glDrawArraysIndirect https://www.opengl.org/registry/specs/ARB/draw_indirect.txt
+glDrawArraysIndirect https://www.opengl.org/sdk/docs/man4/html/glDrawArraysIndirect.xhtml
+glDrawArraysInstanced https://www.opengl.org/sdk/docs/man3/xhtml/glDrawArraysInstanced.xml
+glDrawArraysInstanced https://www.opengl.org/sdk/docs/man4/html/glDrawArraysInstanced.xhtml
+glDrawArraysInstancedARB https://www.opengl.org/registry/specs/ARB/draw_instanced.txt
+glDrawArraysInstancedBaseInstance https://www.opengl.org/registry/specs/ARB/base_instance.txt
+glDrawArraysInstancedEXT https://www.opengl.org/registry/specs/EXT/draw_instanced.txt
+glDrawBuffer https://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffer.xml
+glDrawBuffer https://www.opengl.org/sdk/docs/man3/xhtml/glDrawBuffer.xml
+glDrawBuffer https://www.opengl.org/sdk/docs/man4/html/glDrawBuffer.xhtml
+glDrawBuffers https://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffers.xml
+glDrawBuffers https://www.opengl.org/sdk/docs/man3/xhtml/glDrawBuffers.xml
+glDrawBuffers https://www.opengl.org/sdk/docs/man4/html/glDrawBuffers.xhtml
+glDrawBuffersARB https://www.opengl.org/registry/specs/ARB/draw_buffers.txt
+glDrawBuffersATI https://www.opengl.org/registry/specs/ATI/draw_buffers.txt
+glDrawElementArrayAPPLE https://www.opengl.org/registry/specs/APPLE/element_array.txt
+glDrawElementArrayATI https://www.opengl.org/registry/specs/ATI/element_array.txt
+glDrawElements https://www.opengl.org/sdk/docs/man/xhtml/glDrawElements.xml
+glDrawElements https://www.opengl.org/sdk/docs/man3/xhtml/glDrawElements.xml
+glDrawElements https://www.opengl.org/sdk/docs/man4/html/glDrawElements.xhtml
+glDrawElementsBaseVertex https://www.opengl.org/registry/specs/ARB/draw_elements_base_vertex.txt
+glDrawElementsBaseVertex https://www.opengl.org/sdk/docs/man3/xhtml/glDrawElementsBaseVertex.xml
+glDrawElementsBaseVertex https://www.opengl.org/sdk/docs/man4/html/glDrawElementsBaseVertex.xhtml
+glDrawElementsIndirect https://www.opengl.org/registry/specs/ARB/draw_indirect.txt
+glDrawElementsIndirect https://www.opengl.org/sdk/docs/man4/html/glDrawElementsIndirect.xhtml
+glDrawElementsInstanced https://www.opengl.org/sdk/docs/man3/xhtml/glDrawElementsInstanced.xml
+glDrawElementsInstanced https://www.opengl.org/sdk/docs/man4/html/glDrawElementsInstanced.xhtml
+glDrawElementsInstancedARB https://www.opengl.org/registry/specs/ARB/draw_instanced.txt
+glDrawElementsInstancedBaseInstance https://www.opengl.org/registry/specs/ARB/base_instance.txt
+glDrawElementsInstancedBaseVertex https://www.opengl.org/registry/specs/ARB/draw_elements_base_vertex.txt
+glDrawElementsInstancedBaseVertex https://www.opengl.org/sdk/docs/man3/xhtml/glDrawElementsInstancedBaseVertex.xml
+glDrawElementsInstancedBaseVertex https://www.opengl.org/sdk/docs/man4/html/glDrawElementsInstancedBaseVertex.xhtml
+glDrawElementsInstancedBaseVertexBaseInstance https://www.opengl.org/registry/specs/ARB/base_instance.txt
+glDrawElementsInstancedEXT https://www.opengl.org/registry/specs/EXT/draw_instanced.txt
+glDrawMeshArraysSUN https://www.opengl.org/registry/specs/SUN/mesh_array.txt
+glDrawPixels https://www.opengl.org/sdk/docs/man/xhtml/glDrawPixels.xml
+glDrawRangeElementArrayAPPLE https://www.opengl.org/registry/specs/APPLE/element_array.txt
+glDrawRangeElementArrayATI https://www.opengl.org/registry/specs/ATI/element_array.txt
+glDrawRangeElements https://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElements.xml
+glDrawRangeElements https://www.opengl.org/sdk/docs/man3/xhtml/glDrawRangeElements.xml
+glDrawRangeElements https://www.opengl.org/sdk/docs/man4/html/glDrawRangeElements.xhtml
+glDrawRangeElementsBaseVertex https://www.opengl.org/registry/specs/ARB/draw_elements_base_vertex.txt
+glDrawRangeElementsBaseVertex https://www.opengl.org/sdk/docs/man3/xhtml/glDrawRangeElementsBaseVertex.xml
+glDrawRangeElementsBaseVertex https://www.opengl.org/sdk/docs/man4/html/glDrawRangeElementsBaseVertex.xhtml
+glDrawTransformFeedback https://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
+glDrawTransformFeedback https://www.opengl.org/sdk/docs/man4/html/glDrawTransformFeedback.xhtml
+glDrawTransformFeedbackInstanced https://www.opengl.org/registry/specs/ARB/transform_feedback_instanced.txt
+glDrawTransformFeedbackNV https://www.opengl.org/registry/specs/NV/transform_feedback2.txt
+glDrawTransformFeedbackStream https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt
+glDrawTransformFeedbackStream https://www.opengl.org/sdk/docs/man4/html/glDrawTransformFeedbackStream.xhtml
+glDrawTransformFeedbackStreamInstanced https://www.opengl.org/registry/specs/ARB/transform_feedback_instanced.txt
+glEdgeFlag https://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlag.xml
+glEdgeFlagFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glEdgeFlagPointer https://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlagPointer.xml
+glEdgeFlagPointerEXT https://www.opengl.org/registry/specs/EXT/vertex_array.txt
+glEdgeFlagv https://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlag.xml
+glElementPointerAPPLE https://www.opengl.org/registry/specs/APPLE/element_array.txt
+glElementPointerATI https://www.opengl.org/registry/specs/ATI/element_array.txt
+glEnable https://www.opengl.org/registry/specs/SGIX/instruments.txt
+glEnable https://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml
+glEnable https://www.opengl.org/sdk/docs/man3/xhtml/glEnable.xml
+glEnable https://www.opengl.org/sdk/docs/man4/html/glEnable.xhtml
+glEnableClientState https://www.opengl.org/sdk/docs/man/xhtml/glEnableClientState.xml
+glEnableClientStateIndexedEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glEnableClientStateiEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glEnableIndexedEXT https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glEnableIndexedEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glEnableIndexedEXT https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
+glEnableVertexArrayAttribEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glEnableVertexArrayEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glEnableVertexAttribAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
+glEnableVertexAttribArray https://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml
+glEnableVertexAttribArray https://www.opengl.org/sdk/docs/man3/xhtml/glEnableVertexAttribArray.xml
+glEnableVertexAttribArray https://www.opengl.org/sdk/docs/man4/html/glEnableVertexAttribArray.xhtml
+glEnableVertexAttribArrayARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glEnableVertexAttribArrayARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glEnablei https://www.opengl.org/sdk/docs/man3/xhtml/glEnable.xml
+glEnablei https://www.opengl.org/sdk/docs/man4/html/glEnable.xhtml
+glEnd https://www.opengl.org/sdk/docs/man/xhtml/glBegin.xml
+glEndConditionalRender https://www.opengl.org/sdk/docs/man3/xhtml/glBeginConditionalRender.xml
+glEndConditionalRender https://www.opengl.org/sdk/docs/man4/html/glBeginConditionalRender.xhtml
+glEndConditionalRenderNV https://www.opengl.org/registry/specs/NV/conditional_render.txt
+glEndList https://www.opengl.org/sdk/docs/man/xhtml/glNewList.xml
+glEndOcclusionQueryNV https://www.opengl.org/registry/specs/NV/occlusion_query.txt
+glEndPerfMonitorAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glEndQuery https://www.opengl.org/sdk/docs/man/xhtml/glBeginQuery.xml
+glEndQuery https://www.opengl.org/sdk/docs/man3/xhtml/glBeginQuery.xml
+glEndQuery https://www.opengl.org/sdk/docs/man4/html/glBeginQuery.xhtml
+glEndQueryARB https://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+glEndQueryIndexed https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt
+glEndQueryIndexed https://www.opengl.org/sdk/docs/man4/html/glBeginQueryIndexed.xhtml
+glEndSceneEXT https://www.opengl.org/registry/specs/EXT/scene_marker.txt
+glEndTransformFeedback https://www.opengl.org/sdk/docs/man3/xhtml/glBeginTransformFeedback.xml
+glEndTransformFeedback https://www.opengl.org/sdk/docs/man4/html/glBeginTransformFeedback.xhtml
+glEndTransformFeedbackEXT https://www.opengl.org/registry/specs/EXT/transform_feedback.txt
+glEndTransformFeedbackNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glEndVideoCaptureNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glEvalCoord1d https://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
+glEvalCoord1dv https://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
+glEvalCoord1f https://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
+glEvalCoord1fv https://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
+glEvalCoord2d https://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
+glEvalCoord2dv https://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
+glEvalCoord2f https://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
+glEvalCoord2fv https://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml
+glEvalMapsNV https://www.opengl.org/registry/specs/NV/evaluators.txt
+glEvalMesh1 https://www.opengl.org/sdk/docs/man/xhtml/glEvalMesh.xml
+glEvalMesh2 https://www.opengl.org/sdk/docs/man/xhtml/glEvalMesh.xml
+glEvalPoint1 https://www.opengl.org/sdk/docs/man/xhtml/glEvalPoint.xml
+glEvalPoint2 https://www.opengl.org/sdk/docs/man/xhtml/glEvalPoint.xml
+glExecuteProgramNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glFeedbackBuffer https://www.opengl.org/sdk/docs/man/xhtml/glFeedbackBuffer.xml
+glFeedbackBufferxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glFenceSync https://www.opengl.org/registry/specs/ARB/sync.txt
+glFenceSync https://www.opengl.org/sdk/docs/man3/xhtml/glFenceSync.xml
+glFenceSync https://www.opengl.org/sdk/docs/man4/html/glFenceSync.xhtml
+glFinalCombinerInputNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glFinish https://www.opengl.org/sdk/docs/man/xhtml/glFinish.xml
+glFinish https://www.opengl.org/sdk/docs/man3/xhtml/glFinish.xml
+glFinish https://www.opengl.org/sdk/docs/man4/html/glFinish.xhtml
+glFinishAsyncSGIX https://www.opengl.org/registry/specs/SGIX/async.txt
+glFinishFenceAPPLE https://www.opengl.org/registry/specs/APPLE/fence.txt
+glFinishFenceNV https://www.opengl.org/registry/specs/NV/fence.txt
+glFinishObjectAPPLE https://www.opengl.org/registry/specs/APPLE/fence.txt
+glFinishTextureSUNX https://www.opengl.org/registry/specs/SUNX/constant_data.txt
+glFlush https://www.opengl.org/sdk/docs/man/xhtml/glFlush.xml
+glFlush https://www.opengl.org/sdk/docs/man3/xhtml/glFlush.xml
+glFlush https://www.opengl.org/sdk/docs/man4/html/glFlush.xhtml
+glFlushMappedBufferRange https://www.opengl.org/registry/specs/ARB/map_buffer_range.txt
+glFlushMappedBufferRange https://www.opengl.org/sdk/docs/man3/xhtml/glFlushMappedBufferRange.xml
+glFlushMappedBufferRange https://www.opengl.org/sdk/docs/man4/html/glFlushMappedBufferRange.xhtml
+glFlushMappedBufferRangeAPPLE https://www.opengl.org/registry/specs/APPLE/flush_buffer_range.txt
+glFlushMappedNamedBufferRangeEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glFlushPixelDataRangeNV https://www.opengl.org/registry/specs/NV/pixel_data_range.txt
+glFlushRasterSGIX https://www.opengl.org/registry/specs/SGIX/flush_raster.txt
+glFlushStaticDataIBM https://www.opengl.org/registry/specs/IBM/static_data.txt
+glFlushVertexArrayRangeAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_array_range.txt
+glFlushVertexArrayRangeNV https://www.opengl.org/registry/specs/NV/vertex_array_range.txt
+glFogCoordFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glFogCoordPointer https://www.opengl.org/sdk/docs/man/xhtml/glFogCoordPointer.xml
+glFogCoordPointerEXT https://www.opengl.org/registry/specs/EXT/fog_coord.txt
+glFogCoordd https://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml
+glFogCoorddv https://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml
+glFogCoordf https://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml
+glFogCoordfv https://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml
+glFogCoordhNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glFogCoordhvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glFogFuncSGIS https://www.opengl.org/registry/specs/SGIS/fog_func.txt
+glFogf https://www.opengl.org/sdk/docs/man/xhtml/glFog.xml
+glFogfv https://www.opengl.org/sdk/docs/man/xhtml/glFog.xml
+glFogi https://www.opengl.org/sdk/docs/man/xhtml/glFog.xml
+glFogiv https://www.opengl.org/sdk/docs/man/xhtml/glFog.xml
+glFragmentColorMaterialEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentColorMaterialSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentLightModelfEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentLightModelfSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentLightModelfvEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentLightModelfvSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentLightModeliEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentLightModeliSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentLightModelivEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentLightModelivSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentLightfEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentLightfSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentLightfvEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentLightfvSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentLightiEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentLightiSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentLightivEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentLightivSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentMaterialfEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentMaterialfSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentMaterialfvEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentMaterialfvSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentMaterialiEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentMaterialiSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFragmentMaterialivEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glFragmentMaterialivSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glFrameTerminatorGREMEDY https://www.opengl.org/registry/specs/GREMEDY/frame_terminator.txt
+glFrameZoomSGIX https://www.opengl.org/registry/specs/SGIX/framezoom.txt
+glFramebufferDrawBufferEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glFramebufferDrawBuffersEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glFramebufferReadBufferEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glFramebufferRenderbuffer https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glFramebufferRenderbuffer https://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferRenderbuffer.xml
+glFramebufferRenderbuffer https://www.opengl.org/sdk/docs/man4/html/glFramebufferRenderbuffer.xhtml
+glFramebufferRenderbufferEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glFramebufferTexture https://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTexture.xml
+glFramebufferTexture https://www.opengl.org/sdk/docs/man4/html/glFramebufferTexture.xhtml
+glFramebufferTexture1D https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glFramebufferTexture1D https://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTexture.xml
+glFramebufferTexture1D https://www.opengl.org/sdk/docs/man4/html/glFramebufferTexture.xhtml
+glFramebufferTexture1DEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glFramebufferTexture2D https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glFramebufferTexture2D https://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTexture.xml
+glFramebufferTexture2D https://www.opengl.org/sdk/docs/man4/html/glFramebufferTexture.xhtml
+glFramebufferTexture2DEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glFramebufferTexture3D https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glFramebufferTexture3D https://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTexture.xml
+glFramebufferTexture3D https://www.opengl.org/sdk/docs/man4/html/glFramebufferTexture.xhtml
+glFramebufferTexture3DEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glFramebufferTextureARB https://www.opengl.org/registry/specs/ARB/geometry_shader4.txt
+glFramebufferTextureEXT https://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
+glFramebufferTextureEXT https://www.opengl.org/registry/specs/NV/geometry_program4.txt
+glFramebufferTextureFaceARB https://www.opengl.org/registry/specs/ARB/geometry_shader4.txt
+glFramebufferTextureFaceEXT https://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
+glFramebufferTextureFaceEXT https://www.opengl.org/registry/specs/NV/geometry_program4.txt
+glFramebufferTextureLayer https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glFramebufferTextureLayer https://www.opengl.org/sdk/docs/man3/xhtml/glFramebufferTextureLayer.xml
+glFramebufferTextureLayer https://www.opengl.org/sdk/docs/man4/html/glFramebufferTextureLayer.xhtml
+glFramebufferTextureLayerARB https://www.opengl.org/registry/specs/ARB/geometry_shader4.txt
+glFramebufferTextureLayerEXT https://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
+glFramebufferTextureLayerEXT https://www.opengl.org/registry/specs/EXT/texture_array.txt
+glFramebufferTextureLayerEXT https://www.opengl.org/registry/specs/NV/geometry_program4.txt
+glFreeObjectBufferATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glFrontFace https://www.opengl.org/sdk/docs/man/xhtml/glFrontFace.xml
+glFrontFace https://www.opengl.org/sdk/docs/man3/xhtml/glFrontFace.xml
+glFrontFace https://www.opengl.org/sdk/docs/man4/html/glFrontFace.xhtml
+glFrustum https://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml
+glFrustumfOES https://www.opengl.org/registry/specs/OES/OES_single_precision.txt
+glFrustumxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGenArraySetsEXT https://www.opengl.org/registry/specs/EXT/vertex_array_set.txt
+glGenAsyncMarkersSGIX https://www.opengl.org/registry/specs/SGIX/async.txt
+glGenBuffers https://www.opengl.org/sdk/docs/man/xhtml/glGenBuffers.xml
+glGenBuffers https://www.opengl.org/sdk/docs/man3/xhtml/glGenBuffers.xml
+glGenBuffers https://www.opengl.org/sdk/docs/man4/html/glGenBuffers.xhtml
+glGenBuffersARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glGenFencesAPPLE https://www.opengl.org/registry/specs/APPLE/fence.txt
+glGenFencesNV https://www.opengl.org/registry/specs/NV/fence.txt
+glGenFramebuffers https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glGenFramebuffers https://www.opengl.org/sdk/docs/man3/xhtml/glGenFramebuffers.xml
+glGenFramebuffers https://www.opengl.org/sdk/docs/man4/html/glGenFramebuffers.xhtml
+glGenFramebuffersEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glGenLists https://www.opengl.org/sdk/docs/man/xhtml/glGenLists.xml
+glGenNamesAMD https://www.opengl.org/registry/specs/AMD/name_gen_delete.txt
+glGenOcclusionQueriesNV https://www.opengl.org/registry/specs/NV/occlusion_query.txt
+glGenPathsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGenPerfMonitorsAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glGenProgramPipelines https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glGenProgramPipelines https://www.opengl.org/sdk/docs/man4/html/glGenProgramPipelines.xhtml
+glGenProgramsARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glGenProgramsARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGenProgramsNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGenQueries https://www.opengl.org/sdk/docs/man/xhtml/glGenQueries.xml
+glGenQueries https://www.opengl.org/sdk/docs/man3/xhtml/glGenQueries.xml
+glGenQueries https://www.opengl.org/sdk/docs/man4/html/glGenQueries.xhtml
+glGenQueriesARB https://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+glGenRenderbuffers https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glGenRenderbuffers https://www.opengl.org/sdk/docs/man3/xhtml/glGenRenderbuffers.xml
+glGenRenderbuffers https://www.opengl.org/sdk/docs/man4/html/glGenRenderbuffers.xhtml
+glGenRenderbuffersEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glGenSamplers https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glGenSamplers https://www.opengl.org/sdk/docs/man3/xhtml/glGenSamplers.xml
+glGenSamplers https://www.opengl.org/sdk/docs/man4/html/glGenSamplers.xhtml
+glGenTextures https://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml
+glGenTextures https://www.opengl.org/sdk/docs/man3/xhtml/glGenTextures.xml
+glGenTextures https://www.opengl.org/sdk/docs/man4/html/glGenTextures.xhtml
+glGenTexturesEXT https://www.opengl.org/registry/specs/EXT/texture_object.txt
+glGenTransformFeedbacks https://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
+glGenTransformFeedbacks https://www.opengl.org/sdk/docs/man4/html/glGenTransformFeedbacks.xhtml
+glGenTransformFeedbacksNV https://www.opengl.org/registry/specs/NV/transform_feedback2.txt
+glGenVertexArrays https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
+glGenVertexArrays https://www.opengl.org/sdk/docs/man3/xhtml/glGenVertexArrays.xml
+glGenVertexArrays https://www.opengl.org/sdk/docs/man4/html/glGenVertexArrays.xhtml
+glGenVertexArraysAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_array_object.txt
+glGenerateMipmap https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glGenerateMipmap https://www.opengl.org/sdk/docs/man3/xhtml/glGenerateMipmap.xml
+glGenerateMipmap https://www.opengl.org/sdk/docs/man4/html/glGenerateMipmap.xhtml
+glGenerateMipmapEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glGenerateMultiTexMipmapEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGenerateTextureMipmapEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetActiveAttrib https://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttrib.xml
+glGetActiveAttrib https://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveAttrib.xml
+glGetActiveAttrib https://www.opengl.org/sdk/docs/man4/html/glGetActiveAttrib.xhtml
+glGetActiveAttribARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glGetActiveSubroutineName https://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
+glGetActiveSubroutineName https://www.opengl.org/sdk/docs/man4/html/glGetActiveSubroutineName.xhtml
+glGetActiveSubroutineUniformName https://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
+glGetActiveSubroutineUniformName https://www.opengl.org/sdk/docs/man4/html/glGetActiveSubroutineUniformName.xhtml
+glGetActiveSubroutineUniformiv https://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
+glGetActiveSubroutineUniformiv https://www.opengl.org/sdk/docs/man4/html/glGetActiveSubroutineUniform.xhtml
+glGetActiveUniform https://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml
+glGetActiveUniform https://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniform.xml
+glGetActiveUniform https://www.opengl.org/sdk/docs/man4/html/glGetActiveUniform.xhtml
+glGetActiveUniformARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetActiveUniformBlockName https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glGetActiveUniformBlockName https://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniformBlockName.xml
+glGetActiveUniformBlockName https://www.opengl.org/sdk/docs/man4/html/glGetActiveUniformBlockName.xhtml
+glGetActiveUniformBlockiv https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glGetActiveUniformBlockiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniformBlock.xml
+glGetActiveUniformBlockiv https://www.opengl.org/sdk/docs/man4/html/glGetActiveUniformBlock.xhtml
+glGetActiveUniformName https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glGetActiveUniformName https://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniformName.xml
+glGetActiveUniformName https://www.opengl.org/sdk/docs/man4/html/glGetActiveUniformName.xhtml
+glGetActiveUniformsiv https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glGetActiveUniformsiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetActiveUniformsiv.xml
+glGetActiveUniformsiv https://www.opengl.org/sdk/docs/man4/html/glGetActiveUniformsiv.xhtml
+glGetActiveVaryingNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glGetArrayObjectfvATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glGetArrayObjectivATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glGetAttachedObjectsARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetAttachedShaders https://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedShaders.xml
+glGetAttachedShaders https://www.opengl.org/sdk/docs/man3/xhtml/glGetAttachedShaders.xml
+glGetAttachedShaders https://www.opengl.org/sdk/docs/man4/html/glGetAttachedShaders.xhtml
+glGetAttribLocation https://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml
+glGetAttribLocation https://www.opengl.org/sdk/docs/man3/xhtml/glGetAttribLocation.xml
+glGetAttribLocation https://www.opengl.org/sdk/docs/man4/html/glGetAttribLocation.xhtml
+glGetAttribLocationARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glGetBooleanIndexedvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetBooleanIndexedvEXT https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
+glGetBooleanIndexedvEXT https://www.opengl.org/registry/specs/EXT/transform_feedback.txt
+glGetBooleanIndexedvEXT https://www.opengl.org/registry/specs/NV/explicit_multisample.txt
+glGetBooleanIndexedvEXT https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glGetBooleani_v https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
+glGetBooleani_v https://www.opengl.org/sdk/docs/man4/html/glGet.xhtml
+glGetBooleanv https://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
+glGetBooleanv https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
+glGetBooleanv https://www.opengl.org/sdk/docs/man4/html/glGet.xhtml
+glGetBufferParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteriv.xml
+glGetBufferParameteriv https://www.opengl.org/sdk/docs/man3/xhtml/glGetBufferParameter.xml
+glGetBufferParameteriv https://www.opengl.org/sdk/docs/man4/html/glGetBufferParameter.xhtml
+glGetBufferParameterivARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glGetBufferParameterui64vNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glGetBufferPointerv https://www.opengl.org/sdk/docs/man/xhtml/glGetBufferPointerv.xml
+glGetBufferPointerv https://www.opengl.org/sdk/docs/man3/xhtml/glGetBufferPointerv.xml
+glGetBufferPointerv https://www.opengl.org/sdk/docs/man4/html/glGetBufferPointerv.xhtml
+glGetBufferPointervARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glGetBufferSubData https://www.opengl.org/sdk/docs/man/xhtml/glGetBufferSubData.xml
+glGetBufferSubData https://www.opengl.org/sdk/docs/man3/xhtml/glGetBufferSubData.xml
+glGetBufferSubData https://www.opengl.org/sdk/docs/man4/html/glGetBufferSubData.xhtml
+glGetBufferSubDataARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glGetClipPlane https://www.opengl.org/sdk/docs/man/xhtml/glGetClipPlane.xml
+glGetClipPlanefOES https://www.opengl.org/registry/specs/OES/OES_single_precision.txt
+glGetClipPlanexOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetColorTable https://www.opengl.org/sdk/docs/man/xhtml/glGetColorTable.xml
+glGetColorTableEXT https://www.opengl.org/registry/specs/EXT/paletted_texture.txt
+glGetColorTableParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glGetColorTableParameter.xml
+glGetColorTableParameterfvEXT https://www.opengl.org/registry/specs/EXT/paletted_texture.txt
+glGetColorTableParameterfvSGI https://www.opengl.org/registry/specs/SGI/color_table.txt
+glGetColorTableParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glGetColorTableParameter.xml
+glGetColorTableParameterivEXT https://www.opengl.org/registry/specs/EXT/paletted_texture.txt
+glGetColorTableParameterivSGI https://www.opengl.org/registry/specs/SGI/color_table.txt
+glGetColorTableSGI https://www.opengl.org/registry/specs/SGI/color_table.txt
+glGetCombinerInputParameterfvNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glGetCombinerInputParameterivNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glGetCombinerOutputParameterfvNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glGetCombinerOutputParameterivNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glGetCombinerStageParameterfvNV https://www.opengl.org/registry/specs/NV/register_combiners2.txt
+glGetCompressedMultiTexImageEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetCompressedTexImage https://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml
+glGetCompressedTexImage https://www.opengl.org/sdk/docs/man3/xhtml/glGetCompressedTexImage.xml
+glGetCompressedTexImage https://www.opengl.org/sdk/docs/man4/html/glGetCompressedTexImage.xhtml
+glGetCompressedTexImageARB https://www.opengl.org/registry/specs/ARB/texture_compression.txt
+glGetCompressedTextureImageEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetConvolutionFilter https://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionFilter.xml
+glGetConvolutionFilterEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glGetConvolutionParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionParameter.xml
+glGetConvolutionParameterfvEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glGetConvolutionParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionParameter.xml
+glGetConvolutionParameterivEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glGetConvolutionParameterxvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetDebugMessageLogAMD https://www.opengl.org/registry/specs/AMD/debug_output.txt
+glGetDebugMessageLogARB https://www.opengl.org/registry/specs/ARB/debug_output.txt
+glGetDetailTexFuncSGIS https://www.opengl.org/registry/specs/SGIS/detail_texture.txt
+glGetDoubleIndexedvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetDoublei_v https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glGetDoublei_vEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetDoublev https://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
+glGetDoublev https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
+glGetDoublev https://www.opengl.org/sdk/docs/man4/html/glGet.xhtml
+glGetError https://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml
+glGetError https://www.opengl.org/sdk/docs/man3/xhtml/glGetError.xml
+glGetError https://www.opengl.org/sdk/docs/man4/html/glGetError.xhtml
+glGetFenceivNV https://www.opengl.org/registry/specs/NV/fence.txt
+glGetFinalCombinerInputParameterfvNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glGetFinalCombinerInputParameterivNV https://www.opengl.org/registry/specs/NV/register_combiners.txt
+glGetFixedvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetFloatIndexedvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetFloati_v https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glGetFloati_vEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetFloatv https://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
+glGetFloatv https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
+glGetFloatv https://www.opengl.org/sdk/docs/man4/html/glGet.xhtml
+glGetFogFuncSGIS https://www.opengl.org/registry/specs/SGIS/fog_func.txt
+glGetFragDataIndex https://www.opengl.org/registry/specs/ARB/blend_func_extended.txt
+glGetFragDataIndex https://www.opengl.org/sdk/docs/man3/xhtml/glGetFragDataIndex.xml
+glGetFragDataIndex https://www.opengl.org/sdk/docs/man4/html/glGetFragDataIndex.xhtml
+glGetFragDataLocation https://www.opengl.org/sdk/docs/man3/xhtml/glGetFragDataLocation.xml
+glGetFragDataLocation https://www.opengl.org/sdk/docs/man4/html/glGetFragDataLocation.xhtml
+glGetFragDataLocationEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glGetFragmentLightfvEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glGetFragmentLightfvSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glGetFragmentLightivEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glGetFragmentLightivSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glGetFragmentMaterialfvEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glGetFragmentMaterialfvSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glGetFragmentMaterialivEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glGetFragmentMaterialivSGIX https://www.opengl.org/registry/specs/SGIX/fragment_specular_lighting.txt
+glGetFramebufferAttachmentParameter https://www.opengl.org/sdk/docs/man3/xhtml/glGetFramebufferAttachmentParameter.xml
+glGetFramebufferAttachmentParameter https://www.opengl.org/sdk/docs/man4/html/glGetFramebufferAttachmentParameter.xhtml
+glGetFramebufferAttachmentParameteriv https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glGetFramebufferAttachmentParameterivEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glGetFramebufferParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetGraphicsResetStatusARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetHandleARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetHistogram https://www.opengl.org/sdk/docs/man/xhtml/glGetHistogram.xml
+glGetHistogramEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glGetHistogramParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glGetHistogramParameter.xml
+glGetHistogramParameterfvEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glGetHistogramParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glGetHistogramParameter.xml
+glGetHistogramParameterivEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glGetHistogramParameterxvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetImageTransformParameterfvHP https://www.opengl.org/registry/specs/HP/image_transform.txt
+glGetImageTransformParameterivHP https://www.opengl.org/registry/specs/HP/image_transform.txt
+glGetInfoLogARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetInstrumentsSGIX https://www.opengl.org/registry/specs/SGIX/instruments.txt
+glGetInteger64i_v https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
+glGetInteger64i_v https://www.opengl.org/sdk/docs/man4/html/glGet.xhtml
+glGetInteger64v https://www.opengl.org/registry/specs/ARB/sync.txt
+glGetInteger64v https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
+glGetInteger64v https://www.opengl.org/sdk/docs/man4/html/glGet.xhtml
+glGetIntegerIndexedivEXT https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glGetIntegerIndexedvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetIntegerIndexedvEXT https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
+glGetIntegerIndexedvEXT https://www.opengl.org/registry/specs/EXT/transform_feedback.txt
+glGetIntegerIndexedvEXT https://www.opengl.org/registry/specs/NV/explicit_multisample.txt
+glGetIntegerIndexedvEXT https://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
+glGetIntegerIndexedvEXT https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glGetIntegeri_v https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glGetIntegeri_v https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
+glGetIntegeri_v https://www.opengl.org/sdk/docs/man4/html/glGet.xhtml
+glGetIntegerui64i_vNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glGetIntegerui64vNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glGetIntegerv https://www.opengl.org/registry/specs/SGIX/instruments.txt
+glGetIntegerv https://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
+glGetIntegerv https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml
+glGetIntegerv https://www.opengl.org/sdk/docs/man4/html/glGet.xhtml
+glGetInternalformativ https://www.opengl.org/registry/specs/ARB/internalformat_query.txt
+glGetLightfv https://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml
+glGetLightiv https://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml
+glGetLightxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetListParameterfvSGIX https://www.opengl.org/registry/specs/SGIX/list_priority.txt
+glGetListParameterivSGIX https://www.opengl.org/registry/specs/SGIX/list_priority.txt
+glGetMapAttribParameterfvNV https://www.opengl.org/registry/specs/NV/evaluators.txt
+glGetMapAttribParameterivNV https://www.opengl.org/registry/specs/NV/evaluators.txt
+glGetMapControlPointsNV https://www.opengl.org/registry/specs/NV/evaluators.txt
+glGetMapParameterfvNV https://www.opengl.org/registry/specs/NV/evaluators.txt
+glGetMapParameterivNV https://www.opengl.org/registry/specs/NV/evaluators.txt
+glGetMapdv https://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml
+glGetMapfv https://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml
+glGetMapiv https://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml
+glGetMapxvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetMaterialfv https://www.opengl.org/sdk/docs/man/xhtml/glGetMaterial.xml
+glGetMaterialiv https://www.opengl.org/sdk/docs/man/xhtml/glGetMaterial.xml
+glGetMaterialxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetMinmax https://www.opengl.org/sdk/docs/man/xhtml/glGetMinmax.xml
+glGetMinmaxEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glGetMinmaxParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glGetMinmaxParameter.xml
+glGetMinmaxParameterfvEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glGetMinmaxParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glGetMinmaxParameter.xml
+glGetMinmaxParameterivEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glGetMultiTexEnvfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexEnvivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexGendvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexGenfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexGenivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexImageEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexLevelParameterfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexLevelParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexParameterIivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexParameterIuivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexParameterfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultiTexParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetMultisamplefv https://www.opengl.org/registry/specs/ARB/texture_multisample.txt
+glGetMultisamplefv https://www.opengl.org/sdk/docs/man3/xhtml/glGetMultisample.xml
+glGetMultisamplefv https://www.opengl.org/sdk/docs/man4/html/glGetMultisample.xhtml
+glGetMultisamplefvNV https://www.opengl.org/registry/specs/NV/explicit_multisample.txt
+glGetNamedBufferParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedBufferParameterui64vNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glGetNamedBufferPointervEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedBufferSubDataEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedFramebufferAttachmentParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedProgramLocalParameterIivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedProgramLocalParameterIuivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedProgramLocalParameterdvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedProgramLocalParameterfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedProgramStringEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedProgramivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedRenderbufferParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetNamedStringARB https://www.opengl.org/registry/specs/ARB/shading_language_include.txt
+glGetNamedStringivARB https://www.opengl.org/registry/specs/ARB/shading_language_include.txt
+glGetObjectBufferfvATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glGetObjectBufferivATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glGetObjectParameterfvARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetObjectParameterivAPPLE https://www.opengl.org/registry/specs/APPLE/object_purgeable.txt
+glGetObjectParameterivARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetOcclusionQueryivNV https://www.opengl.org/registry/specs/NV/occlusion_query.txt
+glGetOcclusionQueryuivNV https://www.opengl.org/registry/specs/NV/occlusion_query.txt
+glGetPathColorGenfvNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathColorGenivNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathCommandsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathCoordsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathDashArrayNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathLengthNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathMetricRangeNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathMetricsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathParameterfvNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathParameterivNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathSpacingNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathTexGenfvNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPathTexGenivNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glGetPerfMonitorCounterDataAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glGetPerfMonitorCounterInfoAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glGetPerfMonitorCounterStringAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glGetPerfMonitorCountersAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glGetPerfMonitorGroupStringAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glGetPerfMonitorGroupsAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glGetPixelMapfv https://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml
+glGetPixelMapuiv https://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml
+glGetPixelMapusv https://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml
+glGetPixelTransformParameterfvEXT https://www.opengl.org/registry/specs/EXT/pixel_transform.txt
+glGetPixelTransformParameterivEXT https://www.opengl.org/registry/specs/EXT/pixel_transform.txt
+glGetPointerIndexedvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetPointeri_vEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetPointerv https://www.opengl.org/registry/specs/ARB/debug_output.txt
+glGetPointerv https://www.opengl.org/sdk/docs/man/xhtml/glGetPointerv.xml
+glGetPointervEXT https://www.opengl.org/registry/specs/EXT/vertex_array.txt
+glGetPointervEXT https://www.opengl.org/registry/specs/SGIX/instruments.txt
+glGetPolygonStipple https://www.opengl.org/sdk/docs/man/xhtml/glGetPolygonStipple.xml
+glGetProgramBinary https://www.opengl.org/registry/specs/ARB/get_program_binary.txt
+glGetProgramBinary https://www.opengl.org/sdk/docs/man4/html/glGetProgramBinary.xhtml
+glGetProgramEnvParameterIivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glGetProgramEnvParameterIuivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glGetProgramEnvParameterdvARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glGetProgramEnvParameterdvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetProgramEnvParameterfvARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glGetProgramEnvParameterfvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetProgramInfoLog https://www.opengl.org/sdk/docs/man/xhtml/glGetProgramInfoLog.xml
+glGetProgramInfoLog https://www.opengl.org/sdk/docs/man3/xhtml/glGetProgramInfoLog.xml
+glGetProgramInfoLog https://www.opengl.org/sdk/docs/man4/html/glGetProgramInfoLog.xhtml
+glGetProgramLocalParameterIivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glGetProgramLocalParameterIuivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glGetProgramLocalParameterdvARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glGetProgramLocalParameterdvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetProgramLocalParameterdvARB https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glGetProgramLocalParameterfvARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glGetProgramLocalParameterfvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetProgramLocalParameterfvARB https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glGetProgramNamedParameterdvNV https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glGetProgramNamedParameterfvNV https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glGetProgramParameterdvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGetProgramParameterfvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGetProgramPipelineInfoLog https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glGetProgramPipelineInfoLog https://www.opengl.org/sdk/docs/man4/html/glGetProgramPipelineInfoLog.xhtml
+glGetProgramPipelineiv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glGetProgramPipelineiv https://www.opengl.org/sdk/docs/man4/html/glGetProgramPipeline.xhtml
+glGetProgramStageiv https://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
+glGetProgramStageiv https://www.opengl.org/sdk/docs/man4/html/glGetProgramStage.xhtml
+glGetProgramStringARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glGetProgramStringARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetProgramStringNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGetProgramiv https://www.opengl.org/sdk/docs/man/xhtml/glGetProgram.xml
+glGetProgramiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetProgram.xml
+glGetProgramiv https://www.opengl.org/sdk/docs/man4/html/glGetProgram.xhtml
+glGetProgramivARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glGetProgramivARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetProgramivNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGetQueryIndexediv https://www.opengl.org/registry/specs/ARB/transform_feedback3.txt
+glGetQueryIndexediv https://www.opengl.org/sdk/docs/man4/html/glGetQueryIndexed.xhtml
+glGetQueryObjecti64v https://www.opengl.org/registry/specs/ARB/timer_query.txt
+glGetQueryObjecti64v https://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryObject.xml
+glGetQueryObjecti64v https://www.opengl.org/sdk/docs/man4/html/glGetQueryObject.xhtml
+glGetQueryObjecti64vEXT https://www.opengl.org/registry/specs/EXT/timer_query.txt
+glGetQueryObjectiv https://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObject.xml
+glGetQueryObjectiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryObject.xml
+glGetQueryObjectiv https://www.opengl.org/sdk/docs/man4/html/glGetQueryObject.xhtml
+glGetQueryObjectivARB https://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+glGetQueryObjectui64v https://www.opengl.org/registry/specs/ARB/timer_query.txt
+glGetQueryObjectui64v https://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryObject.xml
+glGetQueryObjectui64v https://www.opengl.org/sdk/docs/man4/html/glGetQueryObject.xhtml
+glGetQueryObjectui64vEXT https://www.opengl.org/registry/specs/EXT/timer_query.txt
+glGetQueryObjectuiv https://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObject.xml
+glGetQueryObjectuiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryObject.xml
+glGetQueryObjectuiv https://www.opengl.org/sdk/docs/man4/html/glGetQueryObject.xhtml
+glGetQueryObjectuivARB https://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+glGetQueryiv https://www.opengl.org/sdk/docs/man/xhtml/glGetQueryiv.xml
+glGetQueryiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetQueryiv.xml
+glGetQueryiv https://www.opengl.org/sdk/docs/man4/html/glGetQueryiv.xhtml
+glGetQueryivARB https://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+glGetRenderbufferParameteriv https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glGetRenderbufferParameteriv https://www.opengl.org/sdk/docs/man3/xhtml/glGetRenderbufferParameter.xml
+glGetRenderbufferParameteriv https://www.opengl.org/sdk/docs/man4/html/glGetRenderbufferParameter.xhtml
+glGetRenderbufferParameterivEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glGetSamplerParameterIiv https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glGetSamplerParameterIuiv https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glGetSamplerParameterfv https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glGetSamplerParameterfv https://www.opengl.org/sdk/docs/man3/xhtml/glGetSamplerParameter.xml
+glGetSamplerParameterfv https://www.opengl.org/sdk/docs/man4/html/glGetSamplerParameter.xhtml
+glGetSamplerParameteriv https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glGetSamplerParameteriv https://www.opengl.org/sdk/docs/man3/xhtml/glGetSamplerParameter.xml
+glGetSamplerParameteriv https://www.opengl.org/sdk/docs/man4/html/glGetSamplerParameter.xhtml
+glGetSeparableFilter https://www.opengl.org/sdk/docs/man/xhtml/glGetSeparableFilter.xml
+glGetSeparableFilterEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glGetShaderInfoLog https://www.opengl.org/sdk/docs/man/xhtml/glGetShaderInfoLog.xml
+glGetShaderInfoLog https://www.opengl.org/sdk/docs/man3/xhtml/glGetShaderInfoLog.xml
+glGetShaderInfoLog https://www.opengl.org/sdk/docs/man4/html/glGetShaderInfoLog.xhtml
+glGetShaderPrecisionFormat https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
+glGetShaderPrecisionFormat https://www.opengl.org/sdk/docs/man4/html/glGetShaderPrecisionFormat.xhtml
+glGetShaderSource https://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSource.xml
+glGetShaderSource https://www.opengl.org/sdk/docs/man3/xhtml/glGetShaderSource.xml
+glGetShaderSource https://www.opengl.org/sdk/docs/man4/html/glGetShaderSource.xhtml
+glGetShaderSourceARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetShaderiv https://www.opengl.org/sdk/docs/man/xhtml/glGetShader.xml
+glGetShaderiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetShader.xml
+glGetShaderiv https://www.opengl.org/sdk/docs/man4/html/glGetShader.xhtml
+glGetSharpenTexFuncSGIS https://www.opengl.org/registry/specs/SGIS/sharpen_texture.txt
+glGetString https://www.opengl.org/sdk/docs/man/xhtml/glGetString.xml
+glGetString https://www.opengl.org/sdk/docs/man3/xhtml/glGetString.xml
+glGetString https://www.opengl.org/sdk/docs/man4/html/glGetString.xhtml
+glGetStringi https://www.opengl.org/sdk/docs/man3/xhtml/glGetString.xml
+glGetStringi https://www.opengl.org/sdk/docs/man4/html/glGetString.xhtml
+glGetSubroutineIndex https://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
+glGetSubroutineIndex https://www.opengl.org/sdk/docs/man4/html/glGetSubroutineIndex.xhtml
+glGetSubroutineUniformLocation https://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
+glGetSubroutineUniformLocation https://www.opengl.org/sdk/docs/man4/html/glGetSubroutineUniformLocation.xhtml
+glGetSynciv https://www.opengl.org/registry/specs/ARB/sync.txt
+glGetSynciv https://www.opengl.org/sdk/docs/man3/xhtml/glGetSync.xml
+glGetSynciv https://www.opengl.org/sdk/docs/man4/html/glGetSync.xhtml
+glGetTexEnvfv https://www.opengl.org/sdk/docs/man/xhtml/glGetTexEnv.xml
+glGetTexEnviv https://www.opengl.org/sdk/docs/man/xhtml/glGetTexEnv.xml
+glGetTexEnvxvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetTexFilterFuncSGIS https://www.opengl.org/registry/specs/SGIS/texture_filter4.txt
+glGetTexGendv https://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml
+glGetTexGenfv https://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml
+glGetTexGeniv https://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml
+glGetTexGenxvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetTexImage https://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml
+glGetTexImage https://www.opengl.org/sdk/docs/man3/xhtml/glGetTexImage.xml
+glGetTexImage https://www.opengl.org/sdk/docs/man4/html/glGetTexImage.xhtml
+glGetTexLevelParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glGetTexLevelParameter.xml
+glGetTexLevelParameterfv https://www.opengl.org/sdk/docs/man3/xhtml/glGetTexLevelParameter.xml
+glGetTexLevelParameterfv https://www.opengl.org/sdk/docs/man4/html/glGetTexLevelParameter.xhtml
+glGetTexLevelParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glGetTexLevelParameter.xml
+glGetTexLevelParameteriv https://www.opengl.org/sdk/docs/man3/xhtml/glGetTexLevelParameter.xml
+glGetTexLevelParameteriv https://www.opengl.org/sdk/docs/man4/html/glGetTexLevelParameter.xhtml
+glGetTexLevelParameterxvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetTexParameterPointervAPPLE https://www.opengl.org/registry/specs/APPLE/texture_range.txt
+glGetTexParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameter.xml
+glGetTexParameterfv https://www.opengl.org/sdk/docs/man3/xhtml/glGetTexParameter.xml
+glGetTexParameterfv https://www.opengl.org/sdk/docs/man4/html/glGetTexParameter.xhtml
+glGetTexParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameter.xml
+glGetTexParameteriv https://www.opengl.org/sdk/docs/man3/xhtml/glGetTexParameter.xml
+glGetTexParameteriv https://www.opengl.org/sdk/docs/man4/html/glGetTexParameter.xhtml
+glGetTexParameterxvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glGetTextureImageEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetTextureLevelParameterfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetTextureLevelParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetTextureParameterIivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetTextureParameterIuivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetTextureParameterfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetTextureParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetTrackMatrixivNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGetTransformFeedbackVarying https://www.opengl.org/sdk/docs/man3/xhtml/glGetTransformFeedbackVarying.xml
+glGetTransformFeedbackVarying https://www.opengl.org/sdk/docs/man4/html/glGetTransformFeedbackVarying.xhtml
+glGetTransformFeedbackVaryingEXT https://www.opengl.org/registry/specs/EXT/transform_feedback.txt
+glGetTransformFeedbackVaryingNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glGetUniformBlockIndex https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glGetUniformBlockIndex https://www.opengl.org/sdk/docs/man3/xhtml/glGetUniformBlockIndex.xml
+glGetUniformBlockIndex https://www.opengl.org/sdk/docs/man4/html/glGetUniformBlockIndex.xhtml
+glGetUniformBufferSizeEXT https://www.opengl.org/registry/specs/EXT/bindable_uniform.txt
+glGetUniformIndices https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glGetUniformIndices https://www.opengl.org/sdk/docs/man3/xhtml/glGetUniformIndices.xml
+glGetUniformIndices https://www.opengl.org/sdk/docs/man4/html/glGetUniformIndices.xhtml
+glGetUniformLocation https://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocation.xml
+glGetUniformLocation https://www.opengl.org/sdk/docs/man3/xhtml/glGetUniformLocation.xml
+glGetUniformLocation https://www.opengl.org/sdk/docs/man4/html/glGetUniformLocation.xhtml
+glGetUniformLocationARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetUniformOffsetEXT https://www.opengl.org/registry/specs/EXT/bindable_uniform.txt
+glGetUniformSubroutineuiv https://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
+glGetUniformSubroutineuiv https://www.opengl.org/sdk/docs/man4/html/glGetUniformSubroutine.xhtml
+glGetUniformdv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glGetUniformfv https://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml
+glGetUniformfv https://www.opengl.org/sdk/docs/man3/xhtml/glGetUniform.xml
+glGetUniformfv https://www.opengl.org/sdk/docs/man4/html/glGetUniform.xhtml
+glGetUniformfvARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetUniformi64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glGetUniformiv https://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml
+glGetUniformiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetUniform.xml
+glGetUniformiv https://www.opengl.org/sdk/docs/man4/html/glGetUniform.xhtml
+glGetUniformivARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glGetUniformui64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glGetUniformui64vNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glGetUniformuivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glGetVariantArrayObjectfvATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glGetVariantArrayObjectivATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glGetVaryingLocationNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glGetVertexArrayIntegeri_vEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetVertexArrayIntegervEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetVertexArrayPointeri_vEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetVertexArrayPointervEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glGetVertexAttribArrayObjectfvATI https://www.opengl.org/registry/specs/ATI/vertex_attrib_array_object.txt
+glGetVertexAttribArrayObjectivATI https://www.opengl.org/registry/specs/ATI/vertex_attrib_array_object.txt
+glGetVertexAttribIiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
+glGetVertexAttribIiv https://www.opengl.org/sdk/docs/man4/html/glGetVertexAttrib.xhtml
+glGetVertexAttribIivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glGetVertexAttribIivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glGetVertexAttribIuiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
+glGetVertexAttribIuiv https://www.opengl.org/sdk/docs/man4/html/glGetVertexAttrib.xhtml
+glGetVertexAttribIuivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glGetVertexAttribIuivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glGetVertexAttribLdv https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glGetVertexAttribLdv https://www.opengl.org/sdk/docs/man4/html/glGetVertexAttrib.xhtml
+glGetVertexAttribLdvEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glGetVertexAttribLi64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glGetVertexAttribLui64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glGetVertexAttribPointerv https://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribPointerv.xml
+glGetVertexAttribPointerv https://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttribPointerv.xml
+glGetVertexAttribPointerv https://www.opengl.org/sdk/docs/man4/html/glGetVertexAttribPointerv.xhtml
+glGetVertexAttribPointervARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetVertexAttribPointervARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glGetVertexAttribPointervNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGetVertexAttribdv https://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml
+glGetVertexAttribdv https://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
+glGetVertexAttribdv https://www.opengl.org/sdk/docs/man4/html/glGetVertexAttrib.xhtml
+glGetVertexAttribdvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetVertexAttribdvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glGetVertexAttribdvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGetVertexAttribfv https://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml
+glGetVertexAttribfv https://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
+glGetVertexAttribfv https://www.opengl.org/sdk/docs/man4/html/glGetVertexAttrib.xhtml
+glGetVertexAttribfvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetVertexAttribfvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glGetVertexAttribfvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGetVertexAttribiv https://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml
+glGetVertexAttribiv https://www.opengl.org/sdk/docs/man3/xhtml/glGetVertexAttrib.xml
+glGetVertexAttribiv https://www.opengl.org/sdk/docs/man4/html/glGetVertexAttrib.xhtml
+glGetVertexAttribivARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glGetVertexAttribivARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glGetVertexAttribivNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glGetVideoCaptureivNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glGetVideoi64vNV https://www.opengl.org/registry/specs/NV/present_video.txt
+glGetVideoivNV https://www.opengl.org/registry/specs/NV/present_video.txt
+glGetVideoui64vNV https://www.opengl.org/registry/specs/NV/present_video.txt
+glGetVideouivNV https://www.opengl.org/registry/specs/NV/present_video.txt
+glGetnColorTableARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnCompressedTexImageARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnConvolutionFilterARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnHistogramARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnMapdvARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnMapfvARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnMapivARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnMinmaxARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnPixelMapfvARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnPixelMapuivARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnPixelMapusvARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnPolygonStippleARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnSeparableFilterARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnTexImageARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnUniformdvARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnUniformfvARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnUniformivARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGetnUniformuivARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glGlobalAlphaFactorbSUN https://www.opengl.org/registry/specs/SUN/global_alpha.txt
+glGlobalAlphaFactordSUN https://www.opengl.org/registry/specs/SUN/global_alpha.txt
+glGlobalAlphaFactorfSUN https://www.opengl.org/registry/specs/SUN/global_alpha.txt
+glGlobalAlphaFactoriSUN https://www.opengl.org/registry/specs/SUN/global_alpha.txt
+glGlobalAlphaFactorsSUN https://www.opengl.org/registry/specs/SUN/global_alpha.txt
+glGlobalAlphaFactorubSUN https://www.opengl.org/registry/specs/SUN/global_alpha.txt
+glGlobalAlphaFactoruiSUN https://www.opengl.org/registry/specs/SUN/global_alpha.txt
+glGlobalAlphaFactorusSUN https://www.opengl.org/registry/specs/SUN/global_alpha.txt
+glHint https://www.opengl.org/sdk/docs/man/xhtml/glHint.xml
+glHint https://www.opengl.org/sdk/docs/man3/xhtml/glHint.xml
+glHint https://www.opengl.org/sdk/docs/man4/html/glHint.xhtml
+glHistogram https://www.opengl.org/sdk/docs/man/xhtml/glHistogram.xml
+glHistogramEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glImageTransformParameterfHP https://www.opengl.org/registry/specs/HP/image_transform.txt
+glImageTransformParameterfvHP https://www.opengl.org/registry/specs/HP/image_transform.txt
+glImageTransformParameteriHP https://www.opengl.org/registry/specs/HP/image_transform.txt
+glImageTransformParameterivHP https://www.opengl.org/registry/specs/HP/image_transform.txt
+glImportSyncEXT https://www.opengl.org/registry/specs/EXT/x11_sync_object.txt
+glIndexFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glIndexMask https://www.opengl.org/sdk/docs/man/xhtml/glIndexMask.xml
+glIndexPointer https://www.opengl.org/sdk/docs/man/xhtml/glIndexPointer.xml
+glIndexPointerEXT https://www.opengl.org/registry/specs/EXT/vertex_array.txt
+glIndexd https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glIndexdv https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glIndexf https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glIndexfv https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glIndexi https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glIndexiv https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glIndexs https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glIndexsv https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glIndexub https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glIndexubv https://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml
+glInitNames https://www.opengl.org/sdk/docs/man/xhtml/glInitNames.xml
+glInstrumentsBufferSGIX https://www.opengl.org/registry/specs/SGIX/instruments.txt
+glInterleavedArrays https://www.opengl.org/sdk/docs/man/xhtml/glInterleavedArrays.xml
+glInterpolatePathsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glIsArraySetEXT https://www.opengl.org/registry/specs/EXT/vertex_array_set.txt
+glIsAsyncMarkerSGIX https://www.opengl.org/registry/specs/SGIX/async.txt
+glIsBuffer https://www.opengl.org/sdk/docs/man/xhtml/glIsBuffer.xml
+glIsBuffer https://www.opengl.org/sdk/docs/man3/xhtml/glIsBuffer.xml
+glIsBuffer https://www.opengl.org/sdk/docs/man4/html/glIsBuffer.xhtml
+glIsBufferARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glIsBufferResidentNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glIsEnabled https://www.opengl.org/sdk/docs/man/xhtml/glIsEnabled.xml
+glIsEnabled https://www.opengl.org/sdk/docs/man3/xhtml/glIsEnabled.xml
+glIsEnabled https://www.opengl.org/sdk/docs/man4/html/glIsEnabled.xhtml
+glIsEnabledIndexedEXT https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glIsEnabledIndexedEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glIsEnabledIndexedEXT https://www.opengl.org/registry/specs/EXT/draw_buffers2.txt
+glIsFenceAPPLE https://www.opengl.org/registry/specs/APPLE/fence.txt
+glIsFenceNV https://www.opengl.org/registry/specs/NV/fence.txt
+glIsFramebuffer https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glIsFramebuffer https://www.opengl.org/sdk/docs/man3/xhtml/glIsFramebuffer.xml
+glIsFramebuffer https://www.opengl.org/sdk/docs/man4/html/glIsFramebuffer.xhtml
+glIsFramebufferEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glIsList https://www.opengl.org/sdk/docs/man/xhtml/glIsList.xml
+glIsNameAMD https://www.opengl.org/registry/specs/AMD/name_gen_delete.txt
+glIsNamedBufferResidentNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glIsNamedStringARB https://www.opengl.org/registry/specs/ARB/shading_language_include.txt
+glIsObjectBufferATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glIsOcclusionQueryNV https://www.opengl.org/registry/specs/NV/occlusion_query.txt
+glIsPathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glIsPointInFillPathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glIsPointInStrokePathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glIsProgram https://www.opengl.org/sdk/docs/man/xhtml/glIsProgram.xml
+glIsProgram https://www.opengl.org/sdk/docs/man3/xhtml/glIsProgram.xml
+glIsProgram https://www.opengl.org/sdk/docs/man4/html/glIsProgram.xhtml
+glIsProgramARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glIsProgramARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glIsProgramNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glIsProgramPipeline https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glIsProgramPipeline https://www.opengl.org/sdk/docs/man4/html/glIsProgramPipeline.xhtml
+glIsQuery https://www.opengl.org/sdk/docs/man/xhtml/glIsQuery.xml
+glIsQuery https://www.opengl.org/sdk/docs/man3/xhtml/glIsQuery.xml
+glIsQuery https://www.opengl.org/sdk/docs/man4/html/glIsQuery.xhtml
+glIsQueryARB https://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+glIsRenderbuffer https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glIsRenderbuffer https://www.opengl.org/sdk/docs/man3/xhtml/glIsRenderbuffer.xml
+glIsRenderbuffer https://www.opengl.org/sdk/docs/man4/html/glIsRenderbuffer.xhtml
+glIsRenderbufferEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glIsSampler https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glIsSampler https://www.opengl.org/sdk/docs/man3/xhtml/glIsSampler.xml
+glIsSampler https://www.opengl.org/sdk/docs/man4/html/glIsSampler.xhtml
+glIsShader https://www.opengl.org/sdk/docs/man/xhtml/glIsShader.xml
+glIsShader https://www.opengl.org/sdk/docs/man3/xhtml/glIsShader.xml
+glIsShader https://www.opengl.org/sdk/docs/man4/html/glIsShader.xhtml
+glIsSync https://www.opengl.org/registry/specs/ARB/sync.txt
+glIsSync https://www.opengl.org/sdk/docs/man3/xhtml/glIsSync.xml
+glIsSync https://www.opengl.org/sdk/docs/man4/html/glIsSync.xhtml
+glIsTexture https://www.opengl.org/sdk/docs/man/xhtml/glIsTexture.xml
+glIsTexture https://www.opengl.org/sdk/docs/man3/xhtml/glIsTexture.xml
+glIsTexture https://www.opengl.org/sdk/docs/man4/html/glIsTexture.xhtml
+glIsTextureEXT https://www.opengl.org/registry/specs/EXT/texture_object.txt
+glIsTransformFeedback https://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
+glIsTransformFeedback https://www.opengl.org/sdk/docs/man4/html/glIsTransformFeedback.xhtml
+glIsTransformFeedbackNV https://www.opengl.org/registry/specs/NV/transform_feedback2.txt
+glIsVertexArray https://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
+glIsVertexArray https://www.opengl.org/sdk/docs/man3/xhtml/glIsVertexArray.xml
+glIsVertexArray https://www.opengl.org/sdk/docs/man4/html/glIsVertexArray.xhtml
+glIsVertexArrayAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_array_object.txt
+glIsVertexAttribEnabledAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
+glJoinSwapGroupSGIX https://www.opengl.org/registry/specs/SGIX/swap_group.txt
+glLightEnviEXT https://www.opengl.org/registry/specs/EXT/fragment_lighting.txt
+glLightModelf https://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
+glLightModelfv https://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
+glLightModeli https://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
+glLightModeliv https://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
+glLightf https://www.opengl.org/sdk/docs/man/xhtml/glLight.xml
+glLightfv https://www.opengl.org/sdk/docs/man/xhtml/glLight.xml
+glLighti https://www.opengl.org/sdk/docs/man/xhtml/glLight.xml
+glLightiv https://www.opengl.org/sdk/docs/man/xhtml/glLight.xml
+glLineStipple https://www.opengl.org/sdk/docs/man/xhtml/glLineStipple.xml
+glLineWidth https://www.opengl.org/sdk/docs/man/xhtml/glLineWidth.xml
+glLineWidth https://www.opengl.org/sdk/docs/man3/xhtml/glLineWidth.xml
+glLineWidth https://www.opengl.org/sdk/docs/man4/html/glLineWidth.xhtml
+glLineWidthxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glLinkProgram https://www.opengl.org/sdk/docs/man/xhtml/glLinkProgram.xml
+glLinkProgram https://www.opengl.org/sdk/docs/man3/xhtml/glLinkProgram.xml
+glLinkProgram https://www.opengl.org/sdk/docs/man4/html/glLinkProgram.xhtml
+glLinkProgramARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glListBase https://www.opengl.org/sdk/docs/man/xhtml/glListBase.xml
+glListParameterfSGIX https://www.opengl.org/registry/specs/SGIX/list_priority.txt
+glListParameterfvSGIX https://www.opengl.org/registry/specs/SGIX/list_priority.txt
+glListParameteriSGIX https://www.opengl.org/registry/specs/SGIX/list_priority.txt
+glListParameterivSGIX https://www.opengl.org/registry/specs/SGIX/list_priority.txt
+glLoadIdentity https://www.opengl.org/sdk/docs/man/xhtml/glLoadIdentity.xml
+glLoadMatrixd https://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml
+glLoadMatrixf https://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml
+glLoadMatrixxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glLoadName https://www.opengl.org/sdk/docs/man/xhtml/glLoadName.xml
+glLoadProgramNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glLoadTransposeMatrixd https://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrix.xml
+glLoadTransposeMatrixf https://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrix.xml
+glLoadTransposeMatrixxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glLogicOp https://www.opengl.org/sdk/docs/man/xhtml/glLogicOp.xml
+glLogicOp https://www.opengl.org/sdk/docs/man3/xhtml/glLogicOp.xml
+glLogicOp https://www.opengl.org/sdk/docs/man4/html/glLogicOp.xhtml
+glMakeBufferNonResidentNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glMakeBufferResidentNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glMakeNamedBufferNonResidentNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glMakeNamedBufferResidentNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glMap1d https://www.opengl.org/sdk/docs/man/xhtml/glMap1.xml
+glMap1f https://www.opengl.org/sdk/docs/man/xhtml/glMap1.xml
+glMap1xOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glMap2d https://www.opengl.org/sdk/docs/man/xhtml/glMap2.xml
+glMap2f https://www.opengl.org/sdk/docs/man/xhtml/glMap2.xml
+glMap2xOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glMapBuffer https://www.opengl.org/sdk/docs/man/xhtml/glMapBuffer.xml
+glMapBuffer https://www.opengl.org/sdk/docs/man3/xhtml/glMapBuffer.xml
+glMapBuffer https://www.opengl.org/sdk/docs/man4/html/glMapBuffer.xhtml
+glMapBufferRange https://www.opengl.org/sdk/docs/man3/xhtml/glMapBufferRange.xml
+glMapBufferRange https://www.opengl.org/sdk/docs/man4/html/glMapBufferRange.xhtml
+glMapControlPointsNV https://www.opengl.org/registry/specs/NV/evaluators.txt
+glMapGrid1d https://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml
+glMapGrid1f https://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml
+glMapGrid1xOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glMapGrid2d https://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml
+glMapGrid2f https://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml
+glMapGrid2xOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glMapNamedBufferEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMapParameterfvNV https://www.opengl.org/registry/specs/NV/evaluators.txt
+glMapParameterivNV https://www.opengl.org/registry/specs/NV/evaluators.txt
+glMapVertexAttrib1dAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
+glMapVertexAttrib1fAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
+glMapVertexAttrib2dAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
+glMapVertexAttrib2fAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_program_evaluators.txt
+glMaterialf https://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml
+glMaterialfv https://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml
+glMateriali https://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml
+glMaterialiv https://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml
+glMatrixFrustumEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixIndexPointerARB https://www.opengl.org/registry/specs/ARB/matrix_palette.txt
+glMatrixLoadIdentityEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixLoadTransposedEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixLoadTransposefEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixLoaddEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixLoadfEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixMode https://www.opengl.org/sdk/docs/man/xhtml/glMatrixMode.xml
+glMatrixMultTransposedEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixMultTransposefEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixMultdEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixMultfEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixOrthoEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixPopEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixPushEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixRotatedEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixRotatefEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixScaledEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixScalefEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixTranslatedEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMatrixTranslatefEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMemoryBarrier https://www.opengl.org/registry/specs/ARB/shader_image_load_store.txt
+glMemoryBarrierEXT https://www.opengl.org/registry/specs/EXT/shader_image_load_store.txt
+glMinSampleShading https://www.opengl.org/sdk/docs/man4/html/glMinSampleShading.xhtml
+glMinSampleShadingARB https://www.opengl.org/registry/specs/ARB/sample_shading.txt
+glMinmax https://www.opengl.org/sdk/docs/man/xhtml/glMinmax.xml
+glMinmaxEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glMultMatrixd https://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml
+glMultMatrixf https://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml
+glMultMatrixxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glMultTransposeMatrixd https://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrix.xml
+glMultTransposeMatrixf https://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrix.xml
+glMultTransposeMatrixxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glMultiDrawArrays https://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawArrays.xml
+glMultiDrawArrays https://www.opengl.org/sdk/docs/man3/xhtml/glMultiDrawArrays.xml
+glMultiDrawArrays https://www.opengl.org/sdk/docs/man4/html/glMultiDrawArrays.xhtml
+glMultiDrawArraysEXT https://www.opengl.org/registry/specs/EXT/multi_draw_arrays.txt
+glMultiDrawArraysIndirectAMD https://www.opengl.org/registry/specs/AMD/multi_draw_indirect.txt
+glMultiDrawElementArrayAPPLE https://www.opengl.org/registry/specs/APPLE/element_array.txt
+glMultiDrawElements https://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawElements.xml
+glMultiDrawElements https://www.opengl.org/sdk/docs/man3/xhtml/glMultiDrawElements.xml
+glMultiDrawElements https://www.opengl.org/sdk/docs/man4/html/glMultiDrawElements.xhtml
+glMultiDrawElementsBaseVertex https://www.opengl.org/registry/specs/ARB/draw_elements_base_vertex.txt
+glMultiDrawElementsBaseVertex https://www.opengl.org/sdk/docs/man3/xhtml/glMultiDrawElementsBaseVertex.xml
+glMultiDrawElementsBaseVertex https://www.opengl.org/sdk/docs/man4/html/glMultiDrawElementsBaseVertex.xhtml
+glMultiDrawElementsEXT https://www.opengl.org/registry/specs/EXT/multi_draw_arrays.txt
+glMultiDrawElementsIndirectAMD https://www.opengl.org/registry/specs/AMD/multi_draw_indirect.txt
+glMultiDrawRangeElementArrayAPPLE https://www.opengl.org/registry/specs/APPLE/element_array.txt
+glMultiModeDrawArraysIBM https://www.opengl.org/registry/specs/IBM/multimode_draw_arrays.txt
+glMultiModeDrawElementsIBM https://www.opengl.org/registry/specs/IBM/multimode_draw_arrays.txt
+glMultiTexBufferEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexCoord1d https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord1dv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord1f https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord1fv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord1hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glMultiTexCoord1hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glMultiTexCoord1i https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord1iv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord1s https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord1sv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord2d https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord2dv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord2f https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord2fv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord2hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glMultiTexCoord2hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glMultiTexCoord2i https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord2iv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord2s https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord2sv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord3d https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord3dv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord3f https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord3fv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord3hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glMultiTexCoord3hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glMultiTexCoord3i https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord3iv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord3s https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord3sv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord4d https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord4dv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord4f https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord4fv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord4hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glMultiTexCoord4hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glMultiTexCoord4i https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord4iv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord4s https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoord4sv https://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml
+glMultiTexCoordP1ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glMultiTexCoordP1uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glMultiTexCoordP2ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glMultiTexCoordP2uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glMultiTexCoordP3ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glMultiTexCoordP3uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glMultiTexCoordP4ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glMultiTexCoordP4uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glMultiTexCoordPointerEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexEnvfEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexEnvfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexEnviEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexEnvivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexGendEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexGendvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexGenfEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexGenfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexGeniEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexGenivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexParameterIivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexParameterIuivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexParameterfEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexParameterfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexParameteriEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexRenderbufferEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexSubImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexSubImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glMultiTexSubImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedBufferDataEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedBufferSubDataEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedCopyBufferSubDataEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedFramebufferRenderbufferEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedFramebufferTexture1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedFramebufferTexture2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedFramebufferTexture3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedFramebufferTextureEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedFramebufferTextureFaceEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedFramebufferTextureLayerEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParameter4dEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParameter4dvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParameter4fEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParameter4fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParameterI4iEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParameterI4ivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParameterI4uiEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParameterI4uivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParameters4fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParametersI4ivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramLocalParametersI4uivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedProgramStringEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedRenderbufferStorageEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedRenderbufferStorageMultisampleCoverageEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedRenderbufferStorageMultisampleEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glNamedStringARB https://www.opengl.org/registry/specs/ARB/shading_language_include.txt
+glNewList https://www.opengl.org/sdk/docs/man/xhtml/glNewList.xml
+glNewObjectBufferATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glNormal3b https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormal3bv https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormal3d https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormal3dv https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormal3f https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormal3fVertex3fSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glNormal3fVertex3fvSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glNormal3fv https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormal3hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glNormal3hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glNormal3i https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormal3iv https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormal3s https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormal3sv https://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
+glNormalFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glNormalP3ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glNormalP3uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glNormalPointer https://www.opengl.org/sdk/docs/man/xhtml/glNormalPointer.xml
+glNormalPointerEXT https://www.opengl.org/registry/specs/EXT/vertex_array.txt
+glNormalPointervINTEL https://www.opengl.org/registry/specs/INTEL/parallel_arrays.txt
+glObjectPurgeableAPPLE https://www.opengl.org/registry/specs/APPLE/object_purgeable.txt
+glObjectUnpurgeableAPPLE https://www.opengl.org/registry/specs/APPLE/object_purgeable.txt
+glOrtho https://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml
+glOrthofOES https://www.opengl.org/registry/specs/OES/OES_single_precision.txt
+glOrthoxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glPassThrough https://www.opengl.org/sdk/docs/man/xhtml/glPassThrough.xml
+glPassThroughxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glPatchParameterfv https://www.opengl.org/registry/specs/ARB/tessellation_shader.txt
+glPatchParameterfv https://www.opengl.org/sdk/docs/man4/html/glPatchParameter.xhtml
+glPatchParameteri https://www.opengl.org/registry/specs/ARB/tessellation_shader.txt
+glPatchParameteri https://www.opengl.org/sdk/docs/man4/html/glPatchParameter.xhtml
+glPathColorGenNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathCommandsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathCoordsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathCoverDepthFuncNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathDashArrayNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathFogGenNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathGlyphRangeNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathGlyphsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathParameterfNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathParameterfvNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathParameteriNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathParameterivNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathStencilDepthOffsetNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathStencilFuncNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathStringNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathSubCommandsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathSubCoordsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPathTexGenNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPauseTransformFeedback https://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
+glPauseTransformFeedback https://www.opengl.org/sdk/docs/man4/html/glPauseTransformFeedback.xhtml
+glPauseTransformFeedbackNV https://www.opengl.org/registry/specs/NV/transform_feedback2.txt
+glPixelDataRangeNV https://www.opengl.org/registry/specs/NV/pixel_data_range.txt
+glPixelMapfv https://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml
+glPixelMapuiv https://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml
+glPixelMapusv https://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml
+glPixelStoref https://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml
+glPixelStoref https://www.opengl.org/sdk/docs/man3/xhtml/glPixelStore.xml
+glPixelStoref https://www.opengl.org/sdk/docs/man4/html/glPixelStore.xhtml
+glPixelStorei https://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml
+glPixelStorei https://www.opengl.org/sdk/docs/man3/xhtml/glPixelStore.xml
+glPixelStorei https://www.opengl.org/sdk/docs/man4/html/glPixelStore.xhtml
+glPixelTexGenSGIX https://www.opengl.org/registry/specs/SGIX/sgix_pixel_texture.txt
+glPixelTransferf https://www.opengl.org/sdk/docs/man/xhtml/glPixelTransfer.xml
+glPixelTransferi https://www.opengl.org/sdk/docs/man/xhtml/glPixelTransfer.xml
+glPixelTransferxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glPixelTransformParameterfEXT https://www.opengl.org/registry/specs/EXT/pixel_transform.txt
+glPixelTransformParameterfvEXT https://www.opengl.org/registry/specs/EXT/pixel_transform.txt
+glPixelTransformParameteriEXT https://www.opengl.org/registry/specs/EXT/pixel_transform.txt
+glPixelTransformParameterivEXT https://www.opengl.org/registry/specs/EXT/pixel_transform.txt
+glPixelZoom https://www.opengl.org/sdk/docs/man/xhtml/glPixelZoom.xml
+glPixelZoomxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glPointAlongPathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glPointParameterf https://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml
+glPointParameterf https://www.opengl.org/sdk/docs/man3/xhtml/glPointParameter.xml
+glPointParameterf https://www.opengl.org/sdk/docs/man4/html/glPointParameter.xhtml
+glPointParameterfARB https://www.opengl.org/registry/specs/ARB/point_parameters.txt
+glPointParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml
+glPointParameterfv https://www.opengl.org/sdk/docs/man3/xhtml/glPointParameter.xml
+glPointParameterfv https://www.opengl.org/sdk/docs/man4/html/glPointParameter.xhtml
+glPointParameterfvARB https://www.opengl.org/registry/specs/ARB/point_parameters.txt
+glPointParameteri https://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml
+glPointParameteri https://www.opengl.org/sdk/docs/man3/xhtml/glPointParameter.xml
+glPointParameteri https://www.opengl.org/sdk/docs/man4/html/glPointParameter.xhtml
+glPointParameteriNV https://www.opengl.org/registry/specs/NV/point_sprite.txt
+glPointParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml
+glPointParameteriv https://www.opengl.org/sdk/docs/man3/xhtml/glPointParameter.xml
+glPointParameteriv https://www.opengl.org/sdk/docs/man4/html/glPointParameter.xhtml
+glPointParameterivNV https://www.opengl.org/registry/specs/NV/point_sprite.txt
+glPointParameterxvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glPointSize https://www.opengl.org/sdk/docs/man/xhtml/glPointSize.xml
+glPointSize https://www.opengl.org/sdk/docs/man3/xhtml/glPointSize.xml
+glPointSize https://www.opengl.org/sdk/docs/man4/html/glPointSize.xhtml
+glPointSizexOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glPollAsyncSGIX https://www.opengl.org/registry/specs/SGIX/async.txt
+glPollInstrumentsSGIX https://www.opengl.org/registry/specs/SGIX/instruments.txt
+glPolygonMode https://www.opengl.org/sdk/docs/man/xhtml/glPolygonMode.xml
+glPolygonMode https://www.opengl.org/sdk/docs/man3/xhtml/glPolygonMode.xml
+glPolygonMode https://www.opengl.org/sdk/docs/man4/html/glPolygonMode.xhtml
+glPolygonOffset https://www.opengl.org/sdk/docs/man/xhtml/glPolygonOffset.xml
+glPolygonOffset https://www.opengl.org/sdk/docs/man3/xhtml/glPolygonOffset.xml
+glPolygonOffset https://www.opengl.org/sdk/docs/man4/html/glPolygonOffset.xhtml
+glPolygonOffsetEXT https://www.opengl.org/registry/specs/EXT/polygon_offset.txt
+glPolygonOffsetxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glPolygonStipple https://www.opengl.org/sdk/docs/man/xhtml/glPolygonStipple.xml
+glPopAttrib https://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml
+glPopClientAttrib https://www.opengl.org/sdk/docs/man/xhtml/glPushClientAttrib.xml
+glPopMatrix https://www.opengl.org/sdk/docs/man/xhtml/glPushMatrix.xml
+glPopName https://www.opengl.org/sdk/docs/man/xhtml/glPushName.xml
+glPresentFrameDualFillNV https://www.opengl.org/registry/specs/NV/present_video.txt
+glPresentFrameKeyedNV https://www.opengl.org/registry/specs/NV/present_video.txt
+glPrimitiveRestartIndex https://www.opengl.org/sdk/docs/man3/xhtml/glPrimitiveRestartIndex.xml
+glPrimitiveRestartIndex https://www.opengl.org/sdk/docs/man4/html/glPrimitiveRestartIndex.xhtml
+glPrimitiveRestartIndexNV https://www.opengl.org/registry/specs/NV/primitive_restart.txt
+glPrimitiveRestartNV https://www.opengl.org/registry/specs/NV/primitive_restart.txt
+glPrioritizeTextures https://www.opengl.org/sdk/docs/man/xhtml/glPrioritizeTextures.xml
+glPrioritizeTexturesEXT https://www.opengl.org/registry/specs/EXT/texture_object.txt
+glPrioritizeTexturesxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glProgramBinary https://www.opengl.org/registry/specs/ARB/get_program_binary.txt
+glProgramBinary https://www.opengl.org/sdk/docs/man4/html/glProgramBinary.xhtml
+glProgramBufferParametersIivNV https://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
+glProgramBufferParametersIuivNV https://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
+glProgramBufferParametersfvNV https://www.opengl.org/registry/specs/NV/parameter_buffer_object.txt
+glProgramEnvParameter4dARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glProgramEnvParameter4dARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glProgramEnvParameter4dvARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glProgramEnvParameter4dvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glProgramEnvParameter4fARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glProgramEnvParameter4fARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glProgramEnvParameter4fvARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glProgramEnvParameter4fvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glProgramEnvParameterI4iNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramEnvParameterI4ivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramEnvParameterI4uiNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramEnvParameterI4uivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramEnvParametersI4ivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramEnvParametersI4uivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramLocalParameter4dARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glProgramLocalParameter4dARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glProgramLocalParameter4dARB https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glProgramLocalParameter4dvARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glProgramLocalParameter4dvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glProgramLocalParameter4dvARB https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glProgramLocalParameter4fARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glProgramLocalParameter4fARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glProgramLocalParameter4fARB https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glProgramLocalParameter4fvARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glProgramLocalParameter4fvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glProgramLocalParameter4fvARB https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glProgramLocalParameterI4iNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramLocalParameterI4ivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramLocalParameterI4uiNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramLocalParameterI4uivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramLocalParametersI4ivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramLocalParametersI4uivNV https://www.opengl.org/registry/specs/NV/gpu_program4.txt
+glProgramNamedParameter4dNV https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glProgramNamedParameter4dvNV https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glProgramNamedParameter4fNV https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glProgramNamedParameter4fvNV https://www.opengl.org/registry/specs/NV/fragment_program.txt
+glProgramParameter4dNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glProgramParameter4dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glProgramParameter4fNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glProgramParameter4fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glProgramParameteri https://www.opengl.org/registry/specs/ARB/get_program_binary.txt
+glProgramParameteri https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramParameteri https://www.opengl.org/sdk/docs/man4/html/glProgramParameter.xhtml
+glProgramParameteriARB https://www.opengl.org/registry/specs/ARB/geometry_shader4.txt
+glProgramParameteriEXT https://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
+glProgramParameters4dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glProgramParameters4fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glProgramStringARB https://www.opengl.org/registry/specs/ARB/fragment_program.txt
+glProgramStringARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glProgramUniform1d https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform1dEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniform1dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform1dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniform1f https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform1f https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform1fEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform1fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform1fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform1fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform1i https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform1i https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform1i64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform1i64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform1iEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform1iv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform1iv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform1ivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform1ui https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform1ui https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform1ui64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform1ui64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform1uiEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform1uiv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform1uiv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform1uivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform2d https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform2dEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniform2dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform2dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniform2f https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform2f https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform2fEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform2fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform2fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform2fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform2i https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform2i https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform2i64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform2i64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform2iEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform2iv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform2iv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform2ivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform2ui https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform2ui https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform2ui64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform2ui64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform2uiEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform2uiv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform2uiv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform2uivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform3d https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform3dEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniform3dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform3dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniform3f https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform3f https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform3fEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform3fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform3fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform3fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform3i https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform3i https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform3i64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform3i64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform3iEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform3iv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform3iv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform3ivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform3ui https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform3ui https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform3ui64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform3ui64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform3uiEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform3uiv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform3uiv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform3uivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform4d https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform4dEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniform4dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform4dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniform4f https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform4f https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform4fEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform4fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform4fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform4fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform4i https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform4i https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform4i64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform4i64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform4iEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform4iv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform4iv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform4ivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform4ui https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform4ui https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform4ui64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform4ui64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glProgramUniform4uiEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniform4uiv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniform4uiv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniform4uivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformMatrix2dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix2dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniformMatrix2fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix2fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniformMatrix2fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformMatrix2x3dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix2x3dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniformMatrix2x3fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix2x3fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniformMatrix2x3fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformMatrix2x4dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix2x4dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniformMatrix2x4fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix2x4fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniformMatrix2x4fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformMatrix3dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix3dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniformMatrix3fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix3fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniformMatrix3fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformMatrix3x2dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix3x2dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniformMatrix3x2fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix3x2fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniformMatrix3x2fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformMatrix3x4dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix3x4dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniformMatrix3x4fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix3x4fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniformMatrix3x4fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformMatrix4dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix4dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniformMatrix4fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix4fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniformMatrix4fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformMatrix4x2dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix4x2dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniformMatrix4x2fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix4x2fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniformMatrix4x2fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformMatrix4x3dv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix4x3dvEXT https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glProgramUniformMatrix4x3fv https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glProgramUniformMatrix4x3fv https://www.opengl.org/sdk/docs/man4/html/glProgramUniform.xhtml
+glProgramUniformMatrix4x3fvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glProgramUniformui64NV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glProgramUniformui64vNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glProgramVertexLimitNV https://www.opengl.org/registry/specs/NV/geometry_program4.txt
+glProvokingVertex https://www.opengl.org/registry/specs/ARB/provoking_vertex.txt
+glProvokingVertex https://www.opengl.org/sdk/docs/man3/xhtml/glProvokingVertex.xml
+glProvokingVertex https://www.opengl.org/sdk/docs/man4/html/glProvokingVertex.xhtml
+glProvokingVertexEXT https://www.opengl.org/registry/specs/EXT/provoking_vertex.txt
+glPushAttrib https://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml
+glPushClientAttrib https://www.opengl.org/sdk/docs/man/xhtml/glPushClientAttrib.xml
+glPushClientAttribDefaultEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glPushMatrix https://www.opengl.org/sdk/docs/man/xhtml/glPushMatrix.xml
+glPushName https://www.opengl.org/sdk/docs/man/xhtml/glPushName.xml
+glQueryCounter https://www.opengl.org/registry/specs/ARB/timer_query.txt
+glQueryCounter https://www.opengl.org/sdk/docs/man3/xhtml/glQueryCounter.xml
+glQueryCounter https://www.opengl.org/sdk/docs/man4/html/glQueryCounter.xhtml
+glQueryMatrixxOES https://www.opengl.org/registry/specs/OES/OES_query_matrix.txt
+glQueryMaxSwapBarriersSGIX https://www.opengl.org/registry/specs/SGIX/swap_barrier.txt
+glRasterPos2d https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos2dv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos2f https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos2fv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos2i https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos2iv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos2s https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos2sv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos3d https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos3dv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos3f https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos3fv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos3i https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos3iv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos3s https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos3sv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos4d https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos4dv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos4f https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos4fv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos4i https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos4iv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos4s https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glRasterPos4sv https://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml
+glReadBuffer https://www.opengl.org/sdk/docs/man/xhtml/glReadBuffer.xml
+glReadBuffer https://www.opengl.org/sdk/docs/man3/xhtml/glReadBuffer.xml
+glReadBuffer https://www.opengl.org/sdk/docs/man4/html/glReadBuffer.xhtml
+glReadInstrumentsSGIX https://www.opengl.org/registry/specs/SGIX/instruments.txt
+glReadPixels https://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml
+glReadPixels https://www.opengl.org/sdk/docs/man3/xhtml/glReadPixels.xml
+glReadPixels https://www.opengl.org/sdk/docs/man4/html/glReadPixels.xhtml
+glReadnPixelsARB https://www.opengl.org/registry/specs/ARB/robustness.txt
+glRectd https://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
+glRectdv https://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
+glRectf https://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
+glRectfv https://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
+glRecti https://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
+glRectiv https://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
+glRects https://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
+glRectsv https://www.opengl.org/sdk/docs/man/xhtml/glRect.xml
+glRectxOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glRectxvOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glReferencePlaneSGIX https://www.opengl.org/registry/specs/SGIX/reference_plane.txt
+glReleaseShaderCompiler https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
+glReleaseShaderCompiler https://www.opengl.org/sdk/docs/man4/html/glReleaseShaderCompiler.xhtml
+glRenderMode https://www.opengl.org/sdk/docs/man/xhtml/glRenderMode.xml
+glRenderbufferStorage https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glRenderbufferStorage https://www.opengl.org/sdk/docs/man3/xhtml/glRenderbufferStorage.xml
+glRenderbufferStorage https://www.opengl.org/sdk/docs/man4/html/glRenderbufferStorage.xhtml
+glRenderbufferStorageEXT https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
+glRenderbufferStorageMultisample https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+glRenderbufferStorageMultisample https://www.opengl.org/sdk/docs/man3/xhtml/glRenderbufferStorageMultisample.xml
+glRenderbufferStorageMultisample https://www.opengl.org/sdk/docs/man4/html/glRenderbufferStorageMultisample.xhtml
+glRenderbufferStorageMultisampleCoverageNV https://www.opengl.org/registry/specs/NV/framebuffer_multisample_coverage.txt
+glRenderbufferStorageMultisampleEXT https://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt
+glReplacementCodePointerSUN https://www.opengl.org/registry/specs/SUN/triangle_list.txt
+glReplacementCodeubSUN https://www.opengl.org/registry/specs/SUN/triangle_list.txt
+glReplacementCodeubvSUN https://www.opengl.org/registry/specs/SUN/triangle_list.txt
+glReplacementCodeuiSUN https://www.opengl.org/registry/specs/SUN/triangle_list.txt
+glReplacementCodeuivSUN https://www.opengl.org/registry/specs/SUN/triangle_list.txt
+glReplacementCodeusSUN https://www.opengl.org/registry/specs/SUN/triangle_list.txt
+glReplacementCodeusvSUN https://www.opengl.org/registry/specs/SUN/triangle_list.txt
+glRequestResidentProgramsNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glResetHistogram https://www.opengl.org/sdk/docs/man/xhtml/glResetHistogram.xml
+glResetHistogramEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glResetMinmax https://www.opengl.org/sdk/docs/man/xhtml/glResetMinmax.xml
+glResetMinmaxEXT https://www.opengl.org/registry/specs/EXT/histogram.txt
+glResizeBuffersMESA https://www.opengl.org/registry/specs/MESA/resize_buffers.txt
+glResumeTransformFeedback https://www.opengl.org/registry/specs/ARB/transform_feedback2.txt
+glResumeTransformFeedback https://www.opengl.org/sdk/docs/man4/html/glResumeTransformFeedback.xhtml
+glResumeTransformFeedbackNV https://www.opengl.org/registry/specs/NV/transform_feedback2.txt
+glRotated https://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml
+glRotatef https://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml
+glRotatexOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glSampleCoverage https://www.opengl.org/sdk/docs/man/xhtml/glSampleCoverage.xml
+glSampleCoverage https://www.opengl.org/sdk/docs/man3/xhtml/glSampleCoverage.xml
+glSampleCoverage https://www.opengl.org/sdk/docs/man4/html/glSampleCoverage.xhtml
+glSampleCoverageARB https://www.opengl.org/registry/specs/ARB/multisample.txt
+glSampleCoverageOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glSampleMaskEXT https://www.opengl.org/registry/specs/EXT/wgl_multisample.txt
+glSampleMaskIndexedNV https://www.opengl.org/registry/specs/NV/explicit_multisample.txt
+glSampleMaskSGIS https://www.opengl.org/registry/specs/SGIS/multisample.txt
+glSampleMaski https://www.opengl.org/registry/specs/ARB/texture_multisample.txt
+glSampleMaski https://www.opengl.org/sdk/docs/man3/xhtml/glSampleMaski.xml
+glSampleMaski https://www.opengl.org/sdk/docs/man4/html/glSampleMaski.xhtml
+glSamplePatternEXT https://www.opengl.org/registry/specs/EXT/wgl_multisample.txt
+glSamplePatternSGIS https://www.opengl.org/registry/specs/SGIS/multisample.txt
+glSamplerParameterIiv https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glSamplerParameterIuiv https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glSamplerParameterf https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glSamplerParameterf https://www.opengl.org/sdk/docs/man3/xhtml/glSamplerParameter.xml
+glSamplerParameterf https://www.opengl.org/sdk/docs/man4/html/glSamplerParameter.xhtml
+glSamplerParameterfv https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glSamplerParameterfv https://www.opengl.org/sdk/docs/man3/xhtml/glSamplerParameter.xml
+glSamplerParameterfv https://www.opengl.org/sdk/docs/man4/html/glSamplerParameter.xhtml
+glSamplerParameteri https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glSamplerParameteri https://www.opengl.org/sdk/docs/man3/xhtml/glSamplerParameter.xml
+glSamplerParameteri https://www.opengl.org/sdk/docs/man4/html/glSamplerParameter.xhtml
+glSamplerParameteriv https://www.opengl.org/registry/specs/ARB/sampler_objects.txt
+glSamplerParameteriv https://www.opengl.org/sdk/docs/man3/xhtml/glSamplerParameter.xml
+glSamplerParameteriv https://www.opengl.org/sdk/docs/man4/html/glSamplerParameter.xhtml
+glScaled https://www.opengl.org/sdk/docs/man/xhtml/glScale.xml
+glScalef https://www.opengl.org/sdk/docs/man/xhtml/glScale.xml
+glScalexOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glScissor https://www.opengl.org/sdk/docs/man/xhtml/glScissor.xml
+glScissor https://www.opengl.org/sdk/docs/man3/xhtml/glScissor.xml
+glScissor https://www.opengl.org/sdk/docs/man4/html/glScissor.xhtml
+glScissorArrayv https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glScissorArrayv https://www.opengl.org/sdk/docs/man4/html/glScissorArray.xhtml
+glScissorIndexed https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glScissorIndexed https://www.opengl.org/sdk/docs/man4/html/glScissorIndexed.xhtml
+glScissorIndexedv https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glScissorIndexedv https://www.opengl.org/sdk/docs/man4/html/glScissorIndexed.xhtml
+glSecondaryColor3b https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3bv https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3d https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3dv https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3f https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3fv https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glSecondaryColor3hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glSecondaryColor3i https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3iv https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3s https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3sv https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3ub https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3ubv https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3ui https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3uiv https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3us https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColor3usv https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml
+glSecondaryColorFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glSecondaryColorP3ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glSecondaryColorP3uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glSecondaryColorPointer https://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColorPointer.xml
+glSecondaryColorPointerEXT https://www.opengl.org/registry/specs/EXT/secondary_color.txt
+glSelectBuffer https://www.opengl.org/sdk/docs/man/xhtml/glSelectBuffer.xml
+glSelectPerfMonitorCountersAMD https://www.opengl.org/registry/specs/AMD/performance_monitor.txt
+glSeparableFilter2D https://www.opengl.org/sdk/docs/man/xhtml/glSeparableFilter2D.xml
+glSeparableFilter2DEXT https://www.opengl.org/registry/specs/EXT/convolution.txt
+glSetFenceAPPLE https://www.opengl.org/registry/specs/APPLE/fence.txt
+glSetFenceNV https://www.opengl.org/registry/specs/NV/fence.txt
+glSetMultisamplefvAMD https://www.opengl.org/registry/specs/AMD/sample_positions.txt
+glShadeModel https://www.opengl.org/sdk/docs/man/xhtml/glShadeModel.xml
+glShaderBinary https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
+glShaderBinary https://www.opengl.org/sdk/docs/man4/html/glShaderBinary.xhtml
+glShaderSource https://www.opengl.org/sdk/docs/man/xhtml/glShaderSource.xml
+glShaderSource https://www.opengl.org/sdk/docs/man3/xhtml/glShaderSource.xml
+glShaderSource https://www.opengl.org/sdk/docs/man4/html/glShaderSource.xhtml
+glShaderSourceARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glSharpenTexFuncSGIS https://www.opengl.org/registry/specs/SGIS/sharpen_texture.txt
+glSpriteParameterfSGIX https://www.opengl.org/registry/specs/SGIX/sprite.txt
+glSpriteParameterfvSGIX https://www.opengl.org/registry/specs/SGIX/sprite.txt
+glSpriteParameteriSGIX https://www.opengl.org/registry/specs/SGIX/sprite.txt
+glSpriteParameterivSGIX https://www.opengl.org/registry/specs/SGIX/sprite.txt
+glStartInstrumentsSGIX https://www.opengl.org/registry/specs/SGIX/instruments.txt
+glStencilClearTagEXT https://www.opengl.org/registry/specs/EXT/stencil_clear_tag.txt
+glStencilFillPathInstancedNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glStencilFillPathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glStencilFunc https://www.opengl.org/sdk/docs/man/xhtml/glStencilFunc.xml
+glStencilFunc https://www.opengl.org/sdk/docs/man3/xhtml/glStencilFunc.xml
+glStencilFunc https://www.opengl.org/sdk/docs/man4/html/glStencilFunc.xhtml
+glStencilFuncSeparate https://www.opengl.org/sdk/docs/man/xhtml/glStencilFuncSeparate.xml
+glStencilFuncSeparate https://www.opengl.org/sdk/docs/man3/xhtml/glStencilFuncSeparate.xml
+glStencilFuncSeparate https://www.opengl.org/sdk/docs/man4/html/glStencilFuncSeparate.xhtml
+glStencilMask https://www.opengl.org/sdk/docs/man/xhtml/glStencilMask.xml
+glStencilMask https://www.opengl.org/sdk/docs/man3/xhtml/glStencilMask.xml
+glStencilMask https://www.opengl.org/sdk/docs/man4/html/glStencilMask.xhtml
+glStencilMaskSeparate https://www.opengl.org/sdk/docs/man/xhtml/glStencilMaskSeparate.xml
+glStencilMaskSeparate https://www.opengl.org/sdk/docs/man3/xhtml/glStencilMaskSeparate.xml
+glStencilMaskSeparate https://www.opengl.org/sdk/docs/man4/html/glStencilMaskSeparate.xhtml
+glStencilOp https://www.opengl.org/sdk/docs/man/xhtml/glStencilOp.xml
+glStencilOp https://www.opengl.org/sdk/docs/man3/xhtml/glStencilOp.xml
+glStencilOp https://www.opengl.org/sdk/docs/man4/html/glStencilOp.xhtml
+glStencilOpSeparate https://www.opengl.org/sdk/docs/man/xhtml/glStencilOpSeparate.xml
+glStencilOpSeparate https://www.opengl.org/sdk/docs/man3/xhtml/glStencilOpSeparate.xml
+glStencilOpSeparate https://www.opengl.org/sdk/docs/man4/html/glStencilOpSeparate.xhtml
+glStencilStrokePathInstancedNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glStencilStrokePathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glStopInstrumentsSGIX https://www.opengl.org/registry/specs/SGIX/instruments.txt
+glStringMarkerGREMEDY https://www.opengl.org/registry/specs/GREMEDY/string_marker.txt
+glTagSampleBufferSGIX https://www.opengl.org/registry/specs/SGIX/tag_sample_buffer.txt
+glTangentPointerEXT https://www.opengl.org/registry/specs/EXT/coordinate_frame.txt
+glTbufferMask3DFX https://www.opengl.org/registry/specs/3DFX/tbuffer.txt
+glTessellationFactorAMD https://www.opengl.org/registry/specs/AMD/vertex_shader_tessellator.txt
+glTessellationModeAMD https://www.opengl.org/registry/specs/AMD/vertex_shader_tessellator.txt
+glTestFenceAPPLE https://www.opengl.org/registry/specs/APPLE/fence.txt
+glTestFenceNV https://www.opengl.org/registry/specs/NV/fence.txt
+glTestObjectAPPLE https://www.opengl.org/registry/specs/APPLE/fence.txt
+glTexBuffer https://www.opengl.org/sdk/docs/man3/xhtml/glTexBuffer.xml
+glTexBuffer https://www.opengl.org/sdk/docs/man4/html/glTexBuffer.xhtml
+glTexBufferARB https://www.opengl.org/registry/specs/ARB/texture_buffer_object.txt
+glTexBufferEXT https://www.opengl.org/registry/specs/EXT/texture_buffer_object.txt
+glTexCoord1d https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord1dv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord1f https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord1fv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord1hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glTexCoord1hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glTexCoord1i https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord1iv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord1s https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord1sv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord2d https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord2dv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord2f https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord2fColor4ubVertex3fSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glTexCoord2fColor4ubVertex3fvSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glTexCoord2fVertex3fSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glTexCoord2fVertex3fvSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glTexCoord2fv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord2hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glTexCoord2hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glTexCoord2i https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord2iv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord2s https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord2sv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord3d https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord3dv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord3f https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord3fv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord3hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glTexCoord3hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glTexCoord3i https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord3iv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord3s https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord3sv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord4d https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord4dv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord4f https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord4fVertex4fSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glTexCoord4fVertex4fvSUN https://www.opengl.org/registry/specs/SUN/vertex.txt
+glTexCoord4fv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord4hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glTexCoord4hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glTexCoord4i https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord4iv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord4s https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoord4sv https://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml
+glTexCoordFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glTexCoordP1ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glTexCoordP1uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glTexCoordP2ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glTexCoordP2uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glTexCoordP3ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glTexCoordP3uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glTexCoordP4ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glTexCoordP4uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glTexCoordPointer https://www.opengl.org/sdk/docs/man/xhtml/glTexCoordPointer.xml
+glTexCoordPointerEXT https://www.opengl.org/registry/specs/EXT/vertex_array.txt
+glTexCoordPointervINTEL https://www.opengl.org/registry/specs/INTEL/parallel_arrays.txt
+glTexEnvf https://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
+glTexEnvfv https://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
+glTexEnvi https://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
+glTexEnviv https://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
+glTexFilterFuncSGIS https://www.opengl.org/registry/specs/SGIS/texture_filter4.txt
+glTexGend https://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
+glTexGendv https://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
+glTexGenf https://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
+glTexGenfv https://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
+glTexGeni https://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
+glTexGeniv https://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml
+glTexImage1D https://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml
+glTexImage1D https://www.opengl.org/sdk/docs/man3/xhtml/glTexImage1D.xml
+glTexImage1D https://www.opengl.org/sdk/docs/man4/html/glTexImage1D.xhtml
+glTexImage2D https://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml
+glTexImage2D https://www.opengl.org/sdk/docs/man3/xhtml/glTexImage2D.xml
+glTexImage2D https://www.opengl.org/sdk/docs/man4/html/glTexImage2D.xhtml
+glTexImage2DMultisample https://www.opengl.org/registry/specs/ARB/texture_multisample.txt
+glTexImage2DMultisample https://www.opengl.org/sdk/docs/man3/xhtml/glTexImage2DMultisample.xml
+glTexImage2DMultisample https://www.opengl.org/sdk/docs/man4/html/glTexImage2DMultisample.xhtml
+glTexImage2DMultisampleCoverageNV https://www.opengl.org/registry/specs/NV/texture_multisample.txt
+glTexImage3D https://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml
+glTexImage3D https://www.opengl.org/sdk/docs/man3/xhtml/glTexImage3D.xml
+glTexImage3D https://www.opengl.org/sdk/docs/man4/html/glTexImage3D.xhtml
+glTexImage3DEXT https://www.opengl.org/registry/specs/EXT/texture3D.txt
+glTexImage3DMultisample https://www.opengl.org/registry/specs/ARB/texture_multisample.txt
+glTexImage3DMultisample https://www.opengl.org/sdk/docs/man3/xhtml/glTexImage3DMultisample.xml
+glTexImage3DMultisample https://www.opengl.org/sdk/docs/man4/html/glTexImage3DMultisample.xhtml
+glTexImage3DMultisampleCoverageNV https://www.opengl.org/registry/specs/NV/texture_multisample.txt
+glTexImage4DSGIS https://www.opengl.org/registry/specs/SGIS/texture4D.txt
+glTexParameterIiv https://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
+glTexParameterIiv https://www.opengl.org/sdk/docs/man4/html/glTexParameter.xhtml
+glTexParameterIivEXT https://www.opengl.org/registry/specs/EXT/texture_integer.txt
+glTexParameterIuiv https://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
+glTexParameterIuiv https://www.opengl.org/sdk/docs/man4/html/glTexParameter.xhtml
+glTexParameterIuivEXT https://www.opengl.org/registry/specs/EXT/texture_integer.txt
+glTexParameterf https://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
+glTexParameterf https://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
+glTexParameterf https://www.opengl.org/sdk/docs/man4/html/glTexParameter.xhtml
+glTexParameterfv https://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
+glTexParameterfv https://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
+glTexParameterfv https://www.opengl.org/sdk/docs/man4/html/glTexParameter.xhtml
+glTexParameteri https://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
+glTexParameteri https://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
+glTexParameteri https://www.opengl.org/sdk/docs/man4/html/glTexParameter.xhtml
+glTexParameteriv https://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
+glTexParameteriv https://www.opengl.org/sdk/docs/man3/xhtml/glTexParameter.xml
+glTexParameteriv https://www.opengl.org/sdk/docs/man4/html/glTexParameter.xhtml
+glTexRenderbufferNV https://www.opengl.org/registry/specs/NV/explicit_multisample.txt
+glTexStorage1D https://www.opengl.org/registry/specs/ARB/texture_storage.txt
+glTexStorage2D https://www.opengl.org/registry/specs/ARB/texture_storage.txt
+glTexStorage3D https://www.opengl.org/registry/specs/ARB/texture_storage.txt
+glTexSubImage1D https://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage1D.xml
+glTexSubImage1D https://www.opengl.org/sdk/docs/man3/xhtml/glTexSubImage1D.xml
+glTexSubImage1D https://www.opengl.org/sdk/docs/man4/html/glTexSubImage1D.xhtml
+glTexSubImage1DEXT https://www.opengl.org/registry/specs/EXT/subtexture.txt
+glTexSubImage2D https://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage2D.xml
+glTexSubImage2D https://www.opengl.org/sdk/docs/man3/xhtml/glTexSubImage2D.xml
+glTexSubImage2D https://www.opengl.org/sdk/docs/man4/html/glTexSubImage2D.xhtml
+glTexSubImage2DEXT https://www.opengl.org/registry/specs/EXT/subtexture.txt
+glTexSubImage3D https://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage3D.xml
+glTexSubImage3D https://www.opengl.org/sdk/docs/man3/xhtml/glTexSubImage3D.xml
+glTexSubImage3D https://www.opengl.org/sdk/docs/man4/html/glTexSubImage3D.xhtml
+glTexSubImage3DEXT https://www.opengl.org/registry/specs/EXT/subtexture.txt
+glTexSubImage4DSGIS https://www.opengl.org/registry/specs/SGIS/texture4D.txt
+glTextureBarrierNV https://www.opengl.org/registry/specs/NV/texture_barrier.txt
+glTextureBufferEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureColorMaskSGIS https://www.opengl.org/registry/specs/SGIS/texture_color_mask.txt
+glTextureFogSGIX https://www.opengl.org/registry/specs/SGIX/fog_texture.txt
+glTextureImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureImage2DMultisampleCoverageNV https://www.opengl.org/registry/specs/NV/texture_multisample.txt
+glTextureImage2DMultisampleNV https://www.opengl.org/registry/specs/NV/texture_multisample.txt
+glTextureImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureImage3DMultisampleCoverageNV https://www.opengl.org/registry/specs/NV/texture_multisample.txt
+glTextureImage3DMultisampleNV https://www.opengl.org/registry/specs/NV/texture_multisample.txt
+glTextureLightEXT https://www.opengl.org/registry/specs/EXT/light_texture.txt
+glTextureMaterialEXT https://www.opengl.org/registry/specs/EXT/light_texture.txt
+glTextureNormalEXT https://www.opengl.org/registry/specs/EXT/texture_perturb_normal.txt
+glTextureParameterIivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureParameterIuivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureParameterfEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureParameterfvEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureParameteriEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureParameterivEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureRangeAPPLE https://www.opengl.org/registry/specs/APPLE/texture_range.txt
+glTextureRenderbufferEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureStorage1DEXT https://www.opengl.org/registry/specs/ARB/texture_storage.txt
+glTextureStorage2DEXT https://www.opengl.org/registry/specs/ARB/texture_storage.txt
+glTextureStorage3DEXT https://www.opengl.org/registry/specs/ARB/texture_storage.txt
+glTextureSubImage1DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureSubImage2DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTextureSubImage3DEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glTrackMatrixNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glTransformFeedbackAttribsNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glTransformFeedbackVaryings https://www.opengl.org/sdk/docs/man3/xhtml/glTransformFeedbackVaryings.xml
+glTransformFeedbackVaryings https://www.opengl.org/sdk/docs/man4/html/glTransformFeedbackVaryings.xhtml
+glTransformFeedbackVaryingsEXT https://www.opengl.org/registry/specs/EXT/transform_feedback.txt
+glTransformFeedbackVaryingsNV https://www.opengl.org/registry/specs/NV/transform_feedback.txt
+glTransformPathNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glTranslated https://www.opengl.org/sdk/docs/man/xhtml/glTranslate.xml
+glTranslatef https://www.opengl.org/sdk/docs/man/xhtml/glTranslate.xml
+glTranslatexOES https://www.opengl.org/registry/specs/OES/OES_fixed_point.txt
+glUniform1d https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniform1dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniform1f https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform1f https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform1f https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform1fARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform1fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform1fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform1fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform1fvARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform1i https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform1i https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform1i https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform1i64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform1i64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform1iARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform1iv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform1iv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform1iv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform1ivARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform1ui https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform1ui https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform1ui64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform1ui64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform1uiEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glUniform1uiv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform1uiv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform1uivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glUniform2d https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniform2dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniform2f https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform2f https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform2f https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform2fARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform2fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform2fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform2fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform2fvARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform2i https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform2i https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform2i https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform2i64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform2i64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform2iARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform2iv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform2iv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform2iv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform2ivARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform2ui https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform2ui https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform2ui64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform2ui64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform2uiEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glUniform2uiv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform2uiv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform2uivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glUniform3d https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniform3dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniform3f https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform3f https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform3f https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform3fARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform3fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform3fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform3fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform3fvARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform3i https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform3i https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform3i https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform3i64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform3i64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform3iARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform3iv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform3iv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform3iv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform3ivARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform3ui https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform3ui https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform3ui64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform3ui64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform3uiEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glUniform3uiv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform3uiv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform3uivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glUniform4d https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniform4dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniform4f https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform4f https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform4f https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform4fARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform4fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform4fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform4fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform4fvARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform4i https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform4i https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform4i https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform4i64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform4i64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform4iARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform4iv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniform4iv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform4iv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform4ivARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniform4ui https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform4ui https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform4ui64NV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform4ui64vNV https://www.opengl.org/registry/specs/NV/gpu_shader5.txt
+glUniform4uiEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glUniform4uiv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniform4uiv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniform4uivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glUniformBlockBinding https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
+glUniformBlockBinding https://www.opengl.org/sdk/docs/man3/xhtml/glUniformBlockBinding.xml
+glUniformBlockBinding https://www.opengl.org/sdk/docs/man4/html/glUniformBlockBinding.xhtml
+glUniformBufferEXT https://www.opengl.org/registry/specs/EXT/bindable_uniform.txt
+glUniformMatrix2dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniformMatrix2fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniformMatrix2fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniformMatrix2fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniformMatrix2fvARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniformMatrix2x3dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniformMatrix2x3fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniformMatrix2x3fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniformMatrix2x3fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniformMatrix2x4dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniformMatrix2x4fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniformMatrix2x4fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniformMatrix2x4fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniformMatrix3dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniformMatrix3fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniformMatrix3fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniformMatrix3fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniformMatrix3fvARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniformMatrix3x2dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniformMatrix3x2fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniformMatrix3x2fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniformMatrix3x2fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniformMatrix3x4dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniformMatrix3x4fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniformMatrix3x4fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniformMatrix3x4fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniformMatrix4dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniformMatrix4fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniformMatrix4fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniformMatrix4fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniformMatrix4fvARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUniformMatrix4x2dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniformMatrix4x2fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniformMatrix4x2fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniformMatrix4x2fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniformMatrix4x3dv https://www.opengl.org/registry/specs/ARB/gpu_shader_fp64.txt
+glUniformMatrix4x3fv https://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml
+glUniformMatrix4x3fv https://www.opengl.org/sdk/docs/man3/xhtml/glUniform.xml
+glUniformMatrix4x3fv https://www.opengl.org/sdk/docs/man4/html/glUniform.xhtml
+glUniformSubroutinesuiv https://www.opengl.org/registry/specs/ARB/shader_subroutine.txt
+glUniformSubroutinesuiv https://www.opengl.org/sdk/docs/man4/html/glUniformSubroutines.xhtml
+glUniformui64NV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glUniformui64vNV https://www.opengl.org/registry/specs/NV/shader_buffer_load.txt
+glUnmapBuffer https://www.opengl.org/sdk/docs/man/xhtml/glMapBuffer.xml
+glUnmapBuffer https://www.opengl.org/sdk/docs/man3/xhtml/glMapBuffer.xml
+glUnmapBuffer https://www.opengl.org/sdk/docs/man4/html/glMapBuffer.xhtml
+glUnmapBufferARB https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
+glUnmapNamedBufferEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glUnmapObjectBufferATI https://www.opengl.org/registry/specs/ATI/map_object_buffer.txt
+glUpdateObjectBufferATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glUseProgram https://www.opengl.org/sdk/docs/man/xhtml/glUseProgram.xml
+glUseProgram https://www.opengl.org/sdk/docs/man3/xhtml/glUseProgram.xml
+glUseProgram https://www.opengl.org/sdk/docs/man4/html/glUseProgram.xhtml
+glUseProgramObjectARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glUseProgramStages https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glUseProgramStages https://www.opengl.org/sdk/docs/man4/html/glUseProgramStages.xhtml
+glUseShaderProgramEXT https://www.opengl.org/registry/specs/EXT/separate_shader_objects.txt
+glValidateProgram https://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml
+glValidateProgram https://www.opengl.org/sdk/docs/man3/xhtml/glValidateProgram.xml
+glValidateProgram https://www.opengl.org/sdk/docs/man4/html/glValidateProgram.xhtml
+glValidateProgramARB https://www.opengl.org/registry/specs/ARB/shader_objects.txt
+glValidateProgramPipeline https://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt
+glValidateProgramPipeline https://www.opengl.org/sdk/docs/man4/html/glValidateProgramPipeline.xhtml
+glVariantArrayObjectATI https://www.opengl.org/registry/specs/ATI/vertex_array_object.txt
+glVertex2d https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex2dv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex2f https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex2fv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex2hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertex2hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertex2i https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex2iv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex2s https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex2sv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex3d https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex3dv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex3f https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex3fv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex3hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertex3hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertex3i https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex3iv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex3s https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex3sv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex4d https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex4dv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex4f https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex4fv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex4hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertex4hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertex4i https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex4iv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex4s https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertex4sv https://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
+glVertexArrayColorOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayEdgeFlagOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayFogCoordOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayIndexOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayMultiTexCoordOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayNormalOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayParameteriAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_array_range.txt
+glVertexArrayRangeAPPLE https://www.opengl.org/registry/specs/APPLE/vertex_array_range.txt
+glVertexArrayRangeNV https://www.opengl.org/registry/specs/NV/vertex_array_range.txt
+glVertexArraySecondaryColorOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayTexCoordOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayVertexAttribIOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayVertexAttribLOffsetEXT https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexArrayVertexAttribLOffsetEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexArrayVertexAttribOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexArrayVertexOffsetEXT https://www.opengl.org/registry/specs/EXT/direct_state_access.txt
+glVertexAttrib1d https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib1d https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib1d https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib1dARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib1dARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib1dNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib1dv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib1dv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib1dv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib1dvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib1dvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib1dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib1f https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib1f https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib1f https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib1fARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib1fARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib1fNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib1fv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib1fv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib1fv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib1fvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib1fvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib1fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib1hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttrib1hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttrib1s https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib1s https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib1s https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib1sARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib1sARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib1sNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib1sv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib1sv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib1sv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib1svARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib1svARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib1svNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib2d https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib2d https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib2d https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib2dARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib2dARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib2dNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib2dv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib2dv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib2dv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib2dvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib2dvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib2dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib2f https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib2f https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib2f https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib2fARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib2fARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib2fNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib2fv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib2fv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib2fv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib2fvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib2fvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib2fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib2hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttrib2hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttrib2s https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib2s https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib2s https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib2sARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib2sARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib2sNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib2sv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib2sv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib2sv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib2svARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib2svARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib2svNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib3d https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib3d https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib3d https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib3dARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib3dARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib3dNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib3dv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib3dv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib3dv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib3dvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib3dvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib3dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib3f https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib3f https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib3f https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib3fARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib3fARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib3fNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib3fv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib3fv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib3fv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib3fvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib3fvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib3fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib3hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttrib3hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttrib3s https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib3s https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib3s https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib3sARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib3sARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib3sNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib3sv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib3sv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib3sv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib3svARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib3svARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib3svNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib4Nbv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nbv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nbv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4NbvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4NbvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4Niv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4Niv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4Niv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4NivARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4NivARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4Nsv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nsv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nsv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4NsvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4NsvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4Nub https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nub https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nub https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4NubARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4NubARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4Nubv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nubv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nubv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4NubvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4NubvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4Nuiv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nuiv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nuiv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4NuivARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4NuivARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4Nusv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nusv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4Nusv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4NusvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4NusvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4bv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4bv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4bv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4bvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4bvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4d https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4d https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4d https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4dARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4dARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4dNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib4dv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4dv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4dv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4dvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4dvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib4f https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4f https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4f https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4fARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4fARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4fNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib4fv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4fv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4fv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4fvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4fvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib4hNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttrib4hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttrib4iv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4iv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4iv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4ivARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4ivARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4s https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4s https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4s https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4sARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4sARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4sNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib4sv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4sv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4sv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4svARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4svARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4svNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib4ubNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib4ubv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4ubv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4ubv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4ubvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4ubvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4ubvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttrib4uiv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4uiv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4uiv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4uivARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4uivARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttrib4usv https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml
+glVertexAttrib4usv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttrib4usv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttrib4usvARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttrib4usvARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttribArrayObjectATI https://www.opengl.org/registry/specs/ATI/vertex_attrib_array_object.txt
+glVertexAttribDivisor https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribDivisor.xml
+glVertexAttribDivisor https://www.opengl.org/sdk/docs/man4/html/glVertexAttribDivisor.xhtml
+glVertexAttribDivisorARB https://www.opengl.org/registry/specs/ARB/instanced_arrays.txt
+glVertexAttribFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glVertexAttribI1i https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI1i https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI1iEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI1iEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI1iv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI1iv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI1ivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI1ivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI1ui https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI1ui https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI1uiEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI1uiEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI1uiv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI1uiv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI1uivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI1uivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI2i https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI2i https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI2iEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI2iEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI2iv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI2iv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI2ivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI2ivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI2ui https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI2ui https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI2uiEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI2uiEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI2uiv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI2uiv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI2uivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI2uivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI3i https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI3i https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI3iEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI3iEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI3iv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI3iv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI3ivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI3ivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI3ui https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI3ui https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI3uiEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI3uiEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI3uiv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI3uiv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI3uivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI3uivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI4bv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI4bv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI4bvEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI4bvEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI4i https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI4i https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI4iEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI4iEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI4iv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI4iv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI4ivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI4ivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI4sv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI4sv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI4svEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI4svEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI4ubv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI4ubv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI4ubvEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI4ubvEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI4ui https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI4ui https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI4uiEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI4uiEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI4uiv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI4uiv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI4uivEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI4uivEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribI4usv https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribI4usv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribI4usvEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribI4usvEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribIFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glVertexAttribIPointer https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribPointer.xml
+glVertexAttribIPointer https://www.opengl.org/sdk/docs/man4/html/glVertexAttribPointer.xhtml
+glVertexAttribIPointerEXT https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt
+glVertexAttribIPointerEXT https://www.opengl.org/registry/specs/NV/vertex_program4.txt
+glVertexAttribL1d https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexAttribL1d https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribL1dEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexAttribL1dv https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexAttribL1dv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribL1dvEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexAttribL1i64NV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL1i64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL1ui64NV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL1ui64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL2d https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexAttribL2d https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribL2dEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexAttribL2dv https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexAttribL2dv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribL2dvEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexAttribL2i64NV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL2i64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL2ui64NV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL2ui64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL3d https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexAttribL3d https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribL3dEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexAttribL3dv https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexAttribL3dv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribL3dvEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexAttribL3i64NV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL3i64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL3ui64NV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL3ui64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL4d https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexAttribL4d https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribL4dEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexAttribL4dv https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexAttribL4dv https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribL4dvEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexAttribL4i64NV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL4i64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL4ui64NV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribL4ui64vNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribLFormatNV https://www.opengl.org/registry/specs/NV/vertex_attrib_integer_64bit.txt
+glVertexAttribLPointer https://www.opengl.org/registry/specs/ARB/vertex_attrib_64bit.txt
+glVertexAttribLPointer https://www.opengl.org/sdk/docs/man4/html/glVertexAttribPointer.xhtml
+glVertexAttribLPointerEXT https://www.opengl.org/registry/specs/EXT/vertex_attrib_64bit.txt
+glVertexAttribP1ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexAttribP1ui https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribP1ui https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribP1uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexAttribP2ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexAttribP2ui https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribP2ui https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribP2uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexAttribP3ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexAttribP3ui https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribP3ui https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribP3uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexAttribP4ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexAttribP4ui https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttrib.xml
+glVertexAttribP4ui https://www.opengl.org/sdk/docs/man4/html/glVertexAttrib.xhtml
+glVertexAttribP4uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexAttribPointer https://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribPointer.xml
+glVertexAttribPointer https://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribPointer.xml
+glVertexAttribPointer https://www.opengl.org/sdk/docs/man4/html/glVertexAttribPointer.xhtml
+glVertexAttribPointerARB https://www.opengl.org/registry/specs/ARB/vertex_program.txt
+glVertexAttribPointerARB https://www.opengl.org/registry/specs/ARB/vertex_shader.txt
+glVertexAttribPointerNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs1dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs1fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs1hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttribs1svNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs2dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs2fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs2hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttribs2svNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs3dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs3fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs3hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttribs3svNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs4dvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs4fvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs4hvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexAttribs4svNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexAttribs4ubvNV https://www.opengl.org/registry/specs/NV/vertex_program.txt
+glVertexBlendARB https://www.opengl.org/registry/specs/ARB/vertex_blend.txt
+glVertexFormatNV https://www.opengl.org/registry/specs/NV/vertex_buffer_unified_memory.txt
+glVertexP2ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexP2uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexP3ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexP3uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexP4ui https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexP4uiv https://www.opengl.org/registry/specs/ARB/vertex_type_2_10_10_10_rev.txt
+glVertexPointer https://www.opengl.org/sdk/docs/man/xhtml/glVertexPointer.xml
+glVertexPointerEXT https://www.opengl.org/registry/specs/EXT/vertex_array.txt
+glVertexPointervINTEL https://www.opengl.org/registry/specs/INTEL/parallel_arrays.txt
+glVertexWeighthNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVertexWeighthvNV https://www.opengl.org/registry/specs/NV/half_float.txt
+glVideoCaptureNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glViewport https://www.opengl.org/sdk/docs/man/xhtml/glViewport.xml
+glViewport https://www.opengl.org/sdk/docs/man3/xhtml/glViewport.xml
+glViewport https://www.opengl.org/sdk/docs/man4/html/glViewport.xhtml
+glViewportArrayv https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glViewportArrayv https://www.opengl.org/sdk/docs/man4/html/glViewportArray.xhtml
+glViewportIndexedf https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glViewportIndexedf https://www.opengl.org/sdk/docs/man4/html/glViewportIndexed.xhtml
+glViewportIndexedfv https://www.opengl.org/registry/specs/ARB/viewport_array.txt
+glViewportIndexedfv https://www.opengl.org/sdk/docs/man4/html/glViewportIndexed.xhtml
+glWaitSync https://www.opengl.org/registry/specs/ARB/sync.txt
+glWaitSync https://www.opengl.org/sdk/docs/man3/xhtml/glWaitSync.xml
+glWaitSync https://www.opengl.org/sdk/docs/man4/html/glWaitSync.xhtml
+glWeightPathsNV https://www.opengl.org/registry/specs/NV/path_rendering.txt
+glWeightPointerARB https://www.opengl.org/registry/specs/ARB/vertex_blend.txt
+glWindowPos2d https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos2dARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos2dMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos2dv https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos2dvARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos2dvMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos2f https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos2fARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos2fMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos2fv https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos2fvARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos2fvMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos2i https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos2iARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos2iMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos2iv https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos2ivARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos2ivMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos2s https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos2sARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos2sMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos2sv https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos2svARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos2svMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos3d https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos3dARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos3dMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos3dv https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos3dvARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos3dvMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos3f https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos3fARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos3fMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos3fv https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos3fvARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos3fvMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos3i https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos3iARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos3iMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos3iv https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos3ivARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos3ivMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos3s https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos3sARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos3sMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos3sv https://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml
+glWindowPos3svARB https://www.opengl.org/registry/specs/ARB/window_pos.txt
+glWindowPos3svMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos4dMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos4dvMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos4fMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos4fvMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos4iMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos4ivMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos4sMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glWindowPos4svMESA https://www.opengl.org/registry/specs/MESA/window_pos.txt
+glXAssociateDMPbufferSGIX https://www.opengl.org/registry/specs/SGIX/dmbuffer.txt
+glXBindChannelToWindowSGIX https://www.opengl.org/registry/specs/SGIX/video_resize.txt
+glXBindHyperpipeSGIX https://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
+glXBindSwapBarrierNV https://www.opengl.org/registry/specs/NV/glx_swap_group.txt
+glXBindVideoCaptureDeviceNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glXBindVideoDeviceNV https://www.opengl.org/registry/specs/NV/present_video.txt
+glXBlitContextFramebufferAMD https://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
+glXChannelRectSGIX https://www.opengl.org/registry/specs/SGIX/video_resize.txt
+glXChannelRectSyncSGIX https://www.opengl.org/registry/specs/SGIX/video_resize.txt
+glXChooseFBConfig https://www.opengl.org/sdk/docs/man/xhtml/glXChooseFBConfig.xml
+glXChooseVisual https://www.opengl.org/sdk/docs/man/xhtml/glXChooseVisual.xml
+glXCopyContext https://www.opengl.org/sdk/docs/man/xhtml/glXCopyContext.xml
+glXCopySubBufferMESA https://www.opengl.org/registry/specs/MESA/copy_sub_buffer.txt
+glXCreateAssociatedContextAMD https://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
+glXCreateAssociatedContextAttribsAMD https://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
+glXCreateContext https://www.opengl.org/sdk/docs/man/xhtml/glXCreateContext.xml
+glXCreateContextAttribsARB https://www.opengl.org/registry/specs/ARB/glx_create_context.txt
+glXCreateContextWithConfigSGIX https://www.opengl.org/registry/specs/SGIX/fbconfig.txt
+glXCreateGLXPbufferSGIX https://www.opengl.org/registry/specs/SGIX/pbuffer.txt
+glXCreateGLXPixmap https://www.opengl.org/sdk/docs/man/xhtml/glXCreateGLXPixmap.xml
+glXCreateGLXPixmapMESA https://www.opengl.org/registry/specs/MESA/pixmap_colormap.txt
+glXCreateGLXPixmapWithConfigSGIX https://www.opengl.org/registry/specs/SGIX/fbconfig.txt
+glXCreateGLXVideoSourceSGIX https://www.opengl.org/registry/specs/SGIX/video_source.txt
+glXCreateNewContext https://www.opengl.org/sdk/docs/man/xhtml/glXCreateNewContext.xml
+glXCreatePbuffer https://www.opengl.org/sdk/docs/man/xhtml/glXCreatePbuffer.xml
+glXCreatePixmap https://www.opengl.org/sdk/docs/man/xhtml/glXCreatePixmap.xml
+glXCreateWindow https://www.opengl.org/sdk/docs/man/xhtml/glXCreateWindow.xml
+glXCushionSGI https://www.opengl.org/registry/specs/SGI/cushion.txt
+glXDeleteAssociatedContextAMD https://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
+glXDestroyContext https://www.opengl.org/sdk/docs/man/xhtml/glXDestroyContext.xml
+glXDestroyGLXPbufferSGIX https://www.opengl.org/registry/specs/SGIX/pbuffer.txt
+glXDestroyGLXPixmap https://www.opengl.org/sdk/docs/man/xhtml/glXDestroyGLXPixmap.xml
+glXDestroyGLXVideoSourceSGIX https://www.opengl.org/registry/specs/SGIX/video_source.txt
+glXDestroyHyperpipeConfigSGIX https://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
+glXDestroyPbuffer https://www.opengl.org/sdk/docs/man/xhtml/glXDestroyPbuffer.xml
+glXDestroyPixmap https://www.opengl.org/sdk/docs/man/xhtml/glXDestroyPixmap.xml
+glXDestroyWindow https://www.opengl.org/sdk/docs/man/xhtml/glXDestroyWindow.xml
+glXEnumerateVideoCaptureDevicesNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glXFreeContextEXT https://www.opengl.org/registry/specs/EXT/import_context.txt
+glXFreeContextEXT https://www.opengl.org/sdk/docs/man/xhtml/glXFreeContextEXT.xml
+glXGetAGPOffsetMESA https://www.opengl.org/registry/specs/MESA/agp_offset.txt
+glXGetClientString https://www.opengl.org/sdk/docs/man/xhtml/glXGetClientString.xml
+glXGetConfig https://www.opengl.org/sdk/docs/man/xhtml/glXGetConfig.xml
+glXGetContextGPUIDAMD https://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
+glXGetContextIDEXT https://www.opengl.org/registry/specs/EXT/import_context.txt
+glXGetContextIDEXT https://www.opengl.org/sdk/docs/man/xhtml/glXGetContextIDEXT.xml
+glXGetCurrentAssociatedContextAMD https://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
+glXGetCurrentContext https://www.opengl.org/sdk/docs/man/xhtml/glXGetCurrentContext.xml
+glXGetCurrentDisplay https://www.opengl.org/sdk/docs/man/xhtml/glXGetCurrentDisplay.xml
+glXGetCurrentDrawable https://www.opengl.org/sdk/docs/man/xhtml/glXGetCurrentDrawable.xml
+glXGetCurrentReadDrawable https://www.opengl.org/sdk/docs/man/xhtml/glXGetCurrentReadDrawable.xml
+glXGetCurrentReadDrawableSGI https://www.opengl.org/registry/specs/SGI/make_current_read.txt
+glXGetFBConfigAttrib https://www.opengl.org/sdk/docs/man/xhtml/glXGetFBConfigAttrib.xml
+glXGetFBConfigAttribSGIX https://www.opengl.org/registry/specs/SGIX/fbconfig.txt
+glXGetFBConfigFromVisualSGIX https://www.opengl.org/registry/specs/SGIX/fbconfig.txt
+glXGetFBConfigs https://www.opengl.org/sdk/docs/man/xhtml/glXGetFBConfigs.xml
+glXGetGPUIDsAMD https://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
+glXGetGPUInfoAMD https://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
+glXGetMscRateOML https://www.opengl.org/registry/specs/OML/glx_sync_control.txt
+glXGetProcAddress https://www.opengl.org/sdk/docs/man/xhtml/glXGetProcAddress.xml
+glXGetSelectedEvent https://www.opengl.org/sdk/docs/man/xhtml/glXGetSelectedEvent.xml
+glXGetSelectedEventSGIX https://www.opengl.org/registry/specs/SGIX/pbuffer.txt
+glXGetSyncValuesOML https://www.opengl.org/registry/specs/OML/glx_sync_control.txt
+glXGetTransparentIndexSUN https://www.opengl.org/registry/specs/SUN/get_transparent_index.txt
+glXGetVideoSyncSGI https://www.opengl.org/registry/specs/SGI/video_sync.txt
+glXGetVisualFromFBConfig https://www.opengl.org/sdk/docs/man/xhtml/glXGetVisualFromFBConfig.xml
+glXHyperpipeAttribSGIX https://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
+glXHyperpipeConfigSGIX https://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
+glXImportContextEXT https://www.opengl.org/registry/specs/EXT/import_context.txt
+glXImportContextEXT https://www.opengl.org/sdk/docs/man/xhtml/glXImportContextEXT.xml
+glXIsDirect https://www.opengl.org/sdk/docs/man/xhtml/glXIsDirect.xml
+glXJoinSwapGroupNV https://www.opengl.org/registry/specs/NV/glx_swap_group.txt
+glXLockVideoCaptureDeviceNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glXMakeAssociatedContextCurrentAMD https://www.opengl.org/registry/specs/AMD/glx_gpu_association.txt
+glXMakeContextCurrent https://www.opengl.org/sdk/docs/man/xhtml/glXMakeContextCurrent.xml
+glXMakeCurrent https://www.opengl.org/sdk/docs/man/xhtml/glXMakeCurrent.xml
+glXMakeCurrentReadSGI https://www.opengl.org/registry/specs/SGI/make_current_read.txt
+glXQueryChannelDeltasSGIX https://www.opengl.org/registry/specs/SGIX/video_resize.txt
+glXQueryChannelRectSGIX https://www.opengl.org/registry/specs/SGIX/video_resize.txt
+glXQueryContext https://www.opengl.org/sdk/docs/man/xhtml/glXQueryContext.xml
+glXQueryContextInfoEXT https://www.opengl.org/registry/specs/EXT/import_context.txt
+glXQueryContextInfoEXT https://www.opengl.org/sdk/docs/man/xhtml/glXQueryContextInfoEXT.xml
+glXQueryDrawable https://www.opengl.org/sdk/docs/man/xhtml/glXQueryDrawable.xml
+glXQueryExtension https://www.opengl.org/sdk/docs/man/xhtml/glXQueryExtension.xml
+glXQueryExtensionsString https://www.opengl.org/sdk/docs/man/xhtml/glXQueryExtensionsString.xml
+glXQueryFrameCountNV https://www.opengl.org/registry/specs/NV/glx_swap_group.txt
+glXQueryGLXPbufferSGIX https://www.opengl.org/registry/specs/SGIX/pbuffer.txt
+glXQueryHyperpipeAttribSGIX https://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
+glXQueryHyperpipeBestAttribSGIX https://www.opengl.org/registry/specs/SGIX/hyperpipe_group.txt
+glXQueryMaxSwapGroupsNV https://www.opengl.org/registry/specs/NV/glx_swap_group.txt
+glXQueryServerString https://www.opengl.org/sdk/docs/man/xhtml/glXQueryServerString.xml
+glXQuerySwapGroupNV https://www.opengl.org/registry/specs/NV/glx_swap_group.txt
+glXQueryVersion https://www.opengl.org/sdk/docs/man/xhtml/glXQueryVersion.xml
+glXQueryVideoCaptureDeviceNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glXReleaseBuffersMESA https://www.opengl.org/registry/specs/MESA/release_buffers.txt
+glXReleaseVideoCaptureDeviceNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+glXResetFrameCountNV https://www.opengl.org/registry/specs/NV/glx_swap_group.txt
+glXSelectEvent https://www.opengl.org/sdk/docs/man/xhtml/glXSelectEvent.xml
+glXSelectEventSGIX https://www.opengl.org/registry/specs/SGIX/pbuffer.txt
+glXSet3DfxModeMESA https://www.opengl.org/registry/specs/MESA/set_3dfx_mode.txt
+glXSwapBuffers https://www.opengl.org/sdk/docs/man/xhtml/glXSwapBuffers.xml
+glXSwapBuffersMscOML https://www.opengl.org/registry/specs/OML/glx_sync_control.txt
+glXSwapIntervalEXT https://www.opengl.org/registry/specs/EXT/swap_control.txt
+glXSwapIntervalSGI https://www.opengl.org/registry/specs/SGI/swap_control.txt
+glXUseXFont https://www.opengl.org/sdk/docs/man/xhtml/glXUseXFont.xml
+glXWaitForMscOML https://www.opengl.org/registry/specs/OML/glx_sync_control.txt
+glXWaitForSbcOML https://www.opengl.org/registry/specs/OML/glx_sync_control.txt
+glXWaitGL https://www.opengl.org/sdk/docs/man/xhtml/glXWaitGL.xml
+glXWaitVideoSyncSGI https://www.opengl.org/registry/specs/SGI/video_sync.txt
+glXWaitX https://www.opengl.org/sdk/docs/man/xhtml/glXWaitX.xml
+gluBeginCurve https://www.opengl.org/sdk/docs/man/xhtml/gluBeginCurve.xml
+gluBeginPolygon https://www.opengl.org/sdk/docs/man/xhtml/gluBeginPolygon.xml
+gluBeginSurface https://www.opengl.org/sdk/docs/man/xhtml/gluBeginSurface.xml
+gluBeginTrim https://www.opengl.org/sdk/docs/man/xhtml/gluBeginTrim.xml
+gluBuild1DMipmapLevels https://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmapLevels.xml
+gluBuild1DMipmaps https://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmaps.xml
+gluBuild2DMipmapLevels https://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmapLevels.xml
+gluBuild2DMipmaps https://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmaps.xml
+gluBuild3DMipmapLevels https://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmapLevels.xml
+gluBuild3DMipmaps https://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmaps.xml
+gluCheckExtension https://www.opengl.org/sdk/docs/man/xhtml/gluCheckExtension.xml
+gluCylinder https://www.opengl.org/sdk/docs/man/xhtml/gluCylinder.xml
+gluDeleteNurbsRenderer https://www.opengl.org/sdk/docs/man/xhtml/gluDeleteNurbsRenderer.xml
+gluDeleteQuadric https://www.opengl.org/sdk/docs/man/xhtml/gluDeleteQuadric.xml
+gluDeleteTess https://www.opengl.org/sdk/docs/man/xhtml/gluDeleteTess.xml
+gluDisk https://www.opengl.org/sdk/docs/man/xhtml/gluDisk.xml
+gluEndCurve https://www.opengl.org/sdk/docs/man/xhtml/gluBeginCurve.xml
+gluEndPolygon https://www.opengl.org/sdk/docs/man/xhtml/gluBeginPolygon.xml
+gluEndSurface https://www.opengl.org/sdk/docs/man/xhtml/gluBeginSurface.xml
+gluEndTrim https://www.opengl.org/sdk/docs/man/xhtml/gluBeginTrim.xml
+gluErrorString https://www.opengl.org/sdk/docs/man/xhtml/gluErrorString.xml
+gluGetNurbsProperty https://www.opengl.org/sdk/docs/man/xhtml/gluGetNurbsProperty.xml
+gluGetString https://www.opengl.org/sdk/docs/man/xhtml/gluGetString.xml
+gluGetTessProperty https://www.opengl.org/sdk/docs/man/xhtml/gluGetTessProperty.xml
+gluLoadSamplingMatrices https://www.opengl.org/sdk/docs/man/xhtml/gluLoadSamplingMatrices.xml
+gluLookAt https://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml
+gluNewNurbsRenderer https://www.opengl.org/sdk/docs/man/xhtml/gluNewNurbsRenderer.xml
+gluNewQuadric https://www.opengl.org/sdk/docs/man/xhtml/gluNewQuadric.xml
+gluNewTess https://www.opengl.org/sdk/docs/man/xhtml/gluNewTess.xml
+gluNextContour https://www.opengl.org/sdk/docs/man/xhtml/gluNextContour.xml
+gluNurbsCallback https://www.opengl.org/sdk/docs/man/xhtml/gluNurbsCallback.xml
+gluNurbsCallbackData https://www.opengl.org/sdk/docs/man/xhtml/gluNurbsCallbackData.xml
+gluNurbsCallbackDataEXT https://www.opengl.org/sdk/docs/man/xhtml/gluNurbsCallbackDataEXT.xml
+gluNurbsCurve https://www.opengl.org/sdk/docs/man/xhtml/gluNurbsCurve.xml
+gluNurbsProperty https://www.opengl.org/sdk/docs/man/xhtml/gluNurbsProperty.xml
+gluNurbsSurface https://www.opengl.org/sdk/docs/man/xhtml/gluNurbsSurface.xml
+gluOrtho2D https://www.opengl.org/sdk/docs/man/xhtml/gluOrtho2D.xml
+gluPartialDisk https://www.opengl.org/sdk/docs/man/xhtml/gluPartialDisk.xml
+gluPerspective https://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml
+gluPickMatrix https://www.opengl.org/sdk/docs/man/xhtml/gluPickMatrix.xml
+gluProject https://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml
+gluPwlCurve https://www.opengl.org/sdk/docs/man/xhtml/gluPwlCurve.xml
+gluQuadricCallback https://www.opengl.org/sdk/docs/man/xhtml/gluQuadricCallback.xml
+gluQuadricDrawStyle https://www.opengl.org/sdk/docs/man/xhtml/gluQuadricDrawStyle.xml
+gluQuadricNormals https://www.opengl.org/sdk/docs/man/xhtml/gluQuadricNormals.xml
+gluQuadricOrientation https://www.opengl.org/sdk/docs/man/xhtml/gluQuadricOrientation.xml
+gluQuadricTexture https://www.opengl.org/sdk/docs/man/xhtml/gluQuadricTexture.xml
+gluScaleImage https://www.opengl.org/sdk/docs/man/xhtml/gluScaleImage.xml
+gluSphere https://www.opengl.org/sdk/docs/man/xhtml/gluSphere.xml
+gluTessBeginContour https://www.opengl.org/sdk/docs/man/xhtml/gluTessBeginContour.xml
+gluTessBeginPolygon https://www.opengl.org/sdk/docs/man/xhtml/gluTessBeginPolygon.xml
+gluTessCallback https://www.opengl.org/sdk/docs/man/xhtml/gluTessCallback.xml
+gluTessEndContour https://www.opengl.org/sdk/docs/man/xhtml/gluTessBeginContour.xml
+gluTessEndPolygon https://www.opengl.org/sdk/docs/man/xhtml/gluTessEndPolygon.xml
+gluTessNormal https://www.opengl.org/sdk/docs/man/xhtml/gluTessNormal.xml
+gluTessProperty https://www.opengl.org/sdk/docs/man/xhtml/gluTessProperty.xml
+gluTessVertex https://www.opengl.org/sdk/docs/man/xhtml/gluTessVertex.xml
+gluTexFilterFuncSGI https://www.opengl.org/registry/specs/SGI/filter4_parameters.txt
+gluUnProject https://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml
+gluUnProject4 https://www.opengl.org/sdk/docs/man/xhtml/gluUnProject4.xml
+sizeof https://www.opengl.org/registry/specs/IBM/multimode_draw_arrays.txt
+wglAssociateImageBufferEventsI3D https://www.opengl.org/registry/specs/I3D/wgl_image_buffer.txt
+wglBeginFrameTrackingI3D https://www.opengl.org/registry/specs/I3D/wgl_swap_frame_usage.txt
+wglBindDisplayColorTableEXT https://www.opengl.org/registry/specs/EXT/wgl_display_color_table.txt
+wglBindSwapBarrierNV https://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
+wglBindVideoCaptureDeviceNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+wglBindVideoDeviceNV https://www.opengl.org/registry/specs/NV/present_video.txt
+wglBlitContextFramebufferAMD https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
wglChoosePixelFormat http://msdn.microsoft.com/en-us/library/dd318284.aspx
-wglChoosePixelFormatARB http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
-wglChoosePixelFormatEXT http://www.opengl.org/registry/specs/EXT/wgl_pixel_format.txt
+wglChoosePixelFormatARB https://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
+wglChoosePixelFormatEXT https://www.opengl.org/registry/specs/EXT/wgl_pixel_format.txt
wglCopyContext http://msdn.microsoft.com/en-us/library/dd374378.aspx
-wglCreateAssociatedContextAMD http://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
-wglCreateAssociatedContextAttribsAMD http://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
-wglCreateBufferRegionARB http://www.opengl.org/registry/specs/ARB/wgl_buffer_region.txt
+wglCreateAssociatedContextAMD https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
+wglCreateAssociatedContextAttribsAMD https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
+wglCreateBufferRegionARB https://www.opengl.org/registry/specs/ARB/wgl_buffer_region.txt
wglCreateContext http://msdn.microsoft.com/en-us/library/dd374379.aspx
-wglCreateContextAttribsARB http://www.opengl.org/registry/specs/ARB/wgl_create_context.txt
-wglCreateDisplayColorTableEXT http://www.opengl.org/registry/specs/EXT/wgl_display_color_table.txt
-wglCreateImageBufferI3D http://www.opengl.org/registry/specs/I3D/wgl_image_buffer.txt
+wglCreateContextAttribsARB https://www.opengl.org/registry/specs/ARB/wgl_create_context.txt
+wglCreateDisplayColorTableEXT https://www.opengl.org/registry/specs/EXT/wgl_display_color_table.txt
+wglCreateImageBufferI3D https://www.opengl.org/registry/specs/I3D/wgl_image_buffer.txt
wglCreateLayerContext http://msdn.microsoft.com/en-us/library/dd374380.aspx
-wglCreatePbufferARB http://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
-wglCreatePbufferEXT http://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
-wglDXCloseDeviceNV http://www.opengl.org/registry/specs/NV/DX_interop.txt
-wglDXLockObjectsNV http://www.opengl.org/registry/specs/NV/DX_interop.txt
-wglDXObjectAccessNV http://www.opengl.org/registry/specs/NV/DX_interop.txt
-wglDXOpenDeviceNV http://www.opengl.org/registry/specs/NV/DX_interop.txt
-wglDXRegisterObjectNV http://www.opengl.org/registry/specs/NV/DX_interop.txt
-wglDXSetResourceShareHandleNV http://www.opengl.org/registry/specs/NV/DX_interop.txt
-wglDXUnlockObjectsNV http://www.opengl.org/registry/specs/NV/DX_interop.txt
-wglDXUnregisterObjectNV http://www.opengl.org/registry/specs/NV/DX_interop.txt
-wglDeleteAssociatedContextAMD http://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
-wglDeleteBufferRegionARB http://www.opengl.org/registry/specs/ARB/wgl_buffer_region.txt
+wglCreatePbufferARB https://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
+wglCreatePbufferEXT https://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
+wglDXCloseDeviceNV https://www.opengl.org/registry/specs/NV/DX_interop.txt
+wglDXLockObjectsNV https://www.opengl.org/registry/specs/NV/DX_interop.txt
+wglDXObjectAccessNV https://www.opengl.org/registry/specs/NV/DX_interop.txt
+wglDXOpenDeviceNV https://www.opengl.org/registry/specs/NV/DX_interop.txt
+wglDXRegisterObjectNV https://www.opengl.org/registry/specs/NV/DX_interop.txt
+wglDXSetResourceShareHandleNV https://www.opengl.org/registry/specs/NV/DX_interop.txt
+wglDXUnlockObjectsNV https://www.opengl.org/registry/specs/NV/DX_interop.txt
+wglDXUnregisterObjectNV https://www.opengl.org/registry/specs/NV/DX_interop.txt
+wglDeleteAssociatedContextAMD https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
+wglDeleteBufferRegionARB https://www.opengl.org/registry/specs/ARB/wgl_buffer_region.txt
wglDeleteContext http://msdn.microsoft.com/en-us/library/dd374381.aspx
wglDescribeLayerPlane http://msdn.microsoft.com/en-us/library/dd374382.aspx
wglDescribePixelFormat http://msdn.microsoft.com/en-us/library/dd318302.aspx
-wglDestroyDisplayColorTableEXT http://www.opengl.org/registry/specs/EXT/wgl_display_color_table.txt
-wglDestroyImageBufferI3D http://www.opengl.org/registry/specs/I3D/wgl_image_buffer.txt
-wglDestroyPbufferARB http://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
-wglDestroyPbufferEXT http://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
-wglDisableFrameLockI3D http://www.opengl.org/registry/specs/I3D/wgl_swap_frame_lock.txt
-wglDisableGenlockI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglEnableFrameLockI3D http://www.opengl.org/registry/specs/I3D/wgl_swap_frame_lock.txt
-wglEnableGenlockI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglEndFrameTrackingI3D http://www.opengl.org/registry/specs/I3D/wgl_swap_frame_usage.txt
-wglEnumerateVideoCaptureDevicesNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-wglEnumerateVideoDevicesNV http://www.opengl.org/registry/specs/NV/present_video.txt
-wglGenlockSampleRateI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglGenlockSourceDelayI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglGenlockSourceEdgeI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglGenlockSourceI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglGetContextGPUIDAMD http://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
-wglGetCurrentAssociatedContextAMD http://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
+wglDestroyDisplayColorTableEXT https://www.opengl.org/registry/specs/EXT/wgl_display_color_table.txt
+wglDestroyImageBufferI3D https://www.opengl.org/registry/specs/I3D/wgl_image_buffer.txt
+wglDestroyPbufferARB https://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
+wglDestroyPbufferEXT https://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
+wglDisableFrameLockI3D https://www.opengl.org/registry/specs/I3D/wgl_swap_frame_lock.txt
+wglDisableGenlockI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglEnableFrameLockI3D https://www.opengl.org/registry/specs/I3D/wgl_swap_frame_lock.txt
+wglEnableGenlockI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglEndFrameTrackingI3D https://www.opengl.org/registry/specs/I3D/wgl_swap_frame_usage.txt
+wglEnumerateVideoCaptureDevicesNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+wglEnumerateVideoDevicesNV https://www.opengl.org/registry/specs/NV/present_video.txt
+wglGenlockSampleRateI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglGenlockSourceDelayI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglGenlockSourceEdgeI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglGenlockSourceI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglGetContextGPUIDAMD https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
+wglGetCurrentAssociatedContextAMD https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
wglGetCurrentContext http://msdn.microsoft.com/en-us/library/dd374383.aspx
wglGetCurrentDC http://msdn.microsoft.com/en-us/library/dd374384.aspx
-wglGetCurrentReadDCARB http://www.opengl.org/registry/specs/ARB/wgl_make_current_read.txt
-wglGetCurrentReadDCEXT http://www.opengl.org/registry/specs/EXT/wgl_make_current_read.txt
-wglGetDigitalVideoParametersI3D http://www.opengl.org/registry/specs/I3D/wgl_digital_video_control.txt
-wglGetFrameUsageI3D http://www.opengl.org/registry/specs/I3D/wgl_swap_frame_usage.txt
-wglGetGPUIDsAMD http://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
-wglGetGPUInfoAMD http://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
-wglGetGammaTableI3D http://www.opengl.org/registry/specs/I3D/wgl_gamma.txt
-wglGetGammaTableParametersI3D http://www.opengl.org/registry/specs/I3D/wgl_gamma.txt
-wglGetGenlockSampleRateI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglGetGenlockSourceDelayI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglGetGenlockSourceEdgeI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglGetGenlockSourceI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglGetCurrentReadDCARB https://www.opengl.org/registry/specs/ARB/wgl_make_current_read.txt
+wglGetCurrentReadDCEXT https://www.opengl.org/registry/specs/EXT/wgl_make_current_read.txt
+wglGetDigitalVideoParametersI3D https://www.opengl.org/registry/specs/I3D/wgl_digital_video_control.txt
+wglGetFrameUsageI3D https://www.opengl.org/registry/specs/I3D/wgl_swap_frame_usage.txt
+wglGetGPUIDsAMD https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
+wglGetGPUInfoAMD https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
+wglGetGammaTableI3D https://www.opengl.org/registry/specs/I3D/wgl_gamma.txt
+wglGetGammaTableParametersI3D https://www.opengl.org/registry/specs/I3D/wgl_gamma.txt
+wglGetGenlockSampleRateI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglGetGenlockSourceDelayI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglGetGenlockSourceEdgeI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglGetGenlockSourceI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
wglGetLayerPaletteEntries http://msdn.microsoft.com/en-us/library/dd374385.aspx
-wglGetMscRateOML http://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
-wglGetPbufferDCARB http://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
-wglGetPbufferDCEXT http://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
+wglGetMscRateOML https://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
+wglGetPbufferDCARB https://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
+wglGetPbufferDCEXT https://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
wglGetPixelFormat http://msdn.microsoft.com/en-us/library/dd318349.aspx
-wglGetPixelFormatAttribfvARB http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
-wglGetPixelFormatAttribfvEXT http://www.opengl.org/registry/specs/EXT/wgl_pixel_format.txt
-wglGetPixelFormatAttribivARB http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
-wglGetPixelFormatAttribivEXT http://www.opengl.org/registry/specs/EXT/wgl_pixel_format.txt
+wglGetPixelFormatAttribfvARB https://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
+wglGetPixelFormatAttribfvEXT https://www.opengl.org/registry/specs/EXT/wgl_pixel_format.txt
+wglGetPixelFormatAttribivARB https://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
+wglGetPixelFormatAttribivEXT https://www.opengl.org/registry/specs/EXT/wgl_pixel_format.txt
wglGetProcAddress http://msdn.microsoft.com/en-us/library/dd374386.aspx
-wglGetSwapIntervalEXT http://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt
-wglGetSyncValuesOML http://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
-wglIsEnabledFrameLockI3D http://www.opengl.org/registry/specs/I3D/wgl_swap_frame_lock.txt
-wglIsEnabledGenlockI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglJoinSwapGroupNV http://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
-wglLoadDisplayColorTableEXT http://www.opengl.org/registry/specs/EXT/wgl_display_color_table.txt
-wglLockVideoCaptureDeviceNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-wglMakeAssociatedContextCurrentAMD http://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
-wglMakeContextCurrentARB http://www.opengl.org/registry/specs/ARB/wgl_make_current_read.txt
-wglMakeContextCurrentEXT http://www.opengl.org/registry/specs/EXT/wgl_make_current_read.txt
+wglGetSwapIntervalEXT https://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt
+wglGetSyncValuesOML https://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
+wglIsEnabledFrameLockI3D https://www.opengl.org/registry/specs/I3D/wgl_swap_frame_lock.txt
+wglIsEnabledGenlockI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglJoinSwapGroupNV https://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
+wglLoadDisplayColorTableEXT https://www.opengl.org/registry/specs/EXT/wgl_display_color_table.txt
+wglLockVideoCaptureDeviceNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+wglMakeAssociatedContextCurrentAMD https://www.opengl.org/registry/specs/AMD/wgl_gpu_association.txt
+wglMakeContextCurrentARB https://www.opengl.org/registry/specs/ARB/wgl_make_current_read.txt
+wglMakeContextCurrentEXT https://www.opengl.org/registry/specs/EXT/wgl_make_current_read.txt
wglMakeCurrent http://msdn.microsoft.com/en-us/library/dd374387.aspx
-wglQueryCurrentContextNV http://www.opengl.org/registry/specs/NV/present_video.txt
-wglQueryFrameCountNV http://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
-wglQueryFrameLockMasterI3D http://www.opengl.org/registry/specs/I3D/wgl_swap_frame_lock.txt
-wglQueryFrameTrackingI3D http://www.opengl.org/registry/specs/I3D/wgl_swap_frame_usage.txt
-wglQueryGenlockMaxSourceDelayI3D http://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
-wglQueryMaxSwapGroupsNV http://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
-wglQueryPbufferARB http://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
-wglQueryPbufferEXT http://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
-wglQuerySwapGroupNV http://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
-wglQueryVideoCaptureDeviceNV http://www.opengl.org/registry/specs/NV/video_capture.txt
+wglQueryCurrentContextNV https://www.opengl.org/registry/specs/NV/present_video.txt
+wglQueryFrameCountNV https://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
+wglQueryFrameLockMasterI3D https://www.opengl.org/registry/specs/I3D/wgl_swap_frame_lock.txt
+wglQueryFrameTrackingI3D https://www.opengl.org/registry/specs/I3D/wgl_swap_frame_usage.txt
+wglQueryGenlockMaxSourceDelayI3D https://www.opengl.org/registry/specs/I3D/wgl_genlock.txt
+wglQueryMaxSwapGroupsNV https://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
+wglQueryPbufferARB https://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
+wglQueryPbufferEXT https://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
+wglQuerySwapGroupNV https://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
+wglQueryVideoCaptureDeviceNV https://www.opengl.org/registry/specs/NV/video_capture.txt
wglRealizeLayerPalette http://msdn.microsoft.com/en-us/library/dd374388.aspx
-wglReleaseImageBufferEventsI3D http://www.opengl.org/registry/specs/I3D/wgl_image_buffer.txt
-wglReleasePbufferDCARB http://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
-wglReleasePbufferDCEXT http://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
-wglReleaseVideoCaptureDeviceNV http://www.opengl.org/registry/specs/NV/video_capture.txt
-wglResetFrameCountNV http://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
-wglRestoreBufferRegionARB http://www.opengl.org/registry/specs/ARB/wgl_buffer_region.txt
-wglSaveBufferRegionARB http://www.opengl.org/registry/specs/ARB/wgl_buffer_region.txt
-wglSetDigitalVideoParametersI3D http://www.opengl.org/registry/specs/I3D/wgl_digital_video_control.txt
-wglSetGammaTableI3D http://www.opengl.org/registry/specs/I3D/wgl_gamma.txt
-wglSetGammaTableParametersI3D http://www.opengl.org/registry/specs/I3D/wgl_gamma.txt
+wglReleaseImageBufferEventsI3D https://www.opengl.org/registry/specs/I3D/wgl_image_buffer.txt
+wglReleasePbufferDCARB https://www.opengl.org/registry/specs/ARB/wgl_pbuffer.txt
+wglReleasePbufferDCEXT https://www.opengl.org/registry/specs/EXT/wgl_pbuffer.txt
+wglReleaseVideoCaptureDeviceNV https://www.opengl.org/registry/specs/NV/video_capture.txt
+wglResetFrameCountNV https://www.opengl.org/registry/specs/NV/wgl_swap_group.txt
+wglRestoreBufferRegionARB https://www.opengl.org/registry/specs/ARB/wgl_buffer_region.txt
+wglSaveBufferRegionARB https://www.opengl.org/registry/specs/ARB/wgl_buffer_region.txt
+wglSetDigitalVideoParametersI3D https://www.opengl.org/registry/specs/I3D/wgl_digital_video_control.txt
+wglSetGammaTableI3D https://www.opengl.org/registry/specs/I3D/wgl_gamma.txt
+wglSetGammaTableParametersI3D https://www.opengl.org/registry/specs/I3D/wgl_gamma.txt
wglSetLayerPaletteEntries http://msdn.microsoft.com/en-us/library/dd374389.aspx
wglSetPixelFormat http://msdn.microsoft.com/en-us/library/dd369049.aspx
-wglSetStereoEmitterState3DL http://www.opengl.org/registry/specs/3DL/stereo_control.txt
+wglSetStereoEmitterState3DL https://www.opengl.org/registry/specs/3DL/stereo_control.txt
wglShareLists http://msdn.microsoft.com/en-us/library/dd374390.aspx
wglSwapBuffers http://msdn.microsoft.com/en-us/library/dd369060.aspx
-wglSwapBuffersMscOML http://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
-wglSwapIntervalEXT http://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt
+wglSwapBuffersMscOML https://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
+wglSwapIntervalEXT https://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt
wglSwapLayerBuffers http://msdn.microsoft.com/en-us/library/dd374391.aspx
-wglSwapLayerBuffersMscOML http://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
+wglSwapLayerBuffersMscOML https://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
wglUseFontBitmaps http://msdn.microsoft.com/en-us/library/dd374392.aspx
wglUseFontOutlines http://msdn.microsoft.com/en-us/library/dd374393.aspx
-wglWaitForMscOML http://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
-wglWaitForSbcOML http://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
+wglWaitForMscOML https://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
+wglWaitForSbcOML https://www.opengl.org/registry/specs/OML/wgl_sync_control.txt
diff --git a/gui/retracer.cpp b/gui/retracer.cpp
index f3f1feb8..02f01454 100644
--- a/gui/retracer.cpp
+++ b/gui/retracer.cpp
@@ -12,7 +12,8 @@
#include <QList>
#include <QImage>
-#include <qjson/parser.h>
+#include "qubjson.h"
+
/**
* Wrapper around a QProcess which enforces IO to block .
@@ -137,7 +138,8 @@ Retracer::Retracer(QObject *parent)
m_captureCall(0),
m_profileGpu(false),
m_profileCpu(false),
- m_profilePixels(false)
+ m_profilePixels(false),
+ m_profileMemory(false)
{
qRegisterMetaType<QList<ApiTraceError> >();
}
@@ -222,16 +224,22 @@ bool Retracer::isProfilingPixels() const
return m_profilePixels;
}
+bool Retracer::isProfilingMemory() const
+{
+ return m_profileMemory;
+}
+
bool Retracer::isProfiling() const
{
- return m_profileGpu || m_profileCpu || m_profilePixels;
+ return m_profileGpu || m_profileCpu || m_profilePixels | m_profileMemory;
}
-void Retracer::setProfiling(bool gpu, bool cpu, bool pixels)
+void Retracer::setProfiling(bool gpu, bool cpu, bool pixels, bool memory)
{
m_profileGpu = gpu;
m_profileCpu = cpu;
m_profilePixels = pixels;
+ m_profileMemory = memory;
}
void Retracer::setCaptureAtCallNumber(qlonglong num)
@@ -264,46 +272,44 @@ void Retracer::setCaptureThumbnails(bool enable)
m_captureThumbnails = enable;
}
-/**
- * Starting point for the retracing thread.
- *
- * Overrides QThread::run().
- */
-void Retracer::run()
+void Retracer::addThumbnailToCapture(qlonglong num)
{
- QString msg = QLatin1String("Replay finished!");
+ if (!m_thumbnailsToCapture.contains(num)) {
+ m_thumbnailsToCapture.append(num);
+ }
+}
- /*
- * Construct command line
- */
+void Retracer::resetThumbnailsToCapture()
+{
+ m_thumbnailsToCapture.clear();
+}
- QString prog;
- QStringList arguments;
+QString Retracer::thumbnailCallSet() const
+{
+ QString callSet;
- switch (m_api) {
- case trace::API_GL:
- prog = QLatin1String("glretrace");
- break;
- case trace::API_EGL:
- prog = QLatin1String("eglretrace");
- break;
- case trace::API_DX:
- case trace::API_D3D7:
- case trace::API_D3D8:
- case trace::API_D3D9:
- case trace::API_DXGI:
-#ifdef Q_OS_WIN
- prog = QLatin1String("d3dretrace");
-#else
- prog = QLatin1String("wine");
- arguments << QLatin1String("d3dretrace.exe");
-#endif
- break;
- default:
- emit finished(QLatin1String("Unsupported API"));
- return;
+ bool isFirst = true;
+
+ foreach (qlonglong callIndex, m_thumbnailsToCapture) {
+ // TODO: detect contiguous ranges
+ if (!isFirst) {
+ callSet.append(QLatin1String(","));
+ } else {
+ isFirst = false;
+ }
+
+ //emit "callIndex"
+ callSet.append(QString::number(callIndex));
}
+ //qDebug() << QLatin1String("debug: call set to capture: ") << callSet;
+ return callSet;
+}
+
+QStringList Retracer::retraceArguments() const
+{
+ QStringList arguments;
+
if (m_singlethread) {
arguments << QLatin1String("--singlethread");
}
@@ -315,7 +321,13 @@ void Retracer::run()
if (m_captureState) {
arguments << QLatin1String("-D");
arguments << QString::number(m_captureCall);
+ arguments << QLatin1String("--dump-format");
+ arguments << QLatin1String("ubjson");
} else if (m_captureThumbnails) {
+ if (!m_thumbnailsToCapture.isEmpty()) {
+ arguments << QLatin1String("-S");
+ arguments << thumbnailCallSet();
+ }
arguments << QLatin1String("-s"); // emit snapshots
arguments << QLatin1String("-"); // emit to stdout
} else if (isProfiling()) {
@@ -330,19 +342,65 @@ void Retracer::run()
if (m_profilePixels) {
arguments << QLatin1String("--ppd");
}
+
+ if (m_profileMemory) {
+ arguments << QLatin1String("--pmem");
+ }
} else {
- if (m_doubleBuffered) {
- arguments << QLatin1String("--db");
- } else {
+ if (!m_doubleBuffered) {
arguments << QLatin1String("--sb");
}
if (m_benchmarking) {
arguments << QLatin1String("-b");
+ } else {
+ arguments << QLatin1String("-d");
}
}
+ return arguments;
+}
- arguments << m_fileName;
+/**
+ * Starting point for the retracing thread.
+ *
+ * Overrides QThread::run().
+ */
+void Retracer::run()
+{
+ QString msg = QLatin1String("Replay finished!");
+
+ /*
+ * Construct command line
+ */
+
+ QString prog;
+ QStringList arguments;
+
+ switch (m_api) {
+ case trace::API_GL:
+ prog = QLatin1String("glretrace");
+ break;
+ case trace::API_EGL:
+ prog = QLatin1String("eglretrace");
+ break;
+ case trace::API_DX:
+ case trace::API_D3D7:
+ case trace::API_D3D8:
+ case trace::API_D3D9:
+ case trace::API_DXGI:
+#ifdef Q_OS_WIN
+ prog = QLatin1String("d3dretrace");
+#else
+ prog = QLatin1String("wine");
+ arguments << QLatin1String("d3dretrace.exe");
+#endif
+ break;
+ default:
+ emit finished(QLatin1String("Unsupported API"));
+ return;
+ }
+
+ arguments << retraceArguments() << m_fileName;
/*
* Support remote execution on a separate target.
@@ -358,6 +416,15 @@ void Retracer::run()
* Start the process.
*/
+ {
+ QDebug debug(QtDebugMsg);
+ debug << "Running:";
+ debug << prog;
+ foreach (const QString &argument, arguments) {
+ debug << argument;
+ }
+ }
+
QProcess process;
process.start(prog, arguments, QIODevice::ReadOnly);
@@ -370,7 +437,7 @@ void Retracer::run()
* Process standard output
*/
- QList<QImage> thumbnails;
+ ImageHash thumbnails;
QVariantMap parsedJson;
trace::Profile* profile = NULL;
@@ -379,32 +446,8 @@ void Retracer::run()
BlockingIODevice io(&process);
if (m_captureState) {
- /*
- * Parse JSON from the output.
- *
- * XXX: QJSON's scanner is inneficient as it abuses single
- * character QIODevice::peek (not cheap), instead of maintaining a
- * lookahead character on its own.
- */
-
- bool ok = false;
- QJson::Parser jsonParser;
-
- // Allow Nan/Infinity
- jsonParser.allowSpecialNumbers(true);
-#if 0
- parsedJson = jsonParser.parse(&io, &ok).toMap();
-#else
- /*
- * XXX: QJSON expects blocking IO, and it looks like
- * BlockingIODevice does not work reliably in all cases.
- */
+ parsedJson = decodeUBJSONObject(&io).toMap();
process.waitForFinished(-1);
- parsedJson = jsonParser.parse(&process, &ok).toMap();
-#endif
- if (!ok) {
- msg = QLatin1String("failed to parse JSON");
- }
} else if (m_captureThumbnails) {
/*
* Parse concatenated PNM images from output.
@@ -454,7 +497,7 @@ void Retracer::run()
}
QImage thumb = thumbnail(snapshot);
- thumbnails.append(thumb);
+ thumbnails.insert(info.commentNumber, thumb);
}
Q_ASSERT(process.state() != QProcess::Running);
diff --git a/gui/retracer.h b/gui/retracer.h
index 4e92642b..bd395e2c 100644
--- a/gui/retracer.h
+++ b/gui/retracer.h
@@ -1,7 +1,7 @@
-#ifndef RETRACER_H
-#define RETRACER_H
+#pragma once
#include "trace_api.hpp"
+#include "apitrace.h"
#include "apitracecall.h"
#include <QThread>
@@ -40,8 +40,9 @@ public:
bool isProfilingGpu() const;
bool isProfilingCpu() const;
bool isProfilingPixels() const;
+ bool isProfilingMemory() const;
bool isProfiling() const;
- void setProfiling(bool gpu, bool cpu, bool pixels);
+ void setProfiling(bool gpu, bool cpu, bool pixels, bool memory);
void setCaptureAtCallNumber(qlonglong num);
qlonglong captureAtCallNumber() const;
@@ -52,11 +53,17 @@ public:
bool captureThumbnails() const;
void setCaptureThumbnails(bool enable);
+ void addThumbnailToCapture(qlonglong num);
+ void resetThumbnailsToCapture();
+ QString thumbnailCallSet() const;
+
+ QStringList retraceArguments() const;
+
signals:
void finished(const QString &output);
void foundState(ApiTraceState *state);
void foundProfile(trace::Profile *profile);
- void foundThumbnails(const QList<QImage> &thumbnails);
+ void foundThumbnails(const ImageHash &thumbnails);
void error(const QString &msg);
void retraceErrors(const QList<ApiTraceError> &errors);
@@ -77,6 +84,9 @@ private:
bool m_profileGpu;
bool m_profileCpu;
bool m_profilePixels;
-};
+ bool m_profileMemory;
-#endif
+ QProcessEnvironment m_processEnvironment;
+
+ QList<qlonglong> m_thumbnailsToCapture;
+};
diff --git a/gui/saverthread.cpp b/gui/saverthread.cpp
index 4ad83c58..e9e5a3fa 100644
--- a/gui/saverthread.cpp
+++ b/gui/saverthread.cpp
@@ -253,6 +253,16 @@ public:
m_editedValue = new trace::String(newString);
}
+ virtual void visit(trace::WString *node)
+ {
+ QString str = m_variant.toString();
+ size_t len = str.length();
+ wchar_t *newString = new wchar_t[len + 1];
+ str.toWCharArray(newString);
+ newString[len] = 0;
+ m_editedValue = new trace::WString(newString);
+ }
+
virtual void visit(trace::Enum *e)
{
m_editedValue = e;
@@ -364,6 +374,7 @@ void SaverThread::run()
} else {
writer.writeCall(call);
}
+ delete call;
}
writer.close();
diff --git a/gui/saverthread.h b/gui/saverthread.h
index e8c6889f..f53296e1 100644
--- a/gui/saverthread.h
+++ b/gui/saverthread.h
@@ -1,5 +1,4 @@
-#ifndef SAVERTHREAD_H
-#define SAVERTHREAD_H
+#pragma once
#include "apitrace.h"
@@ -31,6 +30,3 @@ private:
QString m_writeFileName;
QSet<ApiTraceCall*> m_editedCalls;
};
-
-
-#endif
diff --git a/gui/searchwidget.h b/gui/searchwidget.h
index f59b4a0c..6415ef28 100644
--- a/gui/searchwidget.h
+++ b/gui/searchwidget.h
@@ -1,5 +1,4 @@
-#ifndef SEARCHWIDGET_H
-#define SEARCHWIDGET_H
+#pragma once
#include "ui_searchwidget.h"
#include <QPalette>
@@ -34,5 +33,3 @@ private:
Ui_SearchWidget m_ui;
QPalette m_origPalette;
};
-
-#endif
diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp
index c44b1074..0f6f1c9c 100644
--- a/gui/settingsdialog.cpp
+++ b/gui/settingsdialog.cpp
@@ -1,6 +1,8 @@
#include "settingsdialog.h"
+#include <QFileDialog>
#include <QMessageBox>
+#include <QSettings>
SettingsDialog::SettingsDialog(QWidget *parent)
: QDialog(parent),
@@ -27,6 +29,26 @@ SettingsDialog::SettingsDialog(QWidget *parent)
connect(showFilterEdit, SIGNAL(textEdited(const QString &)),
SLOT(regexpChanged(const QString&)));
+ connect(adbPathEdit, SIGNAL(textEdited(const QString &)),
+ SLOT(adbPathChanged(const QString&)));
+
+
+ {
+ QSettings s;
+ s.beginGroup(QLatin1String("android"));
+ adbPathEdit->setText(s.value(QLatin1String("adbPath"), adbPathEdit->text()).toString());
+ stdoutPort->setValue(s.value(QLatin1String("stdoutPort"), stdoutPort->value()).toInt());
+ stderrPort->setValue(s.value(QLatin1String("stderrPort"), stderrPort->value()).toInt());
+ s.endGroup();
+ }
+
+ connect(chooseAdbPath, SIGNAL(clicked()),
+ SLOT(chooseAdbPathPushed()));
+ connect(stdoutPort, SIGNAL(valueChanged(int)),
+ SLOT(stdoutPortChanged(int)));
+ connect(stderrPort, SIGNAL(valueChanged(int)),
+ SLOT(stderrPortChanged(int)));
+
showFilterCB->setCurrentIndex(0);
showFilterEdit->setText(m_showFilters.constBegin().value().pattern());
}
@@ -139,6 +161,44 @@ void SettingsDialog::regexpChanged(const QString &pattern)
}
}
+void SettingsDialog::adbPathChanged(const QString &adbPath)
+{
+ QSettings s;
+ s.beginGroup(QLatin1String("android"));
+ s.setValue(QLatin1String("adbPath"), adbPath);
+ s.endGroup();
+}
+
+void SettingsDialog::chooseAdbPathPushed()
+{
+ QString fileName = QFileDialog::getOpenFileName(this,
+ tr("Choose adb path"), adbPathEdit->text(), QLatin1String("ADB (adb"
+#ifdef Q_OS_WIN
+ ".exe"
+#endif
+ ")"));
+ if (!fileName.isEmpty()) {
+ adbPathEdit->setText(fileName);
+ adbPathChanged(fileName);
+ }
+}
+
+void SettingsDialog::stdoutPortChanged(int port)
+{
+ QSettings s;
+ s.beginGroup(QLatin1String("android"));
+ s.setValue(QLatin1String("stdoutPort"), port);
+ s.endGroup();
+}
+
+void SettingsDialog::stderrPortChanged(int port)
+{
+ QSettings s;
+ s.beginGroup(QLatin1String("android"));
+ s.setValue(QLatin1String("stderrPort"), port);
+ s.endGroup();
+}
+
void SettingsDialog::setFilterModel(ApiTraceFilter *filter)
{
m_filter = filter;
diff --git a/gui/settingsdialog.h b/gui/settingsdialog.h
index b676b9df..aa2db34f 100644
--- a/gui/settingsdialog.h
+++ b/gui/settingsdialog.h
@@ -1,5 +1,4 @@
-#ifndef SETTINGSDIALOG_H
-#define SETTINGSDIALOG_H
+#pragma once
#include "trace_api.hpp"
#include "apitracefilter.h"
@@ -16,16 +15,20 @@ public:
void accept();
void setFilterModel(ApiTraceFilter *filter);
+
private slots:
void changeRegexp(const QString &name);
void regexpChanged(const QString &pattern);
+ void adbPathChanged(const QString &adbPath);
+ void chooseAdbPathPushed();
+ void stdoutPortChanged(int port);
+ void stderrPortChanged(int port);
private:
void filtersFromModel(const ApiTraceFilter *model);
void filtersToModel(ApiTraceFilter *model);
+
private:
QMap<QString, QRegExp> m_showFilters;
ApiTraceFilter *m_filter;
};
-
-#endif
diff --git a/gui/shaderssourcewidget.h b/gui/shaderssourcewidget.h
index 9a5c3228..d40ea6e8 100644
--- a/gui/shaderssourcewidget.h
+++ b/gui/shaderssourcewidget.h
@@ -1,5 +1,4 @@
-#ifndef SHADERSSOURCEWIDGET_H
-#define SHADERSSOURCEWIDGET_H
+#pragma once
#include "ui_shaderssourcewidget.h"
#include <QWidget>
@@ -22,5 +21,3 @@ private:
QMap<QString, QString> m_sources;
GLSLEdit *m_edit;
};
-
-#endif
diff --git a/gui/thumbnail.h b/gui/thumbnail.h
index 23155648..9cf8fca6 100644
--- a/gui/thumbnail.h
+++ b/gui/thumbnail.h
@@ -1,5 +1,4 @@
-#ifndef THUMBNAIL_H
-#define THUMBNAIL_H
+#pragma once
#define THUMBNAIL_SIZE 64
@@ -9,5 +8,3 @@ inline QImage
thumbnail(const QImage &image, Qt::TransformationMode transformationMode = Qt::FastTransformation) {
return image.scaled(THUMBNAIL_SIZE, THUMBNAIL_SIZE, Qt::KeepAspectRatio, transformationMode);
}
-
-#endif
diff --git a/gui/tracedialog.h b/gui/tracedialog.h
index 0ebe13ad..cf45833d 100644
--- a/gui/tracedialog.h
+++ b/gui/tracedialog.h
@@ -1,5 +1,4 @@
-#ifndef TRACEDIALOG_H
-#define TRACEDIALOG_H
+#pragma once
#include "ui_tracedialog.h"
#include <QDialog>
@@ -22,5 +21,3 @@ private slots:
private:
bool isFileOk(const QString &fileName);
};
-
-#endif
diff --git a/gui/traceloader.cpp b/gui/traceloader.cpp
index 59f8803e..483f9912 100644
--- a/gui/traceloader.cpp
+++ b/gui/traceloader.cpp
@@ -34,7 +34,6 @@ TraceLoader::~TraceLoader()
{
m_parser.close();
qDeleteAll(m_signatures);
- qDeleteAll(m_enumSignatures);
}
void TraceLoader::loadTrace(const QString &filename)
@@ -45,9 +44,7 @@ void TraceLoader::loadTrace(const QString &filename)
if (!m_frameBookmarks.isEmpty()) {
qDeleteAll(m_signatures);
- qDeleteAll(m_enumSignatures);
m_signatures.clear();
- m_enumSignatures.clear();
m_frameBookmarks.clear();
m_createdFrames.clear();
m_parser.close();
@@ -58,14 +55,19 @@ void TraceLoader::loadTrace(const QString &filename)
return;
}
+ if (!m_parser.supportsOffsets()) {
+ emit parseProblem(
+ "This trace in compressed in a format that does not allow random seeking.\n"
+ "Please repack the trace with `apitrace repack`."
+ );
+ m_parser.close();
+ return;
+ }
+
emit startedParsing();
- if (m_parser.supportsOffsets()) {
- scanTrace();
- } else {
- //Load the entire file into memory
- parseTrace();
- }
+ scanTrace();
+
emit guessedApi(static_cast<int>(m_parser.api));
emit finishedParsing();
}
@@ -169,63 +171,6 @@ void TraceLoader::scanTrace()
emit framesLoaded(frames);
}
-void TraceLoader::parseTrace()
-{
- QList<ApiTraceFrame*> frames;
- int frameCount = 0;
- int lastPercentReport = 0;
-
- ApiTraceFrame *currentFrame = new ApiTraceFrame();
- currentFrame->number = frameCount;
-
- FrameContents frameCalls;
- while (frameCalls.load(this, currentFrame, m_helpHash, m_parser)) {
-
- if (frameCalls.topLevelCount() == frameCalls.allCallsCount()) {
- currentFrame->setCalls(frameCalls.allCalls(),
- frameCalls.allCalls(),
- frameCalls.binaryDataSize());
- } else {
- currentFrame->setCalls(frameCalls.topLevelCalls(),
- frameCalls.allCalls(),
- frameCalls.binaryDataSize());
- }
- frames.append(currentFrame);
- if (frames.count() >= FRAMES_TO_CACHE) {
- emit framesLoaded(frames);
- frames.clear();
- }
- if (m_parser.percentRead() - lastPercentReport >= 5) {
- emit parsed(m_parser.percentRead());
- lastPercentReport = m_parser.percentRead();
- }
- ++frameCount;
- currentFrame = new ApiTraceFrame();
- currentFrame->number = frameCount;
-
- frameCalls.reset();
- }
-
- //last frames won't have markers
- // it's just a bunch of Delete calls for every object
- // after the last SwapBuffers
- if (!frameCalls.isEmpty()) {
- if (frameCalls.topLevelCount() == frameCalls.allCallsCount()) {
- currentFrame->setCalls(frameCalls.allCalls(),
- frameCalls.allCalls(),
- frameCalls.binaryDataSize());
- } else {
- currentFrame->setCalls(frameCalls.topLevelCalls(),
- frameCalls.allCalls(),
- frameCalls.binaryDataSize());
- }
- frames.append(currentFrame);
- }
- if (frames.count()) {
- emit framesLoaded(frames);
- }
-}
-
ApiTraceCallSignature * TraceLoader::signature(unsigned id)
{
@@ -242,49 +187,32 @@ void TraceLoader::addSignature(unsigned id, ApiTraceCallSignature *signature)
m_signatures[id] = signature;
}
-ApiTraceEnumSignature * TraceLoader::enumSignature(unsigned id)
-{
- if (id >= m_enumSignatures.count()) {
- m_enumSignatures.resize(id + 1);
- return NULL;
- } else {
- return m_enumSignatures[id];
- }
-}
-
-void TraceLoader::addEnumSignature(unsigned id, ApiTraceEnumSignature *signature)
-{
- m_enumSignatures[id] = signature;
-}
-
void TraceLoader::searchNext(const ApiTrace::SearchRequest &request)
{
Q_ASSERT(m_parser.supportsOffsets());
- if (m_parser.supportsOffsets()) {
- int startFrame = m_createdFrames.indexOf(request.frame);
- const FrameBookmark &frameBookmark = m_frameBookmarks[startFrame];
- m_parser.setBookmark(frameBookmark.start);
- trace::Call *call = 0;
- while ((call = m_parser.parse_call())) {
-
- if (callContains(call, request.text, request.cs)) {
- unsigned frameIdx = callInFrame(call->no);
- ApiTraceFrame *frame = m_createdFrames[frameIdx];
- const QVector<ApiTraceCall*> calls =
- fetchFrameContents(frame);
- for (int i = 0; i < calls.count(); ++i) {
- if (calls[i]->index() == call->no) {
- emit searchResult(request, ApiTrace::SearchResult_Found,
- calls[i]);
- break;
- }
+ int startFrame = m_createdFrames.indexOf(request.frame);
+ const FrameBookmark &frameBookmark = m_frameBookmarks[startFrame];
+ m_parser.setBookmark(frameBookmark.start);
+ trace::Call *call = 0;
+ while ((call = m_parser.parse_call())) {
+
+ if (callContains(call, request.text, request.cs)) {
+ unsigned frameIdx = callInFrame(call->no);
+ ApiTraceFrame *frame = m_createdFrames[frameIdx];
+ const QVector<ApiTraceCall*> calls =
+ fetchFrameContents(frame);
+ for (int i = 0; i < calls.count(); ++i) {
+ if (calls[i]->index() == call->no) {
+ emit searchResult(request, ApiTrace::SearchResult_Found,
+ calls[i]);
+ break;
}
- delete call;
- return;
}
-
delete call;
+ return;
}
+
+ delete call;
}
emit searchResult(request, ApiTrace::SearchResult_NotFound, 0);
}
@@ -292,40 +220,38 @@ void TraceLoader::searchNext(const ApiTrace::SearchRequest &request)
void TraceLoader::searchPrev(const ApiTrace::SearchRequest &request)
{
Q_ASSERT(m_parser.supportsOffsets());
- if (m_parser.supportsOffsets()) {
- int startFrame = m_createdFrames.indexOf(request.frame);
- trace::Call *call = 0;
- QList<trace::Call*> frameCalls;
- int frameIdx = startFrame;
+ int startFrame = m_createdFrames.indexOf(request.frame);
+ trace::Call *call = 0;
+ QList<trace::Call*> frameCalls;
+ int frameIdx = startFrame;
- const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
- int numCallsToParse = frameBookmark.numberOfCalls;
- m_parser.setBookmark(frameBookmark.start);
+ const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
+ int numCallsToParse = frameBookmark.numberOfCalls;
+ m_parser.setBookmark(frameBookmark.start);
- while ((call = m_parser.parse_call())) {
+ while ((call = m_parser.parse_call())) {
- frameCalls.append(call);
- --numCallsToParse;
+ frameCalls.append(call);
+ --numCallsToParse;
- if (numCallsToParse == 0) {
- bool foundCall = searchCallsBackwards(frameCalls,
- frameIdx,
- request);
+ if (numCallsToParse == 0) {
+ bool foundCall = searchCallsBackwards(frameCalls,
+ frameIdx,
+ request);
- qDeleteAll(frameCalls);
- frameCalls.clear();
- if (foundCall) {
- return;
- }
+ qDeleteAll(frameCalls);
+ frameCalls.clear();
+ if (foundCall) {
+ return;
+ }
- --frameIdx;
+ --frameIdx;
- if (frameIdx >= 0) {
- const FrameBookmark &frameBookmark =
- m_frameBookmarks[frameIdx];
- m_parser.setBookmark(frameBookmark.start);
- numCallsToParse = frameBookmark.numberOfCalls;
- }
+ if (frameIdx >= 0) {
+ const FrameBookmark &frameBookmark =
+ m_frameBookmarks[frameIdx];
+ m_parser.setBookmark(frameBookmark.start);
+ numCallsToParse = frameBookmark.numberOfCalls;
}
}
}
@@ -396,30 +322,28 @@ TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame)
return currentFrame->calls();
}
- if (m_parser.supportsOffsets()) {
- unsigned frameIdx = currentFrame->number;
- int numOfCalls = numberOfCallsInFrame(frameIdx);
-
- if (numOfCalls) {
- const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
-
- m_parser.setBookmark(frameBookmark.start);
-
- FrameContents frameCalls(numOfCalls);
- frameCalls.load(this, currentFrame, m_helpHash, m_parser);
- if (frameCalls.topLevelCount() == frameCalls.allCallsCount()) {
- emit frameContentsLoaded(currentFrame,
- frameCalls.allCalls(),
- frameCalls.allCalls(),
- frameCalls.binaryDataSize());
- } else {
- emit frameContentsLoaded(currentFrame,
- frameCalls.topLevelCalls(),
- frameCalls.allCalls(),
- frameCalls.binaryDataSize());
- }
- return frameCalls.allCalls();
+ unsigned frameIdx = currentFrame->number;
+ int numOfCalls = numberOfCallsInFrame(frameIdx);
+
+ if (numOfCalls) {
+ const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
+
+ m_parser.setBookmark(frameBookmark.start);
+
+ FrameContents frameCalls(numOfCalls);
+ frameCalls.load(this, currentFrame, m_helpHash, m_parser);
+ if (frameCalls.topLevelCount() == frameCalls.allCallsCount()) {
+ emit frameContentsLoaded(currentFrame,
+ frameCalls.allCalls(),
+ frameCalls.allCalls(),
+ frameCalls.binaryDataSize());
+ } else {
+ emit frameContentsLoaded(currentFrame,
+ frameCalls.topLevelCalls(),
+ frameCalls.allCalls(),
+ frameCalls.binaryDataSize());
}
+ return frameCalls.allCalls();
}
return QVector<ApiTraceCall*>();
}
diff --git a/gui/traceloader.h b/gui/traceloader.h
index 3714f651..6519a4e7 100644
--- a/gui/traceloader.h
+++ b/gui/traceloader.h
@@ -1,5 +1,4 @@
-#ifndef TRACELOADER_H
-#define TRACELOADER_H
+#pragma once
#include "apitrace.h"
@@ -22,8 +21,7 @@ public:
ApiTraceCallSignature *signature(unsigned id);
void addSignature(unsigned id, ApiTraceCallSignature *signature);
- ApiTraceEnumSignature *enumSignature(unsigned id);
- void addEnumSignature(unsigned id, ApiTraceEnumSignature *signature);
+ trace::EnumSig *enumSignature(unsigned id);
private:
class FrameContents
@@ -58,6 +56,7 @@ public slots:
void search(const ApiTrace::SearchRequest &request);
signals:
+ void parseProblem(const QString &message);
void startedParsing();
void parsed(int percent);
void guessedApi(int api);
@@ -94,7 +93,6 @@ private:
void loadHelpFile();
void guessApi(const trace::Call *call);
void scanTrace();
- void parseTrace();
void searchNext(const ApiTrace::SearchRequest &request);
void searchPrev(const ApiTrace::SearchRequest &request);
@@ -118,7 +116,4 @@ private:
QHash<QString, QUrl> m_helpHash;
QVector<ApiTraceCallSignature*> m_signatures;
- QVector<ApiTraceEnumSignature*> m_enumSignatures;
};
-
-#endif
diff --git a/gui/traceprocess.h b/gui/traceprocess.h
index 343bac96..f3634237 100644
--- a/gui/traceprocess.h
+++ b/gui/traceprocess.h
@@ -1,5 +1,4 @@
-#ifndef TRACEPROCESS_H
-#define TRACEPROCESS_H
+#pragma once
#include <QObject>
#include <QProcess>
@@ -40,5 +39,3 @@ private:
bool m_canTrace;
};
-
-#endif
diff --git a/gui/trimprocess.cpp b/gui/trimprocess.cpp
index 34639c63..854ef88f 100644
--- a/gui/trimprocess.cpp
+++ b/gui/trimprocess.cpp
@@ -60,7 +60,7 @@ void TrimProcess::start()
QString callSetArgument = callSetFormat
.arg(m_trimIndex);
- arguments << QLatin1String("trim");
+ arguments << QLatin1String("trim-auto");
arguments << outputArgument;
arguments << callSetArgument;
arguments << m_tracePath;
diff --git a/gui/trimprocess.h b/gui/trimprocess.h
index 4cce35d8..0d55c889 100644
--- a/gui/trimprocess.h
+++ b/gui/trimprocess.h
@@ -1,5 +1,4 @@
-#ifndef TRIMPROCESS_H
-#define TRIMPROCESS_H
+#pragma once
#include "apitrace.h"
@@ -40,5 +39,3 @@ private:
int m_trimIndex;
QProcess *m_process;
};
-
-#endif
diff --git a/gui/ui/androiddevicedialog.ui b/gui/ui/androiddevicedialog.ui
new file mode 100644
index 00000000..f26b8ba0
--- /dev/null
+++ b/gui/ui/androiddevicedialog.ui
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AndroidDeviceDialog</class>
+ <widget class="QDialog" name="AndroidDeviceDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>636</width>
+ <height>448</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Select Android Device</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="3" column="0" colspan="2">
+ <widget class="QCheckBox" name="defaultDeviceCheckBox">
+ <property name="text">
+ <string>Always use this device for architecture %1</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="refreshDevicesButton">
+ <property name="text">
+ <string>Refresh Device List</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <widget class="QStackedWidget" name="stackedWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="devicesPage">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="1" column="0">
+ <widget class="QTreeView" name="deviceView">
+ <property name="minimumSize">
+ <size>
+ <width>600</width>
+ <height>300</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="missingLabel">
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;aaa&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0057ae;&quot;&gt;My device is missing&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="noDevicesPage">
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="noDeviceFoundLabel">
+ <property name="text">
+ <string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>AndroidDeviceDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AndroidDeviceDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/gui/ui/androidfiledialog.ui b/gui/ui/androidfiledialog.ui
new file mode 100644
index 00000000..662b43b6
--- /dev/null
+++ b/gui/ui/androidfiledialog.ui
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AndroidFileDialog</class>
+ <widget class="QDialog" name="AndroidFileDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>501</width>
+ <height>325</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Look in:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="pathComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="upButton">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTableView" name="filesView">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="showGrid">
+ <bool>false</bool>
+ </property>
+ <property name="cornerButtonEnabled">
+ <bool>false</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>File name:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="fileLineEdit"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AndroidFileDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>294</x>
+ <y>311</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>fileLineEdit</sender>
+ <signal>returnPressed()</signal>
+ <receiver>AndroidFileDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>164</x>
+ <y>262</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>4</x>
+ <y>282</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/gui/ui/imageviewer.ui b/gui/ui/imageviewer.ui
index a86d6ae3..4acfa296 100644
--- a/gui/ui/imageviewer.ui
+++ b/gui/ui/imageviewer.ui
@@ -141,6 +141,15 @@
</item>
<item>
<widget class="QDoubleSpinBox" name="lowerSpinBox">
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-999.999000000000024</double>
+ </property>
+ <property name="maximum">
+ <double>999.999000000000024</double>
+ </property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
@@ -155,6 +164,15 @@
</item>
<item>
<widget class="QDoubleSpinBox" name="upperSpinBox">
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-999.999000000000024</double>
+ </property>
+ <property name="maximum">
+ <double>999.999000000000024</double>
+ </property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
diff --git a/gui/ui/jumpwidget.ui b/gui/ui/jumpwidget.ui
index 675dabfd..fb915359 100644
--- a/gui/ui/jumpwidget.ui
+++ b/gui/ui/jumpwidget.ui
@@ -55,7 +55,7 @@
</sizepolicy>
</property>
<property name="maximum">
- <number>9999999</number>
+ <number>999999999</number>
</property>
</widget>
</item>
diff --git a/gui/ui/mainwindow.ui b/gui/ui/mainwindow.ui
index 129d0275..376f70e3 100644
--- a/gui/ui/mainwindow.ui
+++ b/gui/ui/mainwindow.ui
@@ -45,15 +45,31 @@
<x>0</x>
<y>0</y>
<width>787</width>
- <height>21</height>
+ <height>24</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
+ <widget class="QMenu" name="menu_Android">
+ <property name="title">
+ <string>&amp;Android</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../qapitrace.qrc">
+ <normaloff>:/resources/android.png</normaloff>:/resources/android.png</iconset>
+ </property>
+ <addaction name="actionPullTrace"/>
+ <addaction name="actionPushTrace"/>
+ <addaction name="actionLinkTrace"/>
+ <addaction name="actionRetraceOnAndroid"/>
+ </widget>
<addaction name="actionNew"/>
<addaction name="actionOpen"/>
+ <addaction name="actionSave"/>
+ <addaction name="separator"/>
+ <addaction name="menu_Android"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
@@ -76,6 +92,7 @@
<addaction name="actionLookupState"/>
<addaction name="actionShowThumbnails"/>
<addaction name="actionTrim"/>
+ <addaction name="actionLeakTrace"/>
<addaction name="separator"/>
<addaction name="actionOptions"/>
</widget>
@@ -117,7 +134,7 @@
<widget class="QWidget" name="dockWidgetContents">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
- <widget class="QWebView" name="detailsWebView" native="true">
+ <widget class="QWebView" name="detailsWebView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Ignored">
<horstretch>0</horstretch>
@@ -250,6 +267,39 @@
</item>
</layout>
</widget>
+ <widget class="QWidget" name="buffersTab">
+ <attribute name="title">
+ <string>Buffers</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <widget class="QTreeWidget" name="buffersTreeWidget">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="sortingEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
</layout>
@@ -398,6 +448,26 @@
</widget>
</item>
<item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="bufferExportButton">
+ <property name="text">
+ <string>Export</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -492,6 +562,18 @@
<string>Ctrl+O</string>
</property>
</action>
+ <action name="actionSave">
+ <property name="icon">
+ <iconset resource="../qapitrace.qrc">
+ <normaloff>:/resources/document-edit.png</normaloff>:/resources/document-edit.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Save As...</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+S</string>
+ </property>
+ </action>
<action name="actionQuit">
<property name="icon">
<iconset resource="../qapitrace.qrc">
@@ -553,7 +635,7 @@
</action>
<action name="actionTrim">
<property name="text">
- <string>Tr&amp;im</string>
+ <string>Tr&amp;im (experimental)</string>
</property>
<property name="shortcut">
<string>Ctrl+I</string>
@@ -651,6 +733,58 @@
<string>Ctrl+P</string>
</property>
</action>
+ <action name="actionPullTrace">
+ <property name="icon">
+ <iconset resource="../qapitrace.qrc">
+ <normaloff>:/resources/go-bottom.png</normaloff>:/resources/go-bottom.png</iconset>
+ </property>
+ <property name="text">
+ <string>Pull trace</string>
+ </property>
+ </action>
+ <action name="actionPushTrace">
+ <property name="icon">
+ <iconset resource="../qapitrace.qrc">
+ <normaloff>:/resources/go-top.png</normaloff>:/resources/go-top.png</iconset>
+ </property>
+ <property name="text">
+ <string>Push trace</string>
+ </property>
+ </action>
+ <action name="actionLinkTrace">
+ <property name="icon">
+ <iconset resource="../qapitrace.qrc">
+ <normaloff>:/resources/android-setup.png</normaloff>:/resources/android-setup.png</iconset>
+ </property>
+ <property name="text">
+ <string>Link trace</string>
+ </property>
+ </action>
+ <action name="actionSetup">
+ <property name="icon">
+ <iconset resource="../qapitrace.qrc">
+ <normaloff>:/resources/document-new.png</normaloff>:/resources/document-new.png</iconset>
+ </property>
+ <property name="text">
+ <string>Setup</string>
+ </property>
+ </action>
+ <action name="actionRetraceOnAndroid">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Retrace on Android</string>
+ </property>
+ </action>
+ <action name="actionLeakTrace">
+ <property name="text">
+ <string>&amp;LeakTrace</string>
+ </property>
+ <property name="toolTip">
+ <string>trace opengl object leaks</string>
+ </property>
+ </action>
<zorder>stateDock</zorder>
<zorder>vertexDataDock</zorder>
<zorder>errorsDock</zorder>
@@ -660,7 +794,7 @@
<customwidget>
<class>QWebView</class>
<extends>QWidget</extends>
- <header>QtWebKit/QWebView</header>
+ <header>QtWebKitWidgets/QWebView</header>
</customwidget>
</customwidgets>
<resources>
diff --git a/gui/ui/profilereplaydialog.ui b/gui/ui/profilereplaydialog.ui
index f5991ae4..2478f086 100644
--- a/gui/ui/profilereplaydialog.ui
+++ b/gui/ui/profilereplaydialog.ui
@@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>353</width>
- <height>165</height>
+ <height>202</height>
</rect>
</property>
<property name="windowTitle">
@@ -59,6 +59,16 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QCheckBox" name="memoryUsageCB">
+ <property name="text">
+ <string>Memory usage</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/gui/ui/settings.ui b/gui/ui/settings.ui
index 1d2da3e9..a7dbd4cb 100644
--- a/gui/ui/settings.ui
+++ b/gui/ui/settings.ui
@@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>571</width>
- <height>334</height>
+ <height>465</height>
</rect>
</property>
<property name="windowTitle">
@@ -118,6 +118,124 @@
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Android</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ADB (Android Debugger Bridge) is located in &amp;lt;Android SDK&amp;gt;/platform-tools/adb&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>&amp;adb path:</string>
+ </property>
+ <property name="buddy">
+ <cstring>adbPathEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="adbPathEdit">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>adb</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="chooseAdbPath">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ADB (Android Debugger Bridge) is located in &amp;lt;Android SDK&amp;gt;/platform-tools/adb&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>std&amp;out port:</string>
+ </property>
+ <property name="buddy">
+ <cstring>stdoutPort</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="stdoutPort">
+ <property name="minimum">
+ <number>1024</number>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ <property name="value">
+ <number>52341</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ADB (Android Debugger Bridge) is located in &amp;lt;Android SDK&amp;gt;/platform-tools/adb&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>std&amp;err port:</string>
+ </property>
+ <property name="buddy">
+ <cstring>stderrPort</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="stderrPort">
+ <property name="minimum">
+ <number>1024</number>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ <property name="value">
+ <number>52342</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -138,8 +256,8 @@
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
- <x>252</x>
- <y>329</y>
+ <x>260</x>
+ <y>456</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
@@ -154,8 +272,8 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
- <x>320</x>
- <y>329</y>
+ <x>328</x>
+ <y>456</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
@@ -170,12 +288,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>63</x>
- <y>151</y>
+ <x>83</x>
+ <y>147</y>
</hint>
<hint type="destinationlabel">
- <x>107</x>
- <y>151</y>
+ <x>216</x>
+ <y>148</y>
</hint>
</hints>
</connection>
diff --git a/gui/vertexdatainterpreter.h b/gui/vertexdatainterpreter.h
index 6bf9b11c..1ad46b7d 100644
--- a/gui/vertexdatainterpreter.h
+++ b/gui/vertexdatainterpreter.h
@@ -1,5 +1,4 @@
-#ifndef VERTEXDATAINTERPRETER_H
-#define VERTEXDATAINTERPRETER_H
+#pragma once
#include <QObject>
@@ -49,5 +48,3 @@ private:
int m_components;
int m_startingOffset;
};
-
-#endif
diff --git a/guids/CMakeLists.txt b/guids/CMakeLists.txt
new file mode 100644
index 00000000..69dddc20
--- /dev/null
+++ b/guids/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library (guids STATIC
+ guids.cpp
+)
+
+add_gtest (guids_test guids_test.cpp)
+target_link_libraries (guids_test guids)
diff --git a/guids/guids.cpp b/guids/guids.cpp
new file mode 100644
index 00000000..0a72a5c2
--- /dev/null
+++ b/guids/guids.cpp
@@ -0,0 +1,132 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "guids.hpp"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include <os_string.hpp>
+
+
+struct GuidEntry
+{
+ const char *name;
+ GUID guid;
+};
+
+
+static const GuidEntry
+guidEntries[] = {
+
+#define GUID_ENTRY(l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8,name) \
+ { #name, { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } },
+
+#include "guids_entries.h"
+
+};
+
+
+inline bool
+guidCompare(const GUID &g1, const GUID &g2)
+{
+ int ret;
+ if (g1.Data1 == g2.Data1) {
+ ret = g1.Data2 - g2.Data2;
+ if (ret == 0) {
+ ret = g1.Data3 - g2.Data3;
+ if (ret == 0) {
+ ret = memcmp(g1.Data4, g2.Data4, sizeof g1.Data4);
+ }
+ }
+ } else {
+ ret = g1.Data1 > g2.Data1 ? 1 : -1;
+ }
+ if (&g1 == &g2) {
+ assert(ret == 0);
+ }
+
+ return ret < 0;
+}
+
+inline bool
+guidEntryCompare(const GuidEntry &e1, const GUID &g2)
+{
+ const GUID &g1 = e1.guid;
+ return guidCompare(g1, g2);
+}
+
+
+const char *
+getGuidName(const GUID & guid)
+{
+ const size_t entrySize = sizeof guidEntries[0];
+ const size_t numEntries = sizeof guidEntries / entrySize;
+
+ // Verify GUID entries are sorted
+#ifndef NDEBUG
+ static bool checked = false;
+ if (!checked) {
+ for (size_t i = 0; i < numEntries - 1; ++i) {
+ assert(guidEntryCompare(guidEntries[i], guidEntries[i + 1].guid));
+ }
+ assert(guidEntryCompare(guidEntries[0], guidEntries[numEntries - 1].guid));
+ checked = true;
+ }
+#endif
+
+ // Binary search
+ const GuidEntry *first = guidEntries;
+ const GuidEntry *last = first + numEntries;
+ const GuidEntry *entry;
+ entry = std::lower_bound(first, last, guid, guidEntryCompare);
+ if (entry != last &&
+ !guidCompare(guid, entry->guid)) {
+ return entry->name;
+ }
+
+ // Generic case
+ // See https://en.wikipedia.org/wiki/Globally_unique_identifier#Text_encoding
+ static char name[] = "uuid(00000000-0000-0000-0000-000000000000)";
+ const size_t len = sizeof name - 1;
+ int written;
+ written = snprintf(name,
+ sizeof name,
+ "uuid(%08" PRIx32 "-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+ (uint32_t)guid.Data1,
+ guid.Data2, guid.Data3,
+ guid.Data4[0], guid.Data4[1],
+ guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+ assert(written == len);
+ (void)written;
+ name[len] = '\0';
+
+ return name;
+}
+
diff --git a/guids/guids.hpp b/guids/guids.hpp
new file mode 100644
index 00000000..8fc9f4c6
--- /dev/null
+++ b/guids/guids.hpp
@@ -0,0 +1,51 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+
+#ifdef _WIN32
+
+#include <windows.h> // GUID
+
+#else /* !_WIN32 */
+
+#include <stdint.h>
+
+typedef struct _GUID {
+ uint32_t Data1;
+ uint16_t Data2;
+ uint16_t Data3;
+ uint8_t Data4[8];
+} GUID;
+
+typedef GUID IID;
+
+#endif
+
+
+const char *
+getGuidName(const GUID & guid);
diff --git a/guids/guids_defs.hpp b/guids/guids_defs.hpp
new file mode 100644
index 00000000..a7685bf9
--- /dev/null
+++ b/guids/guids_defs.hpp
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifdef _WIN32
+
+
+#include <windows.h>
+
+
+#define GUID_ENTRY(l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8,name) \
+ EXTERN_C CONST IID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } };
+
+#include "guids_entries.h"
+
+#endif
diff --git a/guids/guids_entries.h b/guids/guids_entries.h
new file mode 100644
index 00000000..908c7a99
--- /dev/null
+++ b/guids/guids_entries.h
@@ -0,0 +1,721 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * GUID table.
+ *
+ * NOTE: Entries must remain sorted, which can be achieved by doing
+ *
+ * :'<,'>!sort -k 1.12,1.75 -u
+ *
+ * on Vim.
+ *
+ * TODO: Remove duplicate entries.
+ */
+
+
+#ifndef GUID_ENTRY
+#error "GUID_ENTRY macro must be defined before including this header"
+#endif
+
+#ifndef GUID_DUPLI
+#define GUID_DUPLI(l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8,name)
+#endif
+
+
+GUID_ENTRY(0x00000000,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,IID_IUnknown)
+GUID_ENTRY(0x00cddea8,0x939b,0x4b83,0xa3,0x40,0xa6,0x85,0x22,0x66,0x66,0xcc,IID_IDXGIOutput1)
+GUID_ENTRY(0x00e48f7b,0xd2c8,0x49e8,0xa8,0x6c,0x02,0x2d,0xee,0x53,0x43,0x1f,IID_ID3D10EffectScalarVariable)
+GUID_ENTRY(0x012f0bd6,0xe662,0x4474,0xbe,0xfd,0xaa,0x53,0xe5,0x14,0x3c,0x6d,D3D11_AUTHENTICATED_QUERY_UNRESTRICTED_PROTECTED_SHARED_RESOURCE_COUNT)
+GUID_DUPLI(0x012f0bd6,0xe662,0x4474,0xbe,0xfd,0xaa,0x53,0xe5,0x14,0x3c,0x6d,D3DAUTHENTICATEDQUERY_UNRESTRICTEDPROTECTEDSHAREDRESOURCECOUNT)
+GUID_ENTRY(0x017c18ac,0x103f,0x4417,0x8c,0x51,0x6b,0xf6,0xef,0x1e,0x56,0xbe,IID_ID3DXBaseEffect)
+GUID_ENTRY(0x02177241,0x69fc,0x400c,0x8f,0xf1,0x93,0xa4,0x4d,0xf6,0x86,0x1d,IID_IDirect3D9Ex)
+GUID_ENTRY(0x0359dc30,0x95e6,0x4568,0x90,0x55,0x27,0x72,0x0d,0x13,0x0e,0x93,IID_ID2D1AnalysisTransform)
+GUID_ENTRY(0x035f3ab4,0x482e,0x4e50,0xb4,0x1f,0x8a,0x7f,0x8b,0xd8,0x96,0x0b,IID_IDXGIResource)
+GUID_ENTRY(0x037e866e,0xf56d,0x4357,0xa8,0xaf,0x9d,0xab,0xbe,0x6e,0x25,0x0e,IID_ID3D11Texture3D)
+GUID_ENTRY(0x03823efb,0x8d8f,0x4e1c,0x9a,0xa2,0xf6,0x4b,0xb2,0xcb,0xfd,0xf1,IID_ID3D11DepthStencilState)
+GUID_ENTRY(0x03916615,0xc644,0x418c,0x9b,0xf4,0x75,0xdb,0x5b,0xe6,0x3c,0xa0,IID_ID3D11RefDefaultTrackingOptions)
+GUID_ENTRY(0x0439fc60,0xca44,0x4994,0x8d,0xee,0x3a,0x9a,0xf7,0xb7,0x32,0xec,IID_IDWriteFactory2)
+GUID_ENTRY(0x04b0d117,0x1041,0x46b1,0xaa,0x8a,0x39,0x52,0x84,0x8b,0xa2,0x2e,IID_ID3DX10MeshBuffer)
+GUID_ENTRY(0x05008617,0xfbfd,0x4051,0xa7,0x90,0x14,0x48,0x84,0xb4,0xf6,0xa9,IID_IDXGIDevice2)
+GUID_ENTRY(0x05eec05d,0x8f7d,0x4362,0xb9,0x99,0xd1,0xba,0xf3,0x57,0xc7,0x04,IID_IDirect3DResource9)
+GUID_ENTRY(0x06114bdb,0x3523,0x470a,0x8d,0xca,0xfb,0xc2,0x84,0x51,0x54,0xf0,D3D11_AUTHENTICATED_CONFIGURE_INITIALIZE)
+GUID_DUPLI(0x06114bdb,0x3523,0x470a,0x8d,0xca,0xfb,0xc2,0x84,0x51,0x54,0xf0,D3DAUTHENTICATEDCONFIGURE_INITIALIZE)
+GUID_ENTRY(0x06152247,0x6f50,0x465a,0x92,0x45,0x11,0x8b,0xfd,0x3b,0x60,0x07,IID_ID2D1Factory)
+GUID_ENTRY(0x06675a80,0x3b9b,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b,IID_IDirectDrawSurface7)
+GUID_ENTRY(0x06cd6e01,0x4219,0x4ebd,0x87,0x09,0x27,0xed,0x23,0x36,0x0c,0x62,DXGI_DEBUG_APP)
+GUID_ENTRY(0x06eab419,0xdeed,0x4018,0x80,0xd2,0x3e,0x1d,0x47,0x1a,0xde,0xb2,CLSID_D2D1Premultiply)
+GUID_ENTRY(0x0742a90b,0xc387,0x483f,0xb9,0x46,0x30,0xa7,0xe4,0xe6,0x14,0x58,IID_ID3D12InfoQueue)
+GUID_ENTRY(0x0772d047,0x1b40,0x48e8,0x9c,0xa6,0xb5,0xf5,0x10,0xde,0x9f,0x01,D3D11_AUTHENTICATED_CONFIGURE_SHARED_RESOURCE)
+GUID_DUPLI(0x0772d047,0x1b40,0x48e8,0x9c,0xa6,0xb5,0xf5,0x10,0xde,0x9f,0x01,D3DAUTHENTICATEDCONFIGURE_SHAREDRESOURCE)
+GUID_ENTRY(0x07ddcd52,0x020e,0x4de8,0xac,0x33,0x6c,0x95,0x3d,0x83,0xf9,0x2d,IID_IDWriteTextLayout3)
+GUID_ENTRY(0x07f857e7,0x077f,0x4119,0x86,0xb9,0xe7,0xae,0x71,0x04,0xcf,0x33,IID_ID3D11PartnerDevice)
+GUID_ENTRY(0x0803425a,0x57f5,0x4dd6,0x94,0x65,0xa8,0x75,0x70,0x83,0x4a,0x08,IID_ID3D10StateBlock)
+GUID_ENTRY(0x08256209,0x099a,0x4b34,0xb8,0x6d,0xc2,0x2b,0x11,0x0e,0x77,0x71,IID_IDWriteLocalizedStrings)
+GUID_ENTRY(0x09c3ca26,0x3ae2,0x4f09,0x9e,0xbc,0xed,0x38,0x65,0xd5,0x3f,0x22,CLSID_D2D1PointSpecular)
+GUID_ENTRY(0x09e0bf36,0x54ac,0x484f,0x88,0x47,0x4b,0xae,0xea,0xb6,0x05,0x3a,IID_ID3D12DebugCommandQueue)
+GUID_ENTRY(0x09e0bf36,0x54ac,0x484f,0x88,0x47,0x4b,0xae,0xea,0xb6,0x05,0x3f,IID_ID3D12DebugCommandList)
+GUID_ENTRY(0x0a753dcf,0xc4d8,0x4b91,0xad,0xf6,0xbe,0x5a,0x60,0xd9,0x5a,0x76,IID_ID3D12Fence)
+GUID_ENTRY(0x0aa1ae0a,0xfa0e,0x4b84,0x86,0x44,0xe0,0x5f,0xf8,0xe5,0xac,0xb5,IID_IDXGIAdapter2)
+GUID_ENTRY(0x0b2b8630,0xad35,0x11d0,0x8e,0xa6,0x00,0x60,0x97,0x97,0xea,0x5b,IID_IDirectDrawSurface4)
+GUID_ENTRY(0x0c711683,0x2853,0x4846,0x9b,0xb0,0xf3,0xe6,0x06,0x39,0xe4,0x6a,IID_ID3D11Texture3D1)
+GUID_ENTRY(0x0cfbaf3a,0x9ff6,0x429a,0x99,0xb3,0xa2,0x79,0x6a,0xf8,0xb8,0x9b,IID_IDirect3DSurface9)
+GUID_ENTRY(0x0d85573c,0x01e3,0x4f7d,0xbf,0xd9,0x0d,0x60,0x60,0x8b,0xf3,0xc3,IID_ID2D1ComputeTransform)
+GUID_ENTRY(0x0d9658ae,0xed45,0x469e,0xa6,0x1d,0x97,0x0e,0xc5,0x83,0xca,0xb4,IID_ID3D12QueryHeap)
+GUID_ENTRY(0x0db207b3,0x9450,0x46a6,0x82,0xde,0x1b,0x96,0xd4,0x4f,0x9c,0xf2,D3D11_AUTHENTICATED_QUERY_RESTRICTED_SHARED_RESOURCE_PROCESS_COUNT)
+GUID_DUPLI(0x0db207b3,0x9450,0x46a6,0x82,0xde,0x1b,0x96,0xd4,0x4f,0x9c,0xf2,D3DAUTHENTICATEDQUERY_RESTRICTEDSHAREDRESOURCEPROCESSCOUNT)
+GUID_ENTRY(0x0e689c9a,0x053d,0x44a0,0x9d,0x92,0xdb,0x0e,0x3d,0x75,0x0f,0x86,IID_IDirect3DIndexBuffer8)
+GUID_ENTRY(0x0ec870a6,0x5d7e,0x4c22,0x8c,0xfc,0x5b,0xaa,0xe0,0x76,0x16,0xed,IID_ID3D12CommandQueue)
+GUID_ENTRY(0x0f4458ec,0x4b32,0x491b,0x9e,0x85,0xbd,0x73,0xf4,0x4d,0x3e,0xb6,CLSID_D2D1HueRotation)
+GUID_ENTRY(0x107af0e0,0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13,D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10)
+GUID_DUPLI(0x107af0e0,0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13,DXVA2_ModeHEVC_VLD_Main10)
+GUID_ENTRY(0x1093c18f,0x8d5e,0x43f0,0xb0,0x64,0x09,0x17,0x31,0x1b,0x52,0x5e,IID_IDWriteTextLayout2)
+GUID_ENTRY(0x10a72a66,0xe91c,0x43f4,0x99,0x3f,0xdd,0xf4,0xb8,0x2b,0x0b,0x4a,IID_ID2D1StrokeStyle1)
+GUID_ENTRY(0x10ec4d5b,0x975a,0x4689,0xb9,0xe4,0xd0,0xaa,0xc3,0x0f,0xe3,0x33,IID_ID3D11VideoDevice)
+GUID_ENTRY(0x1108795c,0x2772,0x4ba9,0xb2,0xa8,0xd4,0x64,0xdc,0x7e,0x27,0x99,IID_ID3D12FunctionReflection)
+GUID_ENTRY(0x119e7452,0xde9e,0x40fe,0x88,0x06,0x88,0xf9,0x0c,0x12,0xb4,0x41,IID_IDXGIDebug)
+GUID_ENTRY(0x11eaa540,0xf9a6,0x4d49,0xae,0x6a,0xe1,0x92,0x21,0xf7,0x0c,0xc4,IID_ID3DXSkinInfo)
+GUID_ENTRY(0x11ec5a5f,0x51dc,0x4945,0xab,0x34,0x6e,0x8c,0x21,0x30,0x0e,0xa5,IID_ID3D11VideoProcessorInputView)
+GUID_ENTRY(0x1217d7a6,0x5039,0x418c,0xb0,0x42,0x9c,0xbe,0x25,0x6a,0xfd,0x6e,IID_ID3D11RasterizerState1)
+GUID_ENTRY(0x126d0349,0x4787,0x4aa6,0x8e,0x1b,0x40,0xc1,0x77,0xc6,0x0a,0x01,IID_IDirect3DDxva2Container9)
+GUID_ENTRY(0x13d29038,0xc3e6,0x4034,0x90,0x81,0x13,0xb5,0x3a,0x41,0x79,0x92,IID_ID2D1TransformGraph)
+GUID_ENTRY(0x14885cc9,0xbab0,0x4f90,0xb6,0xed,0x5c,0x36,0x6a,0x2c,0xd0,0x3d,IID_IDWriteNumberSubstitution)
+GUID_ENTRY(0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b,IID_IDirectDraw7)
+GUID_ENTRY(0x174319a6,0x58e9,0x49b2,0xbb,0x63,0xca,0xf2,0xc8,0x11,0xa3,0xdb,CLSID_D2D1DirectionalBlur)
+GUID_ENTRY(0x1841e5c8,0x16b0,0x489b,0xbc,0xc8,0x44,0xcf,0xb0,0xd5,0xde,0xae,IID_ID3D11DeviceChild)
+GUID_ENTRY(0x187aeb13,0xaaf5,0x4c59,0x87,0x6d,0xe0,0x59,0x08,0x8c,0x0d,0xf8,IID_IDirect3D9ExOverlayExtension)
+GUID_ENTRY(0x189819f1,0x1db6,0x4b57,0xbe,0x54,0x18,0x21,0x33,0x9b,0x85,0xf7,IID_ID3D12Device)
+GUID_ENTRY(0x1911c771,0x1587,0x413e,0xa7,0xe0,0xfb,0x26,0xc3,0xde,0x02,0x68,IID_ID3D11TracingDevice)
+GUID_ENTRY(0x191cfac3,0xa341,0x470d,0xb2,0x6e,0xa8,0x64,0xf4,0x28,0x31,0x9c,IID_IDXGIOutputDuplication)
+GUID_ENTRY(0x193dacdf,0x0db2,0x4c05,0xa5,0x5c,0xef,0x06,0xca,0xc5,0x6f,0xd9,IID_ID3D11RefTrackingOptions)
+GUID_ENTRY(0x1a0d8438,0x1d97,0x4ec1,0xae,0xf9,0xa2,0xfb,0x86,0xed,0x6a,0xcb,IID_IDWriteFontList)
+GUID_ENTRY(0x1a28524c,0xfdd6,0x4aa4,0xae,0x8f,0x83,0x7e,0xb8,0x26,0x7b,0x37,CLSID_D2D1ColorManagement)
+GUID_ENTRY(0x1a799d8a,0x69f7,0x4e4c,0x9f,0xed,0x43,0x7c,0xcc,0x66,0x84,0xcc,IID_ID2D1ConcreteTransform)
+GUID_ENTRY(0x1b36bb7b,0x09b7,0x410a,0xb4,0x45,0x7d,0x14,0x30,0xd7,0xb3,0x3f,IID_IDirect3DResource8)
+GUID_ENTRY(0x1b81be64,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_H264_MOCOMP_NOFGT)
+GUID_DUPLI(0x1b81be64,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeH264_A)
+GUID_ENTRY(0x1b81be65,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_H264_MOCOMP_FGT)
+GUID_DUPLI(0x1b81be65,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeH264_B)
+GUID_ENTRY(0x1b81be66,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_H264_IDCT_NOFGT)
+GUID_DUPLI(0x1b81be66,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeH264_C)
+GUID_ENTRY(0x1b81be67,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_H264_IDCT_FGT)
+GUID_DUPLI(0x1b81be67,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeH264_D)
+GUID_ENTRY(0x1b81be68,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_H264_VLD_NOFGT)
+GUID_DUPLI(0x1b81be68,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeH264_E)
+GUID_ENTRY(0x1b81be69,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_H264_VLD_FGT)
+GUID_DUPLI(0x1b81be69,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeH264_F)
+GUID_ENTRY(0x1b81be80,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_WMV8_POSTPROC)
+GUID_DUPLI(0x1b81be80,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeWMV8_A)
+GUID_ENTRY(0x1b81be81,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_WMV8_MOCOMP)
+GUID_DUPLI(0x1b81be81,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeWMV8_B)
+GUID_ENTRY(0x1b81be90,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_WMV9_POSTPROC)
+GUID_DUPLI(0x1b81be90,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeWMV9_A)
+GUID_ENTRY(0x1b81be91,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_WMV9_MOCOMP)
+GUID_DUPLI(0x1b81be91,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeWMV9_B)
+GUID_ENTRY(0x1b81be94,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_WMV9_IDCT)
+GUID_DUPLI(0x1b81be94,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeWMV9_C)
+GUID_ENTRY(0x1b81bea0,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_VC1_POSTPROC)
+GUID_DUPLI(0x1b81bea0,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeVC1_A)
+GUID_ENTRY(0x1b81bea1,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_VC1_MOCOMP)
+GUID_DUPLI(0x1b81bea1,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeVC1_B)
+GUID_ENTRY(0x1b81bea2,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_VC1_IDCT)
+GUID_DUPLI(0x1b81bea2,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeVC1_C)
+GUID_ENTRY(0x1b81bea3,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_VC1_VLD)
+GUID_DUPLI(0x1b81bea3,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeVC1_D)
+GUID_ENTRY(0x1b81bea4,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,D3D11_DECODER_PROFILE_VC1_D2010)
+GUID_DUPLI(0x1b81bea4,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_ModeVC1_D2010)
+GUID_ENTRY(0x1b81bed0,0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5,DXVA2_NoEncrypt)
+GUID_ENTRY(0x1b940b17,0x2642,0x4d1f,0xab,0x1f,0xb9,0x9b,0xad,0x0c,0x39,0x5f,IID_ID3D10InfoQueue)
+GUID_ENTRY(0x1bc6ea02,0xef36,0x464f,0xbf,0x0c,0x21,0xca,0x39,0xe5,0x16,0x8a,IID_IDXGIFactory4)
+GUID_ENTRY(0x1bf63c95,0x2650,0x405d,0x99,0xc1,0x36,0x36,0xbd,0x1d,0xa0,0xa1,IID_ID3D10ShaderReflectionVariable)
+GUID_ENTRY(0x1c4820bb,0x5771,0x4518,0xa5,0x81,0x2f,0xe4,0xdd,0x0e,0xc6,0x57,IID_ID2D1ColorContext)
+GUID_ENTRY(0x1c51bc64,0xde61,0x46fd,0x98,0x99,0x63,0xa5,0xd8,0xf0,0x39,0x50,IID_ID2D1DCRenderTarget)
+GUID_ENTRY(0x1d7b0652,0x185f,0x41c6,0x85,0xce,0x0c,0x5b,0xe3,0xd4,0xae,0x6c,IID_ID3D11VideoProcessor)
+GUID_ENTRY(0x1dbc4c88,0x94c1,0x46ee,0x90,0x76,0x2c,0x28,0x81,0x8c,0x94,0x81,DXFILEOBJ_EffectParamString)
+GUID_ENTRY(0x1dd9e8da,0x1c77,0x4d40,0xb0,0xcf,0x98,0xfe,0xfd,0xff,0x95,0x12,IID_IDirect3D8)
+GUID_ENTRY(0x1ddd77aa,0x9a4a,0x4cc8,0x9e,0x55,0x98,0xc1,0x96,0xba,0xfc,0x8f,IID_IDXGIFactoryDWM2)
+GUID_ENTRY(0x1edd9491,0x9853,0x4299,0x89,0x8f,0x64,0x32,0x98,0x3b,0x6f,0x3a,IID_IDWriteGdiInterop)
+GUID_ENTRY(0x1ef337e3,0x58e7,0x4f83,0xa6,0x92,0xdb,0x22,0x1f,0x5e,0xd4,0x7e,IID_ID3D11SwitchToRef)
+GUID_ENTRY(0x1fcd2294,0xdf6d,0x4eae,0x86,0xb3,0x0e,0x91,0x60,0xcf,0xb0,0x7b,IID_ID3D10EffectBlendVariable)
+GUID_ENTRY(0x1feb6d69,0x2fe6,0x4ac9,0x8c,0x58,0x1d,0x7f,0x93,0xe7,0xa6,0xa5,CLSID_D2D1GaussianBlur)
+GUID_ENTRY(0x207bcecb,0xd683,0x4a06,0xa8,0xa3,0x9b,0x14,0x9b,0x9f,0x73,0xa4,IID_ID3D11FunctionReflection)
+GUID_ENTRY(0x21af9f0e,0x4d94,0x4ea9,0x97,0x85,0x2c,0xb7,0x6b,0x8c,0x0b,0x34,IID_ID3D10EffectRasterizerVariable)
+GUID_ENTRY(0x2411e7e1,0x12ac,0x4ccf,0xbd,0x14,0x97,0x98,0xe8,0x53,0x4d,0xc0,IID_IDXGIAdapter)
+GUID_ENTRY(0x243b4c52,0x3606,0x4d3a,0x99,0xd7,0xa7,0xe7,0xb3,0x3e,0xd7,0x06,DXGI_DEBUG_D3D10)
+GUID_ENTRY(0x24f416e6,0x1f67,0x4aa7,0xb8,0x8e,0xd3,0x3f,0x6f,0x31,0x28,0xa1,IID_IDirect3DVolume9)
+GUID_ENTRY(0x2518526c,0xe789,0x4111,0xa7,0xb9,0x47,0xef,0x32,0x8d,0x13,0xe6,IID_IDirect3DVolumeTexture9)
+GUID_ENTRY(0x25483823,0xcd46,0x4c7d,0x86,0xca,0x47,0xaa,0x95,0xb8,0x37,0xbd,IID_IDXGIFactory3)
+GUID_ENTRY(0x25cddaa4,0xb1c6,0x47e1,0xac,0x3e,0x98,0x87,0x5b,0x5a,0x2e,0x2a,DXGI_DEBUG_DXGI)
+GUID_ENTRY(0x2633066b,0x4514,0x4c7a,0x8f,0xd8,0x12,0xea,0x98,0x05,0x9d,0x18,IID_IDXGIDecodeSwapChain)
+GUID_ENTRY(0x2634499e,0xd018,0x4d74,0xac,0x17,0x7f,0x72,0x40,0x59,0x52,0x8d,D3D11_AUTHENTICATED_QUERY_CRYPTO_SESSION)
+GUID_DUPLI(0x2634499e,0xd018,0x4d74,0xac,0x17,0x7f,0x72,0x40,0x59,0x52,0x8d,D3DAUTHENTICATEDQUERY_CRYPTOSESSION)
+GUID_ENTRY(0x26dc4561,0xa1ee,0x4ae7,0x96,0xda,0x11,0x8a,0x36,0xc0,0xec,0x95,IID_IDirect3DDevice9Video)
+GUID_ENTRY(0x28211a43,0x7d89,0x476f,0x81,0x81,0x2d,0x61,0x59,0xb2,0x20,0xad,IID_ID2D1Effect)
+GUID_ENTRY(0x28506e39,0xebf6,0x46a1,0xbb,0x47,0xfd,0x85,0x56,0x5a,0xb9,0x57,IID_ID2D1DrawingStateBlock)
+GUID_ENTRY(0x28acf509,0x7f5c,0x48f6,0x86,0x11,0xf3,0x16,0x01,0x0a,0x63,0x80,IID_ID3D11UnorderedAccessView)
+GUID_ENTRY(0x28ca0cc3,0xc2c9,0x40bb,0xb5,0x7f,0x67,0xb7,0x37,0x12,0x2b,0x17,IID_ID3D10EffectRenderTargetViewVariable)
+GUID_ENTRY(0x29038f61,0x3839,0x4626,0x91,0xfd,0x08,0x68,0x79,0x01,0x1a,0x05,IID_IDXGIAdapter1)
+GUID_ENTRY(0x29748ed6,0x8c9c,0x4a6a,0xbe,0x0b,0xd9,0x12,0xe8,0x53,0x89,0x44,IID_IDWriteFont2)
+GUID_DUPLI(0x29748ed6,0x8c9c,0x4a6a,0xbe,0x0b,0xd9,0x12,0xe8,0x53,0x89,0x44,IID_IDWriteFont3) // XXX: Same as IID_IDWriteFont2!?
+GUID_ENTRY(0x29da1d51,0x1321,0x4454,0x80,0x4b,0xf5,0xfc,0x9f,0x86,0x1f,0x0f,IID_ID3D11VideoDevice1)
+GUID_ENTRY(0x2a2d49c0,0x4acf,0x43c7,0x8c,0x6a,0x7c,0x4a,0x27,0x87,0x4d,0x27,CLSID_D2D1Border)
+GUID_ENTRY(0x2b4b1cc8,0xa4ad,0x41f8,0x83,0x22,0xca,0x86,0xfc,0x3e,0xc6,0x75,IID_ID3D10DepthStencilState)
+GUID_ENTRY(0x2c042b5e,0x8c07,0x46d5,0xaa,0xbe,0x8f,0x75,0xcb,0xad,0x4c,0x31,D3D11_AUTHENTICATED_QUERY_OUTPUT_ID_COUNT)
+GUID_DUPLI(0x2c042b5e,0x8c07,0x46d5,0xaa,0xbe,0x8f,0x75,0xcb,0xad,0x4c,0x31,D3DAUTHENTICATEDQUERY_OUTPUTIDCOUNT)
+GUID_ENTRY(0x2c1d867d,0xc290,0x41c8,0xae,0x7e,0x34,0xa9,0x87,0x02,0xe9,0xa5,IID_ID2D1PrintControl)
+GUID_ENTRY(0x2cd90691,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1Resource)
+GUID_ENTRY(0x2cd90694,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1RenderTarget)
+GUID_ENTRY(0x2cd90695,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1BitmapRenderTarget)
+GUID_ENTRY(0x2cd90698,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1HwndRenderTarget)
+GUID_ENTRY(0x2cd9069b,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1Layer)
+GUID_ENTRY(0x2cd9069d,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1StrokeStyle)
+GUID_ENTRY(0x2cd9069e,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1SimplifiedGeometrySink)
+GUID_ENTRY(0x2cd9069f,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1GeometrySink)
+GUID_ENTRY(0x2cd906a1,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1Geometry)
+GUID_ENTRY(0x2cd906a2,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1RectangleGeometry)
+GUID_ENTRY(0x2cd906a3,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1RoundedRectangleGeometry)
+GUID_ENTRY(0x2cd906a4,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1EllipseGeometry)
+GUID_ENTRY(0x2cd906a5,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1PathGeometry)
+GUID_ENTRY(0x2cd906a6,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1GeometryGroup)
+GUID_ENTRY(0x2cd906a7,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1GradientStopCollection)
+GUID_ENTRY(0x2cd906a8,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1Brush)
+GUID_ENTRY(0x2cd906a9,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1SolidColorBrush)
+GUID_ENTRY(0x2cd906aa,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1BitmapBrush)
+GUID_ENTRY(0x2cd906ab,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1LinearGradientBrush)
+GUID_ENTRY(0x2cd906ac,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1RadialGradientBrush)
+GUID_ENTRY(0x2cd906bb,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1TransformedGeometry)
+GUID_ENTRY(0x2cd906c1,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1TessellationSink)
+GUID_ENTRY(0x2cd906c2,0x12e2,0x11dc,0x9f,0xed,0x00,0x11,0x43,0xa0,0x55,0xf9,IID_ID2D1Mesh)
+GUID_ENTRY(0x2cdcd9e0,0x25a0,0x11cf,0xa3,0x1a,0x00,0xaa,0x00,0xb9,0x33,0x56,IID_IDirect3DTexture)
+GUID_ENTRY(0x2f0da53a,0x2add,0x47cd,0x82,0xee,0xd9,0xec,0x34,0x68,0x8e,0x75,IID_IDWriteRenderingParams)
+GUID_ENTRY(0x2f543dc3,0xcfc1,0x4211,0x86,0x4f,0xcf,0xd9,0x1c,0x6f,0x33,0x95,IID_ID2D1GdiMetafile)
+GUID_ENTRY(0x2f642afe,0x9c68,0x4f40,0xb8,0xbe,0x45,0x74,0x01,0xaf,0xcb,0x3d,IID_IDWriteFontSetBuilder)
+GUID_ENTRY(0x3014b9a0,0x62f5,0x478c,0x9b,0x86,0xe4,0xac,0x9f,0x4e,0x41,0x8b,DXFILEOBJ_EffectParamFloats)
+GUID_ENTRY(0x3015a308,0xdcbd,0x47aa,0xa7,0x47,0x19,0x24,0x86,0xd1,0x4d,0x4a,IID_ID3D11AuthenticatedChannel)
+GUID_ENTRY(0x30572f99,0xdac6,0x41db,0xa1,0x6e,0x04,0x86,0x30,0x7e,0x60,0x6a,IID_IDWriteFactory1)
+GUID_ENTRY(0x30961379,0x4609,0x4a41,0x99,0x8e,0x54,0xfe,0x56,0x7e,0xe0,0xc1,IID_IDXGIResource1)
+GUID_ENTRY(0x310d36a0,0xd2e7,0x4c0a,0xaa,0x04,0x6a,0x9d,0x23,0xb8,0x88,0x6a,IID_IDXGISwapChain)
+GUID_ENTRY(0x313f1b4b,0xc7b0,0x4fa2,0x9d,0x9d,0x8d,0x38,0x0b,0x64,0x38,0x5e,IID_ID3DXRenderToEnvMap)
+GUID_ENTRY(0x31627037,0x53ab,0x4200,0x90,0x61,0x05,0xfa,0xa9,0xab,0x45,0xf9,IID_ID3D11VideoProcessorEnumerator)
+GUID_ENTRY(0x31e6e7bc,0xe0ff,0x4d46,0x8c,0x64,0xa0,0xa8,0xc4,0x1c,0x15,0xd3,IID_ID2D1Multithread)
+GUID_ENTRY(0x335aa36e,0x7884,0x43a4,0x9c,0x91,0x7f,0x87,0xfa,0xf3,0xe3,0x7e,DXVA2_VideoProcBobDevice)
+GUID_ENTRY(0x344488b7,0x6846,0x474b,0xb9,0x89,0xf0,0x27,0x44,0x82,0x45,0xe0,IID_ID3D12Debug)
+GUID_ENTRY(0x34ab647b,0x3cc8,0x46ac,0x84,0x1b,0xc0,0x96,0x56,0x45,0xc0,0x46,IID_ID3D12RootSignatureDeserializer)
+GUID_ENTRY(0x35cdd7fc,0x13b2,0x421d,0xa5,0xd7,0x7e,0x44,0x51,0x28,0x7d,0x64,DXGI_DEBUG_DX)
+GUID_ENTRY(0x36bfdcb6,0x9739,0x435d,0xa3,0x0d,0xa6,0x53,0xbe,0xff,0x6a,0x6f,IID_ID2D1DrawTransform)
+GUID_ENTRY(0x38325b96,0xeffb,0x4022,0xba,0x02,0x2e,0x79,0x5b,0x70,0x27,0x5c,IID_ID3D11GeometryShader)
+GUID_ENTRY(0x3b301d64,0xd678,0x4289,0x88,0x97,0x22,0xf8,0x92,0x8b,0x72,0xf3,IID_ID3D11VertexShader)
+GUID_ENTRY(0x3bba0080,0x2421,0x11cf,0xa3,0x1a,0x00,0xaa,0x00,0xb9,0x33,0x56,IID_IDirect3D)
+GUID_ENTRY(0x3c305196,0x50db,0x11d3,0x9c,0xfe,0x00,0xc0,0x4f,0xd9,0x30,0xc5,CLSID_DirectDraw7)
+GUID_ENTRY(0x3c9c5b51,0x995d,0x48d1,0x9b,0x8d,0xfa,0x5c,0xae,0xde,0xd6,0x5c,IID_ID3D11VideoDecoder)
+GUID_ENTRY(0x3ce6cc22,0xdbf2,0x44f4,0x89,0x4d,0xf9,0xc3,0x4a,0x33,0x71,0x39,IID_ID3DX10PatchMesh)
+GUID_DUPLI(0x3ce6cc22,0xdbf2,0x44f4,0x89,0x4d,0xf9,0xc3,0x4a,0x33,0x71,0x39,IID_ID3DXPatchMesh)
+GUID_ENTRY(0x3cf169ce,0xff7c,0x44ab,0x93,0xc0,0xf7,0x8f,0x62,0xd1,0x72,0xe2,DXFILEOBJ_XSkinMeshHeader)
+GUID_ENTRY(0x3d3e0379,0xf9de,0x4d58,0xbb,0x6c,0x18,0xd6,0x29,0x92,0xf1,0xa6,IID_IDXGIDeviceSubObject)
+GUID_ENTRY(0x3d9f916b,0x27dc,0x4ad7,0xb4,0xf1,0x64,0x94,0x53,0x40,0xf5,0x63,IID_ID2D1EffectContext)
+GUID_ENTRY(0x3e02c918,0xcc79,0x4985,0xb6,0x22,0x2d,0x92,0xad,0x70,0x16,0x23,IID_ID3D10EffectDepthStencilViewVariable)
+GUID_ENTRY(0x3e3d67f8,0xaa7a,0x405d,0xa8,0x57,0xba,0x01,0xd4,0x75,0x84,0x26,IID_ID3DXTextureShader)
+GUID_ENTRY(0x3e7efd62,0xa32d,0x46d4,0xa8,0x3c,0x52,0x78,0x88,0x9a,0xc9,0x54,CLSID_D2D1DistantDiffuse)
+GUID_ENTRY(0x3ee5b968,0x2aca,0x4c34,0x8b,0xb5,0x7e,0x0c,0x3d,0x19,0xb7,0x50,IID_IDirect3DCubeTexture8)
+GUID_ENTRY(0x3fe6adea,0x7643,0x4f53,0xbd,0x14,0xa0,0xce,0x63,0xf2,0x40,0x42,IID_ID2D1OffsetTransform)
+GUID_ENTRY(0x3febd6dd,0x4973,0x4787,0x81,0x94,0xe4,0x5f,0x9e,0x28,0x92,0x3e,IID_ID3D12DebugDevice)
+GUID_ENTRY(0x4020e5c2,0x1403,0x4929,0x88,0x3f,0xe2,0xe8,0x49,0xfa,0xc1,0x95,IID_ID3DX10Mesh)
+GUID_DUPLI(0x4020e5c2,0x1403,0x4929,0x88,0x3f,0xe2,0xe8,0x49,0xfa,0xc1,0x95,IID_ID3DXMesh)
+GUID_ENTRY(0x407f8c08,0x5533,0x4331,0xa3,0x41,0x23,0xcc,0x38,0x77,0x84,0x3e,CLSID_D2D1ConvolveMatrix)
+GUID_ENTRY(0x409444c4,0xc419,0x41a0,0xb0,0xc1,0x8c,0xd0,0xc0,0xa1,0x8e,0x42,CLSID_D2D1GammaTransfer)
+GUID_ENTRY(0x41251ab7,0x0beb,0x46f8,0x9d,0xa7,0x59,0xe9,0x3f,0xcc,0xe5,0xde,CLSID_D2D1LuminanceToAlpha)
+GUID_ENTRY(0x41343a53,0xe41a,0x49a2,0x91,0xcd,0x21,0x79,0x3b,0xbb,0x62,0xe5,IID_ID2D1BitmapBrush1)
+GUID_ENTRY(0x41e7d1f2,0xa591,0x4f7b,0xa2,0xe5,0xfa,0x9c,0x84,0x3e,0x1c,0x12,IID_IDXGIFactoryMedia)
+GUID_ENTRY(0x41fff286,0x6ae0,0x4d43,0x9d,0x55,0xa4,0x6e,0x9e,0xfd,0x15,0x8a,D3D11_AUTHENTICATED_CONFIGURE_ENCRYPTION_WHEN_ACCESSIBLE)
+GUID_DUPLI(0x41fff286,0x6ae0,0x4d43,0x9d,0x55,0xa4,0x6e,0x9e,0xfd,0x15,0x8a,D3DAUTHENTICATEDCONFIGURE_ENCRYPTIONWHENACCESSIBLE)
+GUID_ENTRY(0x420bd604,0x1c76,0x4a34,0xa4,0x66,0xe4,0x5d,0x06,0x58,0xa3,0x2c,IID_ID3DX10SkinInfo)
+GUID_ENTRY(0x420d5b32,0xb90c,0x4da4,0xbe,0xf0,0x35,0x9f,0x6a,0x24,0xa8,0x3a,IID_ID3D11DeviceContext2)
+GUID_ENTRY(0x42757488,0x334f,0x47fe,0x98,0x2e,0x1a,0x65,0xd0,0x8c,0xc4,0x62,IID_ID3D11FunctionParameterReflection)
+GUID_ENTRY(0x428c1ee5,0x77b8,0x4450,0x8a,0xb5,0x72,0x21,0x9c,0x21,0xab,0xda,CLSID_D2D1DistantSpecular)
+GUID_ENTRY(0x429b8c22,0x9188,0x4b0c,0x87,0x42,0xac,0xb0,0xbf,0x85,0xc2,0x00,WKPDID_D3DDebugObjectName)
+GUID_ENTRY(0x43d3775c,0x38e5,0x4924,0x8d,0x86,0xd3,0xfc,0xcf,0x15,0x3e,0x9b,D3DKEYEXCHANGE_DXVA)
+GUID_ENTRY(0x4417c142,0x33ad,0x11cf,0x81,0x6f,0x00,0x00,0xc0,0x20,0x15,0x6e,IID_IDirect3DLight)
+GUID_ENTRY(0x4417c144,0x33ad,0x11cf,0x81,0x6f,0x00,0x00,0xc0,0x20,0x15,0x6e,IID_IDirect3DMaterial)
+GUID_ENTRY(0x4417c145,0x33ad,0x11cf,0x81,0x6f,0x00,0x00,0xc0,0x20,0x15,0x6e,IID_IDirect3DExecuteBuffer)
+GUID_ENTRY(0x4417c146,0x33ad,0x11cf,0x81,0x6f,0x00,0x00,0xc0,0x20,0x15,0x6e,IID_IDirect3DViewport)
+GUID_ENTRY(0x4553d47f,0xee7e,0x4e3f,0x94,0x75,0xdb,0xf1,0x37,0x6c,0x48,0x10,DXVA2_VideoProcSoftwareDevice)
+GUID_ENTRY(0x4556be70,0x3abd,0x4f70,0x90,0xbe,0x42,0x17,0x80,0xa6,0xf5,0x15,IID_IDWriteGdiInterop1)
+GUID_ENTRY(0x465217f2,0x5568,0x43cf,0xb5,0xb9,0xf6,0x1d,0x54,0x53,0x1c,0xa1,IID_ID3D11VideoProcessorEnumerator1)
+GUID_ENTRY(0x469e07f7,0x045a,0x48d5,0xaa,0x12,0x68,0xa4,0x78,0xcd,0xf7,0x5d,IID_ID3D11ModuleInstance)
+GUID_ENTRY(0x47dd575d,0xac05,0x4cdd,0x80,0x49,0x9b,0x02,0xcd,0x16,0xf4,0x4c,IID_ID2D1Device)
+GUID_ENTRY(0x483473d7,0xcd46,0x4f9d,0x9d,0x3a,0x31,0x12,0xaa,0x80,0x15,0x9d,IID_ID2D1Properties)
+GUID_ENTRY(0x48570b85,0xd1ee,0x4fcd,0xa2,0x50,0xeb,0x35,0x07,0x22,0xb0,0x37,IID_ID3D11Buffer)
+GUID_ENTRY(0x48fc9f51,0xf6ac,0x48f1,0x8b,0x58,0x3b,0x28,0xac,0x46,0xf7,0x6d,CLSID_D2D1Composite)
+GUID_ENTRY(0x4968b601,0x9d00,0x4cde,0x83,0x46,0x8e,0x7f,0x67,0x58,0x19,0xb6,IID_ID3D10PixelShader)
+GUID_ENTRY(0x4998735c,0x3a19,0x473c,0x97,0x81,0x65,0x68,0x47,0xe3,0xa3,0x47,IID_ID2D1BorderTransform)
+GUID_ENTRY(0x4ae63092,0x6327,0x4c1b,0x80,0xae,0xbf,0xe1,0x2e,0xa3,0x2b,0x86,IID_IDXGISurface1)
+GUID_ENTRY(0x4b35d0cd,0x1e15,0x4258,0x9c,0x98,0x1b,0x13,0x33,0xf6,0xdd,0x3b,IID_ID3D11Asynchronous)
+GUID_ENTRY(0x4b8aaafa,0x140f,0x42ba,0x91,0x31,0x59,0x7e,0xaf,0xaa,0x2e,0xad,IID_IDirect3DVolumeTexture8)
+GUID_ENTRY(0x4b99317b,0xac39,0x4aa6,0xbb,0x0b,0xba,0xa0,0x47,0x84,0x79,0x8f,DXGI_DEBUG_D3D11)
+GUID_ENTRY(0x4b9f0ee0,0x0d7e,0x11d0,0x9b,0x06,0x00,0xa0,0xc9,0x03,0xa3,0xb8,IID_IDirectDrawColorControl)
+GUID_ENTRY(0x4cca5fd8,0x921f,0x42c8,0x85,0x66,0x70,0xca,0xf2,0xa9,0xb7,0x41,WKPDID_D3DDebugObjectNameW)
+GUID_ENTRY(0x4e9e1ddc,0xcd9d,0x4772,0xa8,0x37,0x00,0x18,0x0b,0x9b,0x88,0xfd,IID_ID3D10EffectType)
+GUID_ENTRY(0x4f5b196e,0xc2bd,0x495e,0xbd,0x01,0x1f,0xde,0xd3,0x8e,0x49,0x69,IID_ID3D11ComputeShader)
+GUID_ENTRY(0x50455658,0x3f47,0x4362,0xbf,0x99,0xbf,0xdf,0xcd,0xe9,0xed,0x29,D3D11_AUTHENTICATED_CONFIGURE_PROTECTION)
+GUID_DUPLI(0x50455658,0x3f47,0x4362,0xbf,0x99,0xbf,0xdf,0xcd,0xe9,0xed,0x29,D3DAUTHENTICATEDCONFIGURE_PROTECTION)
+GUID_ENTRY(0x50666c24,0xb82f,0x4eed,0xa1,0x72,0x5b,0x6e,0x7e,0x85,0x22,0xe0,IID_ID3D10EffectMatrixVariable)
+GUID_ENTRY(0x5089b68f,0xe71d,0x4d38,0xbe,0x8e,0xf3,0x63,0xb9,0x5a,0x94,0x05,IID_ID3DX11Scan)
+GUID_ENTRY(0x50936643,0x13e9,0x11d1,0x89,0xaa,0x00,0xa0,0xc9,0x05,0x41,0x29,IID_IDirect3DRefDevice)
+GUID_ENTRY(0x50c83a1c,0xe072,0x4c48,0x87,0xb0,0x36,0x30,0xfa,0x36,0xa6,0xd0,IID_IDXGIFactory2)
+GUID_ENTRY(0x51218251,0x1e33,0x4617,0x9c,0xcb,0x4d,0x3a,0x43,0x67,0xe7,0xbb,IID_ID3D11Texture2D1)
+GUID_ENTRY(0x519ae1bd,0xd19a,0x420d,0xb8,0x49,0x36,0x4f,0x59,0x47,0x76,0xb7,IID_ID2D1RenderInfo)
+GUID_ENTRY(0x51b0ca8b,0xec0b,0x4519,0x87,0x0d,0x8e,0xe1,0xcb,0x50,0x17,0xc7,IID_ID3D10Effect)
+GUID_ENTRY(0x51b8a949,0x1a31,0x47e6,0xbe,0xa0,0x4b,0x30,0xdb,0x53,0xf1,0xe0,IID_ID3DXEffectCompiler)
+GUID_ENTRY(0x51f23923,0xf3e5,0x4bd1,0x91,0xcb,0x60,0x61,0x77,0xd8,0xdb,0x4c,IID_ID3D11ShaderReflectionVariable)
+GUID_ENTRY(0x53585141,0xd9f8,0x4095,0x83,0x21,0xd7,0x3c,0xf6,0xbd,0x11,0x6b,IID_IDWriteFontSet)
+GUID_ENTRY(0x53585141,0xd9f8,0x4095,0x83,0x21,0xd7,0x3c,0xf6,0xbd,0x11,0x6c,IID_IDWriteFontCollection1)
+GUID_ENTRY(0x53737037,0x6d14,0x410b,0x9b,0xfe,0x0b,0x18,0x2b,0xb7,0x09,0x61,IID_IDWriteTextLayout)
+GUID_ENTRY(0x54133220,0x1ce8,0x43d3,0x82,0x36,0x98,0x55,0xc5,0xce,0xec,0xff,IID_ID3D11FunctionLinkingGraph)
+GUID_ENTRY(0x54384f1b,0x5b3e,0x4bb7,0xae,0x01,0x60,0xba,0x30,0x97,0xcb,0xb6,IID_ID3D11LibraryReflection)
+GUID_ENTRY(0x54d7898a,0xa061,0x40a7,0xbe,0xc7,0xe4,0x65,0xbc,0xba,0x2c,0x4f,IID_ID2D1CommandSink)
+GUID_ENTRY(0x54ec77fa,0x1377,0x44e6,0x8c,0x32,0x88,0xfd,0x5f,0x44,0xc8,0x4c,IID_IDXGIDevice)
+GUID_ENTRY(0x553a9ff3,0x5693,0x4df7,0xb5,0x2b,0x74,0x80,0x6f,0x7f,0x2e,0xb9,IID_IDWriteTextAnalyzer2)
+GUID_ENTRY(0x5598b14b,0x9fd7,0x48b7,0x9b,0xdb,0x8f,0x09,0x64,0xeb,0x38,0xbc,IID_ID2D1ComputeInfo)
+GUID_ENTRY(0x55f1112b,0x1dc2,0x4b3c,0x95,0x41,0xf4,0x68,0x94,0xed,0x85,0xb6,IID_IDWriteTypography)
+GUID_ENTRY(0x56648f4d,0xcc8b,0x4444,0xa5,0xad,0xb5,0xa3,0xd7,0x6e,0x91,0xb3,IID_ID3D10EffectConstantBuffer)
+GUID_ENTRY(0x574ccc14,0xf0b3,0x4333,0x82,0x2d,0x93,0xe8,0xa8,0xa0,0x8e,0x4c,DXFILEOBJ_PMVSplitRecord)
+GUID_ENTRY(0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27,IID_IDirectDrawSurface2)
+GUID_ENTRY(0x580ca87e,0x1d3c,0x4d54,0x99,0x1d,0xb7,0xd3,0xe3,0xc2,0x98,0xce,IID_IDirect3DBaseTexture9)
+GUID_ENTRY(0x5810cd44,0x0ca0,0x4701,0xb3,0xfa,0xbe,0xc5,0x18,0x2a,0xe4,0xf6,IID_IDWriteTextAnalysisSink)
+GUID_ENTRY(0x593817a0,0x7db3,0x11cf,0xa2,0xde,0x00,0xaa,0x00,0xb9,0x33,0x56,CLSID_DirectDrawClipper)
+GUID_ENTRY(0x595e39d1,0x2724,0x4663,0x99,0xb1,0xda,0x96,0x9d,0xe2,0x83,0x64,IID_IDXGIOutput2)
+GUID_ENTRY(0x59a6cd0e,0xe10d,0x4c1f,0x88,0xc0,0x63,0xab,0xa1,0xda,0xf3,0x0e,IID_ID3D11Linker)
+GUID_ENTRY(0x5a54a0c9,0xc7ec,0x4bd9,0x8e,0xde,0xf3,0xc7,0x5d,0xc4,0x39,0x3b,DXVA2_VideoProcProgressiveDevice)
+GUID_ENTRY(0x5a58797d,0xa72c,0x478d,0x8b,0xa2,0xef,0xc6,0xb0,0xef,0xe8,0x8e,IID_ID3D12ShaderReflection)
+GUID_ENTRY(0x5b11d51b,0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0,D3D11_DECODER_PROFILE_HEVC_VLD_MAIN)
+GUID_DUPLI(0x5b11d51b,0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0,DXVA2_ModeHEVC_VLD_Main)
+GUID_ENTRY(0x5b160d0f,0xac1b,0x4185,0x8b,0xa8,0xb3,0xae,0x42,0xa5,0xa4,0x55,IID_ID3D12GraphicsCommandList)
+GUID_ENTRY(0x5bf818c3,0x5e43,0x48cb,0xb6,0x31,0x86,0x83,0x96,0xd6,0xa1,0xd4,CLSID_D2D1TableTransfer)
+GUID_ENTRY(0x5c1e0d8a,0x7c23,0x48f9,0x8c,0x59,0xa9,0x29,0x58,0xce,0xff,0x11,IID_ID3DDeviceContextState)
+GUID_ENTRY(0x5cb2d9cf,0x327d,0x459f,0xa0,0xce,0x40,0xc0,0xb2,0x08,0x6b,0xf7,CLSID_D2D1Saturation)
+GUID_ENTRY(0x5cfbeb89,0x1a06,0x46e0,0xb2,0x82,0xe3,0xf9,0xbf,0xa3,0x6a,0x54,IID_ID3D10EffectPass)
+GUID_ENTRY(0x5e5a32a3,0x8dff,0x4773,0x9f,0xf6,0x06,0x96,0xea,0xb7,0x72,0x67,IID_IDWriteBitmapRenderTarget)
+GUID_ENTRY(0x5e7fa7ca,0xdde3,0x424c,0x89,0xf0,0x9f,0xcd,0x6f,0xed,0x58,0xcd,IID_IDWriteFontFaceReference)
+GUID_ENTRY(0x5f174b49,0x0d8b,0x4cfb,0x8b,0xca,0xf1,0xcc,0xe9,0xd0,0x6c,0x67,IID_IDWriteTextFormat1)
+GUID_ENTRY(0x5f49804d,0x7024,0x4d43,0xbf,0xa9,0xd2,0x59,0x84,0xf5,0x38,0x49,IID_IDWriteFontFace)
+GUID_ENTRY(0x5fb6c24d,0xc6dd,0x4231,0x94,0x04,0x50,0xf4,0xd5,0xc3,0x25,0x2d,CLSID_D2D1BitmapSource)
+GUID_ENTRY(0x6007896c,0x3244,0x4afd,0xbf,0x18,0xa6,0xd3,0xbe,0xda,0x50,0x23,IID_IDXGIDevice3)
+GUID_ENTRY(0x6102dee4,0xaf59,0x4b09,0xb9,0x99,0xb4,0x4d,0x73,0xf0,0x9b,0x24,IID_ID3D12CommandAllocator)
+GUID_ENTRY(0x61c23c20,0xae69,0x4d8e,0x94,0xcf,0x50,0x07,0x8d,0xf6,0x38,0xf2,CLSID_D2D1Flood)
+GUID_ENTRY(0x61f21c45,0x3c0e,0x4a74,0x9c,0xea,0x67,0x10,0x0d,0x9a,0xd5,0xe4,IID_ID3D11VideoContext)
+GUID_ENTRY(0x6214d9d2,0x432c,0x4abb,0x9f,0xce,0x21,0x6e,0xea,0x26,0x9e,0x3b,D3D11_AUTHENTICATED_QUERY_ACCESSIBILITY_ATTRIBUTES)
+GUID_DUPLI(0x6214d9d2,0x432c,0x4abb,0x9f,0xce,0x21,0x6e,0xea,0x26,0x9e,0x3b,D3DAUTHENTICATEDQUERY_ACCESSIBILITYATTRIBUTES)
+GUID_ENTRY(0x622c0ed0,0x956e,0x4da9,0x90,0x8a,0x2a,0xf9,0x4f,0x3c,0xe7,0x16,DXFILEOBJ_EffectDWord)
+GUID_ENTRY(0x62b98c44,0x1f82,0x4c67,0xbc,0xd0,0x72,0xcf,0x8f,0x21,0x7e,0x81,IID_ID3D10EffectVectorVariable)
+GUID_ENTRY(0x62baa2d2,0xab54,0x41b7,0xb8,0x72,0x78,0x7e,0x01,0x06,0xa4,0x21,IID_ID2D1PathGeometry1)
+GUID_ENTRY(0x6316be88,0x54cd,0x4040,0xab,0x44,0x20,0x46,0x1b,0xc8,0x1f,0x68,IID_ID3D10GeometryShader)
+GUID_ENTRY(0x631b4766,0x36dc,0x461d,0x8d,0xb6,0xc4,0x7e,0x13,0xe6,0x09,0x16,IID_ID3D11Query1)
+GUID_ENTRY(0x6346cc54,0x2cfc,0x4ad4,0x82,0x24,0xd1,0x58,0x37,0xde,0x77,0x00,D3D11_AUTHENTICATED_CONFIGURE_CRYPTO_SESSION)
+GUID_DUPLI(0x6346cc54,0x2cfc,0x4ad4,0x82,0x24,0xd1,0x58,0x37,0xde,0x77,0x00,D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION)
+GUID_ENTRY(0x639cfad8,0x0fb4,0x4b21,0xa5,0x8a,0x06,0x79,0x20,0x12,0x00,0x09,IID_IDWriteTextAnalysisSource1)
+GUID_ENTRY(0x63ac0b32,0xba44,0x450f,0x88,0x06,0x7f,0x4c,0xa1,0xff,0x2f,0x1b,IID_ID2D1BlendTransform)
+GUID_ENTRY(0x63ee58fb,0x1268,0x4835,0x86,0xda,0xf0,0x08,0xce,0x62,0xf0,0xd6,IID_ID3D12Pageable)
+GUID_ENTRY(0x64108800,0x957d,0x11d0,0x89,0xab,0x00,0xa0,0xc9,0x05,0x41,0x29,IID_IDirect3DDevice)
+GUID_ENTRY(0x645967a4,0x1392,0x4310,0xa7,0x98,0x80,0x53,0xce,0x3e,0x93,0xfd,IID_IDXGIAdapter3)
+GUID_ENTRY(0x649bbadb,0xf0f4,0x4639,0xa1,0x5b,0x24,0x39,0x3f,0xc3,0xab,0xac,D3D11_AUTHENTICATED_QUERY_RESTRICTED_SHARED_RESOURCE_PROCESS)
+GUID_DUPLI(0x649bbadb,0xf0f4,0x4639,0xa1,0x5b,0x24,0x39,0x3f,0xc3,0xab,0xac,D3DAUTHENTICATEDQUERY_RESTRICTEDSHAREDRESOURCEPROCESS)
+GUID_ENTRY(0x65019f75,0x8da2,0x497c,0xb3,0x2c,0xdf,0xa3,0x4e,0x48,0xed,0xe6,IID_ID2D1Image)
+GUID_ENTRY(0x6530d5c7,0x07e9,0x4271,0xa4,0x18,0xe7,0xce,0x4b,0xd1,0xe4,0x80,IID_ID3D10EffectSamplerVariable)
+GUID_ENTRY(0x6543dbb6,0x1b48,0x42f5,0xab,0x82,0xe9,0x7e,0xc7,0x43,0x26,0xf6,IID_ID3D11InfoQueue)
+GUID_ENTRY(0x667ea4c7,0xf1cd,0x4386,0xb5,0x23,0x7c,0x02,0x90,0xb8,0x3c,0xc5,IID_ID3DX10SPMesh)
+GUID_DUPLI(0x667ea4c7,0xf1cd,0x4386,0xb5,0x23,0x7c,0x02,0x90,0xb8,0x3c,0xc5,IID_ID3DXSPMesh)
+GUID_ENTRY(0x66c66a94,0xdddd,0x4b62,0xa6,0x6a,0xf0,0xda,0x33,0xc2,0xb4,0xd0,IID_ID3D10ShaderReflectionConstantBuffer)
+GUID_ENTRY(0x683a4278,0xcd5f,0x4d24,0x90,0xad,0xc4,0xe1,0xb6,0x85,0x5d,0x53,IID_ID3DXPRTEngine)
+GUID_ENTRY(0x688d15c3,0x02b0,0x438d,0xb1,0x3a,0xd1,0xb4,0x4c,0x32,0xc3,0x9a,IID_ID2D1ResourceTexture)
+GUID_ENTRY(0x688e1a58,0x5094,0x47c8,0xad,0xc8,0xfb,0xce,0xa6,0x0a,0xe9,0x2b,IID_IDWriteTextAnalysisSource)
+GUID_ENTRY(0x689f1f85,0xc72e,0x4e33,0x8f,0x19,0x85,0x75,0x4e,0xfd,0x5a,0xce,IID_ID2D1DrawingStateBlock1)
+GUID_ENTRY(0x693ce632,0x7f2f,0x45de,0x93,0xfe,0x18,0xd8,0x8b,0x37,0xaa,0x21,IID_ID2D1DrawInfo)
+GUID_ENTRY(0x696442be,0xa72e,0x4059,0xbc,0x79,0x5b,0x5c,0x98,0x04,0x0f,0xad,IID_ID3D12Resource)
+GUID_ENTRY(0x6985f346,0x2c3d,0x43b3,0xbe,0x8b,0xda,0xae,0x8a,0x03,0xd8,0x94,IID_ID3DXRenderToSurface)
+GUID_ENTRY(0x698cfb3f,0x9289,0x4d95,0x9a,0x57,0x33,0xa9,0x4b,0x5a,0x65,0xf9,IID_ID3DXAnimationSet)
+GUID_ENTRY(0x69c11c3e,0xb46b,0x11d1,0xad,0x7a,0x00,0xc0,0x4f,0xc2,0x9b,0x4e,IID_IDirectDrawGammaControl)
+GUID_ENTRY(0x6aa97485,0x6354,0x4cfc,0x90,0x8c,0xe4,0xa7,0x4f,0x62,0xc9,0x6c,CLSID_D2D12DAffineTransform)
+GUID_ENTRY(0x6aae1ec1,0x662a,0x11d0,0x88,0x9d,0x00,0xaa,0x00,0xbb,0xb7,0x6a,IID_IDirect3D2)
+GUID_ENTRY(0x6b3b2502,0x6e51,0x45b3,0x90,0xee,0x98,0x84,0x26,0x5e,0x8d,0xf3,IID_ID3D12Heap)
+GUID_ENTRY(0x6c14db80,0xa733,0x11ce,0xa5,0x21,0x00,0x20,0xaf,0x0b,0xe5,0x60,IID_IDirectDraw)
+GUID_ENTRY(0x6c14db81,0xa733,0x11ce,0xa5,0x21,0x00,0x20,0xaf,0x0b,0xe5,0x60,IID_IDirectDrawSurface)
+GUID_ENTRY(0x6c14db84,0xa733,0x11ce,0xa5,0x21,0x00,0x20,0xaf,0x0b,0xe5,0x60,IID_IDirectDrawPalette)
+GUID_ENTRY(0x6c14db85,0xa733,0x11ce,0xa5,0x21,0x00,0x20,0xaf,0x0b,0xe5,0x60,IID_IDirectDrawClipper)
+GUID_ENTRY(0x6c26c5c7,0x34e0,0x46fc,0x9c,0xfd,0xe5,0x82,0x37,0x06,0xe2,0x28,CLSID_D2D1DpiCompensation)
+GUID_ENTRY(0x6c53006a,0x4450,0x4199,0xaa,0x5b,0xad,0x16,0x56,0xfe,0xce,0x5e,CLSID_D2D1OpacityMetadata)
+GUID_ENTRY(0x6cc2480d,0x3808,0x4739,0x9f,0x88,0xde,0x49,0xfa,0xcd,0x8d,0x4c,IID_ID3DXCompressedAnimationSet)
+GUID_ENTRY(0x6d3bdbdc,0x5b02,0x4415,0xb8,0x52,0xce,0x5e,0x8b,0xcc,0xb2,0x89,IID_IDirect3DPixelShader9)
+GUID_ENTRY(0x6d4865fe,0x0ab8,0x4d91,0x8f,0x62,0x5d,0xd6,0xbe,0x34,0xa3,0xe0,IID_IDWriteFontFileStream)
+GUID_ENTRY(0x6e6ffa6a,0x9bae,0x4613,0xa5,0x1e,0x91,0x65,0x2d,0x50,0x8c,0x21,IID_ID3D11ShaderReflectionType)
+GUID_ENTRY(0x6e8c49fb,0xa371,0x4770,0xb4,0x40,0x29,0x08,0x60,0x22,0xb7,0x41,IID_ID3D11Counter)
+GUID_ENTRY(0x6f0d123b,0xbad2,0x4167,0xa0,0xd0,0x80,0x22,0x4f,0x25,0xfa,0xbb,DXFILEOBJ_SkinWeights)
+GUID_ENTRY(0x6f15aaf2,0xd208,0x4e89,0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c,IID_ID3D11Texture2D)
+GUID_ENTRY(0x6f3ec719,0x3735,0x42cc,0x80,0x63,0x65,0xcc,0x3c,0xb3,0x66,0x16,D3D11_DECODER_PROFILE_MPEG1_VLD)
+GUID_DUPLI(0x6f3ec719,0x3735,0x42cc,0x80,0x63,0x65,0xcc,0x3c,0xb3,0x66,0x16,DXVA2_ModeMPEG1_VLD)
+GUID_ENTRY(0x6f66a9a0,0xbece,0x4ee8,0xb1,0x1b,0x99,0x0e,0xb3,0x8e,0xd9,0x76,IID_IDXGIOutputDWM)
+GUID_ENTRY(0x6fbd02fb,0x209f,0x46c4,0xb0,0x59,0x2e,0xd1,0x55,0x86,0xa6,0xac,IID_ID3D11RasterizerState2)
+GUID_ENTRY(0x705b9d82,0x76cf,0x49d6,0xb7,0xe6,0xac,0x88,0x72,0xdb,0x01,0x3c,D3D11_DECODER_PROFILE_H264_VLD_MULTIVIEW_NOFGT)
+GUID_DUPLI(0x705b9d82,0x76cf,0x49d6,0xb7,0xe6,0xac,0x88,0x72,0xdb,0x01,0x3c,DXVA2_ModeH264_VLD_Multiview_NoFGT)
+GUID_ENTRY(0x7116d91c,0xe7e4,0x47ce,0xb8,0xc6,0xec,0x81,0x68,0xf4,0x37,0xe5,IID_ID3D12CommandList)
+GUID_ENTRY(0x712bd56d,0x86ff,0x4b71,0x91,0xe1,0xc1,0x3b,0x27,0x4f,0xf2,0xa2,IID_CDXGIAdapter)
+GUID_ENTRY(0x713f394e,0x92ca,0x47e7,0xab,0x81,0x11,0x59,0xc2,0x79,0x1e,0x54,IID_IDXGIFactoryDWM)
+GUID_ENTRY(0x71417501,0x8df9,0x4e0a,0xa7,0x8a,0x25,0x5f,0x97,0x56,0xba,0xff,IID_ID3D10EffectStringVariable)
+GUID_ENTRY(0x72755049,0x5ff7,0x435d,0x83,0x48,0x4b,0xe9,0x7c,0xfa,0x6c,0x7c,IID_IDWriteFontFileEnumerator)
+GUID_ENTRY(0x727cad4e,0xd6af,0x4c9e,0x8a,0x08,0xd6,0x95,0xb1,0x1c,0xaa,0x49,IID_IDWriteFontFileLoader)
+GUID_ENTRY(0x7385e5df,0x8fe8,0x41d5,0x86,0xb6,0xd7,0xb4,0x85,0x47,0xb6,0xcf,IID_IDirect3DDevice8)
+GUID_ENTRY(0x739d886a,0xcef5,0x47dc,0x87,0x69,0x1a,0x8b,0x41,0xbe,0xbb,0xb0,IID_IDWriteFontFile)
+GUID_ENTRY(0x75b68faa,0x347d,0x4159,0x8f,0x45,0xa0,0x64,0x0f,0x01,0xcd,0x9a,IID_ID3D11BlendState)
+GUID_ENTRY(0x765a30f3,0xf624,0x4c6f,0xa8,0x28,0xac,0xe9,0x48,0x62,0x24,0x45,IID_ID3D12PipelineState)
+GUID_ENTRY(0x770aae78,0xf26f,0x4dba,0xa8,0x29,0x25,0x3c,0x83,0xd1,0xb3,0x87,IID_IDXGIFactory1)
+GUID_ENTRY(0x77db970f,0x6276,0x48ba,0xba,0x28,0x07,0x01,0x43,0xb4,0x39,0x2c,IID_IDXGIDevice1)
+GUID_ENTRY(0x790a45f7,0x0d42,0x4876,0x98,0x3a,0x0a,0x55,0xcf,0xe6,0xf4,0xaa,IID_IDXGISwapChain1)
+GUID_ENTRY(0x791e8298,0x3ef3,0x4230,0x98,0x80,0xc9,0xbd,0xec,0xc4,0x20,0x64,IID_IDWriteBitmapRenderTarget1)
+GUID_ENTRY(0x794950f2,0xadfc,0x458a,0x90,0x5e,0x10,0xa1,0x0b,0x0b,0x50,0x3b,IID_IDirect3DSwapChain9)
+GUID_ENTRY(0x79aab587,0x6dbc,0x4fa7,0x82,0xde,0x37,0xfa,0x17,0x81,0xc5,0xce,IID_ID3DXEffectStateManager)
+GUID_ENTRY(0x79cf2233,0x7536,0x4948,0x9d,0x36,0x1e,0x46,0x92,0xdc,0x57,0x60,IID_ID3D11Debug)
+GUID_ENTRY(0x7a503555,0x4a83,0x11d1,0xa5,0xdb,0x00,0xa0,0xc9,0x03,0x67,0xf8,IID_IDirect3DVertexBuffer)
+GUID_ENTRY(0x7b3b6153,0xa886,0x4544,0xab,0x37,0x65,0x37,0xc8,0x50,0x04,0x03,IID_ID3D11UnorderedAccessView1)
+GUID_ENTRY(0x7b7166ec,0x21c7,0x44ae,0xb2,0x1a,0xc9,0xae,0x32,0x1a,0xe3,0x69,IID_IDXGIFactory)
+GUID_ENTRY(0x7c9dd65e,0xd3f7,0x4529,0xac,0xee,0x78,0x58,0x30,0xac,0xde,0x35,IID_IDirect3DIndexBuffer9)
+GUID_ENTRY(0x7d97dbf7,0xe085,0x42d4,0x81,0xe3,0x6a,0x88,0x3b,0xde,0xd1,0x18,IID_IDWriteGlyphRunAnalysis)
+GUID_ENTRY(0x7ed943dd,0x52e8,0x40b5,0xa8,0xd8,0x76,0x68,0x5c,0x40,0x63,0x30,IID_ID3DX10BaseMesh)
+GUID_DUPLI(0x7ed943dd,0x52e8,0x40b5,0xa8,0xd8,0x76,0x68,0x5c,0x40,0x63,0x30,IID_ID3DXBaseMesh)
+GUID_ENTRY(0x7f9b00b3,0xf125,0x4890,0x87,0x6e,0x1c,0x42,0xbf,0x69,0x7c,0x4d,DXFILEOBJ_CompressedAnimationSet)
+GUID_ENTRY(0x80849279,0xc799,0x4797,0x8c,0x33,0x04,0x07,0xa0,0x7d,0x9e,0x06,IID_ID3D10EffectShaderVariable)
+GUID_ENTRY(0x80dad800,0xe21f,0x4e83,0x96,0xce,0xbf,0xcc,0xe5,0x00,0xdb,0x7c,IID_IDWriteTextAnalyzer1)
+GUID_ENTRY(0x818a1105,0x7932,0x44f4,0xaa,0x86,0x08,0xae,0x7b,0x2f,0x2c,0x93,CLSID_D2D1SpotDiffuse)
+GUID_ENTRY(0x81bdcbca,0x64d4,0x426d,0xae,0x8d,0xad,0x01,0x47,0xf4,0x27,0x5c,IID_IDirect3D9)
+GUID_ENTRY(0x81c5b77b,0x13f8,0x4cdd,0xad,0x20,0xc8,0x90,0x54,0x7a,0xc6,0x5d,CLSID_D2D1Blend)
+GUID_ENTRY(0x82237326,0x8111,0x4f7c,0xbc,0xf4,0xb5,0xc1,0x17,0x55,0x64,0xfe,IID_ID2D1GdiMetafileSink)
+GUID_ENTRY(0x8337a8a6,0xa216,0x444a,0xb2,0xf4,0x31,0x47,0x33,0xa7,0x3a,0xea,IID_ID3D12ShaderReflectionVariable)
+GUID_ENTRY(0x8339fde3,0x106f,0x47ab,0x83,0x73,0x1c,0x62,0x95,0xeb,0x10,0xb3,IID_IDWriteInlineObject)
+GUID_ENTRY(0x838f01ec,0x9729,0x4527,0xaa,0xdb,0xdf,0x70,0xad,0xe7,0xfe,0xa9,IID_ID3DXTextureGutterHelper)
+GUID_ENTRY(0x839d1216,0xbb2e,0x412b,0xb7,0xf4,0xa9,0xdb,0xeb,0xe0,0x8e,0xd1,IID_ID3D11View)
+GUID_ENTRY(0x839ddca3,0x9b4e,0x41e4,0xb0,0x53,0x89,0x2b,0xd2,0xa1,0x1e,0xe7,D3D11_AUTHENTICATED_QUERY_OUTPUT_ID)
+GUID_DUPLI(0x839ddca3,0x9b4e,0x41e4,0xb0,0x53,0x89,0x2b,0xd2,0xa1,0x1e,0xe7,D3DAUTHENTICATEDQUERY_OUTPUTID)
+GUID_ENTRY(0x84e63de0,0x46aa,0x11cf,0x81,0x6f,0x00,0x00,0xc0,0x20,0x15,0x6e,IID_IDirect3DHALDevice)
+GUID_ENTRY(0x85c31227,0x3de5,0x4f00,0x9b,0x3a,0xf1,0x1a,0xc3,0x8c,0x18,0xb5,IID_IDirect3DTexture9)
+GUID_ENTRY(0x86695f12,0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60,D3D11_DECODER_PROFILE_MPEG2and1_VLD)
+GUID_DUPLI(0x86695f12,0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60,DXVA2_ModeMPEG2and1_VLD)
+GUID_ENTRY(0x8767df22,0xbacc,0x11d1,0x89,0x69,0x00,0xa0,0xc9,0x06,0x29,0xa8,IID_IDirect3DNullDevice)
+GUID_ENTRY(0x881949a1,0xd6f3,0x11d0,0x89,0xab,0x00,0xa0,0xc9,0x05,0x41,0x29,IID_IDirect3DMMXDevice)
+GUID_ENTRY(0x881db7d0,0xf7ee,0x4d4d,0xa6,0xd2,0x46,0x97,0xac,0xc6,0x6e,0xe8,CLSID_D2D1Histogram)
+GUID_ENTRY(0x8875769a,0xd579,0x4088,0xaa,0xeb,0x53,0x4d,0x1a,0xd8,0x4e,0x96,IID_ID3DX10PMesh)
+GUID_DUPLI(0x8875769a,0xd579,0x4088,0xaa,0xeb,0x53,0x4d,0x1a,0xd8,0x4e,0x96,IID_ID3DXPMesh)
+GUID_ENTRY(0x89d6ac4f,0x09f2,0x4229,0xb2,0xcd,0x37,0x74,0x0a,0x6d,0xfd,0x81,D3D11_DECODER_ENCRYPTION_HW_CENC)
+GUID_ENTRY(0x8a6bb301,0x7e7e,0x41f4,0xa8,0xe0,0x5b,0x32,0xf7,0xf9,0x9b,0x18,IID_IDXGIOutput3)
+GUID_ENTRY(0x8aeeeac7,0x05f9,0x44d4,0xb5,0x91,0x00,0x0b,0x0d,0xf1,0xcb,0x95,IID_IDirect3DVertexBuffer8)
+GUID_ENTRY(0x8ba5fb08,0x5195,0x40e2,0xac,0x58,0x0d,0x98,0x9c,0x3a,0x01,0x02,IID_ID3D10Blob)
+GUID_DUPLI(0x8ba5fb08,0x5195,0x40e2,0xac,0x58,0x0d,0x98,0x9c,0x3a,0x01,0x02,IID_ID3DXBuffer)
+GUID_ENTRY(0x8c3a39f0,0x916e,0x4690,0x80,0x4f,0x4c,0x80,0x01,0x35,0x5d,0x25,IID_IDirectXVideoProcessor)
+GUID_ENTRY(0x8cea8d1e,0x77b0,0x4986,0xb3,0xb9,0x2f,0x0c,0x0e,0xae,0x78,0x87,CLSID_D2D1Brightness)
+GUID_ENTRY(0x8d536ca1,0x0cca,0x4956,0xa8,0x37,0x78,0x69,0x63,0x75,0x55,0x84,IID_ID3D11ShaderReflection)
+GUID_ENTRY(0x8e349d19,0x54db,0x4a56,0x9d,0xc9,0x11,0x9d,0x87,0xbd,0xb8,0x04,IID_ID3D12LibraryReflection)
+GUID_ENTRY(0x8e5c6061,0x628a,0x4c8e,0x82,0x64,0xbb,0xe4,0x5c,0xb3,0xd5,0xdd,IID_ID3D11HullShader)
+GUID_ENTRY(0x8efb471d,0x616c,0x4f49,0x90,0xf7,0x12,0x7b,0xb7,0x63,0xfa,0x51,IID_ID3D12DescriptorHeap)
+GUID_ENTRY(0x8f0f30db,0x446a,0x4282,0x9f,0xa2,0x28,0xf7,0x5c,0x1f,0x39,0xad,IID_IDXGISwapChainDWM1)
+GUID_ENTRY(0x905db94b,0xa00c,0x4140,0x9d,0xf5,0x2b,0x64,0xca,0x9e,0xa3,0x57,IID_ID3D12DeviceChild)
+GUID_ENTRY(0x9064d822,0x80a7,0x465c,0xa9,0x86,0xdf,0x65,0xf7,0x8b,0x8f,0xeb,IID_IDWriteTextLayout1)
+GUID_ENTRY(0x90866fcd,0x488e,0x454b,0xaf,0x06,0xe5,0x04,0x1b,0x66,0xc3,0x6c,CLSID_D2D1DiscreteTransfer)
+GUID_ENTRY(0x90f732e2,0x5092,0x4606,0xa8,0x19,0x86,0x51,0x97,0x0b,0xac,0xcd,IID_ID2D1BoundsAdjustmentTransform)
+GUID_ENTRY(0x91308b87,0x9040,0x411d,0x8c,0x67,0xc3,0x92,0x53,0xce,0x38,0x02,IID_ID3D11ShaderResourceView1)
+GUID_ENTRY(0x913e2be4,0xfdcf,0x4fe2,0xa5,0xf0,0x24,0x54,0xf1,0x4f,0xf4,0x08,CLSID_D2D1Atlas)
+GUID_ENTRY(0x917e0427,0xc61e,0x4a14,0x9c,0x64,0xaf,0xe6,0x5f,0x9e,0x98,0x44,DXFILEOBJ_PMAttributeRange)
+GUID_ENTRY(0x91886caf,0x1c3d,0x4d2e,0xa0,0xab,0x3e,0x4c,0x7d,0x8d,0x33,0x03,IID_IDirect3DSwapChain9Ex)
+GUID_ENTRY(0x921f03d6,0x641c,0x47df,0x85,0x2d,0xb4,0xbb,0x61,0x53,0xae,0x11,CLSID_D2D1ColorMatrix)
+GUID_ENTRY(0x928c088b,0x76b9,0x4c6b,0xa5,0x36,0xa5,0x90,0x85,0x38,0x76,0xcd,IID_IDirect3DSwapChain8)
+GUID_ENTRY(0x93281500,0x8cf8,0x11d0,0x89,0xab,0x00,0xa0,0xc9,0x05,0x41,0x29,IID_IDirect3DViewport2)
+GUID_ENTRY(0x93281501,0x8cf8,0x11d0,0x89,0xab,0x00,0xa0,0xc9,0x05,0x41,0x29,IID_IDirect3DDevice2)
+GUID_ENTRY(0x93281502,0x8cf8,0x11d0,0x89,0xab,0x00,0xa0,0xc9,0x05,0x41,0x29,IID_IDirect3DTexture2)
+GUID_ENTRY(0x93281503,0x8cf8,0x11d0,0x89,0xab,0x00,0xa0,0xc9,0x05,0x41,0x29,IID_IDirect3DMaterial2)
+GUID_ENTRY(0x94413cf4,0xa6fc,0x4248,0x8b,0x50,0x66,0x74,0x34,0x8f,0xca,0xd3,IID_IDWriteRenderingParams1)
+GUID_ENTRY(0x94d99bdb,0xf1f8,0x4ab0,0xb2,0x36,0x7d,0xa0,0x17,0x0e,0xda,0xb1,IID_IDXGISwapChain3)
+GUID_ENTRY(0x94f81a73,0x9212,0x4376,0x9c,0x58,0xb1,0x6a,0x3a,0x0d,0x39,0x92,IID_ID2D1Factory2)
+GUID_ENTRY(0x9537ab04,0x3250,0x412e,0x82,0x13,0xfc,0xd2,0xf8,0x67,0x79,0x33,IID_ID3D10EffectPool)
+GUID_DUPLI(0x9537ab04,0x3250,0x412e,0x82,0x13,0xfc,0xd2,0xf8,0x67,0x79,0x33,IID_ID3DXEffectPool)
+GUID_ENTRY(0x99503cc1,0x66c7,0x45c9,0xa8,0x75,0x8a,0xd8,0xa7,0x91,0x44,0x01,CLSID_D2D1YCbCr)
+GUID_ENTRY(0x9a1b41c3,0xd3bb,0x466a,0x87,0xfc,0xfe,0x67,0x55,0x6a,0x3b,0x65,IID_IDWriteFactory3)
+GUID_ENTRY(0x9b32f9ad,0xbdcc,0x40a6,0xa3,0x9d,0xd5,0xc8,0x65,0x84,0x57,0x20,IID_ID3D11CryptoSession)
+GUID_ENTRY(0x9b6bd711,0x4f74,0x41c9,0x9e,0x7b,0x0b,0xe2,0xd7,0xd9,0x3b,0x4f,D3D11_CRYPTO_TYPE_AES128_CTR)
+GUID_DUPLI(0x9b6bd711,0x4f74,0x41c9,0x9e,0x7b,0x0b,0xe2,0xd7,0xd9,0x3b,0x4f,D3DCRYPTOTYPE_AES128_CTR)
+GUID_ENTRY(0x9b7e4c00,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10DeviceChild)
+GUID_ENTRY(0x9b7e4c01,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Resource)
+GUID_ENTRY(0x9b7e4c02,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Buffer)
+GUID_ENTRY(0x9b7e4c03,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Texture1D)
+GUID_ENTRY(0x9b7e4c04,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Texture2D)
+GUID_ENTRY(0x9b7e4c05,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Texture3D)
+GUID_ENTRY(0x9b7e4c07,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10ShaderResourceView)
+GUID_ENTRY(0x9b7e4c08,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10RenderTargetView)
+GUID_ENTRY(0x9b7e4c09,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10DepthStencilView)
+GUID_ENTRY(0x9b7e4c0a,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10VertexShader)
+GUID_ENTRY(0x9b7e4c0b,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10InputLayout)
+GUID_ENTRY(0x9b7e4c0c,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10SamplerState)
+GUID_ENTRY(0x9b7e4c0d,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Asynchronous)
+GUID_ENTRY(0x9b7e4c0e,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Query)
+GUID_ENTRY(0x9b7e4c0f,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Device)
+GUID_ENTRY(0x9b7e4c10,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Predicate)
+GUID_ENTRY(0x9b7e4c11,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Counter)
+GUID_ENTRY(0x9b7e4c87,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10ShaderResourceView1)
+GUID_ENTRY(0x9b7e4c8f,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Device1)
+GUID_ENTRY(0x9b7e4e00,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Multithread)
+GUID_ENTRY(0x9b7e4e01,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10Debug)
+GUID_ENTRY(0x9b7e4e02,0x342c,0x4106,0xa1,0x9f,0x4f,0x27,0x04,0xf6,0x89,0xf0,IID_ID3D10SwitchToRef)
+GUID_ENTRY(0x9b8b1336,0x00a5,0x4668,0x92,0xb7,0xce,0xd5,0xd8,0xbf,0x9b,0x7b,IID_ID2D1VertexBuffer)
+GUID_ENTRY(0x9bb4ab81,0xab1a,0x4d8f,0xb5,0x06,0xfc,0x04,0x20,0x0b,0x6e,0xe7,IID_ID3D11RasterizerState)
+GUID_ENTRY(0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5,IID_IDirectDraw4)
+GUID_ENTRY(0x9c906818,0x31d7,0x4fd3,0xa1,0x51,0x7c,0x5e,0x22,0x5d,0xb5,0x5a,IID_IDWriteTextFormat)
+GUID_ENTRY(0x9d06dffa,0xd1e5,0x4d07,0x83,0xa8,0x1b,0xb1,0x23,0xf2,0xf8,0x41,IID_ID3D11Device2)
+GUID_ENTRY(0x9d8e1289,0xd7b3,0x465f,0x81,0x26,0x25,0x0e,0x34,0x9a,0xf8,0x5d,IID_IDXGIKeyedMutex)
+GUID_ENTRY(0x9daf9369,0x3846,0x4d0e,0xa4,0x4e,0x0c,0x60,0x79,0x34,0xa5,0xd7,CLSID_D2D1Scale)
+GUID_ENTRY(0x9e415a43,0x7ba6,0x4a73,0x87,0x43,0xb7,0x3d,0x47,0xe8,0x84,0x76,DXFILEOBJ_AnimTicksPerSecond)
+GUID_ENTRY(0x9eb576dd,0x9f77,0x4d86,0x81,0xaa,0x8b,0xab,0x5f,0xe4,0x90,0xe2,IID_ID3D11Predicate)
+GUID_ENTRY(0x9eb767fd,0x4269,0x4467,0xb8,0xc2,0xeb,0x30,0xcb,0x30,0x57,0x43,IID_ID2D1CommandSink1)
+GUID_ENTRY(0x9fdac92a,0x1876,0x48c3,0xaf,0xad,0x25,0xb9,0x4f,0x84,0xa9,0xb6,IID_ID3D11DepthStencilView)
+GUID_ENTRY(0xa048285e,0x25a9,0x4527,0xbd,0x93,0xd6,0x8b,0x68,0xc4,0x42,0x54,IID_ID3D11VideoProcessorOutputView)
+GUID_ENTRY(0xa04bfb29,0x08ef,0x43d6,0xa4,0x9c,0xa9,0xbd,0xbd,0xcb,0xe6,0x86,IID_ID3D11Device1)
+GUID_ENTRY(0xa05c8c37,0xd2c6,0x4732,0xb3,0xa0,0x9c,0xe0,0xb0,0xdc,0x9a,0xe6,IID_ID3D11Device3)
+GUID_ENTRY(0xa0cade0f,0x06d5,0x4cf4,0xa1,0xc7,0xf3,0xcd,0xd7,0x25,0xaa,0x75,IID_IDirect3DDeviceManager9)
+GUID_ENTRY(0xa16907d7,0xbc02,0x4801,0x99,0xe8,0x8c,0xf7,0xf4,0x85,0xf7,0x74,IID_ID2D1GeometryRealization)
+GUID_ENTRY(0xa2296057,0xea42,0x4099,0x98,0x3b,0x53,0x9f,0xb6,0x50,0x54,0x26,IID_ID2D1Bitmap)
+GUID_ENTRY(0xa248fd3f,0x3e6c,0x4e63,0x9f,0x03,0x7f,0x68,0xec,0xc9,0x1d,0xb9,IID_ID2D1EffectImpl)
+GUID_ENTRY(0xa24bc4d1,0x769e,0x43f7,0x80,0x13,0x98,0xff,0x56,0x6c,0x18,0xe2,IID_ID3D11CommandList)
+GUID_ENTRY(0xa2a07292,0x89af,0x4345,0xbe,0x2e,0xc5,0x3d,0x9f,0xbb,0x6e,0x9f,IID_ID3D10RasterizerState)
+GUID_ENTRY(0xa3eb5d44,0xfc22,0x429d,0x9a,0xfb,0x32,0x21,0xcb,0x97,0x19,0xa6,DXFILEOBJ_Patch)
+GUID_ENTRY(0xa4665c60,0x2673,0x11cf,0xa3,0x1a,0x00,0xaa,0x00,0xb9,0x33,0x56,IID_IDirect3DRGBDevice)
+GUID_ENTRY(0xa64c844a,0xe282,0x4756,0x8b,0x80,0x25,0x0c,0xde,0x04,0x39,0x8c,DXFILEOBJ_FaceAdjacency)
+GUID_ENTRY(0xa6cd7faa,0xb0b7,0x4a2f,0x94,0x36,0x86,0x62,0xa6,0x57,0x97,0xcb,IID_ID3D11ClassInstance)
+GUID_ENTRY(0xa71efdb4,0x9fdb,0x4838,0xad,0x90,0xcf,0xc3,0xbe,0x8c,0x3d,0xaf,IID_IDWriteFontFace1)
+GUID_ENTRY(0xa758d465,0xfe8d,0x45ad,0x9c,0xf0,0xd0,0x1e,0x56,0x26,0x6a,0x07,IID_ID3DXPRTCompBuffer)
+GUID_ENTRY(0xa7f026da,0xa5f8,0x4487,0xa5,0x64,0x15,0xe3,0x43,0x57,0x65,0x1e,IID_ID3D11VideoContext1)
+GUID_ENTRY(0xa84cee02,0x3eea,0x4eee,0xa8,0x27,0x87,0xc1,0xa0,0x2a,0x0f,0xcc,IID_IDWriteFontCollection)
+GUID_ENTRY(0xa84eb584,0xc495,0x48aa,0xb9,0x4d,0x8b,0xd2,0xd6,0xfb,0xce,0x05,D3D11_AUTHENTICATED_QUERY_PROTECTION)
+GUID_DUPLI(0xa84eb584,0xc495,0x48aa,0xb9,0x4d,0x8b,0xd2,0xd6,0xfb,0xce,0x05,D3DAUTHENTICATEDQUERY_PROTECTION)
+GUID_ENTRY(0xa898a84c,0x3873,0x4588,0xb0,0x8b,0xeb,0xbf,0x97,0x8d,0xf0,0x41,IID_ID2D1Bitmap1)
+GUID_ENTRY(0xa8be2ac4,0x199f,0x4946,0xb3,0x31,0x79,0x59,0x9f,0xb9,0x8d,0xe7,IID_IDXGISwapChain2)
+GUID_ENTRY(0xa915128c,0xd954,0x4c79,0xbf,0xe1,0x64,0xdb,0x92,0x31,0x94,0xd6,IID_ID3DX11SegmentedScan)
+GUID_ENTRY(0xab3c758f,0x093e,0x4356,0xb7,0x62,0x4d,0xb1,0x8f,0x1b,0x3a,0x01,IID_ID3DXConstantTable)
+GUID_ENTRY(0xab4e9afd,0x1d1c,0x46e6,0xa7,0x2f,0x08,0x69,0x91,0x7b,0x0d,0xe8,D3DCRYPTOTYPE_PROPRIETARY)
+GUID_ENTRY(0xab998b5b,0x4258,0x44a9,0x9f,0xeb,0x94,0xe5,0x97,0xa6,0xba,0xae,D3D11_DECODER_PROFILE_MPEG4PT2_VLD_ADVSIMPLE_GMC)
+GUID_DUPLI(0xab998b5b,0x4258,0x44a9,0x9f,0xeb,0x94,0xe5,0x97,0xa6,0xba,0xae,DXVA2_ModeMPEG4pt2_VLD_AdvSimple_GMC)
+GUID_ENTRY(0xaba496dd,0xb617,0x4cb8,0xa8,0x66,0xbc,0x44,0xd7,0xeb,0x1f,0xa2,IID_IDXGISurface2)
+GUID_ENTRY(0xac8948ec,0xf86d,0x43e2,0x96,0xde,0x31,0xfc,0x35,0xf9,0x6d,0x9e,IID_ID3DXAnimationController)
+GUID_ENTRY(0xacd16696,0x8c14,0x4f5d,0x87,0x7e,0xfe,0x3f,0xc1,0xd3,0x27,0x37,IID_IDWriteFont)
+GUID_ENTRY(0xacd16696,0x8c14,0x4f5d,0x87,0x7e,0xfe,0x3f,0xc1,0xd3,0x27,0x38,IID_IDWriteFont1)
+GUID_ENTRY(0xad47c8fd,0x63ef,0x4acc,0x9b,0x51,0x67,0x97,0x9c,0x03,0x6c,0x06,CLSID_D2D1LinearTransfer)
+GUID_ENTRY(0xae02eedb,0xc735,0x4690,0x8d,0x52,0x5a,0x8d,0xc2,0x02,0x13,0xaa,IID_IDXGIOutput)
+GUID_ENTRY(0xae1572f4,0x5dd0,0x4777,0x99,0x8b,0x92,0x79,0x47,0x2a,0xe6,0x3b,IID_ID2D1GradientStopCollection1)
+GUID_ENTRY(0xae897105,0x00e6,0x45bf,0xbb,0x8e,0x28,0x1d,0xd6,0xdb,0x8e,0x1b,IID_ID3D10EffectVariable)
+GUID_ENTRY(0xaec22fb8,0x76f3,0x4639,0x9b,0xe0,0x28,0xeb,0x43,0xa6,0x7a,0x2e,IID_IDXGIObject)
+GUID_ENTRY(0xaf482368,0x330a,0x46a5,0x9a,0x5c,0x01,0xc7,0x1a,0xf2,0x4c,0x8d,IID_ID3D10EffectDepthStencilVariable)
+GUID_ENTRY(0xb02d7a1a,0x05e0,0x4a71,0x8e,0xf4,0x5c,0x5b,0xbf,0x47,0x50,0x86,IID_IDXGISwapChainXAML)
+GUID_ENTRY(0xb06fe5b9,0x43ec,0x4393,0x88,0x1b,0xdb,0xe4,0xdc,0x72,0xfd,0xa7,IID_IDWriteFontDownloadListener)
+GUID_ENTRY(0xb0784138,0x3b76,0x4bc5,0xb1,0x3b,0x0f,0xa2,0xad,0x02,0x65,0x9f,CLSID_D2D1Tile)
+GUID_ENTRY(0xb07c4fe5,0x310d,0x4ba8,0xa2,0x3c,0x4f,0x0f,0x20,0x6f,0x21,0x8b,IID_IDirect3DStateBlock9)
+GUID_ENTRY(0xb0ab3b60,0x33d7,0x11d1,0xa9,0x81,0x00,0xc0,0x4f,0xd7,0xb1,0x74,IID_IDirect3DDevice3)
+GUID_ENTRY(0xb0ab3b61,0x33d7,0x11d1,0xa9,0x81,0x00,0xc0,0x4f,0xd7,0xb1,0x74,IID_IDirect3DViewport3)
+GUID_ENTRY(0xb0d941a0,0x85e7,0x4d8b,0x9f,0xd3,0x5c,0xed,0x99,0x34,0x48,0x2a,IID_IDWriteTextAnalysisSink1)
+GUID_ENTRY(0xb0e06fe0,0x8192,0x4e1a,0xb1,0xca,0x36,0xd7,0x41,0x47,0x10,0xb2,IID_ID3D11ShaderResourceView)
+GUID_ENTRY(0xb1170d8a,0x628d,0x4da3,0xad,0x3b,0x82,0xdd,0xb0,0x8b,0x49,0x70,D3D11_KEY_EXCHANGE_HW_PROTECTION)
+GUID_ENTRY(0xb18b10ce,0x2649,0x405a,0x87,0x0f,0x95,0xf7,0x77,0xd4,0x31,0x3a,IID_IDirect3DDevice9Ex)
+GUID_ENTRY(0xb2d9f3ec,0xc9fe,0x4a11,0xa2,0xec,0xd8,0x62,0x08,0xf7,0xc0,0xa2,IID_IDWriteLocalFontFileLoader)
+GUID_ENTRY(0xb2daad8b,0x03d4,0x4dbf,0x95,0xeb,0x32,0xab,0x4b,0x63,0xd0,0xab,IID_ID3DUserDefinedAnnotation)
+GUID_ENTRY(0xb2efe1e7,0x729f,0x4102,0x94,0x9f,0x50,0x5f,0xa2,0x1b,0xf6,0x66,IID_ID2D1TransformNode)
+GUID_ENTRY(0xb30f7066,0x203c,0x4b07,0x93,0xfc,0xce,0xaa,0xfd,0x61,0x24,0x1e,D3D11_AUTHENTICATED_QUERY_ENCRYPTION_WHEN_ACCESSIBLE_GUID_COUNT)
+GUID_DUPLI(0xb30f7066,0x203c,0x4b07,0x93,0xfc,0xce,0xaa,0xfd,0x61,0x24,0x1e,D3DAUTHENTICATEDQUERY_ENCRYPTIONWHENACCESSIBLEGUIDCOUNT)
+GUID_ENTRY(0xb3a6f3e0,0x2b43,0x11cf,0xa2,0xde,0x00,0xaa,0x00,0xb9,0x33,0x56,IID_IDirectDraw2)
+GUID_ENTRY(0xb3f7a938,0x4c93,0x4310,0xa6,0x75,0xb3,0x0d,0x6d,0xe5,0x05,0x53,IID_ID3DX11FFT)
+GUID_ENTRY(0xb4211cfa,0x51b9,0x4a9f,0xab,0x78,0xdb,0x99,0xb2,0xbb,0x67,0x8e,IID_IDirect3DBaseTexture8)
+GUID_ENTRY(0xb4e3c01d,0xe79e,0x4637,0x91,0xb2,0x51,0x0e,0x9f,0x4c,0x9b,0x8f,IID_ID3D11DeviceContext3)
+GUID_ENTRY(0xb4f34a19,0x2383,0x4d76,0x94,0xf6,0xec,0x34,0x36,0x57,0xc3,0xdc,IID_ID2D1CommandList)
+GUID_ENTRY(0xb64bb1b5,0xfd70,0x4df6,0xbf,0x91,0x19,0xd0,0xa1,0x24,0x55,0xe3,IID_IDirect3DVertexBuffer9)
+GUID_ENTRY(0xb6c3e656,0xec8b,0x4b92,0x9b,0x62,0x68,0x16,0x59,0x52,0x29,0x47,DXFILEOBJ_PMInfo)
+GUID_ENTRY(0xb6e70a0e,0x8ef9,0x4e83,0x94,0xad,0xec,0xc8,0xb0,0xc0,0x48,0x97,DXFILEOBJ_FVFData)
+GUID_ENTRY(0xb71e6052,0x5aea,0x4fa3,0x83,0x2e,0xf6,0x0d,0x43,0x1f,0x7e,0x91,IID_IDWriteFontDownloadQueue)
+GUID_ENTRY(0xb7924baa,0x391b,0x412a,0x8c,0x5c,0xe4,0x4c,0xc2,0xd8,0x67,0xdc,IID_IDWriteRenderingParams3)
+GUID_ENTRY(0xb79cc8da,0x337f,0x400f,0xb0,0x9d,0xb2,0xed,0xf8,0xa8,0x4e,0x47,IID_ID2DPrivateInfo)
+GUID_ENTRY(0xb7e6163e,0x7f46,0x43b4,0x84,0xb3,0xe4,0xe6,0x24,0x9c,0x36,0x5d,IID_IDWriteTextAnalyzer)
+GUID_ENTRY(0xb7f916dd,0xdb3b,0x49c1,0x84,0xd7,0xe4,0x5e,0xf9,0x9e,0xc7,0x26,IID_IDirectXVideoMemoryConfiguration)
+GUID_ENTRY(0xb859ee5a,0xd838,0x4b5b,0xa2,0xe8,0x1a,0xdc,0x7d,0x93,0xdb,0x48,IID_IDWriteFactory)
+GUID_ENTRY(0xb8d65549,0xd7c9,0x4995,0x89,0xcf,0x53,0xa9,0xa8,0xb0,0x31,0xe3,DXFILEOBJ_VertexDuplicationIndices)
+GUID_ENTRY(0xb96eebca,0xb326,0x4ea5,0x88,0x2f,0x2f,0xf5,0xba,0xe0,0x21,0xdd,IID_IDirect3DSurface8)
+GUID_ENTRY(0xb9e303c3,0xc08c,0x4f91,0x8b,0x7b,0x38,0x65,0x6b,0xc4,0x8c,0x20,CLSID_D2D1PointDiffuse)
+GUID_ENTRY(0xb9ec94e1,0xb9a6,0x4251,0xba,0x18,0x94,0x89,0x3f,0x02,0xc0,0xea,DXFILEOBJ_PatchMesh9)
+GUID_ENTRY(0xba0b762d,0x7d28,0x43ec,0xb9,0xdc,0x2f,0x84,0x44,0x3b,0x06,0x14,IID_ID3DXSprite)
+GUID_ENTRY(0xba0b762d,0x8d28,0x43ec,0xb9,0xdc,0x2f,0x84,0x44,0x3b,0x06,0x14,IID_ID3DX10Sprite)
+GUID_ENTRY(0xbb12d362,0xdaee,0x4b9a,0xaa,0x1d,0x14,0xba,0x40,0x1c,0xfa,0x1f,IID_ID2D1Factory1)
+GUID_ENTRY(0xbb223240,0xe72b,0x11d0,0xa9,0xb4,0x00,0xaa,0x00,0xc0,0x99,0x3e,IID_IDirect3D3)
+GUID_ENTRY(0xbb2c6faa,0xb5fb,0x4082,0x8e,0x6b,0x38,0x8b,0x8c,0xfa,0x90,0xe1,IID_ID3D11DeviceContext1)
+GUID_ENTRY(0xbc1b18a5,0xb1fb,0x42ab,0xbd,0x94,0xb5,0x82,0x8b,0x4b,0xf7,0xbe,D3D11_AUTHENTICATED_QUERY_CHANNEL_TYPE)
+GUID_DUPLI(0xbc1b18a5,0xb1fb,0x42ab,0xbd,0x94,0xb5,0x82,0x8b,0x4b,0xf7,0xbe,D3DAUTHENTICATEDQUERY_CHANNELTYPE)
+GUID_ENTRY(0xbd7349f5,0x14f1,0x42e4,0x9c,0x79,0x97,0x23,0x80,0xdb,0x40,0xc0,IID_IDirect3DVolume8)
+GUID_ENTRY(0xbf22ad00,0x03ea,0x4690,0x80,0x77,0x47,0x33,0x46,0x20,0x9b,0x7e,D3D11_DECODER_PROFILE_MPEG2_IDCT)
+GUID_DUPLI(0xbf22ad00,0x03ea,0x4690,0x80,0x77,0x47,0x33,0x46,0x20,0x9b,0x7e,DXVA2_ModeMPEG2_IDCT)
+GUID_ENTRY(0xbf22e553,0x292c,0x4781,0x9f,0xea,0x62,0xbd,0x55,0x4b,0xdd,0x93,DXFILEOBJ_DeclData)
+GUID_ENTRY(0xc0a7157b,0xd872,0x4b1d,0x80,0x73,0xef,0xc2,0xac,0xd4,0xb1,0xfc,IID_ID3D10EffectShaderResourceVariable)
+GUID_ENTRY(0xc0bfa96c,0xe089,0x44fb,0x8e,0xaf,0x26,0xf8,0x79,0x61,0x90,0xda,IID_ID3D11DeviceContext)
+GUID_ENTRY(0xc0c5fda1,0x8899,0x4194,0xb1,0xf6,0x54,0x3c,0x6d,0x2e,0xd3,0x14,IID_IDXGIDeviceDWM)
+GUID_ENTRY(0xc1949895,0xd72a,0x4a1d,0x8e,0x5d,0xed,0x85,0x7d,0x17,0x15,0x20,D3D11_KEY_EXCHANGE_RSAES_OAEP)
+GUID_DUPLI(0xc1949895,0xd72a,0x4a1d,0x8e,0x5d,0xed,0x85,0x7d,0x17,0x15,0x20,D3DKEYEXCHANGE_RSAES_OAEP)
+GUID_ENTRY(0xc2844d0b,0x3d86,0x46e7,0x85,0xba,0x52,0x6c,0x92,0x40,0xf3,0xfb,CLSID_D2D13DPerspectiveTransform)
+GUID_ENTRY(0xc2931aea,0x2a85,0x4f20,0x86,0x0f,0xfb,0xa1,0xfd,0x25,0x6e,0x18,IID_ID3D11VideoDecoderOutputView)
+GUID_ENTRY(0xc3457783,0xa846,0x47ce,0x95,0x20,0xce,0xa6,0xf6,0x6e,0x74,0x47,IID_ID3D10ShaderReflection1)
+GUID_ENTRY(0xc36a797c,0xec80,0x4f0a,0x89,0x85,0xa7,0xb2,0x47,0x50,0x82,0xd1,IID_ID3D12CommandSignature)
+GUID_ENTRY(0xc40a00f2,0xb93a,0x4d80,0xae,0x8c,0x5a,0x1c,0x63,0x4f,0x58,0xe4,IID_IMFSample)
+GUID_ENTRY(0xc4fec28f,0x7966,0x4e95,0x9f,0x94,0xf4,0x31,0xcb,0x56,0xc3,0xb8,IID_ID3D12Object)
+GUID_ENTRY(0xc530ad7d,0x9b16,0x4395,0xa9,0x79,0xba,0x2e,0xcf,0xf8,0x3a,0xdd,IID_ID3D10ShaderReflectionType)
+GUID_ENTRY(0xc54a6b66,0x72df,0x4ee8,0x8b,0xe5,0xa9,0x46,0xa1,0x42,0x92,0x14,IID_ID3D12RootSignature)
+GUID_ENTRY(0xc59598b4,0x48b3,0x4869,0xb9,0xb1,0xb1,0x61,0x8b,0x14,0xa8,0xb7,IID_ID3D12ShaderReflectionConstantBuffer)
+GUID_ENTRY(0xc5a05f0c,0x16f2,0x4adf,0x9f,0x4d,0xa8,0xc4,0xd5,0x8a,0xc5,0x50,IID_IDXGIDebug1)
+GUID_ENTRY(0xc67ea361,0x1863,0x4e69,0x89,0xdb,0x69,0x5d,0x3e,0x9a,0x5b,0x6b,CLSID_D2D1Shadow)
+GUID_ENTRY(0xc7885ba7,0xf990,0x4fe7,0x92,0x2d,0x85,0x15,0xe4,0x77,0xdd,0x85,IID_ID3DXMatrixStack)
+GUID_ENTRY(0xc902b03f,0x60a7,0x49ba,0x99,0x36,0x2a,0x3a,0xb3,0x7a,0x7e,0x33,IID_ID3D10View)
+GUID_DUPLI(0xc93fecfa,0x6967,0x478a,0xab,0xbc,0x40,0x2d,0x90,0x62,0x1f,0xcb,IID_ID3DX10ThreadPump)
+GUID_ENTRY(0xc93fecfa,0x6967,0x478a,0xab,0xbc,0x40,0x2d,0x90,0x62,0x1f,0xcb,IID_ID3DX11ThreadPump)
+GUID_ENTRY(0xca9c46f4,0xd3c5,0x11d1,0xb7,0x5a,0x00,0x60,0x08,0x52,0xb3,0x12,IID_IDirect3DMaterial3)
+GUID_ENTRY(0xcac701ee,0x80fc,0x4122,0x82,0x42,0x10,0xb3,0x9c,0x8c,0xec,0x34,IID_ID3D11Module)
+GUID_ENTRY(0xcafcb56c,0x6ac3,0x4889,0xbf,0x47,0x9e,0x23,0xbb,0xd2,0x60,0xec,IID_IDXGISurface)
+GUID_ENTRY(0xcc86fabe,0xda55,0x401d,0x85,0xe7,0xe3,0xc9,0xde,0x28,0x77,0xe9,IID_ID3D11BlendState1)
+GUID_ENTRY(0xcca920e4,0x52f0,0x492b,0xbf,0xa8,0x29,0xc7,0x2e,0xe0,0xa4,0x68,IID_IDWriteFontCollectionLoader)
+GUID_ENTRY(0xcef08cf9,0x7b4f,0x4429,0x96,0x24,0x2a,0x69,0x0a,0x93,0x32,0x01,IID_ID3DXFile)
+GUID_ENTRY(0xcef08cfa,0x7b4f,0x4429,0x96,0x24,0x2a,0x69,0x0a,0x93,0x32,0x01,IID_ID3DXFileSaveObject)
+GUID_ENTRY(0xcef08cfb,0x7b4f,0x4429,0x96,0x24,0x2a,0x69,0x0a,0x93,0x32,0x01,IID_ID3DXFileSaveData)
+GUID_ENTRY(0xcef08cfc,0x7b4f,0x4429,0x96,0x24,0x2a,0x69,0x0a,0x93,0x32,0x01,IID_ID3DXFileEnumObject)
+GUID_ENTRY(0xcef08cfd,0x7b4f,0x4429,0x96,0x24,0x2a,0x69,0x0a,0x93,0x32,0x01,IID_ID3DXFileData)
+GUID_ENTRY(0xcf2bb6ae,0x889a,0x4ad7,0xba,0x29,0xa2,0xfd,0x73,0x2c,0x9f,0xc9,CLSID_D2D1Turbulence)
+GUID_ENTRY(0xcf59a98c,0xa950,0x4326,0x91,0xef,0x9b,0xba,0xa1,0x7b,0xfd,0x95,DXGI_DEBUG_D3D12)
+GUID_ENTRY(0xcfee3140,0x1157,0x47ca,0x8b,0x85,0x31,0xbf,0xcf,0x3f,0x2d,0x0e,IID_IDWriteStringList)
+GUID_ENTRY(0xd0149dc0,0x90e8,0x4ec8,0x81,0x44,0xe9,0x00,0xad,0x26,0x6b,0xb2,WKPDID_CommentStringW)
+GUID_ENTRY(0xd0223b96,0xbf7a,0x43fd,0x92,0xbd,0xa4,0x3b,0x0d,0x82,0xb9,0xeb,IID_IDirect3DDevice9)
+GUID_ENTRY(0xd02c95cc,0xedba,0x4305,0x9b,0x5d,0x18,0x20,0xd7,0x70,0x4b,0xbf,DXFILEOBJ_PatchMesh)
+GUID_ENTRY(0xd21768e1,0x23a4,0x4823,0xa1,0x4b,0x7c,0x3e,0xba,0x85,0xd6,0x58,IID_ID2D1Device1)
+GUID_ENTRY(0xd31fbe17,0xf157,0x41a2,0x8d,0x24,0xcb,0x77,0x9e,0x05,0x60,0xe8,IID_IDWriteColorGlyphRunEnumerator)
+GUID_ENTRY(0xd379ba7f,0x9042,0x4ac4,0x9f,0x5e,0x58,0x19,0x2a,0x4c,0x6b,0xd8,IID_ID3DXLine)
+GUID_ENTRY(0xd37d7598,0x09be,0x4222,0xa2,0x36,0x20,0x81,0x34,0x1c,0xc1,0xf2,IID_IDWriteFontFace3)
+GUID_ENTRY(0xd37f57e4,0x6908,0x459f,0xa1,0x99,0xe7,0x2f,0x24,0xf7,0x99,0x87,IID_ID2D1DeviceContext1)
+GUID_ENTRY(0xd3e0e934,0x22a0,0x427e,0xaa,0xe4,0x7d,0x95,0x74,0xb5,0x9d,0xb1,IID_IDWriteTextRenderer1)
+GUID_ENTRY(0xd40e20b6,0xf8f7,0x42ad,0xab,0x20,0x4b,0xaf,0x8f,0x15,0xdf,0xaa,IID_ID3D10ShaderReflection)
+GUID_ENTRY(0xd55b097e,0xbdb6,0x4c52,0xb0,0x3d,0x60,0x51,0xc8,0x9d,0x0e,0x42,DXFILEOBJ_EffectString)
+GUID_ENTRY(0xd5f04ff9,0x3418,0x45d8,0x95,0x61,0x32,0xa7,0x6a,0xae,0x2d,0xdd,D3D11_DECODER_PROFILE_H264_VLD_WITHFMOASO_NOFGT)
+GUID_DUPLI(0xd5f04ff9,0x3418,0x45d8,0x95,0x61,0x32,0xa7,0x6a,0xae,0x2d,0xdd,DXVA2_ModeH264_VLD_WithFMOASO_NoFGT)
+GUID_ENTRY(0xd67441c7,0x672a,0x476f,0x9e,0x82,0xcd,0x55,0xb4,0x49,0x49,0xce,IID_IDXGIInfoQueue)
+GUID_ENTRY(0xd6c00747,0x87b7,0x425e,0xb8,0x4d,0x44,0xd1,0x08,0x56,0x0a,0xfd,IID_ID3D11Query)
+GUID_ENTRY(0xd722fb4d,0x7a68,0x437a,0xb2,0x0c,0x58,0x04,0xee,0x24,0x94,0xa6,GUID_DeviceType)
+GUID_ENTRY(0xd79be8da,0x0cf1,0x4c81,0xb8,0x2a,0x69,0xa4,0xe2,0x36,0xf4,0x3d,D3D11_DECODER_PROFILE_H264_VLD_STEREO_PROGRESSIVE_NOFGT)
+GUID_DUPLI(0xd79be8da,0x0cf1,0x4c81,0xb8,0x2a,0x69,0xa4,0xe2,0x36,0xf4,0x3d,DXVA2_ModeH264_VLD_Stereo_Progressive_NoFGT)
+GUID_ENTRY(0xd79dbb70,0x5f21,0x4d36,0xbb,0xc2,0xff,0x52,0x5c,0x21,0x3c,0xdc,IID_ID3DX10Font)
+GUID_DUPLI(0xd79dbb70,0x5f21,0x4d36,0xbb,0xc2,0xff,0x52,0x5c,0x21,0x3c,0xdc,IID_ID3DXFont)
+GUID_ENTRY(0xd7b70ee0,0x4340,0x11cf,0xb0,0x63,0x00,0x20,0xaf,0xc2,0xcd,0x35,CLSID_DirectDraw)
+GUID_ENTRY(0xd80dd70c,0x8d2f,0x4751,0x94,0xa1,0x03,0xc7,0x9b,0x35,0x56,0xdb,IID_ID3D11LinkingNode)
+GUID_ENTRY(0xd8b768ff,0x64bc,0x4e66,0x98,0x2b,0xec,0x8e,0x87,0xf6,0x93,0xf7,IID_IDWriteFontFace2)
+GUID_ENTRY(0xd9771460,0xa695,0x4f26,0xbb,0xd3,0x27,0xb8,0x40,0xb5,0x41,0xcc,IID_IDirect3DQuery9)
+GUID_ENTRY(0xda044e00,0x69b2,0x11d0,0xa1,0xd5,0x00,0xaa,0x00,0xb8,0xdf,0xbb,IID_IDirectDrawSurface3)
+GUID_ENTRY(0xda20d8ef,0x812a,0x4c43,0x98,0x02,0x62,0xec,0x4a,0xbd,0x7a,0xdd,IID_IDWriteFontFamily)
+GUID_ENTRY(0xda20d8ef,0x812a,0x4c43,0x98,0x02,0x62,0xec,0x4a,0xbd,0x7a,0xde,IID_IDWriteFontList1)
+GUID_ENTRY(0xda20d8ef,0x812a,0x4c43,0x98,0x02,0x62,0xec,0x4a,0xbd,0x7a,0xdf,IID_IDWriteFontFamily1)
+GUID_ENTRY(0xda6fea51,0x564c,0x4487,0x98,0x10,0xf0,0xd0,0xf9,0xb4,0xe3,0xa5,IID_ID3D11SamplerState)
+GUID_ENTRY(0xdb122ce8,0xd1c9,0x4292,0xb2,0x37,0x24,0xed,0x3d,0xe8,0xb1,0x75,IID_ID3D10EffectTechnique)
+GUID_ENTRY(0xdb1800dd,0x0c34,0x4cf9,0xbe,0x90,0x31,0xcc,0x0a,0x56,0x53,0xe1,IID_ID2D1SourceTransform)
+GUID_ENTRY(0xdb6f6ddb,0xac77,0x4e88,0x82,0x53,0x81,0x9d,0xf9,0xbb,0xf1,0x40,IID_ID3D11Device)
+GUID_ENTRY(0xdc7dca35,0x2196,0x414d,0x9f,0x53,0x61,0x78,0x84,0x03,0x2a,0x60,IID_IDXGIOutput4)
+GUID_ENTRY(0xdc8e63f3,0xd12b,0x4952,0xb4,0x7b,0x5e,0x45,0x02,0x6a,0x86,0x2d,IID_ID3D11Resource)
+GUID_ENTRY(0xdd13c59c,0x36fa,0x4098,0xa8,0xfb,0xc7,0xed,0x39,0xdc,0x85,0x46,IID_IDirect3DVertexDeclaration9)
+GUID_ENTRY(0xdd95b90b,0xf05f,0x4f6a,0xbd,0x65,0x25,0xbf,0xb2,0x64,0xbd,0x84,IID_IDXGISwapChainMedia)
+GUID_ENTRY(0xddf57cba,0x9543,0x46e4,0xa1,0x2b,0xf2,0x07,0xa0,0xfe,0x7f,0xed,IID_ID3D11ClassLinkage)
+GUID_ENTRY(0xdfdba067,0x0b8d,0x4865,0x87,0x5b,0xd7,0xb4,0x51,0x6c,0xc1,0x64,IID_ID3D11RenderTargetView)
+GUID_ENTRY(0xe0db51c3,0x6f77,0x4bae,0xb3,0xd5,0xe4,0x75,0x09,0xb3,0x58,0x38,IID_ID2D1GdiInteropRenderTarget)
+GUID_ENTRY(0xe13963bc,0xae51,0x4c5d,0xb0,0x0f,0xcf,0xa3,0xa9,0xd9,0x7c,0xe5,DXFILEOBJ_EffectParamDWord)
+GUID_ENTRY(0xe23f7110,0x0e9a,0x4324,0xaf,0x47,0x6a,0x2c,0x0c,0x46,0xf3,0x5b,CLSID_D2D1Crop)
+GUID_ENTRY(0xe331f7e4,0x0559,0x4cc2,0x8e,0x99,0x1c,0xec,0x16,0x57,0x92,0x8f,DXFILEOBJ_EffectInstance)
+GUID_ENTRY(0xe4819ddc,0x4cf0,0x4025,0xbd,0x26,0x5d,0xe8,0x2a,0x3e,0x07,0xb7,IID_ID3D11InputLayout)
+GUID_ENTRY(0xe48ae283,0xda80,0x490b,0x87,0xe6,0x43,0xe9,0xa9,0xcf,0xda,0x08,DXGI_DEBUG_ALL)
+GUID_ENTRY(0xe4a36723,0xfdfe,0x4b22,0xb1,0x46,0x3c,0x04,0xc0,0x7f,0x4c,0xc8,IID_HelperName)
+GUID_ENTRY(0xe4cdd575,0x2866,0x4f01,0xb1,0x2e,0x7e,0xec,0xe1,0xec,0x93,0x58,IID_IDirect3DTexture8)
+GUID_ENTRY(0xe6a9f44b,0x61b0,0x4563,0x9e,0xa4,0x63,0xd2,0xa3,0xc6,0xfe,0x66,D3D11_DECODER_PROFILE_MPEG2_MOCOMP)
+GUID_DUPLI(0xe6a9f44b,0x61b0,0x4563,0x9e,0xa4,0x63,0xd2,0xa3,0xc6,0xfe,0x66,DXVA2_ModeMPEG2_MoComp)
+GUID_ENTRY(0xe8467b04,0xec61,0x4b8a,0xb5,0xde,0xd4,0xd7,0x3d,0xeb,0xea,0x5a,CLSID_D2D13DTransform)
+GUID_ENTRY(0xe8f7fe7a,0x191c,0x466d,0xad,0x95,0x97,0x56,0x78,0xbd,0xa9,0x98,IID_ID2D1DeviceContext)
+GUID_ENTRY(0xe913c351,0x783d,0x48ca,0xa1,0xd1,0x4f,0x30,0x62,0x84,0xad,0x56,IID_ID3D12ShaderReflectionType)
+GUID_ENTRY(0xea82e40d,0x51dc,0x4f33,0x93,0xd4,0xdb,0x7c,0x91,0x25,0xae,0x8c,IID_ID3D11PixelShader)
+GUID_ENTRY(0xea9dbf1a,0xc88e,0x4486,0x85,0x4a,0x98,0xaa,0x01,0x38,0xf3,0x0c,IID_IDXGIDisplayControl)
+GUID_ENTRY(0xeae6c40d,0x626a,0x4c2d,0xbf,0xcb,0x39,0x10,0x01,0xab,0xe2,0x02,CLSID_D2D1Morphology)
+GUID_ENTRY(0xeaf3a2da,0xecf4,0x4d24,0xb6,0x44,0xb3,0x4f,0x68,0x42,0x02,0x4b,IID_IDWritePixelSnapping)
+GUID_ENTRY(0xeb62d63d,0x93dd,0x4318,0x8a,0xe8,0xc6,0xf8,0x3a,0xd3,0x71,0xb8,IID_ID3D11ShaderReflectionConstantBuffer)
+GUID_ENTRY(0xec1791c7,0xdad3,0x4f15,0x9e,0xc3,0xfa,0xa9,0x3d,0x60,0xd4,0xf0,D3D11_AUTHENTICATED_QUERY_CURRENT_ENCRYPTION_WHEN_ACCESSIBLE)
+GUID_DUPLI(0xec1791c7,0xdad3,0x4f15,0x9e,0xc3,0xfa,0xa9,0x3d,0x60,0xd4,0xf0,D3DAUTHENTICATEDQUERY_CURRENTENCRYPTIONWHENACCESSIBLE)
+GUID_ENTRY(0xec1c539d,0x8cff,0x4e2a,0xbc,0xc4,0xf5,0x69,0x2f,0x99,0xf4,0x80,D3D11_AUTHENTICATED_QUERY_DEVICE_HANDLE)
+GUID_DUPLI(0xec1c539d,0x8cff,0x4e2a,0xbc,0xc4,0xf5,0x69,0x2f,0x99,0xf4,0x80,D3DAUTHENTICATEDQUERY_DEVICEHANDLE)
+GUID_ENTRY(0xec25f42d,0x7006,0x4f2b,0xb3,0x3e,0x02,0xcc,0x33,0x75,0x73,0x3f,IID_ID3D12FunctionParameterReflection)
+GUID_ENTRY(0xed418a9f,0x010d,0x4eda,0x9a,0xe3,0x9a,0x65,0x35,0x8d,0x8d,0x2e,D3D11_DECODER_PROFILE_MPEG4PT2_VLD_ADVSIMPLE_NOGMC)
+GUID_DUPLI(0xed418a9f,0x010d,0x4eda,0x9a,0xe3,0x9a,0x65,0x35,0x8d,0x8d,0x2e,DXVA2_ModeMPEG4pt2_VLD_AdvSimple_NoGMC)
+GUID_ENTRY(0xedad8d19,0x8a35,0x4d6d,0x85,0x66,0x2e,0xa2,0x76,0xcd,0xe1,0x61,IID_ID3D10BlendState)
+GUID_ENTRY(0xedad8d99,0x8a35,0x4d6d,0x85,0x66,0x2e,0xa2,0x76,0xcd,0xe1,0x61,IID_ID3D10BlendState1)
+GUID_ENTRY(0xedae421e,0x7654,0x4a37,0x9d,0xb8,0x71,0xac,0xc1,0xbe,0xb3,0xc1,CLSID_D2D1SpotSpecular)
+GUID_ENTRY(0xedc48364,0x0417,0x4111,0x94,0x50,0x43,0x84,0x5f,0xa9,0xf8,0x90,CLSID_D2D1DisplacementMap)
+GUID_ENTRY(0xee27417f,0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9,D3D11_DECODER_PROFILE_MPEG2_VLD)
+GUID_DUPLI(0xee27417f,0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9,DXVA2_ModeMPEG2_VLD)
+GUID_ENTRY(0xef1a287d,0x342a,0x4f76,0x8f,0xdb,0xda,0x0d,0x6e,0xa9,0xf9,0x2b,IID_ID2D1Transform)
+GUID_ENTRY(0xef8a8135,0x5cc6,0x45fe,0x88,0x25,0xc5,0xa0,0x72,0x4e,0xb8,0x19,IID_IDWriteTextRenderer)
+GUID_ENTRY(0xefa008f9,0xf7a1,0x48bf,0xb0,0x5c,0xf2,0x24,0x71,0x3c,0xc0,0xff,IID_IDWriteFontFallback)
+GUID_ENTRY(0xefc5557e,0x6265,0x4613,0x8a,0x94,0x43,0x85,0x78,0x89,0xeb,0x36,IID_IDirect3DVertexShader9)
+GUID_ENTRY(0xefd64d74,0xc9e8,0x41d7,0xa5,0xe9,0xe9,0xb0,0xe3,0x9f,0xa3,0x19,D3D11_DECODER_PROFILE_MPEG4PT2_VLD_SIMPLE)
+GUID_DUPLI(0xefd64d74,0xc9e8,0x41d7,0xa5,0xe9,0xe9,0xb0,0xe3,0x9f,0xa3,0x19,DXVA2_ModeMPEG4pt2_VLD_Simple)
+GUID_ENTRY(0xf13ebcd1,0x672c,0x4f8b,0xa6,0x31,0x95,0x39,0xca,0x74,0x8d,0x71,IID_IWarpPrivateAPI)
+GUID_ENTRY(0xf1827e47,0x00a8,0x49cd,0x90,0x8c,0x9d,0x11,0x95,0x5f,0x87,0x28,IID_ID3DXPRTBuffer)
+GUID_ENTRY(0xf1cfe2b3,0x0de3,0x4e28,0xaf,0xa1,0x15,0x5a,0x75,0x0a,0x28,0x2d,DXFILEOBJ_EffectFloats)
+GUID_ENTRY(0xf2086b20,0x259f,0x11cf,0xa3,0x1a,0x00,0xaa,0x00,0xb9,0x33,0x56,IID_IDirect3DRampDevice)
+GUID_ENTRY(0xf2b0810a,0xfd00,0x43c9,0x91,0x8c,0xdf,0x94,0xe2,0xd8,0xef,0x7d,IID_IDirectXVideoDecoder)
+GUID_ENTRY(0xf5049e77,0x4861,0x11d2,0xa4,0x07,0x00,0xa0,0xc9,0x06,0x29,0xa8,IID_IDirect3D7)
+GUID_ENTRY(0xf5049e78,0x4861,0x11d2,0xa4,0x07,0x00,0xa0,0xc9,0x06,0x29,0xa8,IID_IDirect3DTnLHalDevice)
+GUID_ENTRY(0xf5049e79,0x4861,0x11d2,0xa4,0x07,0x00,0xa0,0xc9,0x06,0x29,0xa8,IID_IDirect3DDevice7)
+GUID_ENTRY(0xf5049e7d,0x4861,0x11d2,0xa4,0x07,0x00,0xa0,0xc9,0x06,0x29,0xa8,IID_IDirect3DVertexBuffer7)
+GUID_ENTRY(0xf582c508,0x0f36,0x490c,0x99,0x77,0x31,0xee,0xce,0x26,0x8c,0xfa,IID_ID3D11DomainShader)
+GUID_ENTRY(0xf67e0edd,0x9e3d,0x4ecc,0x8c,0x32,0x41,0x83,0x25,0x3d,0xfe,0x70,IID_IDWriteTextFormat2)
+GUID_ENTRY(0xf69f223b,0x45d3,0x4aa0,0x98,0xc8,0xc4,0x0c,0x2b,0x23,0x10,0x29,IID_IDXGISwapChainDWM)
+GUID_ENTRY(0xf6ceb4b3,0x4e4c,0x40dd,0xb8,0x83,0x8d,0x8d,0xe5,0xea,0x0c,0xd5,IID_ID3DXEffect)
+GUID_ENTRY(0xf752461c,0x1e23,0x48f6,0xb9,0xf8,0x83,0x50,0x85,0x0f,0x33,0x6f,DXFILEOBJ_VertexElement)
+GUID_ENTRY(0xf83a5958,0xe986,0x4bda,0xbe,0xb0,0x41,0x1f,0x6a,0x7a,0x01,0xb7,D3D11_AUTHENTICATED_QUERY_ENCRYPTION_WHEN_ACCESSIBLE_GUID)
+GUID_DUPLI(0xf83a5958,0xe986,0x4bda,0xbe,0xb0,0x41,0x1f,0x6a,0x7a,0x01,0xb7,D3DAUTHENTICATEDQUERY_ENCRYPTIONWHENACCESSIBLEGUID)
+GUID_ENTRY(0xf898b024,0xb5c8,0x42cd,0xa1,0x4f,0xac,0x5a,0xdb,0xf4,0xbe,0x22,IID_IDXGIDeviceXAML)
+GUID_ENTRY(0xf8fb5c27,0xc6b3,0x4f75,0xa4,0xc8,0x43,0x9a,0xf2,0xef,0x56,0x4c,IID_ID3D11Texture1D)
+GUID_ENTRY(0xf9aaccbb,0xc2b6,0x4cfc,0x87,0x79,0x57,0x07,0xb1,0x76,0x05,0x52,D3D11_DECODER_PROFILE_H264_VLD_STEREO_NOFGT)
+GUID_DUPLI(0xf9aaccbb,0xc2b6,0x4cfc,0x87,0x79,0x57,0x07,0xb1,0x76,0x05,0x52,DXVA2_ModeH264_VLD_Stereo_NoFGT)
+GUID_ENTRY(0xf9d711c3,0x9777,0x40ae,0x87,0xe8,0x3e,0x5a,0xf9,0xbf,0x09,0x48,IID_IDWriteRenderingParams2)
+GUID_ENTRY(0xfa0ab799,0x7a9c,0x48ca,0x8c,0x5b,0x23,0x7e,0x71,0xa5,0x44,0x34,IID_IDirect3DCryptoSession9)
+GUID_ENTRY(0xfa4e8e3a,0x9786,0x407d,0x8b,0x4c,0x59,0x95,0x89,0x37,0x64,0xaf,IID_ID3DXKeyframedAnimationSet)
+GUID_ENTRY(0xfb3a8e1a,0x2e3c,0x4de1,0x84,0x42,0x40,0x43,0xe0,0xb0,0x94,0x95,_D2D_INTERNAL_DEVICE_CREATION_OPTIONS)
+GUID_ENTRY(0xfb9ac489,0xad8d,0x41ed,0x99,0x99,0xbb,0x63,0x47,0xd1,0x10,0xf7,CLSID_D2D1UnPremultiply)
+GUID_ENTRY(0xfc151437,0x049a,0x4784,0xa2,0x4a,0xf1,0xc4,0xda,0xf2,0x09,0x87,CLSID_D2D1ArithmeticComposite)
+GUID_ENTRY(0xfc51a550,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02,IID_IDirectXVideoAccelerationService)
+GUID_ENTRY(0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02,IID_IDirectXVideoDecoderService)
+GUID_ENTRY(0xfc51a552,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02,IID_IDirectXVideoProcessorService)
+GUID_ENTRY(0xfd882d06,0x8aba,0x4fb8,0xb8,0x49,0x8b,0xe8,0xb7,0x3e,0x14,0xde,IID_IDWriteFontFallbackBuilder)
+GUID_ENTRY(0xfe9e984d,0x3f95,0x407c,0xb5,0xdb,0xcb,0x94,0xd4,0xe8,0xf8,0x7c,IID_ID2D1ImageBrush)
+GUID_ENTRY(0xff24beee,0xda21,0x4beb,0x98,0xb5,0xd2,0xf8,0x99,0xf9,0x8a,0xf9,IID_IDirect3DAuthenticatedChannel9)
+GUID_ENTRY(0xffbe2e23,0xf011,0x418a,0xac,0x56,0x5c,0xee,0xd7,0xc5,0xb9,0x4b,IID_ID3D11RenderTargetView1)
+GUID_ENTRY(0xfff32f81,0xd953,0x473a,0x92,0x23,0x93,0xd6,0x52,0xab,0xa9,0x3f,IID_IDirect3DCubeTexture9)
+
+
+#undef GUID_ENTRY
+#undef GUID_DUPLI
diff --git a/guids/guids_test.cpp b/guids/guids_test.cpp
new file mode 100644
index 00000000..03988f0d
--- /dev/null
+++ b/guids/guids_test.cpp
@@ -0,0 +1,56 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "guids.hpp"
+
+#include "gtest/gtest.h"
+
+
+TEST(guids, name_known)
+{
+
+# define GUID_ENTRY(l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8,name) \
+ static const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; \
+ EXPECT_STREQ(#name, getGuidName(name));
+
+# include "guids_entries.h"
+
+}
+
+
+TEST(guids, name_unknown)
+{
+ static const GUID dummy = {0x01234567,0x89AB,0xCDEF,{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}};
+ EXPECT_STREQ("uuid(01234567-89ab-cdef-0123-456789abcdef)",
+ getGuidName(dummy));
+}
+
+
+int
+main(int argc, char **argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/helpers/CMakeLists.txt b/helpers/CMakeLists.txt
index 53a639fc..e2277d04 100644
--- a/helpers/CMakeLists.txt
+++ b/helpers/CMakeLists.txt
@@ -2,12 +2,20 @@
# API helpers
+include_directories (
+ ${CMAKE_BINARY_DIR}/dispatch
+ ${CMAKE_SOURCE_DIR}/dispatch
+)
+
+add_convenience_library (glhelpers
+ glprofile.cpp
+ eglsize.cpp
+)
+add_dependencies (glhelpers glproc)
+
+
if (WIN32)
- add_library (d3dhelpers STATIC
+ add_convenience_library (d3dhelpers
d3dshader.cpp
)
- set_target_properties (d3dhelpers PROPERTIES
- # Ensure it can be statically linked in shared libraries
- COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}"
- )
endif ()
diff --git a/helpers/com_ptr.hpp b/helpers/com_ptr.hpp
new file mode 100644
index 00000000..d85483df
--- /dev/null
+++ b/helpers/com_ptr.hpp
@@ -0,0 +1,112 @@
+/**************************************************************************
+ *
+ * Copyright 2014 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+
+#include <assert.h>
+
+#include <windows.h>
+
+
+/**
+ * Simple smart pointer template for COM interfaces.
+ *
+ * - https://msdn.microsoft.com/en-us/magazine/dn904668.aspx
+ * - https://msdn.microsoft.com/en-us/library/417w8b3b.aspx
+ * - https://msdn.microsoft.com/en-us/library/ezzw7k98.aspx
+ */
+template< typename T >
+class com_ptr
+{
+private:
+ T *p;
+
+public:
+ com_ptr(void) :
+ p(nullptr)
+ {
+ }
+
+ com_ptr(T *_p) :
+ p(_p)
+ {
+ }
+
+ ~com_ptr() {
+ T *temp = p;
+ p = nullptr;
+ if (temp) {
+ temp->Release();
+ }
+ }
+
+ // Used when initializing
+ T **
+ operator & () {
+ assert(p == nullptr);
+ return &p;
+ }
+
+ // Implict cast to T*
+ operator T * () const {
+ return p;
+ }
+
+ struct no_ref_count : public T
+ {
+ private:
+ ULONG STDMETHODCALLTYPE AddRef(void);
+ ULONG STDMETHODCALLTYPE Release(void);
+ };
+
+ // Methods
+ no_ref_count *
+ operator -> () const {
+ assert(p != nullptr);
+ return static_cast< no_ref_count *>(p);
+ }
+
+ com_ptr &
+ operator = (T *q) {
+ if (p != q) {
+ T *temp = p;
+ p = q;
+ if (temp) {
+ temp->Release();
+ }
+ if (q) {
+ q->AddRef();
+ }
+ }
+ return *this;
+ }
+
+ com_ptr(const com_ptr &) = delete;
+ com_ptr & operator= (const com_ptr &) = delete;
+};
+
+
+
diff --git a/helpers/d3d10size.hpp b/helpers/d3d10size.hpp
index d15e2ec2..1818b177 100644
--- a/helpers/d3d10size.hpp
+++ b/helpers/d3d10size.hpp
@@ -30,8 +30,7 @@
* Auxiliary functions to compute the size of array/blob arguments.
*/
-#ifndef _D3D10SIZE_HPP_
-#define _D3D10SIZE_HPP_
+#pragma once
/* We purposedly don't include any D3D header, so that this header can be used
@@ -42,6 +41,7 @@
#include <algorithm>
#include "dxgisize.hpp"
+#include "com_ptr.hpp"
inline UINT
@@ -192,7 +192,7 @@ _calcSubresourceSize(ID3D10Resource *pDstResource, UINT DstSubresource, const D3
UINT Width;
UINT Height = 1;
UINT Depth = 1;
- UINT MipLevel = 0;
+ UINT MipLevels = 1;
switch (Type) {
case D3D10_RESOURCE_DIMENSION_BUFFER:
@@ -209,7 +209,7 @@ _calcSubresourceSize(ID3D10Resource *pDstResource, UINT DstSubresource, const D3
static_cast<ID3D10Texture1D *>(pDstResource)->GetDesc(&Desc);
Format = Desc.Format;
Width = Desc.Width;
- MipLevel = DstSubresource % Desc.MipLevels;
+ MipLevels = Desc.MipLevels;
}
break;
case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
@@ -219,7 +219,7 @@ _calcSubresourceSize(ID3D10Resource *pDstResource, UINT DstSubresource, const D3
Format = Desc.Format;
Width = Desc.Width;
Height = Desc.Height;
- MipLevel = DstSubresource % Desc.MipLevels;
+ MipLevels = Desc.MipLevels;
}
break;
case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
@@ -230,6 +230,7 @@ _calcSubresourceSize(ID3D10Resource *pDstResource, UINT DstSubresource, const D3
Width = Desc.Width;
Height = Desc.Height;
Depth = Desc.Depth;
+ MipLevels = Desc.MipLevels;
}
break;
case D3D10_RESOURCE_DIMENSION_UNKNOWN:
@@ -242,10 +243,39 @@ _calcSubresourceSize(ID3D10Resource *pDstResource, UINT DstSubresource, const D3
Width = pDstBox->right - pDstBox->left;
Height = pDstBox->bottom - pDstBox->top;
Depth = pDstBox->back - pDstBox->front;
+ } else {
+ assert(Width > 0);
+ assert(Height > 0);
+ assert(Depth > 0);
+ UINT MipLevel = DstSubresource % MipLevels;
+ Width = std::max(Width >> MipLevel, UINT(1));
+ Height = std::max(Height >> MipLevel, UINT(1));
+ Depth = std::max(Depth >> MipLevel, UINT(1));
}
- return _calcMipDataSize(MipLevel, Format, Width, Height, SrcRowPitch, Depth, SrcDepthPitch);
+ return _calcDataSize(Format, Width, Height, SrcRowPitch, Depth, SrcDepthPitch);
+}
+
+
+static inline D3D10_QUERY
+_getQueryType(ID3D10Query *pQuery)
+{
+ D3D10_QUERY_DESC Desc;
+ pQuery->GetDesc(&Desc);
+ return Desc.Query;
+}
+
+
+static inline D3D10_QUERY
+_getQueryType(ID3D10Asynchronous *pAsync)
+{
+ com_ptr<ID3D10Query> pQuery;
+ HRESULT hr;
+ hr = pAsync->QueryInterface(IID_ID3D10Query, (void **)&pQuery);
+ if (FAILED(hr)) {
+ return (D3D10_QUERY)-1;
+ }
+ return _getQueryType(pQuery);
}
-#endif /* _D3D10SIZE_HPP_ */
diff --git a/helpers/d3d11size.hpp b/helpers/d3d11size.hpp
index 2ac53095..e3b55eb3 100644
--- a/helpers/d3d11size.hpp
+++ b/helpers/d3d11size.hpp
@@ -30,8 +30,7 @@
* Auxiliary functions to compute the size of array/blob arguments.
*/
-#ifndef _D3D11SIZE_HPP_
-#define _D3D11SIZE_HPP_
+#pragma once
/* We purposedly don't include any D3D header, so that this header can be used
@@ -42,6 +41,7 @@
#include <algorithm>
#include "dxgisize.hpp"
+#include "com_ptr.hpp"
inline UINT
@@ -60,11 +60,21 @@ _getNumMipLevels(const D3D11_TEXTURE2D_DESC *pDesc) {
}
inline UINT
+_getNumMipLevels(const D3D11_TEXTURE2D_DESC1 *pDesc) {
+ return pDesc->MipLevels != 0 ? pDesc->MipLevels : _getNumMipLevels(pDesc->Width, pDesc->Height);
+}
+
+inline UINT
_getNumMipLevels(const D3D11_TEXTURE3D_DESC *pDesc) {
return pDesc->MipLevels != 0 ? pDesc->MipLevels : _getNumMipLevels(pDesc->Width, pDesc->Height, pDesc->Depth);
}
inline UINT
+_getNumMipLevels(const D3D11_TEXTURE3D_DESC1 *pDesc) {
+ return pDesc->MipLevels != 0 ? pDesc->MipLevels : _getNumMipLevels(pDesc->Width, pDesc->Height, pDesc->Depth);
+}
+
+inline UINT
_getNumSubResources(const D3D11_BUFFER_DESC *pDesc) {
return 1;
}
@@ -80,10 +90,20 @@ _getNumSubResources(const D3D11_TEXTURE2D_DESC *pDesc) {
}
inline UINT
+_getNumSubResources(const D3D11_TEXTURE2D_DESC1 *pDesc) {
+ return _getNumMipLevels(pDesc) * pDesc->ArraySize;
+}
+
+inline UINT
_getNumSubResources(const D3D11_TEXTURE3D_DESC *pDesc) {
return _getNumMipLevels(pDesc);
}
+inline UINT
+_getNumSubResources(const D3D11_TEXTURE3D_DESC1 *pDesc) {
+ return _getNumMipLevels(pDesc);
+}
+
static inline size_t
_calcSubresourceSize(const D3D11_BUFFER_DESC *pDesc, UINT Subresource, UINT RowPitch = 0, UINT SlicePitch = 0) {
return pDesc->ByteWidth;
@@ -102,12 +122,24 @@ _calcSubresourceSize(const D3D11_TEXTURE2D_DESC *pDesc, UINT Subresource, UINT R
}
static inline size_t
+_calcSubresourceSize(const D3D11_TEXTURE2D_DESC1 *pDesc, UINT Subresource, UINT RowPitch, UINT SlicePitch = 0) {
+ UINT MipLevel = Subresource % _getNumMipLevels(pDesc);
+ return _calcMipDataSize(MipLevel, pDesc->Format, pDesc->Width, pDesc->Height, RowPitch, 1, SlicePitch);
+}
+
+static inline size_t
_calcSubresourceSize(const D3D11_TEXTURE3D_DESC *pDesc, UINT Subresource, UINT RowPitch, UINT SlicePitch) {
UINT MipLevel = Subresource;
return _calcMipDataSize(MipLevel, pDesc->Format, pDesc->Width, pDesc->Height, RowPitch, pDesc->Depth, SlicePitch);
}
static inline size_t
+_calcSubresourceSize(const D3D11_TEXTURE3D_DESC1 *pDesc, UINT Subresource, UINT RowPitch, UINT SlicePitch) {
+ UINT MipLevel = Subresource;
+ return _calcMipDataSize(MipLevel, pDesc->Format, pDesc->Width, pDesc->Height, RowPitch, pDesc->Depth, SlicePitch);
+}
+
+static inline size_t
_calcSubresourceSize(ID3D11Resource *pDstResource, UINT DstSubresource, const D3D11_BOX *pDstBox, UINT SrcRowPitch, UINT SrcDepthPitch) {
if (pDstBox &&
(pDstBox->left >= pDstBox->right ||
@@ -123,7 +155,7 @@ _calcSubresourceSize(ID3D11Resource *pDstResource, UINT DstSubresource, const D3
UINT Width;
UINT Height = 1;
UINT Depth = 1;
- UINT MipLevel = 0;
+ UINT MipLevels = 1;
switch (Type) {
case D3D11_RESOURCE_DIMENSION_BUFFER:
@@ -140,7 +172,7 @@ _calcSubresourceSize(ID3D11Resource *pDstResource, UINT DstSubresource, const D3
static_cast<ID3D11Texture1D *>(pDstResource)->GetDesc(&Desc);
Format = Desc.Format;
Width = Desc.Width;
- MipLevel = DstSubresource % Desc.MipLevels;
+ MipLevels = Desc.MipLevels;
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
@@ -150,7 +182,7 @@ _calcSubresourceSize(ID3D11Resource *pDstResource, UINT DstSubresource, const D3
Format = Desc.Format;
Width = Desc.Width;
Height = Desc.Height;
- MipLevel = DstSubresource % Desc.MipLevels;
+ MipLevels = Desc.MipLevels;
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
@@ -161,6 +193,7 @@ _calcSubresourceSize(ID3D11Resource *pDstResource, UINT DstSubresource, const D3
Width = Desc.Width;
Height = Desc.Height;
Depth = Desc.Depth;
+ MipLevels = Desc.MipLevels;
}
break;
case D3D11_RESOURCE_DIMENSION_UNKNOWN:
@@ -173,9 +206,17 @@ _calcSubresourceSize(ID3D11Resource *pDstResource, UINT DstSubresource, const D3
Width = pDstBox->right - pDstBox->left;
Height = pDstBox->bottom - pDstBox->top;
Depth = pDstBox->back - pDstBox->front;
+ } else {
+ assert(Width > 0);
+ assert(Height > 0);
+ assert(Depth > 0);
+ UINT MipLevel = DstSubresource % MipLevels;
+ Width = std::max(Width >> MipLevel, UINT(1));
+ Height = std::max(Height >> MipLevel, UINT(1));
+ Depth = std::max(Depth >> MipLevel, UINT(1));
}
- return _calcMipDataSize(MipLevel, Format, Width, Height, SrcRowPitch, Depth, SrcDepthPitch);
+ return _calcDataSize(Format, Width, Height, SrcRowPitch, Depth, SrcDepthPitch);
}
@@ -194,4 +235,49 @@ _getMapDesc(ID3D11DeviceContext* pContext, ID3D11Resource * pResource, UINT Subr
}
-#endif /* _D3D11SIZE_HPP_ */
+static inline void
+_normalizeMap(ID3D11Resource * pResource, D3D11_MAPPED_SUBRESOURCE * pMappedResource)
+{
+ D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pResource->GetType(&Type);
+
+ switch (Type) {
+ default:
+ case D3D11_RESOURCE_DIMENSION_UNKNOWN:
+ assert(0);
+ /* fall-through */
+ case D3D11_RESOURCE_DIMENSION_BUFFER:
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ pMappedResource->RowPitch = 0;
+ /* fall-through */
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ pMappedResource->DepthPitch = 0;
+ break;
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ break;
+ }
+}
+
+
+static inline D3D11_QUERY
+_getQueryType(ID3D11Query *pQuery)
+{
+ D3D11_QUERY_DESC Desc;
+ pQuery->GetDesc(&Desc);
+ return Desc.Query;
+}
+
+
+static inline D3D11_QUERY
+_getQueryType(ID3D11Asynchronous *pAsync)
+{
+ com_ptr<ID3D11Query> pQuery;
+ HRESULT hr;
+ hr = pAsync->QueryInterface(IID_ID3D11Query, (void **)&pQuery);
+ if (FAILED(hr)) {
+ return (D3D11_QUERY)-1;
+ }
+ return _getQueryType(pQuery);
+}
+
+
diff --git a/helpers/d3d7size.hpp b/helpers/d3d7size.hpp
new file mode 100644
index 00000000..5d0f6204
--- /dev/null
+++ b/helpers/d3d7size.hpp
@@ -0,0 +1,118 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/*
+ * Auxiliary functions to compute the size of array/blob arguments.
+ */
+
+#pragma once
+
+
+static inline size_t
+_getVertexSize(DWORD dwFVF) {
+ size_t size = 0;
+
+ assert((dwFVF & D3DFVF_RESERVED0) == 0);
+
+ switch (dwFVF & D3DFVF_POSITION_MASK) {
+ case D3DFVF_XYZ:
+ size += 3 * sizeof(FLOAT);
+ break;
+ case D3DFVF_XYZRHW:
+ size += 4 * sizeof(FLOAT);
+ break;
+ case D3DFVF_XYZB1:
+ size += (3 + 1) * sizeof(FLOAT);
+ break;
+ case D3DFVF_XYZB2:
+ size += (3 + 2) * sizeof(FLOAT);
+ break;
+ case D3DFVF_XYZB3:
+ size += (3 + 3) * sizeof(FLOAT);
+ break;
+ case D3DFVF_XYZB4:
+ size += (3 + 4) * sizeof(FLOAT);
+ break;
+ case D3DFVF_XYZB5:
+ size += (3 + 5) * sizeof(FLOAT);
+ break;
+#if DIRECT3D_VERSION >= 0x0900
+ case D3DFVF_XYZW:
+ size += 4 * sizeof(FLOAT);
+ break;
+#endif
+ }
+
+ if (dwFVF & D3DFVF_NORMAL) {
+ size += 3 * sizeof(FLOAT);
+ }
+#if DIRECT3D_VERSION >= 0x0800
+ if (dwFVF & D3DFVF_PSIZE) {
+ size += sizeof(FLOAT);
+ }
+#else
+ if (dwFVF & D3DFVF_RESERVED1) {
+ // D3DLVERTEX
+ size += sizeof(DWORD);
+ }
+#endif
+ if (dwFVF & D3DFVF_DIFFUSE) {
+ size += sizeof(D3DCOLOR);
+ }
+ if (dwFVF & D3DFVF_SPECULAR) {
+ size += sizeof(D3DCOLOR);
+ }
+
+ DWORD dwNumTextures = (dwFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
+ for (DWORD CoordIndex = 0; CoordIndex < dwNumTextures; ++CoordIndex) {
+ // See D3DFVF_TEXCOORDSIZE*
+ DWORD dwTexCoordSize = (dwFVF >> (CoordIndex*2 + 16)) & 3;
+ switch (dwTexCoordSize) {
+ case D3DFVF_TEXTUREFORMAT2:
+ size += 2 * sizeof(FLOAT);
+ break;
+ case D3DFVF_TEXTUREFORMAT1:
+ size += 1 * sizeof(FLOAT);
+ break;
+ case D3DFVF_TEXTUREFORMAT3:
+ size += 3 * sizeof(FLOAT);
+ break;
+ case D3DFVF_TEXTUREFORMAT4:
+ size += 4 * sizeof(FLOAT);
+ break;
+ }
+ }
+
+ assert((dwFVF & D3DFVF_RESERVED2) == 0);
+
+ return size;
+}
+
+
+
+
diff --git a/helpers/d3d8size.hpp b/helpers/d3d8size.hpp
index b84b9002..b446a4b5 100644
--- a/helpers/d3d8size.hpp
+++ b/helpers/d3d8size.hpp
@@ -30,8 +30,7 @@
* Auxiliary functions to compute the size of array/blob arguments.
*/
-#ifndef _D3D8SIZE_HPP_
-#define _D3D8SIZE_HPP_
+#pragma once
#include "d3dcommonsize.hpp"
@@ -47,6 +46,94 @@ _declCount(const DWORD *pDeclaration) {
static inline void
+_getFormatSize(D3DFORMAT Format, size_t & BlockSize, UINT & BlockWidth, UINT & BlockHeight)
+{
+ BlockSize = 0;
+ BlockWidth = 1;
+ BlockHeight = 1;
+
+ switch ((DWORD)Format) {
+
+ case D3DFMT_R3G3B2:
+ case D3DFMT_A8:
+ case D3DFMT_P8:
+ case D3DFMT_L8:
+ case D3DFMT_A4L4:
+ BlockSize = 8;
+ break;
+
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_A4R4G4B4:
+ case D3DFMT_A8R3G3B2:
+ case D3DFMT_X4R4G4B4:
+ case D3DFMT_A8P8:
+ case D3DFMT_A8L8:
+ case D3DFMT_V8U8:
+ case D3DFMT_L6V5U5:
+ case D3DFMT_D16_LOCKABLE:
+ case D3DFMT_D15S1:
+ case D3DFMT_D16:
+ case D3DFMT_INDEX16:
+ BlockSize = 16;
+ break;
+
+ case D3DFMT_R8G8B8:
+ BlockSize = 24;
+ break;
+
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A2B10G10R10:
+ case D3DFMT_G16R16:
+ case D3DFMT_X8L8V8U8:
+ case D3DFMT_Q8W8V8U8:
+ case D3DFMT_V16U16:
+ case D3DFMT_W11V11U10:
+ case D3DFMT_A2W10V10U10:
+ case D3DFMT_D32:
+ case D3DFMT_D24S8:
+ case D3DFMT_D24X8:
+ case D3DFMT_D24X4S4:
+ case D3DFMT_INDEX32:
+ BlockSize = 32;
+ break;
+
+ case D3DFMT_UYVY:
+ case D3DFMT_YUY2:
+ BlockWidth = 2;
+ BlockSize = 32;
+ break;
+
+ case D3DFMT_DXT1:
+ BlockHeight = BlockWidth = 4;
+ BlockSize = 64;
+ break;
+
+ case D3DFMT_DXT2:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT4:
+ case D3DFMT_DXT5:
+ BlockHeight = BlockWidth = 4;
+ BlockSize = 128;
+ break;
+
+ case D3DFMT_UNKNOWN:
+ case D3DFMT_VERTEXDATA:
+ os::log("apitrace: warning: %s: unexpected D3DFMT %u\n", __FUNCTION__, Format);
+ BlockSize = 0;
+ break;
+
+ default:
+ os::log("apitrace: warning: %s: unknown D3DFMT %u\n", __FUNCTION__, Format);
+ BlockWidth = 0;
+ break;
+ }
+}
+
+
+static inline void
_getMapInfo(IDirect3DVertexBuffer8 *pBuffer, UINT OffsetToLock, UINT SizeToLock, BYTE ** ppbData,
void * & pLockedData, size_t & MappedSize) {
pLockedData = *ppbData;
@@ -108,7 +195,7 @@ _getMapInfo(IDirect3DSurface8 *pSurface, const D3DLOCKED_RECT *pLockedRect, cons
Height = Desc.Height;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
+ MappedSize = _getLockSize(Desc.Format, pRect, Width, Height, pLockedRect->Pitch);
}
@@ -136,7 +223,7 @@ _getMapInfo(IDirect3DTexture8 *pTexture, UINT Level, const D3DLOCKED_RECT *pLock
Height = Desc.Height;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
+ MappedSize = _getLockSize(Desc.Format, pRect, Width, Height, pLockedRect->Pitch);
}
@@ -166,7 +253,7 @@ _getMapInfo(IDirect3DCubeTexture8 *pTexture, D3DCUBEMAP_FACES FaceType, UINT Lev
Height = Desc.Height;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
+ MappedSize = _getLockSize(Desc.Format, pRect, Width, Height, pLockedRect->Pitch);
}
@@ -197,7 +284,7 @@ _getMapInfo(IDirect3DVolume8 *pVolume, const D3DLOCKED_BOX *pLockedVolume, const
Depth = Desc.Depth;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
+ MappedSize = _getLockSize(Desc.Format, pBox, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
}
@@ -228,8 +315,7 @@ _getMapInfo(IDirect3DVolumeTexture8 *pTexture, UINT Level, const D3DLOCKED_BOX *
Depth = Desc.Depth;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
+ MappedSize = _getLockSize(Desc.Format, pBox, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
}
-#endif /* _D3D8SIZE_HPP_ */
diff --git a/helpers/d3d9size.hpp b/helpers/d3d9size.hpp
index 04f5e593..a6aca446 100644
--- a/helpers/d3d9size.hpp
+++ b/helpers/d3d9size.hpp
@@ -30,8 +30,7 @@
* Auxiliary functions to compute the size of array/blob arguments.
*/
-#ifndef _D3D9SIZE_HPP_
-#define _D3D9SIZE_HPP_
+#pragma once
#include "d3dcommonsize.hpp"
@@ -47,6 +46,146 @@ _declCount(const D3DVERTEXELEMENT9 *pVertexElements) {
return count;
}
+
+static inline void
+_getFormatSize(D3DFORMAT Format, size_t & BlockSize, UINT & BlockWidth, UINT & BlockHeight)
+{
+ BlockSize = 0;
+ BlockWidth = 1;
+ BlockHeight = 1;
+
+ switch ((DWORD)Format) {
+
+ case D3DFMT_A1:
+ BlockSize = 1;
+ break;
+
+ case D3DFMT_R3G3B2:
+ case D3DFMT_A8:
+ case D3DFMT_P8:
+ case D3DFMT_L8:
+ case D3DFMT_A4L4:
+ case D3DFMT_S8_LOCKABLE:
+ case D3DFMT_BINARYBUFFER:
+ BlockSize = 8;
+ break;
+
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_A4R4G4B4:
+ case D3DFMT_A8R3G3B2:
+ case D3DFMT_X4R4G4B4:
+ case D3DFMT_A8P8:
+ case D3DFMT_A8L8:
+ case D3DFMT_V8U8:
+ case D3DFMT_L6V5U5:
+ case D3DFMT_D16_LOCKABLE:
+ case D3DFMT_D15S1:
+ case D3DFMT_D16:
+ case D3DFMT_L16:
+ case D3DFMT_INDEX16:
+ case D3DFMT_R16F:
+ case D3DFMT_CxV8U8:
+ case D3DFMT_DF16:
+ BlockSize = 16;
+ break;
+
+ case D3DFMT_R8G8B8:
+ BlockSize = 24;
+ break;
+
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A2B10G10R10:
+ case D3DFMT_A8B8G8R8:
+ case D3DFMT_X8B8G8R8:
+ case D3DFMT_G16R16:
+ case D3DFMT_A2R10G10B10:
+ case D3DFMT_X8L8V8U8:
+ case D3DFMT_Q8W8V8U8:
+ case D3DFMT_V16U16:
+ case D3DFMT_A2W10V10U10:
+ case D3DFMT_D32:
+ case D3DFMT_D24S8:
+ case D3DFMT_D24X8:
+ case D3DFMT_D24X4S4:
+ case D3DFMT_D32F_LOCKABLE:
+ case D3DFMT_D24FS8:
+ case D3DFMT_D32_LOCKABLE:
+ case D3DFMT_INDEX32:
+ case D3DFMT_G16R16F:
+ case D3DFMT_R32F:
+ case D3DFMT_A2B10G10R10_XR_BIAS:
+ case D3DFMT_DF24:
+ case D3DFMT_INTZ:
+ case D3DFMT_AYUV:
+ case D3DFMT_RAWZ:
+ BlockSize = 32;
+ break;
+
+ case D3DFMT_A16B16G16R16:
+ case D3DFMT_Q16W16V16U16:
+ case D3DFMT_A16B16G16R16F:
+ case D3DFMT_G32R32F:
+ BlockSize = 64;
+ break;
+
+ case D3DFMT_A32B32G32R32F:
+ BlockSize = 128;
+ break;
+
+ case D3DFMT_UYVY:
+ case D3DFMT_R8G8_B8G8:
+ case D3DFMT_YUY2:
+ case D3DFMT_G8R8_G8B8:
+ BlockWidth = 2;
+ BlockSize = 32;
+ break;
+
+ case D3DFMT_DXT1:
+ BlockHeight = BlockWidth = 4;
+ BlockSize = 64;
+ break;
+
+ case D3DFMT_DXT2:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT4:
+ case D3DFMT_DXT5:
+ BlockHeight = BlockWidth = 4;
+ BlockSize = 128;
+ break;
+
+ case D3DFMT_NV12:
+ case D3DFMT_YV12:
+ // Planar YUV
+ case D3DFMT_ATI1N:
+ case D3DFMT_ATI2N:
+ /*
+ * Because these are unsupported formats, RowPitch is not set to the
+ * number of bytes between row of blocks, but instead in such way that
+ * Height * RowPitch will match the expected size.
+ */
+ BlockWidth = 0;
+ BlockSize = 0;
+ break;
+
+ case D3DFMT_UNKNOWN:
+ case D3DFMT_VERTEXDATA:
+ case D3DFMT_NULL:
+ case D3DFMT_MULTI2_ARGB8: // https://msdn.microsoft.com/en-us/library/bb147219.aspx
+ os::log("apitrace: warning: %s: unexpected D3DFMT %u\n", __FUNCTION__, Format);
+ BlockSize = 0;
+ break;
+
+ default:
+ os::log("apitrace: warning: %s: unknown D3DFMT %u\n", __FUNCTION__, Format);
+ BlockWidth = 0;
+ break;
+ }
+}
+
+
static inline void
_getMapInfo(IDirect3DVertexBuffer9 *pBuffer, UINT OffsetToLock, UINT SizeToLock, void ** ppbData,
void * & pLockedData, size_t & MappedSize) {
@@ -109,7 +248,7 @@ _getMapInfo(IDirect3DSurface9 *pSurface, const D3DLOCKED_RECT *pLockedRect, cons
Height = Desc.Height;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
+ MappedSize = _getLockSize(Desc.Format, pRect, Width, Height, pLockedRect->Pitch);
}
@@ -137,7 +276,7 @@ _getMapInfo(IDirect3DTexture9 *pTexture, UINT Level, const D3DLOCKED_RECT *pLock
Height = Desc.Height;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
+ MappedSize = _getLockSize(Desc.Format, pRect, Width, Height, pLockedRect->Pitch);
}
@@ -167,7 +306,7 @@ _getMapInfo(IDirect3DCubeTexture9 *pTexture, D3DCUBEMAP_FACES FaceType, UINT Lev
Height = Desc.Height;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
+ MappedSize = _getLockSize(Desc.Format, pRect, Width, Height, pLockedRect->Pitch);
}
@@ -198,7 +337,7 @@ _getMapInfo(IDirect3DVolume9 *pVolume, const D3DLOCKED_BOX *pLockedVolume, const
Depth = Desc.Depth;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
+ MappedSize = _getLockSize(Desc.Format, pBox, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
}
@@ -229,8 +368,7 @@ _getMapInfo(IDirect3DVolumeTexture9 *pTexture, UINT Level, const D3DLOCKED_BOX *
Depth = Desc.Depth;
}
- MappedSize = _getLockSize(Desc.Format, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
+ MappedSize = _getLockSize(Desc.Format, pBox, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
}
-#endif /* _D3D9SIZE_HPP_ */
diff --git a/helpers/d3dcommonsize.hpp b/helpers/d3dcommonsize.hpp
index 6619b13a..766d49e8 100644
--- a/helpers/d3dcommonsize.hpp
+++ b/helpers/d3dcommonsize.hpp
@@ -30,8 +30,7 @@
* Auxiliary functions to compute the size of array/blob arguments.
*/
-#ifndef _D3DCOMMONSIZE_HPP_
-#define _D3DCOMMONSIZE_HPP_
+#pragma once
/* We purposedly don't include any D3D header, so that this header can be used
@@ -115,8 +114,11 @@ _shaderSize(const DWORD *pFunction)
}
+static inline void
+_getFormatSize(D3DFORMAT Format, size_t & BlockSize, UINT & BlockWidth, UINT & BlockHeight);
+
static inline size_t
-_getLockSize(D3DFORMAT Format, UINT Width, UINT Height, INT RowPitch, UINT Depth = 1, INT SlicePitch = 0) {
+_getLockSize(D3DFORMAT Format, bool Partial, UINT Width, UINT Height, INT RowPitch, UINT Depth = 1, INT SlicePitch = 0) {
if (Width == 0 || Height == 0 || Depth == 0) {
return 0;
}
@@ -126,59 +128,39 @@ _getLockSize(D3DFORMAT Format, UINT Width, UINT Height, INT RowPitch, UINT Depth
return 0;
}
- if (SlicePitch < 0) {
- os::log("apitrace: warning: %s: negative slice pitch %i\n", __FUNCTION__, SlicePitch);
- return 0;
- }
-
- switch ((DWORD)Format) {
- case D3DFMT_DXT1:
- case D3DFMT_DXT2:
- case D3DFMT_DXT3:
- case D3DFMT_DXT4:
- case D3DFMT_DXT5:
- Width = (Width + 3) / 4;
- Height = (Height + 3) / 4;
- break;
-
-#if DIRECT3D_VERSION >= 0x900
- case D3DFMT_ATI1N:
- case D3DFMT_ATI2N:
- /*
- * Because these are unsupported formats, RowPitch is not set to the
- * number of bytes between row of blocks, but instead in such way that
- * Height * RowPitch will match the expected size.
- */
- break;
-#endif /* DIRECT3D_VERSION >= 0x900 */
-
- case D3DFMT_UYVY:
- case D3DFMT_YUY2:
-#if DIRECT3D_VERSION >= 0x900
- case D3DFMT_R8G8_B8G8:
- case D3DFMT_G8R8_G8B8:
-#endif /* DIRECT3D_VERSION >= 0x900 */
- Width = (Width + 1) / 2;
- break;
-
-#if DIRECT3D_VERSION >= 0x900
- case D3DFMT_NV12:
- case D3DFMT_YV12:
- return (Height + ((Height + 1) / 2)) * RowPitch;
-
- case D3DFMT_NULL:
- return 0;
-#endif /* DIRECT3D_VERSION >= 0x900 */
-
- default:
- break;
+ size_t size;
+ if (Format == MAKEFOURCC('N','V','1','2') ||
+ Format == MAKEFOURCC('Y','V','1','2')) {
+ // Planar YUV
+ size = (Height + (Height + 1)/2) * RowPitch;
+ } else {
+ size_t BlockSize;
+ UINT BlockWidth;
+ UINT BlockHeight;
+ _getFormatSize(Format, BlockSize, BlockWidth, BlockHeight);
+ assert(BlockHeight);
+ Height = (Height + BlockHeight - 1) / BlockHeight;
+
+ size = Height * RowPitch;
+
+ if (Partial || Height == 1) {
+ // Must take pixel size in consideration
+ if (BlockWidth) {
+ Width = (Width + BlockWidth - 1) / BlockWidth;
+ size = (Width * BlockSize + 7)/ 8;
+ if (Height > 1) {
+ size += (Height - 1) * RowPitch;
+ }
+ }
+ }
}
- (void)Width;
-
- size_t size = Height * RowPitch;
-
if (Depth > 1) {
+ if (SlicePitch < 0) {
+ os::log("apitrace: warning: %s: negative slice pitch %i\n", __FUNCTION__, SlicePitch);
+ return 0;
+ }
+
size += (Depth - 1) * SlicePitch;
}
@@ -186,4 +168,3 @@ _getLockSize(D3DFORMAT Format, UINT Width, UINT Height, INT RowPitch, UINT Depth
}
-#endif /* _D3DCOMMONSIZE_HPP_ */
diff --git a/helpers/d3dshader.cpp b/helpers/d3dshader.cpp
index 06a71357..73867bd7 100644
--- a/helpers/d3dshader.cpp
+++ b/helpers/d3dshader.cpp
@@ -142,7 +142,7 @@ DisassembleShader(const void *pShaderBytecode, SIZE_T BytecodeLength, IDisassemb
char szFilename[MAX_PATH];
HMODULE hModule = NULL;
int version;
- for (version = 44; version >= 33; --version) {
+ for (version = 47; version >= 33; --version) {
_snprintf(szFilename, sizeof(szFilename), "d3dcompiler_%i.dll", version);
hModule = LoadLibraryA(szFilename);
if (hModule) {
@@ -154,6 +154,8 @@ DisassembleShader(const void *pShaderBytecode, SIZE_T BytecodeLength, IDisassemb
}
}
if (!pfnD3DDisassemble) {
+ os::log("apitrace: warning: failed to load d3dcompiler_xx.dll\n");
+
/*
* Fallback to D3D10DisassembleShader, which should be always present.
*/
diff --git a/helpers/d3dshader.hpp b/helpers/d3dshader.hpp
index 169785ef..4acc01dd 100644
--- a/helpers/d3dshader.hpp
+++ b/helpers/d3dshader.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _D3DSHADER_HPP_
-#define _D3DSHADER_HPP_
+#pragma once
#include <windows.h>
@@ -48,4 +47,3 @@ HRESULT
DisassembleShader(const void *pShader, SIZE_T BytecodeLength, IDisassemblyBuffer **ppDisassembly);
-#endif /* _D3DSHADER_HPP_ */
diff --git a/helpers/dxgisize.hpp b/helpers/dxgisize.hpp
index cbe526fb..5ebbb43c 100644
--- a/helpers/dxgisize.hpp
+++ b/helpers/dxgisize.hpp
@@ -30,8 +30,7 @@
* Auxiliary functions to compute the size of array/blob arguments.
*/
-#ifndef _DXGISIZE_HPP_
-#define _DXGISIZE_HPP_
+#pragma once
/* We purposedly don't include any D3D header, so that this header can be used
@@ -60,8 +59,9 @@ struct _MAP_DESC
static size_t
-_calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT Depth = 1, UINT DepthPitch = 0) {
- if (Width == 0 || Height == 0 || Depth == 0) {
+_calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch)
+{
+ if (Width == 0 || Height == 0) {
return 0;
}
@@ -132,6 +132,7 @@ _calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT D
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ case DXGI_FORMAT_AYUV:
BlockSize = 32;
break;
case DXGI_FORMAT_R8G8_TYPELESS:
@@ -148,6 +149,8 @@ _calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT D
case DXGI_FORMAT_R16_SINT:
case DXGI_FORMAT_B5G6R5_UNORM:
case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ case DXGI_FORMAT_A8P8:
BlockSize = 16;
break;
case DXGI_FORMAT_R8_TYPELESS:
@@ -156,6 +159,7 @@ _calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT D
case DXGI_FORMAT_R8_SNORM:
case DXGI_FORMAT_R8_SINT:
case DXGI_FORMAT_A8_UNORM:
+ case DXGI_FORMAT_P8:
BlockSize = 8;
break;
case DXGI_FORMAT_R1_UNORM:
@@ -163,6 +167,7 @@ _calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT D
break;
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_YUY2:
BlockSize = 32;
BlockWidth = 2;
break;
@@ -195,8 +200,25 @@ _calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT D
BlockWidth = 4;
BlockHeight = 4;
break;
+
+ case DXGI_FORMAT_NV12:
+ return (Height + (Height + 1)/2) * RowPitch;
+
+ case DXGI_FORMAT_Y410:
+ case DXGI_FORMAT_Y416:
+ case DXGI_FORMAT_P010:
+ case DXGI_FORMAT_P016:
+ case DXGI_FORMAT_420_OPAQUE:
+ case DXGI_FORMAT_Y210:
+ case DXGI_FORMAT_Y216:
+ case DXGI_FORMAT_NV11:
+ case DXGI_FORMAT_AI44:
+ case DXGI_FORMAT_IA44:
+ os::log("apitrace: warning: %s: unsupported DXGI format %u\n", __FUNCTION__, Format);
+ return 0;
+
default:
- os::log("apitrace: warning: %s: unknown format 0x%04X\n", __FUNCTION__, Format);
+ os::log("apitrace: warning: %s: unknown DXGI format %u\n", __FUNCTION__, Format);
return 0;
}
@@ -209,13 +231,25 @@ _calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT D
size += (Height - 1) * RowPitch;
}
- if (Depth > 1) {
+ return size;
+}
+
+static size_t
+_calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT Depth, UINT DepthPitch)
+{
+ if (Depth == 0) {
+ return 0;
+ }
+
+ size_t size = _calcDataSize(Format, Width, Height, RowPitch);
+ if (size && Depth > 1) {
size += (Depth - 1) * DepthPitch;
}
return size;
}
+
static size_t
_calcMipDataSize(UINT MipLevel, DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT Depth = 1, UINT DepthPitch = 0) {
if (Width == 0 || Height == 0 || Depth == 0) {
@@ -264,4 +298,3 @@ _getMapDesc(IDXGISurface *pResource, DXGI_MAPPED_RECT * pLockedRect, UINT MapFla
}
-#endif /* _DXGISIZE_HPP_ */
diff --git a/helpers/eglsize.hpp b/helpers/eglsize.hpp
index 3da79d12..2025fd46 100644
--- a/helpers/eglsize.hpp
+++ b/helpers/eglsize.hpp
@@ -29,8 +29,7 @@
/*
* Auxiliary functions to compute the size of array/blob arguments.
*/
-#ifndef _EGLSIZE_HPP_
-#define _EGLSIZE_HPP_
+#pragma once
#ifndef _WIN32
@@ -55,5 +54,3 @@ void
_EGLImageKHR_free_image_info(struct image_info *info);
#endif // !defined(_WIN32)
-
-#endif
diff --git a/helpers/glprofile.cpp b/helpers/glprofile.cpp
new file mode 100644
index 00000000..5520c032
--- /dev/null
+++ b/helpers/glprofile.cpp
@@ -0,0 +1,325 @@
+/**************************************************************************
+ *
+ * Copyright 2014 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "glprofile.hpp"
+
+#include <assert.h>
+
+#include <sstream>
+
+#include "os.hpp"
+#include "glproc.hpp"
+
+
+namespace glprofile {
+
+
+bool
+Profile::matches(const Profile expected) const
+{
+ if (api != expected.api) {
+ return false;
+ }
+
+ if (!versionGreaterOrEqual(expected.major, expected.minor)) {
+ return false;
+ }
+
+ /*
+ * GLX_ARB_create_context/WGL_ARB_create_context specs state that
+ *
+ * "If version 3.1 is requested, the context returned may implement
+ * any of the following versions:
+ *
+ * * Version 3.1. The GL_ARB_compatibility extension may or may not
+ * be implemented, as determined by the implementation.
+ *
+ * * The core profile of version 3.2 or greater."
+ */
+ if (core != expected.core &&
+ (expected.major != 3 || expected.minor != 1)) {
+ return false;
+ }
+
+ /*
+ * Only check forward-compatible flag prior to 3.2 contexts.
+ *
+ * Note that on MacOSX all 3.2+ context must be forward-compatible.
+ */
+#ifndef __APPLE__
+ if (forwardCompatible > expected.forwardCompatible) {
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+
+std::string
+Profile::str(void) const
+{
+ std::stringstream ss;
+ ss << *this;
+ return ss.str();
+}
+
+
+std::ostream &
+operator << (std::ostream &os, const Profile & profile) {
+ os << "OpenGL";
+ if (profile.api == API_GLES) {
+ os << " ES";
+ }
+ os << " " << profile.major << "." << profile.minor;
+ if (profile.api == API_GL) {
+ if (profile.versionGreaterOrEqual(3, 2)) {
+ os << " " << (profile.core ? "core" : "compat");
+ }
+ if (profile.forwardCompatible) {
+ os << " forward-compatible";
+ }
+ }
+ return os;
+}
+
+
+static inline bool
+isDigit(char c) {
+ return c >= '0' && c <= '9';
+}
+
+
+static unsigned
+parseNumber(const char * & p)
+{
+ unsigned n = 0;
+ char c = *p;
+ while (isDigit(c)) {
+ unsigned digit = c - '0';
+ n *= 10;
+ n += digit;
+ ++p;
+ c = *p;
+ }
+ return n;
+}
+
+
+/*
+ * Parse API and version numbers from a GL_VERSION string.
+ *
+ * OpenGL 2.1 specification states that GL_VERSION string is laid out as
+ *
+ * <version number><space><vendor-specific information>
+ *
+ * Where <version number> is either of the form <major number>.<minor number>
+ * or <major number>.<minor number>.<release number>, where the numbers all
+ * have one or more digits. The release number and vendor specific
+ * information are optional.
+ *
+ * OpenGL ES 1.x specification states that GL_VERSION is laid out as
+ *
+ * "OpenGL ES-XX 1.x" XX={CM,CL}
+ *
+ * OpenGL ES 2 and 3 specifications state that GL_VERSION is laid out as
+ *
+ * "OpenGL ES N.M vendor-specific information"
+ */
+static Profile
+parseVersion(const char *version)
+{
+ Profile profile(API_GL, 0, 0, false);
+
+ const char *p = version;
+
+ if (p[0] == 'O' &&
+ p[1] == 'p' &&
+ p[2] == 'e' &&
+ p[3] == 'n' &&
+ p[4] == 'G' &&
+ p[5] == 'L' &&
+ p[6] == ' ' &&
+ p[7] == 'E' &&
+ p[8] == 'S') {
+ p += 9;
+
+ profile.api = API_GLES;
+
+ // skip `-{CM,CL}`
+ if (*p == '-') {
+ ++p;
+ while (*p != ' ') {
+ if (*p == '\0') {
+ goto malformed;
+ }
+ ++p;
+ }
+ }
+
+ // skip white-space
+ while (*p == ' ') {
+ if (*p == '\0') {
+ goto malformed;
+ }
+ ++p;
+ }
+ }
+
+ if (!isDigit(*p)) {
+ goto malformed;
+ }
+
+ profile.major = parseNumber(p);
+ if (*p++ == '.' &&
+ isDigit(*p)) {
+ profile.minor = parseNumber(p);
+ } else {
+ goto malformed;
+ }
+
+ return profile;
+
+malformed:
+ os::log("warning: malformed GL_VERSION (\"%s\")\n", version);
+ return profile;
+}
+
+
+/*
+ * Get the profile of the current context.
+ */
+Profile
+getCurrentContextProfile(void)
+{
+ Profile profile(API_GL, 0, 0, false);
+
+ assert(parseVersion("3.0 Mesa 10.3.2") == Profile(API_GL, 3, 0));
+ assert(parseVersion("3.3 (Core Profile) Mesa 10.3.2") == Profile(API_GL, 3, 3));
+ assert(parseVersion("4.4.0 NVIDIA 331.89") == Profile(API_GL, 4, 4));
+ assert(parseVersion("OpenGL ES 3.0 Mesa 10.3.2") == Profile(API_GLES, 3, 0));
+
+ const char *version = (const char *)_glGetString(GL_VERSION);
+ if (!version) {
+ os::log("apitrace: warning: got null GL_VERSION\n");
+ return profile;
+ }
+
+ // Parse the version string.
+ profile = parseVersion(version);
+
+ if (profile.major >= 3) {
+ /*
+ * From OpenGL and OpenGL ES version 3 onwards, the GL version may also
+ * be queried via GL_MAJOR VERSION and GL_MINOR_VERSION, which should
+ * match the major number and minor number in GL_VERSION string, so use
+ * it to check we parsed the versions correcly.
+ */
+
+ GLint majorVersion = 0;
+ _glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
+ GLint minorVersion = 0;
+ _glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
+
+ if (majorVersion != profile.major ||
+ minorVersion != profile.minor) {
+ os::log("apitrace: warning: OpenGL context version mismatch (GL_VERSION=\"%s\", but GL_MAJOR/MINOR_VERSION=%u.%u)\n",
+ version, majorVersion, minorVersion);
+ }
+ }
+
+ if (profile.api == API_GL) {
+ if (profile.versionGreaterOrEqual(3, 0)) {
+ GLint contextFlags = 0;
+ _glGetIntegerv(GL_CONTEXT_FLAGS, &contextFlags);
+ if (contextFlags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) {
+ profile.forwardCompatible = true;
+ }
+ }
+
+ if (profile.versionGreaterOrEqual(3, 2)) {
+ GLint profileMask = 0;
+ _glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profileMask);
+ if (profileMask & GL_CONTEXT_CORE_PROFILE_BIT) {
+ profile.core = true;
+ }
+ }
+ }
+
+ return profile;
+
+}
+
+
+void
+Extensions::getCurrentContextExtensions(const Profile & profile)
+{
+ assert(strings.empty());
+ if (profile.major >= 3) {
+ // Use glGetStringi
+ GLint num_strings = 0;
+ _glGetIntegerv(GL_NUM_EXTENSIONS, &num_strings);
+ assert(num_strings);
+ for (int i = 0; i < num_strings; ++i) {
+ const char *extension = reinterpret_cast<const char *>(_glGetStringi(GL_EXTENSIONS, i));
+ assert(extension);
+ if (extension) {
+ strings.insert(extension);
+ }
+ }
+ } else {
+ // Use glGetString
+ const char *begin = reinterpret_cast<const char *>(_glGetString(GL_EXTENSIONS));
+ assert(begin);
+ if (begin) {
+ do {
+ const char *end = begin;
+ char c = *end;
+ while (c != '\0' && c != ' ') {
+ ++end;
+ c = *end;
+ }
+ if (end != begin) {
+ strings.insert(std::string(begin, end));
+ }
+ if (c == '\0') {
+ break;
+ }
+ begin = end + 1;
+ } while(true);
+ }
+ }
+}
+
+
+bool
+Extensions::has(const char *string) const
+{
+ return strings.find(string) != strings.end();
+}
+
+
+} /* namespace glprofile */
diff --git a/helpers/glprofile.hpp b/helpers/glprofile.hpp
new file mode 100644
index 00000000..397777dd
--- /dev/null
+++ b/helpers/glprofile.hpp
@@ -0,0 +1,143 @@
+/**************************************************************************
+ *
+ * Copyright 2014 VMware, Inc.
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Representation and manipulation of OpenGL context profiles.
+ */
+
+
+#pragma once
+
+
+#include <ostream>
+#include <set>
+#include <string>
+
+
+namespace glprofile {
+
+
+enum Api {
+ API_GL = 0,
+ API_GLES
+};
+
+
+struct Profile {
+ unsigned major:8;
+ unsigned minor:8;
+ unsigned api:1;
+ unsigned core:1;
+ unsigned forwardCompatible:1;
+
+ inline
+ Profile(
+ Api _api = API_GL,
+ unsigned _major = 1,
+ unsigned _minor = 0,
+ bool _core = false,
+ bool _forwardCompatible = false
+ ) {
+ api = _api;
+ major = _major;
+ minor = _minor;
+ core = _core;
+ forwardCompatible = _forwardCompatible;
+ }
+
+ inline bool
+ desktop(void) {
+ return api == API_GL;
+ }
+
+ inline bool
+ es(void) const {
+ return api == API_GLES;
+ }
+
+ inline bool
+ versionGreaterOrEqual(unsigned refMajor, unsigned refMinor) const {
+ return major > refMajor ||
+ (major == refMajor && minor >= refMinor);
+ }
+
+ inline bool
+ versionGreaterOrEqual(Api refApi, unsigned refMajor, unsigned refMinor) const {
+ return api == refApi && versionGreaterOrEqual(refMajor, refMinor);
+ }
+
+ bool
+ matches(const Profile expected) const;
+
+ // Comparison operator, mainly for use in std::map
+ inline bool
+ operator == (const Profile & other) const {
+ return major == other.major &&
+ minor == other.minor &&
+ api == other.api &&
+ core == other.core &&
+ forwardCompatible == other.forwardCompatible;
+ }
+
+ // Comparison operator, mainly for use in std::map
+ inline bool
+ operator < (const Profile & other) const {
+ return major < other.major ||
+ minor < other.minor ||
+ api < other.api ||
+ core < other.core ||
+ forwardCompatible < other.forwardCompatible;
+ }
+
+ std::string
+ str(void) const;
+};
+
+
+std::ostream &
+operator << (std::ostream &os, const Profile & profile);
+
+
+Profile
+getCurrentContextProfile(void);
+
+
+struct Extensions
+{
+ std::set<std::string> strings;
+
+ void
+ getCurrentContextExtensions(const Profile & profile);
+
+ bool
+ has(const char *string) const;
+};
+
+
+
+} /* namespace glprofile */
+
+
diff --git a/helpers/glsize.hpp b/helpers/glsize.hpp
index 0293a139..46cb4b18 100644
--- a/helpers/glsize.hpp
+++ b/helpers/glsize.hpp
@@ -31,8 +31,7 @@
* Auxiliary functions to compute the size of array/blob arguments, depending.
*/
-#ifndef _GL_SIZE_HPP_
-#define _GL_SIZE_HPP_
+#pragma once
#include <string.h>
@@ -44,29 +43,37 @@
#include "glimports.hpp"
+// Vertex/element formats
static inline size_t
-_gl_type_size(GLenum type)
+_gl_type_size(GLenum type, GLint size = 1)
{
switch (type) {
case GL_BOOL:
case GL_BYTE:
case GL_UNSIGNED_BYTE:
- return 1;
+ return size * 1;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_2_BYTES:
case GL_HALF_FLOAT:
- return 2;
+ return size * 2;
case GL_3_BYTES:
- return 3;
+ return size * 3;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
case GL_4_BYTES:
case GL_FIXED:
- return 4;
+ return size * 4;
case GL_DOUBLE:
- return 8;
+ return size * 8;
+ case GL_INT_2_10_10_10_REV:
+ case GL_INT_10_10_10_2_OES:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_10_10_10_2_OES:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ // packed
+ return 4;
default:
os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type);
return 0;
@@ -139,6 +146,36 @@ _gl_uniform_size(GLenum type, GLenum &elemType, GLint &numCols, GLint &numRows)
elemType = GL_UNSIGNED_INT;
numCols = 4;
break;
+ case GL_INT64_ARB:
+ elemType = GL_INT64_ARB;
+ break;
+ case GL_INT64_VEC2_ARB:
+ elemType = GL_INT64_ARB;
+ numCols = 2;
+ break;
+ case GL_INT64_VEC3_ARB:
+ elemType = GL_INT64_ARB;
+ numCols = 3;
+ break;
+ case GL_INT64_VEC4_ARB:
+ elemType = GL_INT64_ARB;
+ numCols = 4;
+ break;
+ case GL_UNSIGNED_INT64_ARB:
+ elemType = GL_UNSIGNED_INT64_ARB;
+ break;
+ case GL_UNSIGNED_INT64_VEC2_ARB:
+ elemType = GL_UNSIGNED_INT64_ARB;
+ numCols = 2;
+ break;
+ case GL_UNSIGNED_INT64_VEC3_ARB:
+ elemType = GL_UNSIGNED_INT64_ARB;
+ numCols = 3;
+ break;
+ case GL_UNSIGNED_INT64_VEC4_ARB:
+ elemType = GL_UNSIGNED_INT64_ARB;
+ numCols = 4;
+ break;
case GL_BOOL:
elemType = GL_BOOL;
break;
@@ -310,7 +347,7 @@ _glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei count)
os::log("apitrace: warning: %s: unexpected size 0x%04X\n", __FUNCTION__, size);
}
- size_t elementSize = size*_gl_type_size(type);
+ size_t elementSize = _gl_type_size(type, size);
if (!stride) {
stride = (GLsizei)elementSize;
}
@@ -345,6 +382,17 @@ _element_array_buffer_binding(void) {
return _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);
}
+/**
+ * Same as glGetVertexAttribiv, but passing the result in the return value.
+ */
+static inline GLint
+_glGetVertexAttribi(GLuint index, GLenum pname) {
+ GLint param = 0;
+ _glGetVertexAttribiv(index, pname, &param);
+ return param;
+}
+
+
static inline GLuint
_glDrawArrays_count(GLint first, GLsizei count)
{
@@ -375,7 +423,7 @@ _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indice
// Read indices from index buffer object
GLintptr offset = (GLintptr)indices;
GLsizeiptr size = count*_gl_type_size(type);
- GLvoid *temp = malloc(size);
+ temp = malloc(size);
if (!temp) {
return 0;
}
@@ -389,26 +437,48 @@ _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indice
}
GLuint maxindex = 0;
+
+ GLboolean restart_enabled = _glIsEnabled(GL_PRIMITIVE_RESTART);
+ while ((_glGetError() == GL_INVALID_ENUM))
+ ;
+
+ GLuint restart_index = 0;
+ if (restart_enabled) {
+ restart_index = (GLuint)_glGetInteger(GL_PRIMITIVE_RESTART_INDEX);
+ }
+
GLsizei i;
if (type == GL_UNSIGNED_BYTE) {
const GLubyte *p = (const GLubyte *)indices;
for (i = 0; i < count; ++i) {
- if (p[i] > maxindex) {
- maxindex = p[i];
+ GLuint index = p[i];
+ if (restart_enabled && index == restart_index) {
+ continue;
+ }
+ if (index > maxindex) {
+ maxindex = index;
}
}
} else if (type == GL_UNSIGNED_SHORT) {
const GLushort *p = (const GLushort *)indices;
for (i = 0; i < count; ++i) {
- if (p[i] > maxindex) {
- maxindex = p[i];
+ GLuint index = p[i];
+ if (restart_enabled && index == restart_index) {
+ continue;
+ }
+ if (index > maxindex) {
+ maxindex = index;
}
}
} else if (type == GL_UNSIGNED_INT) {
const GLuint *p = (const GLuint *)indices;
for (i = 0; i < count; ++i) {
- if (p[i] > maxindex) {
- maxindex = p[i];
+ GLuint index = p[i];
+ if (restart_enabled && index == restart_index) {
+ continue;
+ }
+ if (index > maxindex) {
+ maxindex = index;
}
}
} else {
@@ -424,10 +494,19 @@ _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indice
return maxindex + 1;
}
-#define _glDrawRangeElementsBaseVertex_count(start, end, count, type, indices, basevertex) _glDrawElementsBaseVertex_count(count, type, indices, basevertex)
+static inline GLuint
+_glDrawRangeElementsBaseVertex_count(GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+{
+ if (end < start ||
+ count < 0) {
+ return 0;
+ }
+
+ return end + basevertex + 1;
+}
-#define _glDrawElements_count(count, type, indices) _glDrawElementsBaseVertex_count(count, type, indices, 0);
-#define _glDrawRangeElements_count(start, end, count, type, indices) _glDrawElements_count(count, type, indices)
+#define _glDrawElements_count(count, type, indices) _glDrawElementsBaseVertex_count(count, type, indices, 0)
+#define _glDrawRangeElements_count(start, end, count, type, indices) _glDrawRangeElementsBaseVertex_count(start, end, count, type, indices, 0)
#define _glDrawRangeElementsEXT_count _glDrawRangeElements_count
/* FIXME take in consideration instancing */
@@ -442,145 +521,18 @@ _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indice
#define _glDrawElementsInstancedBaseVertexBaseInstance_count(count, type, indices, primcount, basevertex, baseinstance) _glDrawElementsBaseVertex_count(count, type, indices, basevertex)
#define _glDrawArraysInstancedARB_count _glDrawArraysInstanced_count
-#define _glDrawElementsInstancedARB_count _glDrawElementsInstanced_count
#define _glDrawArraysInstancedEXT_count _glDrawArraysInstanced_count
+#define _glDrawArraysInstancedANGLE_count _glDrawArraysInstanced_count
+#define _glDrawArraysInstancedBaseInstanceEXT_count _glDrawArraysInstancedBaseInstance_count
+#define _glDrawElementsBaseVertexEXT_count _glDrawElementsBaseVertex_count
+#define _glDrawElementsInstancedARB_count _glDrawElementsInstanced_count
#define _glDrawElementsInstancedEXT_count _glDrawElementsInstanced_count
+#define _glDrawElementsInstancedANGLE_count _glDrawElementsInstanced_count
+#define _glDrawElementsInstancedBaseInstanceEXT_count _glDrawElementsInstancedBaseInstance_count
+#define _glDrawElementsInstancedBaseVertexEXT_count _glDrawElementsInstancedBaseVertex_count
+#define _glDrawElementsInstancedBaseVertexBaseInstanceEXT_count _glDrawElementsInstancedBaseVertexBaseInstance_count
+#define _glDrawRangeElementsBaseVertexEXT_count _glDrawRangeElementsBaseVertex_count
-typedef struct {
- GLuint count;
- GLuint primCount;
- GLuint first;
- GLuint baseInstance;
-} DrawArraysIndirectCommand;
-
-static inline GLuint
-_glMultiDrawArraysIndirect_count(const GLvoid *indirect, GLsizei drawcount, GLsizei stride) {
- const DrawArraysIndirectCommand *cmd;
- GLvoid *temp = 0;
-
- if (drawcount <= 0) {
- return 0;
- }
-
- if (stride == 0) {
- stride = sizeof *cmd;
- }
-
- GLint draw_indirect_buffer = _glGetInteger(GL_DRAW_INDIRECT_BUFFER_BINDING);
- if (draw_indirect_buffer) {
- // Read commands from indirect buffer object
- GLintptr offset = (GLintptr)indirect;
- GLsizeiptr size = sizeof *cmd + (drawcount - 1) * stride;
- GLvoid *temp = malloc(size);
- if (!temp) {
- return 0;
- }
- memset(temp, 0, size);
- _glGetBufferSubData(GL_DRAW_INDIRECT_BUFFER, offset, size, temp);
- indirect = temp;
- } else {
- if (!indirect) {
- return 0;
- }
- }
-
- GLuint count = 0;
- for (GLsizei i = 0; i < drawcount; ++i) {
- cmd = (const DrawArraysIndirectCommand *)((const GLbyte *)indirect + i * stride);
-
- GLuint count_i = _glDrawArraysInstancedBaseInstance_count(
- cmd->first,
- cmd->count,
- cmd->primCount,
- cmd->baseInstance
- );
-
- count = std::max(count, count_i);
- }
-
- if (draw_indirect_buffer) {
- free(temp);
- }
-
- return count;
-}
-
-static inline GLuint
-_glDrawArraysIndirect_count(const GLvoid *indirect) {
- return _glMultiDrawArraysIndirect_count(indirect, 1, 0);
-}
-
-typedef struct {
- GLuint count;
- GLuint primCount;
- GLuint firstIndex;
- GLuint baseVertex;
- GLuint baseInstance;
-} DrawElementsIndirectCommand;
-
-static inline GLuint
-_glMultiDrawElementsIndirect_count(GLenum type, const GLvoid *indirect, GLsizei drawcount, GLsizei stride) {
- const DrawElementsIndirectCommand *cmd;
- GLvoid *temp = 0;
-
- if (drawcount <= 0) {
- return 0;
- }
-
- if (stride == 0) {
- stride = sizeof *cmd;
- }
-
- GLint draw_indirect_buffer = _glGetInteger(GL_DRAW_INDIRECT_BUFFER_BINDING);
- if (draw_indirect_buffer) {
- // Read commands from indirect buffer object
- GLintptr offset = (GLintptr)indirect;
- GLsizeiptr size = sizeof *cmd + (drawcount - 1) * stride;
- GLvoid *temp = malloc(size);
- if (!temp) {
- return 0;
- }
- memset(temp, 0, size);
- _glGetBufferSubData(GL_DRAW_INDIRECT_BUFFER, offset, size, temp);
- indirect = temp;
- } else {
- if (!indirect) {
- return 0;
- }
- }
-
- cmd = (const DrawElementsIndirectCommand *)indirect;
-
- GLuint count = 0;
- for (GLsizei i = 0; i < drawcount; ++i) {
- cmd = (const DrawElementsIndirectCommand *)((const GLbyte *)indirect + i * stride);
-
- GLuint count_i = _glDrawElementsInstancedBaseVertexBaseInstance_count(
- cmd->count,
- type,
- (GLvoid *)(uintptr_t)(cmd->firstIndex * _gl_type_size(type)),
- cmd->primCount,
- cmd->baseVertex,
- cmd->baseInstance
- );
-
- count = std::max(count, count_i);
- }
-
- if (draw_indirect_buffer) {
- free(temp);
- }
-
- return count;
-}
-
-static inline GLuint
-_glDrawElementsIndirect_count(GLenum type, const GLvoid *indirect) {
- return _glMultiDrawElementsIndirect_count(type, indirect, 1, 0);
-}
-
-#define _glMultiDrawArraysIndirectAMD_count _glMultiDrawArraysIndirect_count
-#define _glMultiDrawElementsIndirectAMD_count _glMultiDrawElementsIndirect_count
static inline GLuint
_glMultiDrawArrays_count(const GLint *first, const GLsizei *count, GLsizei drawcount) {
@@ -614,6 +566,7 @@ _glMultiDrawElementsBaseVertex_count(const GLsizei *count, GLenum type, const GL
#define _glMultiDrawArraysEXT_count _glMultiDrawArrays_count
#define _glMultiDrawElementsEXT_count _glMultiDrawElements_count
+#define _glMultiDrawElementsBaseVertexEXT_count _glMultiDrawElementsBaseVertex_count
#define _glMultiModeDrawArraysIBM_count(first, count, drawcount, modestride) _glMultiDrawArrays_count(first, count, drawcount)
#define _glMultiModeDrawElementsIBM_count(count, type, indices, drawcount, modestride) _glMultiDrawElements_count(count, type, (const GLvoid **)indices, drawcount)
@@ -785,37 +738,28 @@ _align(X x, Y y) {
return (x + (y - 1)) & ~(y - 1);
}
-static inline void
-_gl_format_size(GLenum format, GLenum type,
- unsigned & bits_per_element, unsigned & bits_per_pixel)
+static inline unsigned
+_gl_format_size(GLenum format, GLenum type)
{
- unsigned num_channels = _gl_format_channels(format);
+ unsigned num_elements = _gl_format_channels(format);
switch (type) {
case GL_BITMAP:
- bits_per_pixel = bits_per_element = 1;
- break;
+ return 1;
case GL_BYTE:
case GL_UNSIGNED_BYTE:
- bits_per_element = 8;
- bits_per_pixel = bits_per_element * num_channels;
- break;
+ return 8 * num_elements;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_HALF_FLOAT:
- bits_per_element = 16;
- bits_per_pixel = bits_per_element * num_channels;
- break;
+ return 16 * num_elements;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
- bits_per_element = 32;
- bits_per_pixel = bits_per_element * num_channels;
- break;
+ return 32 * num_elements;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
- bits_per_pixel = bits_per_element = 8;
- break;
+ return 8;
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL_UNSIGNED_SHORT_5_5_5_1:
@@ -824,8 +768,7 @@ _gl_format_size(GLenum format, GLenum type,
case GL_UNSIGNED_SHORT_5_6_5_REV:
case GL_UNSIGNED_SHORT_8_8_MESA:
case GL_UNSIGNED_SHORT_8_8_REV_MESA:
- bits_per_pixel = bits_per_element = 16;
- break;
+ return 16;
case GL_UNSIGNED_INT_8_8_8_8:
case GL_UNSIGNED_INT_8_8_8_8_REV:
case GL_UNSIGNED_INT_10_10_10_2:
@@ -835,32 +778,27 @@ _gl_format_size(GLenum format, GLenum type,
case GL_UNSIGNED_INT_5_9_9_9_REV:
case GL_UNSIGNED_INT_S8_S8_8_8_NV:
case GL_UNSIGNED_INT_8_8_S8_S8_REV_NV:
- bits_per_pixel = bits_per_element = 32;
- break;
+ return 32;
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
- bits_per_pixel = bits_per_element = 64;
- break;
+ assert(num_elements == 2);
+ return 32 * 2;
default:
os::log("apitrace: warning: %s: unexpected type GLenum 0x%04X\n", __FUNCTION__, type);
- bits_per_pixel = bits_per_element = 0;
- break;
+ return 0;
}
}
static inline size_t
-_glClearBufferData_size(GLenum format, GLenum type) {
- unsigned bits_per_element;
- unsigned bits_per_pixel;
- _gl_format_size(format, type, bits_per_element, bits_per_pixel);
+_glClearBufferData_size(GLenum format, GLenum type)
+{
+ unsigned bits_per_pixel = _gl_format_size(format, type);
return (bits_per_pixel + 7)/8;
}
static inline size_t
-_gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage) {
-
- unsigned bits_per_element;
- unsigned bits_per_pixel;
- _gl_format_size(format, type, bits_per_element, bits_per_pixel);
+_gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage)
+{
+ unsigned bits_per_pixel = _gl_format_size(format, type);
GLint alignment = 4;
GLint row_length = 0;
@@ -884,11 +822,13 @@ _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsize
size_t row_stride = (row_length*bits_per_pixel + 7)/8;
- if ((bits_per_element == 1*8 ||
- bits_per_element == 2*8 ||
- bits_per_element == 4*8 ||
- bits_per_element == 8*8) &&
- (GLint)bits_per_element < alignment*8) {
+ /*
+ * The OpenGL specification states that the unpack alignment should be
+ * ignored if the number of bits per element is not 1, 2, 4, or 8 times the
+ * number of bits in a GL ubyte, but the matter of fact is that the number
+ * of bits per element is always one of those.
+ */
+ if (_is_pot(alignment)) {
row_stride = _align(row_stride, alignment);
}
@@ -929,31 +869,6 @@ _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsize
#define _glTexImage2D_size(format, type, width, height) _gl_image_size(format, type, width, height, 1, can_unpack_subimage())
#define _glTexImage1D_size(format, type, width) _gl_image_size(format, type, width, 1, 1, can_unpack_subimage())
-#define _glTexSubImage3D_size(format, type, width, height, depth) _glTexImage3D_size(format, type, width, height, depth)
-#define _glTexSubImage2D_size(format, type, width, height) _glTexImage2D_size(format, type, width, height)
-#define _glTexSubImage1D_size(format, type, width) _glTexImage1D_size(format, type, width)
-
-#define _glTexImage3DEXT_size _glTexImage3D_size
-#define _glTexImage2DEXT_size _glTexImage2D_size
-#define _glTexImage1DEXT_size _glTexImage1D_size
-#define _glTexSubImage3DEXT_size _glTexSubImage3D_size
-#define _glTexSubImage2DEXT_size _glTexSubImage2D_size
-#define _glTexSubImage1DEXT_size _glTexSubImage1D_size
-
-#define _glTextureImage3DEXT_size _glTexImage3D_size
-#define _glTextureImage2DEXT_size _glTexImage2D_size
-#define _glTextureImage1DEXT_size _glTexImage1D_size
-#define _glTextureSubImage3DEXT_size _glTexSubImage3D_size
-#define _glTextureSubImage2DEXT_size _glTexSubImage2D_size
-#define _glTextureSubImage1DEXT_size _glTexSubImage1D_size
-
-#define _glMultiTexImage3DEXT_size _glTexImage3D_size
-#define _glMultiTexImage2DEXT_size _glTexImage2D_size
-#define _glMultiTexImage1DEXT_size _glTexImage1D_size
-#define _glMultiTexSubImage3DEXT_size _glTexSubImage3D_size
-#define _glMultiTexSubImage2DEXT_size _glTexSubImage2D_size
-#define _glMultiTexSubImage1DEXT_size _glTexSubImage1D_size
-
#define _glDrawPixels_size(format, type, width, height) _glTexImage2D_size(format, type, width, height)
#define _glConvolutionFilter1D_size(format, type, width) _glTexImage1D_size(format, type, width)
#define _glConvolutionFilter2D_size(format, type, width, height) _glTexImage2D_size(format, type, width, height)
@@ -1338,6 +1253,9 @@ _gl_PathColorGen_size(GLenum genMode, GLenum colorFormat)
case GL_NONE:
coeffsPerComponent = 0;
break;
+ case GL_CONSTANT:
+ coeffsPerComponent = 1;
+ break;
case GL_OBJECT_LINEAR:
case GL_PATH_OBJECT_BOUNDING_BOX_NV:
coeffsPerComponent = 3;
@@ -1380,6 +1298,9 @@ _gl_PathTexGen_size(GLenum genMode, GLsizei components)
switch (genMode) {
case GL_NONE:
return 0;
+ case GL_CONSTANT:
+ coeffsPerComponent = 1;
+ break;
case GL_OBJECT_LINEAR:
case GL_PATH_OBJECT_BOUNDING_BOX_NV:
coeffsPerComponent = 3;
@@ -1417,6 +1338,7 @@ static size_t valuesPerGetPathParameter(GLenum pname)
case GL_PATH_CLIENT_LENGTH_NV:
case GL_PATH_STROKE_COVER_MODE_NV:
case GL_PATH_STROKE_MASK_NV:
+ case GL_PATH_STROKE_BOUND_NV:
case GL_PATH_STROKE_OVERSAMPLE_COUNT_NV:
case GL_PATH_SAMPLE_QUALITY_NV:
return 1;
@@ -1484,4 +1406,3 @@ _glGetDebugMessageLog_length(const Char * string, const GLsizei *lengths, GLuint
return size;
}
-#endif /* _GL_SIZE_HPP_ */
diff --git a/image/image.hpp b/image/image.hpp
index 8d40bbf2..e6f0d226 100644
--- a/image/image.hpp
+++ b/image/image.hpp
@@ -27,12 +27,13 @@
* Image I/O.
*/
-#ifndef _IMAGE_HPP_
-#define _IMAGE_HPP_
+#pragma once
#include <iostream>
+#include <string>
+
namespace image {
@@ -58,6 +59,8 @@ public:
// Pixels in RGBA format
unsigned char *pixels;
+ std::string label;
+
inline Image(unsigned w, unsigned h, unsigned c = 4, bool f = false, ChannelType t = TYPE_UNORM8) :
width(w),
height(h),
@@ -112,10 +115,10 @@ public:
writeMD5(std::ostream &os) const;
bool
- writePNG(std::ostream &os) const;
+ writePNG(std::ostream &os, bool strip_alpha = false) const;
bool
- writePNG(const char *filename) const;
+ writePNG(const char *filename, bool strip_alpha = false) const;
void
writeRAW(std::ostream &os) const;
@@ -138,6 +141,7 @@ struct PNMInfo
unsigned height;
unsigned channels;
ChannelType channelType;
+ int commentNumber;
};
const char *
@@ -150,4 +154,3 @@ readPNM(const char *buffer, size_t bufferSize);
} /* namespace image */
-#endif /* _IMAGE_HPP_ */
diff --git a/image/image_md5.cpp b/image/image_md5.cpp
index cc7dd2b4..85141e18 100644
--- a/image/image_md5.cpp
+++ b/image/image_md5.cpp
@@ -28,9 +28,7 @@
#include <fstream>
#include "image.hpp"
-extern "C" {
- #include "md5.h"
-}
+#include "md5.h"
using namespace std;
diff --git a/image/image_png.cpp b/image/image_png.cpp
index 826a071a..72b9f9a8 100644
--- a/image/image_png.cpp
+++ b/image/image_png.cpp
@@ -31,6 +31,7 @@
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
+#include <math.h>
#include <fstream>
@@ -50,18 +51,48 @@ pngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length)
os->write((const char *)data, length);
}
-bool
-Image::writePNG(std::ostream &os) const
+
+static inline uint8_t
+floatToUnorm8(float c)
{
- assert(channelType == TYPE_UNORM8);
+ if (c <= 0.0f) {
+ return 0;
+ }
+ if (c >= 1.0f) {
+ return 255;
+ }
+ return c * 255.0f + 0.5f;
+}
+
+static inline uint8_t
+floatToSRGB(float c)
+{
+ if (c <= 0.0f) {
+ return 0;
+ }
+ if (c >= 1.0f) {
+ return 255;
+ }
+ if (c <= 0.0031308f) {
+ c *= 12.92f;
+ } else {
+ c = 1.055f * powf(c, 1.0f/2.4f) - 0.055f;
+ }
+ return c * 255.0f + 0.5f;
+}
+
+
+bool
+Image::writePNG(std::ostream &os, bool strip_alpha) const
+{
png_structp png_ptr;
png_infop info_ptr;
int color_type;
switch (channels) {
case 4:
- color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ color_type = strip_alpha ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA;
break;
case 3:
color_type = PNG_COLOR_TYPE_RGB;
@@ -102,17 +133,31 @@ Image::writePNG(std::ostream &os) const
png_write_info(png_ptr, info_ptr);
- if (!flipped) {
- for (unsigned y = 0; y < height; ++y) {
- png_bytep row = (png_bytep)(pixels + y*width*channels);
- png_write_rows(png_ptr, &row, 1);
+ if (channels == 4 && strip_alpha) {
+ png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+ }
+
+ switch (channelType) {
+ case TYPE_UNORM8:
+ for (const unsigned char *row = start(); row != end(); row += stride()) {
+ png_write_rows(png_ptr, (png_bytepp) &row, 1);
}
- } else {
- unsigned y = height;
- while (y--) {
- png_bytep row = (png_bytep)(pixels + y*width*channels);
- png_write_rows(png_ptr, &row, 1);
+ break;
+ case TYPE_FLOAT:
+ png_bytep rowUnorm8 = new png_byte[width * channels];
+ for (const unsigned char *row = start(); row != end(); row += stride()) {
+ const float *rowFloat = (const float *)row;
+ for (unsigned x = 0, i = 0; x < width; ++x) {
+ for (unsigned channel = 0; channel < channels; ++channel, ++i) {
+ float c = rowFloat[i];
+ bool srgb = channels >= 3 && channel < 3;
+ rowUnorm8[i] = srgb ? floatToSRGB(c) : floatToUnorm8(c);
+ }
+ }
+ png_write_rows(png_ptr, (png_bytepp) &rowUnorm8, 1);
}
+ delete [] rowUnorm8;
+ break;
}
png_write_end(png_ptr, info_ptr);
@@ -126,13 +171,13 @@ no_png:
bool
-Image::writePNG(const char *filename) const
+Image::writePNG(const char *filename, bool strip_alpha) const
{
std::ofstream os(filename, std::ofstream::binary);
if (!os) {
return false;
}
- return writePNG(os);
+ return writePNG(os, strip_alpha);
}
diff --git a/image/image_pnm.cpp b/image/image_pnm.cpp
index 4ed62609..14c1e558 100644
--- a/image/image_pnm.cpp
+++ b/image/image_pnm.cpp
@@ -65,7 +65,7 @@ Image::writePNM(std::ostream &os, const char *comment) const
outChannels = 1;
} else if (channels <= 3) {
identifier = "PF";
- outChannels = 4;
+ outChannels = 3;
} else {
// Non-standard extension for 4 floats
identifier = "PX";
@@ -74,6 +74,7 @@ Image::writePNM(std::ostream &os, const char *comment) const
break;
default:
assert(0);
+ return;
}
os << identifier << "\n";
@@ -211,6 +212,7 @@ readPNMHeader(const char *buffer, size_t bufferSize, PNMInfo &info)
info.channels = 0;
info.width = 0;
info.height = 0;
+ info.commentNumber = -1;
const char *currentBuffer = buffer;
const char *nextBuffer;
@@ -255,6 +257,13 @@ readPNMHeader(const char *buffer, size_t bufferSize, PNMInfo &info)
// skip over optional comment
if (*currentBuffer == '#') {
+ // advance past '#'
+ currentBuffer += 1;
+ bufferSize += 1;
+
+ // actually try to read a number
+ sscanf(currentBuffer, "%d", &info.commentNumber);
+
// advance past comment line
nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
bufferSize -= nextBuffer - currentBuffer;
diff --git a/inject/CMakeLists.txt b/inject/CMakeLists.txt
index b653f0db..6c24370d 100644
--- a/inject/CMakeLists.txt
+++ b/inject/CMakeLists.txt
@@ -1,12 +1,25 @@
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+include_directories (${CMAKE_SOURCE_DIR}/thirdparty/devcon)
+
add_library (injectee MODULE
injectee.cpp
)
set_target_properties (injectee PROPERTIES
PREFIX ""
)
+if (MSVC)
+ set_target_properties (injectee PROPERTIES LINK_FLAGS "/ENTRY:DllMainStartup")
+else ()
+ if (CMAKE_SIZEOF_VOID_P EQUAL 4)
+ set_target_properties (injectee PROPERTIES LINK_FLAGS "-Wl,--entry=_DllMainStartup@12")
+ else ()
+ set_target_properties (injectee PROPERTIES LINK_FLAGS "-Wl,--entry=DllMainStartup")
+ endif ()
+endif ()
+
install (TARGETS injectee LIBRARY DESTINATION bin)
+install_pdb (injectee DESTINATION bin)
add_executable (injector
injector.cpp
@@ -14,4 +27,10 @@ add_executable (injector
set_target_properties (injector PROPERTIES
OUTPUT_NAME inject
)
+target_link_libraries (injector
+ ${GETOPT_LIBRARIES}
+ devcon
+ psapi
+)
install (TARGETS injector RUNTIME DESTINATION bin)
+install_pdb (injector DESTINATION bin)
diff --git a/inject/inject.h b/inject/inject.h
index 873160e5..be9da508 100644
--- a/inject/inject.h
+++ b/inject/inject.h
@@ -38,6 +38,42 @@
#include <windows.h>
+#include <sddl.h>
+
+
+static void
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+debugPrintf(const char *format, ...);
+
+
+static void
+logLastError(const char *szMsg)
+{
+ DWORD dwLastError = GetLastError();
+
+ // http://msdn.microsoft.com/en-gb/library/windows/desktop/ms680582.aspx
+ LPSTR lpErrorMsg = NULL;
+ DWORD cbWritten;
+ cbWritten = FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dwLastError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR) &lpErrorMsg,
+ 0, NULL);
+
+ if (cbWritten) {
+ debugPrintf("inject: error: %s: %s", szMsg, lpErrorMsg);
+ } else {
+ debugPrintf("inject: error: %s: %lu\n", szMsg, dwLastError);
+ }
+
+ LocalFree(lpErrorMsg);
+}
static inline const char *
@@ -97,6 +133,7 @@ getModuleName(char *szModuleName, size_t n, const char *szFilename) {
struct SharedMem
{
BOOL bReplaced;
+ char cVerbosity;
char szDllName[4096 - sizeof(BOOL)];
};
@@ -106,20 +143,28 @@ static HANDLE hFileMapping = NULL;
static SharedMem *
-OpenSharedMemory(void) {
+OpenSharedMemory(SECURITY_DESCRIPTOR *lpSecurityDescriptor)
+{
if (pSharedMem) {
return pSharedMem;
}
+ SECURITY_ATTRIBUTES sa;
+ ZeroMemory(&sa, sizeof sa);
+ sa.nLength = sizeof sa;
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = lpSecurityDescriptor;
+
hFileMapping = CreateFileMapping(
INVALID_HANDLE_VALUE, // system paging file
- NULL, // lpAttributes
+ &sa, // lpAttributes
PAGE_READWRITE, // read/write access
0, // dwMaximumSizeHigh
sizeof(SharedMem), // dwMaximumSizeLow
TEXT("injectfilemap")); // name of map object
+
if (hFileMapping == NULL) {
- fprintf(stderr, "Failed to create file mapping\n");
+ logLastError("failed to create file mapping");
return NULL;
}
@@ -132,7 +177,7 @@ OpenSharedMemory(void) {
0, // dwFileOffsetLow
0); // dwNumberOfBytesToMap (entire file)
if (pSharedMem == NULL) {
- fprintf(stderr, "Failed to map view \n");
+ logLastError("failed to map view");
return NULL;
}
@@ -158,35 +203,84 @@ CloseSharedMem(void) {
}
-static inline VOID
-SetSharedMem(LPCSTR lpszSrc) {
- SharedMem *pSharedMem = OpenSharedMemory();
- if (!pSharedMem) {
- return;
+/*
+ * XXX: Mixed architecture don't quite work. See also
+ * http://www.corsix.org/content/dll-injection-and-wow64
+ */
+static BOOL
+isDifferentArch(HANDLE hProcess)
+{
+ typedef BOOL (WINAPI *PFNISWOW64PROCESS)(HANDLE, PBOOL);
+ PFNISWOW64PROCESS pfnIsWow64Process;
+ pfnIsWow64Process = (PFNISWOW64PROCESS)
+ GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process");
+ if (!pfnIsWow64Process) {
+ return FALSE;
}
- LPSTR lpszDst = pSharedMem->szDllName;
-
- size_t n = 1;
- while (*lpszSrc && n < sizeof pSharedMem->szDllName) {
- *lpszDst++ = *lpszSrc++;
- n++;
+ // NOTE: IsWow64Process will return false on 32-bits Windows
+ BOOL isThisWow64;
+ BOOL isOtherWow64;
+ if (!pfnIsWow64Process(GetCurrentProcess(), &isThisWow64) ||
+ !pfnIsWow64Process(hProcess, &isOtherWow64)) {
+ logLastError("IsWow64Process failed");
+ return FALSE;
}
- *lpszDst = '\0';
+
+ return bool(isThisWow64) != bool(isOtherWow64);
}
-static inline VOID
-GetSharedMem(LPSTR lpszDst, size_t n) {
- SharedMem *pSharedMem = OpenSharedMemory();
- if (!pSharedMem) {
- return;
+static BOOL
+injectDll(HANDLE hProcess, const char *szDllPath)
+{
+ BOOL bRet = FALSE;
+ PTHREAD_START_ROUTINE lpStartAddress;
+ HANDLE hThread;
+ DWORD hModule;
+
+ // Allocate memory in the target process to hold the DLL name
+ size_t szDllPathLength = strlen(szDllPath) + 1;
+ void *lpMemory = VirtualAllocEx(hProcess, NULL, szDllPathLength, MEM_COMMIT, PAGE_READWRITE);
+ if (!lpMemory) {
+ logLastError("failed to allocate memory in the process");
+ goto no_memory;
}
- LPCSTR lpszSrc = pSharedMem->szDllName;
+ // Copy DLL name into the target process
+ if (!WriteProcessMemory(hProcess, lpMemory, szDllPath, szDllPathLength, NULL)) {
+ logLastError("failed to write into process memory");
+ goto no_thread;
+ }
- while (*lpszSrc && --n) {
- *lpszDst++ = *lpszSrc++;
+ /*
+ * Get LoadLibraryA address from kernel32.dll. It's the same for all the
+ * process (XXX: but only within the same architecture).
+ */
+ lpStartAddress =
+ (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("KERNEL32"), "LoadLibraryA");
+
+ // Create remote thread in another process
+ hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, lpMemory, 0, NULL);
+ if (!hThread) {
+ logLastError("failed to create remote thread");
+ goto no_thread;
}
- *lpszDst = '\0';
+
+ // Wait for it to finish
+ WaitForSingleObject(hThread, INFINITE);
+
+ GetExitCodeThread(hThread, &hModule);
+ if (!hModule) {
+ debugPrintf("inject: error: failed to load %s into the remote process %lu\n",
+ szDllPath, GetProcessId(hProcess));
+ } else {
+ bRet = TRUE;
+ }
+
+ CloseHandle(hThread);
+no_thread:
+ VirtualFreeEx(hProcess, lpMemory, 0, MEM_RELEASE);
+no_memory:
+ return bRet;
}
diff --git a/inject/injectee.cpp b/inject/injectee.cpp
index d7a192c7..56eaffc0 100644
--- a/inject/injectee.cpp
+++ b/inject/injectee.cpp
@@ -40,18 +40,30 @@
#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
+#include <string.h>
+
+#include <algorithm>
+#include <set>
+#include <map>
+#include <functional>
#include <windows.h>
#include <tlhelp32.h>
+#include <delayimp.h>
#include "inject.h"
-#define VERBOSITY 0
+static int VERBOSITY = 0;
#define NOOP 0
-static CRITICAL_SECTION Mutex = {(PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0};
+static CRITICAL_SECTION g_Mutex;
+
+
+
+static HMODULE g_hThisModule = NULL;
+static HMODULE g_hHookModule = NULL;
static void
@@ -68,6 +80,22 @@ debugPrintf(const char *format, ...)
}
+EXTERN_C void
+_assert(const char *_Message, const char *_File, unsigned _Line)
+{
+ debugPrintf("Assertion failed: %s, file %s, line %u\n", _Message, _File, _Line);
+ TerminateProcess(GetCurrentProcess(), 1);
+}
+
+
+EXTERN_C void
+_wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line)
+{
+ debugPrintf("Assertion failed: %S, file %S, line %u\n", _Message, _File, _Line);
+ TerminateProcess(GetCurrentProcess(), 1);
+}
+
+
static HMODULE WINAPI
MyLoadLibraryA(LPCSTR lpLibFileName);
@@ -84,50 +112,261 @@ static FARPROC WINAPI
MyGetProcAddress(HMODULE hModule, LPCSTR lpProcName);
+static void
+MyCreateProcessCommon(BOOL bRet,
+ DWORD dwCreationFlags,
+ LPPROCESS_INFORMATION lpProcessInformation)
+{
+ if (!bRet) {
+ debugPrintf("inject: warning: failed to create child process\n");
+ return;
+ }
+
+ DWORD dwLastError = GetLastError();
+
+ if (isDifferentArch(lpProcessInformation->hProcess)) {
+ debugPrintf("inject: error: child process %lu has different architecture\n",
+ GetProcessId(lpProcessInformation->hProcess));
+ } else {
+ char szDllPath[MAX_PATH];
+ GetModuleFileNameA(g_hThisModule, szDllPath, sizeof szDllPath);
+
+ if (!injectDll(lpProcessInformation->hProcess, szDllPath)) {
+ debugPrintf("inject: warning: failed to inject into child process %lu\n",
+ GetProcessId(lpProcessInformation->hProcess));
+ }
+ }
+
+ if (!(dwCreationFlags & CREATE_SUSPENDED)) {
+ ResumeThread(lpProcessInformation->hThread);
+ }
+
+ SetLastError(dwLastError);
+}
+
+static BOOL WINAPI
+MyCreateProcessA(LPCSTR lpApplicationName,
+ LPSTR lpCommandLine,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ LPCSTR lpCurrentDirectory,
+ LPSTARTUPINFOA lpStartupInfo,
+ LPPROCESS_INFORMATION lpProcessInformation)
+{
+ if (VERBOSITY >= 2) {
+ debugPrintf("inject: intercepting %s(\"%s\", \"%s\", ...)\n",
+ __FUNCTION__,
+ lpApplicationName,
+ lpCommandLine);
+ }
+
+ BOOL bRet;
+ bRet = CreateProcessA(lpApplicationName,
+ lpCommandLine,
+ lpProcessAttributes,
+ lpThreadAttributes,
+ bInheritHandles,
+ dwCreationFlags | CREATE_SUSPENDED,
+ lpEnvironment,
+ lpCurrentDirectory,
+ lpStartupInfo,
+ lpProcessInformation);
+
+ MyCreateProcessCommon(bRet, dwCreationFlags, lpProcessInformation);
+
+ return bRet;
+}
+
+static BOOL WINAPI
+MyCreateProcessW(LPCWSTR lpApplicationName,
+ LPWSTR lpCommandLine,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ LPCWSTR lpCurrentDirectory,
+ LPSTARTUPINFOW lpStartupInfo,
+ LPPROCESS_INFORMATION lpProcessInformation)
+{
+ if (VERBOSITY >= 2) {
+ debugPrintf("inject: intercepting %s(\"%S\", \"%S\", ...)\n",
+ __FUNCTION__,
+ lpApplicationName,
+ lpCommandLine);
+ }
+
+ BOOL bRet;
+ bRet = CreateProcessW(lpApplicationName,
+ lpCommandLine,
+ lpProcessAttributes,
+ lpThreadAttributes,
+ bInheritHandles,
+ dwCreationFlags | CREATE_SUSPENDED,
+ lpEnvironment,
+ lpCurrentDirectory,
+ lpStartupInfo,
+ lpProcessInformation);
+
+ MyCreateProcessCommon(bRet, dwCreationFlags, lpProcessInformation);
+
+ return bRet;
+}
+
+typedef BOOL
+(WINAPI *PFNCREATEPROCESSASUSERW) (HANDLE, LPCWSTR, LPWSTR,
+ LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID,
+ LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
+
+static PFNCREATEPROCESSASUSERW pfnCreateProcessAsUserW;
+
+static BOOL WINAPI
+MyCreateProcessAsUserW(HANDLE hToken,
+ LPCWSTR lpApplicationName,
+ LPWSTR lpCommandLine,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ LPCWSTR lpCurrentDirectory,
+ LPSTARTUPINFOW lpStartupInfo,
+ LPPROCESS_INFORMATION lpProcessInformation)
+{
+ if (VERBOSITY >= 2) {
+ debugPrintf("inject: intercepting %s(\"%S\", \"%S\", ...)\n",
+ __FUNCTION__,
+ lpApplicationName,
+ lpCommandLine);
+ }
+
+ // Certain WINE versions (at least 1.6.2) don't export
+ // kernel32.dll!CreateProcessAsUserW
+ assert(pfnCreateProcessAsUserW);
+
+ BOOL bRet;
+ bRet = pfnCreateProcessAsUserW(hToken,
+ lpApplicationName,
+ lpCommandLine,
+ lpProcessAttributes,
+ lpThreadAttributes,
+ bInheritHandles,
+ dwCreationFlags,
+ lpEnvironment,
+ lpCurrentDirectory,
+ lpStartupInfo,
+ lpProcessInformation);
+
+ MyCreateProcessCommon(bRet, dwCreationFlags, lpProcessInformation);
+
+ return bRet;
+}
+
+
+template< class T, class I >
+inline T *
+rvaToVa(HMODULE hModule, I rva)
+{
+ assert(rva != 0);
+ return reinterpret_cast<T *>(reinterpret_cast<PBYTE>(hModule) + rva);
+}
+
+
static const char *
-getImportDescriptionName(HMODULE hModule, const PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor) {
- const char* szName = (const char*)((PBYTE)hModule + pImportDescriptor->Name);
- return szName;
+getDescriptorName(HMODULE hModule,
+ const PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor)
+{
+ return rvaToVa<const char>(hModule, pImportDescriptor->Name);
}
+static const char *
+getDescriptorName(HMODULE hModule,
+ const PImgDelayDescr pDelayDescriptor)
+{
+ if (pDelayDescriptor->grAttrs & dlattrRva) {
+ return rvaToVa<const char>(hModule, pDelayDescriptor->rvaDLLName);
+ } else {
+ // old-stye, with ImgDelayDescr::szName being a LPCSTR
+ return reinterpret_cast<LPCSTR>(pDelayDescriptor->rvaDLLName);
+ }
+}
-static PIMAGE_IMPORT_DESCRIPTOR
-getImportDescriptor(HMODULE hModule,
- const char *szModule,
- const char *pszDllName)
+
+static PIMAGE_OPTIONAL_HEADER
+getOptionalHeader(HMODULE hModule,
+ const char *szModule)
+{
+ PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(hModule);
+ if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
+ debugPrintf("inject: warning: %s: unexpected DOS header magic (0x%04x)\n",
+ szModule, pDosHeader->e_magic);
+ return NULL;
+ }
+ PIMAGE_NT_HEADERS pNtHeaders = rvaToVa<IMAGE_NT_HEADERS>(hModule, pDosHeader->e_lfanew);
+ if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
+ debugPrintf("inject: warning: %s: unexpected NT header signature (0x%08lx)\n",
+ szModule, pNtHeaders->Signature);
+ return NULL;
+ }
+ assert(pNtHeaders->OptionalHeader.NumberOfRvaAndSizes > 0);
+ PIMAGE_OPTIONAL_HEADER pOptionalHeader = &pNtHeaders->OptionalHeader;
+ return pOptionalHeader;
+}
+
+static PVOID
+getImageDirectoryEntry(HMODULE hModule,
+ const char *szModule,
+ UINT Entry)
{
MEMORY_BASIC_INFORMATION MemoryInfo;
if (VirtualQuery(hModule, &MemoryInfo, sizeof MemoryInfo) != sizeof MemoryInfo) {
- debugPrintf("%s: %s: VirtualQuery failed\n", __FUNCTION__, szModule);
+ debugPrintf("inject: warning: %s: VirtualQuery failed\n", szModule);
return NULL;
}
if (MemoryInfo.Protect & (PAGE_NOACCESS | PAGE_EXECUTE)) {
- debugPrintf("%s: %s: no read access (Protect = 0x%08x)\n", __FUNCTION__, szModule, MemoryInfo.Protect);
+ debugPrintf("inject: warning: %s: no read access (Protect = 0x%08lx)\n", szModule, MemoryInfo.Protect);
return NULL;
}
- PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
- PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((PBYTE)hModule + pDosHeader->e_lfanew);
-
- PIMAGE_OPTIONAL_HEADER pOptionalHeader = &pNtHeaders->OptionalHeader;
-
- UINT_PTR ImportAddress = pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
+ PIMAGE_OPTIONAL_HEADER pOptionalHeader = getOptionalHeader(hModule, szModule);
+ if (!pOptionalHeader ||
+ pOptionalHeader->DataDirectory[Entry].Size == 0) {
+ return NULL;
+ }
+ UINT_PTR ImportAddress = pOptionalHeader->DataDirectory[Entry].VirtualAddress;
if (!ImportAddress) {
return NULL;
}
- PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((PBYTE)hModule + ImportAddress);
+ return rvaToVa<VOID>(hModule, ImportAddress);
+}
- while (pImportDescriptor->FirstThunk) {
- const char* szName = getImportDescriptionName(hModule, pImportDescriptor);
- if (stricmp(pszDllName, szName) == 0) {
- return pImportDescriptor;
- }
- ++pImportDescriptor;
- }
- return NULL;
+static PIMAGE_IMPORT_DESCRIPTOR
+getFirstImportDescriptor(HMODULE hModule, const char *szModule)
+{
+ PVOID pEntry = getImageDirectoryEntry(hModule, szModule, IMAGE_DIRECTORY_ENTRY_IMPORT);
+ return reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(pEntry);
+}
+
+
+static PImgDelayDescr
+getDelayImportDescriptor(HMODULE hModule, const char *szModule)
+{
+ PVOID pEntry = getImageDirectoryEntry(hModule, szModule, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
+ return reinterpret_cast<PImgDelayDescr>(pEntry);
+}
+
+
+static PIMAGE_EXPORT_DIRECTORY
+getExportDescriptor(HMODULE hModule)
+{
+ PVOID pEntry = getImageDirectoryEntry(hModule, "(wrapper)", IMAGE_DIRECTORY_ENTRY_EXPORT);
+ return reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(pEntry);
}
@@ -140,195 +379,337 @@ replaceAddress(LPVOID *lpOldAddress, LPVOID lpNewAddress)
return TRUE;
}
- EnterCriticalSection(&Mutex);
+ EnterCriticalSection(&g_Mutex);
if (!(VirtualProtect(lpOldAddress, sizeof *lpOldAddress, PAGE_READWRITE, &flOldProtect))) {
- LeaveCriticalSection(&Mutex);
+ LeaveCriticalSection(&g_Mutex);
return FALSE;
}
*lpOldAddress = lpNewAddress;
if (!(VirtualProtect(lpOldAddress, sizeof *lpOldAddress, flOldProtect, &flOldProtect))) {
- LeaveCriticalSection(&Mutex);
+ LeaveCriticalSection(&g_Mutex);
return FALSE;
}
- LeaveCriticalSection(&Mutex);
+ LeaveCriticalSection(&g_Mutex);
return TRUE;
}
+/* Return pointer to patcheable function address.
+ *
+ * See also:
+ *
+ * - An In-Depth Look into the Win32 Portable Executable File Format, Part 2, Matt Pietrek,
+ * http://msdn.microsoft.com/en-gb/magazine/cc301808.aspx
+ *
+ * - http://www.microsoft.com/msj/1298/hood/hood1298.aspx
+ *
+ */
static LPVOID *
-getOldFunctionAddress(HMODULE hModule,
- PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor,
- const char* pszFunctionName)
-{
- PIMAGE_THUNK_DATA pOriginalFirstThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDescriptor->OriginalFirstThunk);
- PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDescriptor->FirstThunk);
-
- //debugPrintf(" %s\n", __FUNCTION__);
-
- while (pOriginalFirstThunk->u1.Function) {
- PIMAGE_IMPORT_BY_NAME pImport = (PIMAGE_IMPORT_BY_NAME)((PBYTE)hModule + pOriginalFirstThunk->u1.AddressOfData);
- const char* szName = (const char* )pImport->Name;
- //debugPrintf(" %s\n", szName);
- if (strcmp(pszFunctionName, szName) == 0) {
- //debugPrintf(" %s succeeded\n", __FUNCTION__);
- return (LPVOID *)(&pFirstThunk->u1.Function);
- }
- ++pOriginalFirstThunk;
- ++pFirstThunk;
+getPatchAddress(HMODULE hModule,
+ const char *szDescriptorName,
+ DWORD OriginalFirstThunk,
+ DWORD FirstThunk,
+ const char* pszFunctionName,
+ LPVOID lpOldAddress)
+{
+ if (VERBOSITY >= 4) {
+ debugPrintf("inject: %s(%s, %s)\n", __FUNCTION__,
+ szDescriptorName,
+ pszFunctionName);
}
- //debugPrintf(" %s failed\n", __FUNCTION__);
+ PIMAGE_THUNK_DATA pThunkIAT = rvaToVa<IMAGE_THUNK_DATA>(hModule, FirstThunk);
+
+ UINT_PTR pOldFunction = (UINT_PTR)lpOldAddress;
+
+ PIMAGE_THUNK_DATA pThunk;
+ if (OriginalFirstThunk) {
+ pThunk = rvaToVa<IMAGE_THUNK_DATA>(hModule, OriginalFirstThunk);
+ } else {
+ pThunk = pThunkIAT;
+ }
+
+ while (pThunk->u1.Function) {
+ if (OriginalFirstThunk == 0 ||
+ pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) {
+ // No name -- search by the real function address
+ if (!pOldFunction) {
+ return NULL;
+ }
+ if (pThunkIAT->u1.Function == pOldFunction) {
+ return (LPVOID *)(&pThunkIAT->u1.Function);
+ }
+ } else {
+ // Search by name
+ PIMAGE_IMPORT_BY_NAME pImport = rvaToVa<IMAGE_IMPORT_BY_NAME>(hModule, pThunk->u1.AddressOfData);
+ const char* szName = (const char* )pImport->Name;
+ if (strcmp(pszFunctionName, szName) == 0) {
+ return (LPVOID *)(&pThunkIAT->u1.Function);
+ }
+ }
+ ++pThunk;
+ ++pThunkIAT;
+ }
return NULL;
}
-static void
-replaceModule(HMODULE hModule,
- const char *szModule,
- PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor,
- HMODULE hNewModule)
+static LPVOID *
+getPatchAddress(HMODULE hModule,
+ PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor,
+ const char* pszFunctionName,
+ LPVOID lpOldAddress)
{
- PIMAGE_THUNK_DATA pOriginalFirstThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDescriptor->OriginalFirstThunk);
- PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDescriptor->FirstThunk);
+ assert(pImportDescriptor->TimeDateStamp != 0 || pImportDescriptor->Name != 0);
+
+ return getPatchAddress(hModule,
+ getDescriptorName(hModule, pImportDescriptor),
+ pImportDescriptor->OriginalFirstThunk,
+ pImportDescriptor->FirstThunk,
+ pszFunctionName,
+ lpOldAddress);
+}
- while (pOriginalFirstThunk->u1.Function) {
- PIMAGE_IMPORT_BY_NAME pImport = (PIMAGE_IMPORT_BY_NAME)((PBYTE)hModule + pOriginalFirstThunk->u1.AddressOfData);
- const char* szFunctionName = (const char* )pImport->Name;
- if (VERBOSITY > 0) {
- debugPrintf(" hooking %s->%s!%s\n", szModule,
- getImportDescriptionName(hModule, pImportDescriptor),
- szFunctionName);
- }
- PROC pNewProc = GetProcAddress(hNewModule, szFunctionName);
- if (!pNewProc) {
- debugPrintf("warning: no replacement for %s\n", szFunctionName);
- } else {
- LPVOID *lpOldAddress = (LPVOID *)(&pFirstThunk->u1.Function);
- replaceAddress(lpOldAddress, (LPVOID)pNewProc);
- if (pSharedMem) {
- pSharedMem->bReplaced = TRUE;
- }
- }
-
- ++pOriginalFirstThunk;
- ++pFirstThunk;
- }
+// See
+// http://www.microsoft.com/msj/1298/hood/hood1298.aspx
+// http://msdn.microsoft.com/en-us/library/16b2dyk5.aspx
+static LPVOID *
+getPatchAddress(HMODULE hModule,
+ PImgDelayDescr pDelayDescriptor,
+ const char* pszFunctionName,
+ LPVOID lpOldAddress)
+{
+ assert(pDelayDescriptor->rvaDLLName != 0);
+
+ return getPatchAddress(hModule,
+ getDescriptorName(hModule, pDelayDescriptor),
+ pDelayDescriptor->rvaINT,
+ pDelayDescriptor->rvaIAT,
+ pszFunctionName,
+ lpOldAddress);
}
+template< class T >
static BOOL
-hookFunction(HMODULE hModule,
- const char *szModule,
- const char *pszDllName,
- const char *pszFunctionName,
- LPVOID lpNewAddress)
-{
- PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = getImportDescriptor(hModule, szModule, pszDllName);
- if (pImportDescriptor == NULL) {
- return FALSE;
- }
- LPVOID* lpOldFunctionAddress = getOldFunctionAddress(hModule, pImportDescriptor, pszFunctionName);
- if (lpOldFunctionAddress == NULL) {
+patchFunction(HMODULE hModule,
+ const char *szModule,
+ const char *pszDllName,
+ T pImportDescriptor,
+ const char *pszFunctionName,
+ LPVOID lpOldAddress,
+ LPVOID lpNewAddress)
+{
+ LPVOID* lpPatchAddress = getPatchAddress(hModule, pImportDescriptor, pszFunctionName, lpOldAddress);
+ if (lpPatchAddress == NULL) {
return FALSE;
}
- if (*lpOldFunctionAddress == lpNewAddress) {
+ if (*lpPatchAddress == lpNewAddress) {
return TRUE;
}
- if (VERBOSITY >= 3) {
- debugPrintf(" hooking %s->%s!%s\n", szModule, pszDllName, pszFunctionName);
+ DWORD Offset = (DWORD)(UINT_PTR)lpPatchAddress - (UINT_PTR)hModule;
+ if (VERBOSITY > 0) {
+ debugPrintf("inject: patching %s!0x%lx -> %s!%s\n", szModule, Offset, pszDllName, pszFunctionName);
}
- return replaceAddress(lpOldFunctionAddress, lpNewAddress);
+ BOOL bRet;
+ bRet = replaceAddress(lpPatchAddress, lpNewAddress);
+ if (!bRet) {
+ debugPrintf("inject: failed to patch %s!0x%lx -> %s!%s\n", szModule, Offset, pszDllName, pszFunctionName);
+ }
+
+ return bRet;
}
-static BOOL
-replaceImport(HMODULE hModule,
- const char *szModule,
- const char *pszDllName,
- HMODULE hNewModule)
-{
- if (NOOP) {
- return TRUE;
+
+struct StrCompare : public std::binary_function<const char *, const char *, bool> {
+ bool operator() (const char * s1, const char * s2) const {
+ return strcmp(s1, s2) < 0;
}
+};
- PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = getImportDescriptor(hModule, szModule, pszDllName);
- if (pImportDescriptor == NULL) {
- return TRUE;
+typedef std::map<const char *, LPVOID, StrCompare> FunctionMap;
+
+struct StrICompare : public std::binary_function<const char *, const char *, bool> {
+ bool operator() (const char * s1, const char * s2) const {
+ return stricmp(s1, s2) < 0;
}
+};
- replaceModule(hModule, szModule, pImportDescriptor, hNewModule);
+struct Module {
+ bool bInternal;
+ FunctionMap functionMap;
+};
- return TRUE;
+typedef std::map<const char *, Module, StrICompare> ModulesMap;
+
+/* This is only modified at DLL_PROCESS_ATTACH time. */
+static ModulesMap modulesMap;
+
+
+static inline bool
+isMatchModuleName(const char *szModuleName)
+{
+ ModulesMap::const_iterator modIt = modulesMap.find(szModuleName);
+ return modIt != modulesMap.end();
}
-static HMODULE g_hThisModule = NULL;
+/* Set of previously hooked modules */
+static std::set<HMODULE>
+g_hHookedModules;
+
+
+enum Action {
+ ACTION_HOOK,
+ ACTION_UNHOOK,
-struct Replacement {
- const char *szMatchModule;
- HMODULE hReplaceModule;
};
-static unsigned numReplacements = 0;
-static Replacement replacements[32];
+template< class T >
+void
+patchDescriptor(HMODULE hModule,
+ const char *szModule,
+ T pImportDescriptor,
+ Action action)
+{
+ const char* szDescriptorName = getDescriptorName(hModule, pImportDescriptor);
+
+ ModulesMap::const_iterator modIt = modulesMap.find(szDescriptorName);
+ if (modIt != modulesMap.end()) {
+ const char *szMatchModule = modIt->first; // same as szDescriptorName
+ const Module & module = modIt->second;
+
+ const FunctionMap & functionMap = module.functionMap;
+ FunctionMap::const_iterator fnIt;
+ for (fnIt = functionMap.begin(); fnIt != functionMap.end(); ++fnIt) {
+ const char *szFunctionName = fnIt->first;
+ LPVOID lpHookAddress = fnIt->second;
+
+ // Knowning the real address is useful when patching imports by ordinal
+ LPVOID lpRealAddress = NULL;
+ HMODULE hRealModule = GetModuleHandleA(szDescriptorName);
+ if (hRealModule) {
+ // FIXME: this assertion can fail when the wrapper name is the same as the original DLL
+ //assert(hRealModule != g_hHookModule);
+ if (hRealModule != g_hHookModule) {
+ lpRealAddress = (LPVOID)GetProcAddress(hRealModule, szFunctionName);
+ }
+ }
+
+ LPVOID lpOldAddress = lpRealAddress;
+ LPVOID lpNewAddress = lpHookAddress;
+
+ if (action == ACTION_UNHOOK) {
+ std::swap(lpOldAddress, lpNewAddress);
+ }
+
+ BOOL bPatched;
+ bPatched = patchFunction(hModule, szModule, szMatchModule, pImportDescriptor, szFunctionName, lpOldAddress, lpNewAddress);
+ if (action == ACTION_HOOK && bPatched && !module.bInternal && pSharedMem) {
+ pSharedMem->bReplaced = TRUE;
+ }
+ }
+ }
+}
static void
-hookModule(HMODULE hModule,
- const char *szModule)
+patchModule(HMODULE hModule,
+ const char *szModule,
+ Action action)
{
+ /* Never patch this module */
if (hModule == g_hThisModule) {
return;
}
- for (unsigned i = 0; i < numReplacements; ++i) {
- if (hModule == replacements[i].hReplaceModule) {
+ /* Never patch our hook module */
+ if (hModule == g_hHookModule) {
+ return;
+ }
+
+ /* Hook modules only once */
+ if (action == ACTION_HOOK) {
+ std::pair< std::set<HMODULE>::iterator, bool > ret;
+ EnterCriticalSection(&g_Mutex);
+ ret = g_hHookedModules.insert(hModule);
+ LeaveCriticalSection(&g_Mutex);
+ if (!ret.second) {
return;
}
}
- hookFunction(hModule, szModule, "kernel32.dll", "LoadLibraryA", (LPVOID)MyLoadLibraryA);
- hookFunction(hModule, szModule, "kernel32.dll", "LoadLibraryW", (LPVOID)MyLoadLibraryW);
- hookFunction(hModule, szModule, "kernel32.dll", "LoadLibraryExA", (LPVOID)MyLoadLibraryExA);
- hookFunction(hModule, szModule, "kernel32.dll", "LoadLibraryExW", (LPVOID)MyLoadLibraryExW);
- hookFunction(hModule, szModule, "kernel32.dll", "GetProcAddress", (LPVOID)MyGetProcAddress);
-
const char *szBaseName = getBaseName(szModule);
- for (unsigned i = 0; i < numReplacements; ++i) {
- if (stricmp(szBaseName, replacements[i].szMatchModule) == 0) {
- return;
- }
+
+ /* Don't hook our replacement modules to avoid tracing internal APIs */
+ /* XXX: is this really a good idea? */
+ if (isMatchModuleName(szBaseName)) {
+ return;
}
- /* Don't hook internal dependencies */
- if (stricmp(szBaseName, "d3d10core.dll") == 0 ||
- stricmp(szBaseName, "d3d10level9.dll") == 0 ||
- stricmp(szBaseName, "d3d10sdklayers.dll") == 0 ||
- stricmp(szBaseName, "d3d10_1core.dll") == 0 ||
- stricmp(szBaseName, "d3d11sdklayers.dll") == 0 ||
- stricmp(szBaseName, "d3d11_1sdklayers.dll") == 0) {
+ /* Leave these modules alone.
+ *
+ * Hooking other injection DLLs easily leads to infinite recursion (and
+ * stack overflow), especially when those libraries use techniques like
+ * modifying the hooked functions prolog (instead of patching IAT like we
+ * do).
+ *
+ * See also:
+ * - http://www.nynaeve.net/?p=62
+ */
+ if (stricmp(szBaseName, "kernel32.dll") == 0 ||
+ stricmp(szBaseName, "AcLayers.dll") == 0 ||
+ stricmp(szBaseName, "ConEmuHk.dll") == 0 ||
+ stricmp(szBaseName, "gameoverlayrenderer.dll") == 0 ||
+ stricmp(szBaseName, "gameoverlayrenderer64.dll") == 0) {
return;
}
- for (unsigned i = 0; i < numReplacements; ++i) {
- replaceImport(hModule, szModule, replacements[i].szMatchModule, replacements[i].hReplaceModule);
- replaceImport(hModule, szModule, replacements[i].szMatchModule, replacements[i].hReplaceModule);
- replaceImport(hModule, szModule, replacements[i].szMatchModule, replacements[i].hReplaceModule);
+ if (VERBOSITY > 0) {
+ debugPrintf("inject: found module %s\n", szModule);
+ }
+
+ PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = getFirstImportDescriptor(hModule, szModule);
+ if (pImportDescriptor) {
+ while (pImportDescriptor->FirstThunk) {
+
+ patchDescriptor(hModule, szModule, pImportDescriptor, action);
+
+ ++pImportDescriptor;
+ }
+ }
+
+ PImgDelayDescr pDelayDescriptor = getDelayImportDescriptor(hModule, szModule);
+ if (pDelayDescriptor) {
+ while (pDelayDescriptor->rvaDLLName) {
+ if (VERBOSITY > 1) {
+ const char* szName = getDescriptorName(hModule, pDelayDescriptor);
+ debugPrintf("inject: found %sdelay-load import entry for module %s\n",
+ pDelayDescriptor->grAttrs & dlattrRva ? "" : "old-style ",
+ szName);
+ }
+
+ patchDescriptor(hModule, szModule, pDelayDescriptor, action);
+
+ ++pDelayDescriptor;
+ }
}
}
+
static void
-hookAllModules(void)
+patchAllModules(Action action)
{
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
if (hModuleSnap == INVALID_HANDLE_VALUE) {
@@ -337,23 +718,9 @@ hookAllModules(void)
MODULEENTRY32 me32;
me32.dwSize = sizeof me32;
-
- if (VERBOSITY > 0) {
- static bool first = true;
- if (first) {
- if (Module32First(hModuleSnap, &me32)) {
- debugPrintf(" modules:\n");
- do {
- debugPrintf(" %s\n", me32.szExePath);
- } while (Module32Next(hModuleSnap, &me32));
- }
- first = false;
- }
- }
-
if (Module32First(hModuleSnap, &me32)) {
do {
- hookModule(me32.hModule, me32.szExePath);
+ patchModule(me32.hModule, me32.szExePath, action);
} while (Module32Next(hModuleSnap, &me32));
}
@@ -361,133 +728,214 @@ hookAllModules(void)
}
-
-
-static HMODULE WINAPI
-MyLoadLibrary(LPCSTR lpLibFileName, HANDLE hFile = NULL, DWORD dwFlags = 0)
-{
- // To Send the information to the server informing that,
- // LoadLibrary is invoked.
- HMODULE hModule = LoadLibraryExA(lpLibFileName, hFile, dwFlags);
-
- //hookModule(hModule, lpLibFileName);
- hookAllModules();
-
- return hModule;
-}
-
static HMODULE WINAPI
MyLoadLibraryA(LPCSTR lpLibFileName)
{
+ HMODULE hModule = LoadLibraryA(lpLibFileName);
+ DWORD dwLastError = GetLastError();
+
if (VERBOSITY >= 2) {
- debugPrintf("%s(\"%s\")\n", __FUNCTION__, lpLibFileName);
+ debugPrintf("inject: intercepting %s(\"%s\") = 0x%p\n",
+ __FUNCTION__ + 2, lpLibFileName, hModule);
}
if (VERBOSITY > 0) {
const char *szBaseName = getBaseName(lpLibFileName);
- for (unsigned i = 0; i < numReplacements; ++i) {
- if (stricmp(szBaseName, replacements[i].szMatchModule) == 0) {
- debugPrintf("%s(\"%s\")\n", __FUNCTION__, lpLibFileName);
+ if (isMatchModuleName(szBaseName)) {
+ if (VERBOSITY < 2) {
+ debugPrintf("inject: intercepting %s(\"%s\")\n", __FUNCTION__, lpLibFileName);
+ }
#ifdef __GNUC__
- void *caller = __builtin_return_address (0);
-
- HMODULE hModule = 0;
- BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
- (LPCTSTR)caller,
- &hModule);
- assert(bRet);
- char szCaller[256];
- DWORD dwRet = GetModuleFileNameA(hModule, szCaller, sizeof szCaller);
- assert(dwRet);
- debugPrintf(" called from %s\n", szCaller);
+ void *caller = __builtin_return_address (0);
+
+ HMODULE hModule = 0;
+ BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (LPCTSTR)caller,
+ &hModule);
+ assert(bRet);
+ char szCaller[MAX_PATH];
+ DWORD dwRet = GetModuleFileNameA(hModule, szCaller, sizeof szCaller);
+ assert(dwRet);
+ debugPrintf("inject: called from %s\n", szCaller);
#endif
- break;
- }
}
}
- return MyLoadLibrary(lpLibFileName);
+ // Hook all new modules (and not just this one, to pick up any dependencies)
+ patchAllModules(ACTION_HOOK);
+
+ SetLastError(dwLastError);
+ return hModule;
}
static HMODULE WINAPI
MyLoadLibraryW(LPCWSTR lpLibFileName)
{
+ HMODULE hModule = LoadLibraryW(lpLibFileName);
+ DWORD dwLastError = GetLastError();
+
if (VERBOSITY >= 2) {
- debugPrintf("%s(L\"%S\")\n", __FUNCTION__, lpLibFileName);
+ debugPrintf("inject: intercepting %s(L\"%S\") = 0x%p\n",
+ __FUNCTION__ + 2, lpLibFileName, hModule);
}
- char szFileName[256];
- wcstombs(szFileName, lpLibFileName, sizeof szFileName);
+ // Hook all new modules (and not just this one, to pick up any dependencies)
+ patchAllModules(ACTION_HOOK);
+
+ SetLastError(dwLastError);
+ return hModule;
+}
+
+#ifndef LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
+#define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100
+#endif
+#ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR
+#define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x00000200
+#endif
+#ifndef LOAD_LIBRARY_SEARCH_USER_DIRS
+#define LOAD_LIBRARY_SEARCH_USER_DIRS 0x00000400
+#endif
+#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
+#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
+#endif
+#ifndef LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
+#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000
+#endif
+
+static inline DWORD
+adjustFlags(DWORD dwFlags)
+{
+ /*
+ * XXX: LoadLibraryEx seems to interpret "application directory" in respect
+ * to the module that's calling it. So when the application restricts the
+ * search path to application directory via
+ * LOAD_LIBRARY_SEARCH_APPLICATION_DIR or LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
+ * flags, kernel32.dll ends up searching on the directory of the inject.dll
+ * module.
+ *
+ * XXX: What about SetDefaultDllDirectories?
+ *
+ */
+ if (dwFlags & (LOAD_LIBRARY_SEARCH_APPLICATION_DIR |
+ LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) {
+ dwFlags &= ~(LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
+ LOAD_LIBRARY_SEARCH_APPLICATION_DIR |
+ LOAD_LIBRARY_SEARCH_USER_DIRS |
+ LOAD_LIBRARY_SEARCH_SYSTEM32 |
+ LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
+ }
- return MyLoadLibrary(szFileName);
+ return dwFlags;
}
static HMODULE WINAPI
MyLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
+ HMODULE hModule = LoadLibraryExA(lpLibFileName, hFile, adjustFlags(dwFlags));
+ DWORD dwLastError = GetLastError();
+
if (VERBOSITY >= 2) {
- debugPrintf("%s(\"%s\")\n", __FUNCTION__, lpLibFileName);
+ debugPrintf("inject: intercepting %s(\"%s\", 0x%p, 0x%lx) = 0x%p\n",
+ __FUNCTION__ + 2, lpLibFileName, hFile, dwFlags, hModule);
}
- return MyLoadLibrary(lpLibFileName, hFile, dwFlags);
+
+ // Hook all new modules (and not just this one, to pick up any dependencies)
+ patchAllModules(ACTION_HOOK);
+
+ SetLastError(dwLastError);
+ return hModule;
}
static HMODULE WINAPI
MyLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
+ HMODULE hModule = LoadLibraryExW(lpLibFileName, hFile, adjustFlags(dwFlags));
+ DWORD dwLastError = GetLastError();
+
if (VERBOSITY >= 2) {
- debugPrintf("%s(L\"%S\")\n", __FUNCTION__, lpLibFileName);
+ debugPrintf("inject: intercepting %s(L\"%S\", 0x%p, 0x%lx) = 0x%p\n",
+ __FUNCTION__ + 2, lpLibFileName, hFile, dwFlags, hModule);
}
- char szFileName[256];
- wcstombs(szFileName, lpLibFileName, sizeof szFileName);
+ // Hook all new modules (and not just this one, to pick up any dependencies)
+ patchAllModules(ACTION_HOOK);
- return MyLoadLibrary(szFileName, hFile, dwFlags);
+ SetLastError(dwLastError);
+ return hModule;
+}
+
+
+static void
+logGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
+ if (HIWORD(lpProcName) == 0) {
+ debugPrintf("inject: intercepting %s(%u)\n", "GetProcAddress", LOWORD(lpProcName));
+ } else {
+ debugPrintf("inject: intercepting %s(\"%s\")\n", "GetProcAddress", lpProcName);
+ }
}
static FARPROC WINAPI
MyGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
- if (VERBOSITY >= 99) {
+ if (VERBOSITY >= 3) {
/* XXX this can cause segmentation faults */
- debugPrintf("%s(\"%s\")\n", __FUNCTION__, lpProcName);
- }
-
- assert(hModule != g_hThisModule);
- for (unsigned i = 0; i < numReplacements; ++i) {
- if (hModule == replacements[i].hReplaceModule) {
- if (pSharedMem) {
- pSharedMem->bReplaced = TRUE;
- }
- return GetProcAddress(hModule, lpProcName);
- }
+ logGetProcAddress(hModule, lpProcName);
}
if (!NOOP) {
- char szModule[256];
+ char szModule[MAX_PATH];
DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);
assert(dwRet);
const char *szBaseName = getBaseName(szModule);
- for (unsigned i = 0; i < numReplacements; ++i) {
+ ModulesMap::const_iterator modIt;
+ modIt = modulesMap.find(szBaseName);
+ if (modIt != modulesMap.end()) {
+ if (VERBOSITY > 1 && VERBOSITY < 3) {
+ logGetProcAddress(hModule, lpProcName);
+ }
- if (stricmp(szBaseName, replacements[i].szMatchModule) == 0) {
- if (VERBOSITY > 0) {
- debugPrintf(" %s(\"%s\", \"%s\")\n", __FUNCTION__, szModule, lpProcName);
+ const Module & module = modIt->second;
+ const FunctionMap & functionMap = module.functionMap;
+ FunctionMap::const_iterator fnIt;
+
+ if (HIWORD(lpProcName) == 0) {
+ FARPROC proc = GetProcAddress(hModule, lpProcName);
+ if (!proc) {
+ return proc;
}
- FARPROC pProcAddress = GetProcAddress(replacements[i].hReplaceModule, lpProcName);
- if (pProcAddress) {
- if (VERBOSITY >= 2) {
- debugPrintf(" replacing %s!%s\n", szBaseName, lpProcName);
- }
- if (pSharedMem) {
- pSharedMem->bReplaced = TRUE;
- }
- return pProcAddress;
- } else {
- if (VERBOSITY > 0) {
- debugPrintf(" ignoring %s!%s\n", szBaseName, lpProcName);
+
+ for (fnIt = functionMap.begin(); fnIt != functionMap.end(); ++fnIt) {
+ FARPROC pRealProc = GetProcAddress(hModule, fnIt->first);
+ if (proc == pRealProc) {
+ if (VERBOSITY > 0) {
+ debugPrintf("inject: replacing %s!%s\n", szBaseName, lpProcName);
+ }
+ return (FARPROC)fnIt->second;
}
- break;
+
+ }
+
+ debugPrintf("inject: ignoring %s!@%u\n", szBaseName, LOWORD(lpProcName));
+
+ return proc;
+ }
+
+ fnIt = functionMap.find(lpProcName);
+
+ if (fnIt != functionMap.end()) {
+ LPVOID pProcAddress = fnIt->second;
+ if (VERBOSITY > 0) {
+ debugPrintf("inject: replacing %s!%s\n", szBaseName, lpProcName);
+ }
+ if (!module.bInternal && pSharedMem) {
+ pSharedMem->bReplaced = TRUE;
+ }
+ return (FARPROC)pProcAddress;
+ } else {
+ if (VERBOSITY > 0 && !module.bInternal) {
+ debugPrintf("inject: ignoring %s!%s\n", szBaseName, lpProcName);
}
}
}
@@ -497,29 +945,106 @@ MyGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
}
+static BOOL WINAPI
+MyFreeLibrary(HMODULE hModule)
+{
+ if (VERBOSITY >= 2) {
+ debugPrintf("inject: intercepting %s(0x%p)\n", __FUNCTION__, hModule);
+ }
+
+ BOOL bRet = FreeLibrary(hModule);
+ DWORD dwLastError = GetLastError();
+
+ EnterCriticalSection(&g_Mutex);
+ // TODO: Only clear the modules that have been freed
+ g_hHookedModules.clear();
+ LeaveCriticalSection(&g_Mutex);
+
+ SetLastError(dwLastError);
+ return bRet;
+}
+
+
+static void
+registerLibraryLoaderHooks(const char *szMatchModule)
+{
+ Module & module = modulesMap[szMatchModule];
+ module.bInternal = true;
+ FunctionMap & functionMap = module.functionMap;
+ functionMap["LoadLibraryA"] = (LPVOID)MyLoadLibraryA;
+ functionMap["LoadLibraryW"] = (LPVOID)MyLoadLibraryW;
+ functionMap["LoadLibraryExA"] = (LPVOID)MyLoadLibraryExA;
+ functionMap["LoadLibraryExW"] = (LPVOID)MyLoadLibraryExW;
+ functionMap["GetProcAddress"] = (LPVOID)MyGetProcAddress;
+ functionMap["FreeLibrary"] = (LPVOID)MyFreeLibrary;
+}
+
+static void
+registerProcessThreadsHooks(const char *szMatchModule)
+{
+ Module & module = modulesMap[szMatchModule];
+ module.bInternal = true;
+ FunctionMap & functionMap = module.functionMap;
+ functionMap["CreateProcessA"] = (LPVOID)MyCreateProcessA;
+ functionMap["CreateProcessW"] = (LPVOID)MyCreateProcessW;
+ // NOTE: CreateProcessAsUserA is implemented by advapi32.dll
+ functionMap["CreateProcessAsUserW"] = (LPVOID)MyCreateProcessAsUserW;
+ // TODO: CreateProcessWithTokenW
+}
+
+static void
+registerModuleHooks(const char *szMatchModule, HMODULE hReplaceModule)
+{
+ Module & module = modulesMap[szMatchModule];
+ module.bInternal = false;
+ FunctionMap & functionMap = module.functionMap;
+
+ PIMAGE_EXPORT_DIRECTORY pExportDescriptor = getExportDescriptor(hReplaceModule);
+ assert(pExportDescriptor);
+
+ DWORD *pAddressOfNames = (DWORD *)((BYTE *)hReplaceModule + pExportDescriptor->AddressOfNames);
+ for (DWORD i = 0; i < pExportDescriptor->NumberOfNames; ++i) {
+ const char *szFunctionName = (const char *)((BYTE *)hReplaceModule + pAddressOfNames[i]);
+ LPVOID lpNewAddress = (LPVOID)GetProcAddress(hReplaceModule, szFunctionName);
+ assert(lpNewAddress);
+
+ functionMap[szFunctionName] = lpNewAddress;
+ }
+}
+
+static void
+dumpRegisteredHooks(void)
+{
+ if (VERBOSITY > 1) {
+ ModulesMap::const_iterator modIt;
+ for (modIt = modulesMap.begin(); modIt != modulesMap.end(); ++modIt) {
+ const char *szMatchModule = modIt->first;
+ const Module & module = modIt->second;
+ const FunctionMap & functionMap = module.functionMap;
+ FunctionMap::const_iterator fnIt;
+ for (fnIt = functionMap.begin(); fnIt != functionMap.end(); ++fnIt) {
+ const char *szFunctionName = fnIt->first;
+ debugPrintf("inject: registered hook for %s!%s%s\n",
+ szMatchModule, szFunctionName,
+ module.bInternal ? " (internal)" : "");
+ }
+ }
+ }
+}
+
+
EXTERN_C BOOL WINAPI
-DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
+DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
const char *szNewDllName = NULL;
- HMODULE hNewModule = NULL;
const char *szNewDllBaseName;
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
- if (VERBOSITY > 0) {
- debugPrintf("DLL_PROCESS_ATTACH\n");
- }
+ InitializeCriticalSection(&g_Mutex);
g_hThisModule = hinstDLL;
- {
- char szProcess[MAX_PATH];
- GetModuleFileNameA(NULL, szProcess, sizeof szProcess);
- if (VERBOSITY > 0) {
- debugPrintf(" attached to %s\n", szProcess);
- }
- }
-
/*
* Calling LoadLibrary inside DllMain is strongly discouraged. But it
* works quite well, provided that the loaded DLL does not require or do
@@ -530,51 +1055,94 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
* - http://msdn.microsoft.com/en-us/library/ms682583
*/
-#if !USE_SHARED_MEM
- szNewDllName = getenv("INJECT_DLL");
- if (!szNewDllName) {
- debugPrintf("warning: INJECT_DLL not set\n");
- return FALSE;
+ if (!USE_SHARED_MEM) {
+ szNewDllName = getenv("INJECT_DLL");
+ if (!szNewDllName) {
+ debugPrintf("inject: warning: INJECT_DLL not set\n");
+ return FALSE;
+ }
+ } else {
+ SharedMem *pSharedMem = OpenSharedMemory(NULL);
+ if (!pSharedMem) {
+ debugPrintf("inject: error: failed to open shared memory\n");
+ return FALSE;
+ }
+
+ VERBOSITY = pSharedMem->cVerbosity;
+
+ static char szSharedMemCopy[MAX_PATH];
+ strncpy(szSharedMemCopy, pSharedMem->szDllName, _countof(szSharedMemCopy) - 1);
+ szSharedMemCopy[_countof(szSharedMemCopy) - 1] = '\0';
+
+ szNewDllName = szSharedMemCopy;
}
-#else
- static char szSharedMemCopy[MAX_PATH];
- GetSharedMem(szSharedMemCopy, sizeof szSharedMemCopy);
- szNewDllName = szSharedMemCopy;
-#endif
+
if (VERBOSITY > 0) {
- debugPrintf(" injecting %s\n", szNewDllName);
+ debugPrintf("inject: DLL_PROCESS_ATTACH\n");
}
- hNewModule = LoadLibraryA(szNewDllName);
- if (!hNewModule) {
- debugPrintf("warning: failed to load %s\n", szNewDllName);
+ if (VERBOSITY > 0) {
+ char szProcess[MAX_PATH];
+ GetModuleFileNameA(NULL, szProcess, sizeof szProcess);
+ debugPrintf("inject: attached to process %s\n", szProcess);
+ }
+
+ if (VERBOSITY > 0) {
+ debugPrintf("inject: loading %s\n", szNewDllName);
+ }
+
+ g_hHookModule = LoadLibraryA(szNewDllName);
+ if (!g_hHookModule) {
+ debugPrintf("inject: warning: failed to load %s\n", szNewDllName);
return FALSE;
}
- szNewDllBaseName = getBaseName(szNewDllName);
- if (stricmp(szNewDllBaseName, "dxgitrace.dll") == 0) {
- replacements[numReplacements].szMatchModule = "dxgi.dll";
- replacements[numReplacements].hReplaceModule = hNewModule;
- ++numReplacements;
+ // Ensure we use kernel32.dll's CreateProcessAsUserW, and not advapi32.dll's.
+ {
+ HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
+ assert(hKernel32);
+ pfnCreateProcessAsUserW = (PFNCREATEPROCESSASUSERW)GetProcAddress(hKernel32, "CreateProcessAsUserW");
+ }
- replacements[numReplacements].szMatchModule = "d3d10.dll";
- replacements[numReplacements].hReplaceModule = hNewModule;
- ++numReplacements;
+ /*
+ * Hook kernel32.dll functions, and its respective Windows API Set.
+ *
+ * http://msdn.microsoft.com/en-us/library/dn505783.aspx (Windows 8.1)
+ * http://msdn.microsoft.com/en-us/library/hh802935.aspx (Windows 8)
+ */
- replacements[numReplacements].szMatchModule = "d3d10_1.dll";
- replacements[numReplacements].hReplaceModule = hNewModule;
- ++numReplacements;
+ registerLibraryLoaderHooks("kernel32.dll");
+ registerLibraryLoaderHooks("api-ms-win-core-libraryloader-l1-1-0.dll");
+ registerLibraryLoaderHooks("api-ms-win-core-libraryloader-l1-1-1.dll");
+ registerLibraryLoaderHooks("api-ms-win-core-libraryloader-l1-2-0.dll");
+ registerLibraryLoaderHooks("api-ms-win-core-kernel32-legacy-l1-1-0.dll");
+ registerLibraryLoaderHooks("api-ms-win-core-kernel32-legacy-l1-1-1.dll");
- replacements[numReplacements].szMatchModule = "d3d11.dll";
- replacements[numReplacements].hReplaceModule = hNewModule;
- ++numReplacements;
+ registerProcessThreadsHooks("kernel32.dll");
+ registerProcessThreadsHooks("api-ms-win-core-processthreads-l1-1-0.dll");
+ registerProcessThreadsHooks("api-ms-win-core-processthreads-l1-1-1.dll");
+ registerProcessThreadsHooks("api-ms-win-core-processthreads-l1-1-2.dll");
+
+ szNewDllBaseName = getBaseName(szNewDllName);
+ if (stricmp(szNewDllBaseName, "dxgitrace.dll") == 0) {
+ registerModuleHooks("dxgi.dll", g_hHookModule);
+ registerModuleHooks("d3d10.dll", g_hHookModule);
+ registerModuleHooks("d3d10_1.dll", g_hHookModule);
+ registerModuleHooks("d3d11.dll", g_hHookModule);
+ registerModuleHooks("d3d9.dll", g_hHookModule); // for D3DPERF_*
+ } else if (stricmp(szNewDllBaseName, "d3d9.dll") == 0) {
+ registerModuleHooks("d3d9.dll", g_hHookModule);
+ registerModuleHooks("dxva2.dll", g_hHookModule);
+ } else if (stricmp(szNewDllBaseName, "d2d1trace.dll") == 0) {
+ registerModuleHooks("d2d1.dll", g_hHookModule);
+ registerModuleHooks("dwrite.dll", g_hHookModule);
} else {
- replacements[numReplacements].szMatchModule = szNewDllBaseName;
- replacements[numReplacements].hReplaceModule = hNewModule;
- ++numReplacements;
+ registerModuleHooks(szNewDllBaseName, g_hHookModule);
}
- hookAllModules();
+ dumpRegisteredHooks();
+
+ patchAllModules(ACTION_HOOK);
break;
case DLL_THREAD_ATTACH:
@@ -585,9 +1153,52 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
case DLL_PROCESS_DETACH:
if (VERBOSITY > 0) {
- debugPrintf("DLL_PROCESS_DETACH\n");
+ debugPrintf("inject: DLL_PROCESS_DETACH\n");
+ }
+
+ assert(!lpvReserved);
+
+ patchAllModules(ACTION_UNHOOK);
+
+ if (g_hHookModule) {
+ FreeLibrary(g_hHookModule);
}
break;
}
return TRUE;
}
+
+
+/*
+ * Prevent the C/C++ runtime from destroying things when the program
+ * terminates.
+ *
+ * There is no effective way to control the order DLLs receive
+ * DLL_PROCESS_DETACH -- patched DLLs might get detacched after we are --, and
+ * unpatching our hooks doesn't always work. So instead just do nothing (and
+ * prevent C/C++ runtime from doing anything too), so our hooks can still work
+ * after we are dettached.
+ */
+
+#ifdef _MSC_VER
+# define DLLMAIN_CRT_STARTUP _DllMainCRTStartup
+#else
+# define DLLMAIN_CRT_STARTUP DllMainCRTStartup
+# pragma GCC optimize ("no-stack-protector")
+#endif
+
+EXTERN_C BOOL WINAPI
+DLLMAIN_CRT_STARTUP(HANDLE hDllHandle, DWORD dwReason, LPVOID lpvReserved);
+
+EXTERN_C BOOL WINAPI
+DllMainStartup(HANDLE hDllHandle, DWORD dwReason, LPVOID lpvReserved)
+{
+ if (dwReason == DLL_PROCESS_DETACH && lpvReserved) {
+ if (VERBOSITY > 0) {
+ debugPrintf("inject: DLL_PROCESS_DETACH\n");
+ }
+ return TRUE;
+ }
+
+ return DLLMAIN_CRT_STARTUP(hDllHandle, dwReason, lpvReserved);
+}
diff --git a/inject/injector.cpp b/inject/injector.cpp
index e7557582..4034c413 100644
--- a/inject/injector.cpp
+++ b/inject/injector.cpp
@@ -41,13 +41,40 @@
*/
#include <string>
+#include <stdio.h>
+#include <assert.h>
#include <windows.h>
-#include <stdio.h>
+#include <psapi.h>
+#include <dwmapi.h>
+#include <tlhelp32.h>
+
+#include <getopt.h>
+
+#ifndef ERROR_ELEVATION_REQUIRED
+#define ERROR_ELEVATION_REQUIRED 740
+#endif
+#include "os_version.hpp"
+#include "devcon.hpp"
#include "inject.h"
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
+#endif
+
+
+static void
+debugPrintf(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+}
+
+
/**
* Determine whether an argument should be quoted.
*/
@@ -106,40 +133,472 @@ quoteArg(std::string &s, const char *arg)
}
+// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms686335.aspx
+static void
+restartService(const char *lpServiceName)
+{
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ assert(hSCManager);
+ if (!hSCManager) {
+ return;
+ }
+
+ SC_HANDLE hService = OpenServiceA(hSCManager, lpServiceName, SC_MANAGER_ALL_ACCESS);
+ assert(hService);
+ if (!hService) {
+ return;
+ }
+
+ SERVICE_STATUS_PROCESS ssp;
+ DWORD cbBytesNeeded;
+ QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE) &ssp, sizeof ssp, &cbBytesNeeded);
+
+ BOOL bRet;
+ if (ssp.dwCurrentState == SERVICE_RUNNING) {
+ bRet = ControlService(hService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS) &ssp);
+ assert(bRet);
+ while (ssp.dwCurrentState != SERVICE_STOPPED) {
+ Sleep(ssp.dwWaitHint);
+ QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE) &ssp, sizeof ssp, &cbBytesNeeded);
+ }
+ bRet = StartService(hService, 0, NULL);
+ assert(bRet);
+ }
+
+ CloseServiceHandle(hService);
+ CloseServiceHandle(hSCManager);
+}
+
+
+// Force DWM process to recreate all its Direct3D objects.
+static void
+restartDwmComposition(HANDLE hProcess)
+{
+ HRESULT hr;
+
+ HMODULE hModule = LoadLibraryA("dwmapi");
+ assert(hModule);
+ if (!hModule) {
+ return;
+ }
+
+ typedef HRESULT (WINAPI *PFNDWMISCOMPOSITIONENABLED)(BOOL *pfEnabled);
+ PFNDWMISCOMPOSITIONENABLED pfnDwmIsCompositionEnabled = (PFNDWMISCOMPOSITIONENABLED)GetProcAddress(hModule, "DwmIsCompositionEnabled");
+ assert(pfnDwmIsCompositionEnabled);
+ if (!pfnDwmIsCompositionEnabled) {
+ return;
+ }
+
+ typedef HRESULT (WINAPI *PFNDWMENABLECOMPOSITION)(UINT uCompositionAction);
+ PFNDWMENABLECOMPOSITION pfnDwmEnableComposition = (PFNDWMENABLECOMPOSITION)GetProcAddress(hModule, "DwmEnableComposition");
+ assert(pfnDwmEnableComposition);
+ if (!pfnDwmEnableComposition) {
+ return;
+ }
+
+
+ BOOL bIsWindows8OrGreater = IsWindows8OrGreater();
+ if (bIsWindows8OrGreater) {
+ // Windows 8 ignores DwmEnableComposition(DWM_EC_DISABLECOMPOSITION).
+ // It is however possible to force DWM to restart by restarting the
+ // display device via the devcon utility
+ devconEnable(DEVCON_CLASS_DISPLAY);
+ } else {
+
+ BOOL fEnabled = FALSE;
+ hr = pfnDwmIsCompositionEnabled(&fEnabled);
+ if (FAILED(hr) || !fEnabled) {
+ return;
+ }
+
+ fprintf(stderr, "info: restarting DWM composition\n");
+
+ hr = pfnDwmEnableComposition(DWM_EC_DISABLECOMPOSITION);
+ assert(SUCCEEDED(hr));
+ if (FAILED(hr)) {
+ return;
+ }
+
+ Sleep(1000/30);
+
+ hr = pfnDwmEnableComposition(DWM_EC_ENABLECOMPOSITION);
+ assert(SUCCEEDED(hr));
+ (void)hr;
+ }
+
+ fprintf(stderr, "Press any key when finished tracing\n");
+ getchar();
+
+ DWORD dwExitCode;
+ if (GetExitCodeProcess(hProcess, &dwExitCode) &&
+ dwExitCode != STILL_ACTIVE) {
+ // DWM process has already terminated
+ return;
+ }
+
+ fprintf(stderr, "info: restarting DWM process\n");
+ if (bIsWindows8OrGreater) {
+ // From Windows 8 onwards DWM no longer runs as a service. We just
+ // kill it and winlogon parent process will respawn it.
+ if (!TerminateProcess(hProcess, 0)) {
+ logLastError("failed to terminate DWM process");
+ }
+ } else {
+ hr = pfnDwmEnableComposition(DWM_EC_DISABLECOMPOSITION);
+ assert(SUCCEEDED(hr));
+
+ restartService("uxsms");
+ }
+}
+
+
+static BOOL
+attachDebugger(DWORD dwProcessId)
+{
+ long lRet;
+
+ HKEY hKey;
+ lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", 0, KEY_READ, &hKey);
+ if (lRet != ERROR_SUCCESS) {
+ debugPrintf("inject: error: RegOpenKeyExA failed\n");
+ return FALSE;
+ }
+
+ char szDebugger[1024];
+ DWORD cbDebugger = sizeof szDebugger;
+ lRet = RegQueryValueExA(hKey, "Debugger", NULL, NULL, (BYTE *)szDebugger, &cbDebugger);
+
+ RegCloseKey(hKey);
+
+ if (lRet != ERROR_SUCCESS) {
+ if (lRet == ERROR_FILE_NOT_FOUND) {
+ debugPrintf("inject: error: no automatic debugger configured\n");
+ } else {
+ debugPrintf("inject: error: RegQueryValueExA failed (0x%08lx)\n", lRet);
+ }
+ return FALSE;
+ }
+
+ SECURITY_ATTRIBUTES sa = { sizeof sa, 0, TRUE };
+ HANDLE hEvent = CreateEvent(&sa, FALSE, FALSE, NULL);
+
+ char szDebuggerCommand[1024];
+ _snprintf(szDebuggerCommand, sizeof szDebuggerCommand, szDebugger,
+ dwProcessId, (DWORD)(UINT_PTR)hEvent, NULL);
+
+ debugPrintf("%s\n", szDebuggerCommand);
+
+ PROCESS_INFORMATION pi;
+ ZeroMemory(&pi, sizeof pi);
+ STARTUPINFOA si;
+ ZeroMemory(&si, sizeof si);
+ si.cb = sizeof &si;
+
+ BOOL bRet = FALSE;
+ if (!CreateProcessA(
+ NULL,
+ szDebuggerCommand,
+ NULL, // process attributes
+ NULL, // thread attributes
+ TRUE, // inherit (event) handles
+ 0,
+ NULL, // environment
+ NULL, // current directory
+ &si,
+ &pi)) {
+ debugPrintf("inject: error: failed to execute \"%s\" with 0x%08lx\n",
+ szDebuggerCommand,
+ GetLastError());
+ } else {
+ HANDLE handles[] = {
+ hEvent,
+ pi.hProcess
+ };
+
+ DWORD dwRet = WaitForMultipleObjects(_countof(handles), handles, FALSE, INFINITE);
+ bRet = dwRet == WAIT_OBJECT_0;
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ }
+
+ CloseHandle(hEvent);
+
+ return bRet;
+}
+
+
+static DWORD
+getProcessIdByName(const char *szProcessName)
+{
+ DWORD dwProcessId = 0;
+
+ HANDLE hProcessSnap;
+ hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (hProcessSnap != INVALID_HANDLE_VALUE) {
+ PROCESSENTRY32 pe32;
+ pe32.dwSize = sizeof pe32;
+ if (Process32First(hProcessSnap, &pe32)) {
+ do {
+ if (stricmp(szProcessName, pe32.szExeFile) == 0) {
+ dwProcessId = pe32.th32ProcessID;
+ break;
+ }
+ } while (Process32Next(hProcessSnap, &pe32));
+ }
+ CloseHandle(hProcessSnap);
+ }
+
+ return dwProcessId;
+}
+
+
+static bool
+isNumber(const char *arg) {
+ while (*arg) {
+ if (!isdigit(*arg++)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+static BOOL
+ejectDll(HANDLE hProcess, const char *szDllPath)
+{
+ /*
+ * Enumerate all modules.
+ */
+
+ HMODULE *phModules = NULL;
+ DWORD cb = sizeof *phModules *
+#ifdef NDEBUG
+ 32
+#else
+ 4
+#endif
+ ;
+ DWORD cbNeeded = 0;
+ while (true) {
+ phModules = (HMODULE *)realloc(phModules, cb);
+ if (!EnumProcessModules(hProcess, phModules, cb, &cbNeeded)) {
+ logLastError("failed to enumerate modules in remote process");
+ free(phModules);
+ return FALSE;
+ }
+
+ if (cbNeeded < cb) {
+ break;
+ }
+
+ cb *= 2;
+ }
+
+ DWORD cNumModules = cbNeeded / sizeof *phModules;
+
+ /*
+ * Search our DLL.
+ */
+
+ const char *szDllName = getBaseName(szDllPath);
+ HMODULE hModule = NULL;
+ for (unsigned i = 0; i < cNumModules; ++i) {
+ char szModName[MAX_PATH];
+ if (GetModuleFileNameExA(hProcess, phModules[i], szModName, ARRAY_SIZE(szModName))) {
+ if (stricmp(getBaseName(szModName), szDllName) == 0) {
+ hModule = phModules[i];
+ break;
+ }
+ }
+ }
+
+ free(phModules);
+
+ if (!hModule) {
+ debugPrintf("inject: error: failed to find %s module in the remote process\n", szDllName);
+ return FALSE;
+ }
+
+ PTHREAD_START_ROUTINE lpStartAddress =
+ (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("KERNEL32"), "FreeLibrary");
+
+ HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, hModule, 0, NULL);
+ if (!hThread) {
+ logLastError("failed to create remote thread");
+ return FALSE;
+ }
+
+ WaitForSingleObject(hThread, INFINITE);
+
+ DWORD bRet = 0;
+ GetExitCodeThread(hThread, &bRet);
+ if (!bRet) {
+ debugPrintf("inject: error: failed to unload %s from the remote process\n", szDllPath);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static void
+help(void)
+{
+ fprintf(stderr,
+ "usage:\n"
+ " inject -D <dllname.dll> <command> [args] ...\n"
+ " inject -D <dllname.dll> <process-id>\n"
+ " inject -D <dllname.dll> !<process-name>\n"
+ );
+}
+
+
+static const char *short_options =
+"hdD:p:t:v";
+
+static const struct
+option long_options[] = {
+ { "help", no_argument, NULL, 'h'},
+ { "debug", no_argument, NULL, 'd'},
+ { "dll", required_argument, NULL, 'D'},
+ { "pid", required_argument, NULL, 'p'},
+ { "tid", required_argument, NULL, 't'},
+ { "verbose", no_argument, 0, 'v'},
+ { NULL, 0, NULL, 0}
+};
+
+
int
main(int argc, char *argv[])
{
+ BOOL bDebug = FALSE;
+ BOOL bAttach = FALSE;
+ DWORD dwProcessId = 0;
+ DWORD dwThreadId = 0;
+ char cVerbosity = 0;
+
+ const char *szDll = NULL;
- if (argc < 3) {
- fprintf(stderr, "inject dllname.dll command [args] ...\n");
+ int option_index = 0;
+ while (true) {
+ int opt = getopt_long_only(argc, argv, short_options, long_options, &option_index);
+ if (opt == -1) {
+ break;
+ }
+ switch (opt) {
+ case 'h':
+ help();
+ return 0;
+ case 'd':
+ bDebug = TRUE;
+ break;
+ case 'D':
+ szDll = optarg;
+ break;
+ case 'p':
+ dwProcessId = strtoul(optarg, NULL, 0);
+ bAttach = TRUE;
+ break;
+ case 't':
+ dwThreadId = strtoul(optarg, NULL, 0);
+ bAttach = TRUE;
+ break;
+ case 'v':
+ ++cVerbosity;
+ break;
+ default:
+ debugPrintf("inject: invalid option '%c'\n", optopt);
+ help();
+ return 1;
+ }
+ }
+
+ if (!bAttach) {
+ if (argc - optind < 1) {
+ debugPrintf("inject: error: insufficient number of arguments\n");
+ help();
+ return 1;
+ }
+
+ if (isNumber(argv[optind])) {
+ dwProcessId = atol(argv[optind]);
+ bAttach = TRUE;
+ } else if (argv[optind][0] == '!') {
+ const char *szProcessName = &argv[optind][1];
+ dwProcessId = getProcessIdByName(szProcessName);
+ if (!dwProcessId) {
+ debugPrintf("error: failed to find process %s\n", szProcessName);
+ return 1;
+ }
+ bAttach = TRUE;
+ }
+ }
+
+ if (!szDll) {
+ debugPrintf("inject: error: DLL not specificed\n");
+ help();
return 1;
}
- const char *szDll = argv[1];
-#if !USE_SHARED_MEM
- SetEnvironmentVariableA("INJECT_DLL", szDll);
-#else
- SetSharedMem(szDll);
-#endif
+ HANDLE hSemaphore = NULL;
+ if (!USE_SHARED_MEM) {
+ SetEnvironmentVariableA("INJECT_DLL", szDll);
+ } else {
+ hSemaphore = CreateSemaphore(NULL, 1, 1, "inject_semaphore");
+ if (hSemaphore == NULL) {
+ debugPrintf("error: failed to create semaphore\n");
+ return 1;
+ }
+
+ DWORD dwWait = WaitForSingleObject(hSemaphore, 0);
+ if (dwWait == WAIT_TIMEOUT) {
+ debugPrintf("info: waiting for another inject instance to finish\n");
+ dwWait = WaitForSingleObject(hSemaphore, INFINITE);
+ }
+ if (dwWait != WAIT_OBJECT_0) {
+ debugPrintf("error: failed to enter semaphore gate\n");
+ return 1;
+ }
+
+ // Create a NULL DACL to enable the shared memory being accessed by any
+ // process we attach to.
+ SECURITY_DESCRIPTOR sd;
+ SECURITY_DESCRIPTOR *lpSD = NULL;
+ if (InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) &&
+ SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE))
+ {
+ lpSD = &sd;
+ }
+
+ SharedMem *pSharedMem = OpenSharedMemory(lpSD);
+ if (!pSharedMem) {
+ debugPrintf("error: failed to open shared memory\n");
+ return 1;
+ }
+
+ pSharedMem->cVerbosity = cVerbosity;
+ strncpy(pSharedMem->szDllName, szDll, _countof(pSharedMem->szDllName) - 1);
+ pSharedMem->szDllName[_countof(pSharedMem->szDllName) - 1] = '\0';
+ }
+
+ BOOL bAttachDwm = FALSE;
PROCESS_INFORMATION processInfo;
HANDLE hProcess;
- BOOL bAttach;
- if (isdigit(argv[2][0])) {
- bAttach = TRUE;
-
+ if (bAttach) {
BOOL bRet;
HANDLE hToken = NULL;
bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken);
if (!bRet) {
- fprintf(stderr, "error: OpenProcessToken returned %u\n", (unsigned)bRet);
+ debugPrintf("error: OpenProcessToken returned %u\n", (unsigned)bRet);
return 1;
}
LUID Luid;
bRet = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Luid);
if (!bRet) {
- fprintf(stderr, "error: LookupPrivilegeValue returned %u\n", (unsigned)bRet);
+ debugPrintf("error: LookupPrivilegeValue returned %u\n", (unsigned)bRet);
return 1;
}
@@ -149,7 +608,7 @@ main(int argc, char *argv[])
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof tp, NULL, NULL);
if (!bRet) {
- fprintf(stderr, "error: AdjustTokenPrivileges returned %u\n", (unsigned)bRet);
+ debugPrintf("error: AdjustTokenPrivileges returned %u\n", (unsigned)bRet);
return 1;
}
@@ -159,22 +618,28 @@ main(int argc, char *argv[])
PROCESS_QUERY_LIMITED_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
- PROCESS_VM_READ;
- DWORD dwProcessId = atol(argv[2]);
+ PROCESS_VM_READ |
+ PROCESS_TERMINATE;
hProcess = OpenProcess(
dwDesiredAccess,
FALSE /* bInheritHandle */,
dwProcessId);
if (!hProcess) {
- DWORD dwLastError = GetLastError();
- fprintf(stderr, "error: failed to open process %lu (%lu)\n", dwProcessId, dwLastError);
+ logLastError("failed to open process");
return 1;
}
+
+ char szProcess[MAX_PATH];
+ DWORD dwRet = GetModuleFileNameEx(hProcess, 0, szProcess, sizeof szProcess);
+ assert(dwRet);
+ if (dwRet &&
+ stricmp(getBaseName(szProcess), "dwm.exe") == 0) {
+ bAttachDwm = TRUE;
+ }
} else {
- bAttach = FALSE;
std::string commandLine;
char sep = 0;
- for (int i = 2; i < argc; ++i) {
+ for (int i = optind; i < argc; ++i) {
const char *arg = argv[i];
if (sep) {
@@ -206,39 +671,35 @@ main(int argc, char *argv[])
NULL, // current directory
&startupInfo,
&processInfo)) {
- fprintf(stderr, "error: failed to execute %s\n", commandLine.c_str());
+ DWORD dwLastError = GetLastError();
+ fprintf(stderr, "inject: error: failed to execute %s (%lu)\n",
+ commandLine.c_str(), dwLastError);
+ if (dwLastError == ERROR_ELEVATION_REQUIRED) {
+ fprintf(stderr, "error: target program requires elevated priviledges and must be started from an Administrator Command Prompt, or UAC must be disabled\n");
+ }
return 1;
}
hProcess = processInfo.hProcess;
}
- /*
- * XXX: Mixed architecture don't quite work. See also
- * http://www.corsix.org/content/dll-injection-and-wow64
- */
- {
- typedef BOOL (WINAPI *PFNISWOW64PROCESS)(HANDLE, PBOOL);
- PFNISWOW64PROCESS pfnIsWow64Process;
- pfnIsWow64Process = (PFNISWOW64PROCESS)
- GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process");
- if (pfnIsWow64Process) {
- BOOL isParentWow64 = FALSE;
- BOOL isChildWow64 = FALSE;
- if (pfnIsWow64Process(GetCurrentProcess(), &isParentWow64) &&
- pfnIsWow64Process(hProcess, &isChildWow64) &&
- isParentWow64 != isChildWow64) {
- fprintf(stderr, "error: binaries mismatch: you need to use the "
+ if (isDifferentArch(hProcess)) {
+ debugPrintf("error: binaries mismatch: you need to use the "
#ifdef _WIN64
- "32-bits"
+ "32-bits"
#else
- "64-bits"
+ "64-bits"
#endif
- " apitrace binaries to trace this application\n");
- TerminateProcess(hProcess, 1);
- return 1;
- }
- }
+ " apitrace binaries to trace this application\n");
+ TerminateProcess(hProcess, 1);
+ return 1;
+ }
+
+ if (bAttachDwm && IsWindows8OrGreater()) {
+ // Switch to Microsoft Basic Display Driver before injecting, so that
+ // we don't trace with it.
+ devconDisable(DEVCON_CLASS_DISPLAY);
+ Sleep(1000);
}
const char *szDllName;
@@ -249,69 +710,72 @@ main(int argc, char *argv[])
getDirName(szDllPath);
strncat(szDllPath, szDllName, sizeof szDllPath - strlen(szDllPath) - 1);
- size_t szDllPathLength = strlen(szDllPath) + 1;
-
- // Allocate memory in the target process to hold the DLL name
- void *lpMemory = VirtualAllocEx(hProcess, NULL, szDllPathLength, MEM_COMMIT, PAGE_READWRITE);
- if (!lpMemory) {
- fprintf(stderr, "error: failed to allocate memory in the process\n");
- TerminateProcess(hProcess, 1);
- return 1;
+ if (bDebug) {
+ if (!attachDebugger(GetProcessId(hProcess))) {
+ if (!bAttach) {
+ TerminateProcess(hProcess, 1);
+ }
+ return 1;
+ }
}
- // Copy DLL name into the target process
- if (!WriteProcessMemory(hProcess, lpMemory, szDllPath, szDllPathLength, NULL)) {
- fprintf(stderr, "error: failed to write into process memory\n");
- TerminateProcess(hProcess, 1);
+#if 1
+ if (!injectDll(hProcess, szDllPath)) {
+ if (!bAttach) {
+ TerminateProcess(hProcess, 1);
+ }
return 1;
}
+#endif
- /*
- * Get LoadLibraryA address from kernel32.dll. It's the same for all the
- * process (XXX: but only within the same architecture).
- */
- PTHREAD_START_ROUTINE lpStartAddress =
- (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("KERNEL32"), "LoadLibraryA");
+ DWORD exitCode;
- // Create remote thread in another process
- HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, lpMemory, 0, NULL);
- if (!hThread) {
- fprintf(stderr, "error: failed to create remote thread\n");
- TerminateProcess(hProcess, 1);
- return 1;
- }
+ if (bAttach) {
+ if (bAttachDwm) {
+ restartDwmComposition(hProcess);
+ } else {
+ fprintf(stderr, "Press any key when finished tracing\n");
+ getchar();
- // Wait for it to finish
- WaitForSingleObject(hThread, INFINITE);
+ ejectDll(hProcess, szDllPath);
+ }
- DWORD hModule = 0;
- GetExitCodeThread(hThread, &hModule);
- if (!hModule) {
- fprintf(stderr, "error: failed to inject %s\n", szDllPath);
- TerminateProcess(hProcess, 1);
- return 1;
- }
+ if (dwThreadId) {
+ HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, TRUE, dwThreadId);
+ if (hThread) {
+ ResumeThread(hThread);
+ WaitForSingleObject(hThread, INFINITE);
+ CloseHandle(hThread);
+ } else {
+ debugPrintf("inject: failed to open thread %lu\n", dwThreadId);
+ }
+ return 0;
+ }
- if (bAttach) {
- return 0;
- }
+ exitCode = 0;
+ } else {
+ // Start main process thread
+ ResumeThread(processInfo.hThread);
+
+ // Wait for it to finish
+ WaitForSingleObject(hProcess, INFINITE);
- // Start main process thread
- ResumeThread(processInfo.hThread);
+ if (pSharedMem && !pSharedMem->bReplaced) {
+ debugPrintf("warning: %s was never used: application probably does not use this API\n", szDll);
+ }
- // Wait for it to finish
- WaitForSingleObject(hProcess, INFINITE);
+ exitCode = ~0;
+ GetExitCodeProcess(hProcess, &exitCode);
- if (pSharedMem && !pSharedMem->bReplaced) {
- fprintf(stderr, "warning: %s was never used: application probably does not use this API\n", szDll);
+ CloseHandle(processInfo.hThread);
}
- DWORD exitCode = ~0;
- GetExitCodeProcess(hProcess, &exitCode);
-
CloseHandle(hProcess);
- CloseHandle(processInfo.hThread);
- return (int)exitCode;
+ if (hSemaphore) {
+ ReleaseSemaphore(hSemaphore, 1, NULL);
+ CloseHandle(hSemaphore);
+ }
+ return (int)exitCode;
}
diff --git a/retrace/.gitignore b/retrace/.gitignore
index 978f7a33..09c0c935 100644
--- a/retrace/.gitignore
+++ b/retrace/.gitignore
@@ -1,4 +1,6 @@
d3dretrace_d3d9.cpp
d3dretrace_dxgi.cpp
+dxgistate_so.cpp
glretrace_gl.cpp
glstate_params.cpp
+!android/java/apitrace
diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt
index c936dd2f..c845a13e 100644
--- a/retrace/CMakeLists.txt
+++ b/retrace/CMakeLists.txt
@@ -7,6 +7,7 @@ include_directories (
${CMAKE_BINARY_DIR}/dispatch
${CMAKE_SOURCE_DIR}/dispatch
${CMAKE_SOURCE_DIR}/image
+ ${CMAKE_SOURCE_DIR}/thirdparty/dxerr
)
add_definitions (-DRETRACE)
@@ -15,32 +16,39 @@ add_custom_command (
OUTPUT glretrace_gl.cpp
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/glretrace_gl.cpp
DEPENDS
- glretrace.py
- retrace.py
- ${CMAKE_SOURCE_DIR}/specs/glapi.py
- ${CMAKE_SOURCE_DIR}/specs/glesapi.py
- ${CMAKE_SOURCE_DIR}/specs/gltypes.py
- ${CMAKE_SOURCE_DIR}/specs/stdapi.py
+ glretrace.py
+ retrace.py
+ ${CMAKE_SOURCE_DIR}/specs/glapi.py
+ ${CMAKE_SOURCE_DIR}/specs/gltypes.py
+ ${CMAKE_SOURCE_DIR}/specs/stdapi.py
)
add_custom_command (
OUTPUT glstate_params.cpp
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glstate_params.py > ${CMAKE_CURRENT_BINARY_DIR}/glstate_params.cpp
DEPENDS
- glstate_params.py
- ${CMAKE_SOURCE_DIR}/specs/glparams.py
- ${CMAKE_SOURCE_DIR}/specs/gltypes.py
- ${CMAKE_SOURCE_DIR}/specs/stdapi.py
+ glstate_params.py
+ ${CMAKE_SOURCE_DIR}/specs/glparams.py
+ ${CMAKE_SOURCE_DIR}/specs/gltypes.py
+ ${CMAKE_SOURCE_DIR}/specs/stdapi.py
)
+if (WIN32)
+ set (ws_os ws_win32.cpp)
+endif ()
+
add_library (retrace_common STATIC
retrace.cpp
retrace_main.cpp
retrace_stdc.cpp
retrace_swizzle.cpp
json.cpp
+ state_writer.cpp
+ state_writer_json.cpp
+ state_writer_ubjson.cpp
+ ws.cpp
+ ${ws_os}
)
-
target_link_libraries (retrace_common
image
common
@@ -48,25 +56,42 @@ target_link_libraries (retrace_common
${SNAPPY_LIBRARIES}
${GETOPT_LIBRARIES}
)
+if (NOT ANDROID AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ target_link_libraries (retrace_common rt)
+endif ()
+if (WIN32)
+ target_link_libraries (retrace_common dxerr winmm)
+endif ()
+
add_library (glretrace_common STATIC
glretrace_gl.cpp
glretrace_cgl.cpp
glretrace_glx.cpp
glretrace_wgl.cpp
+ glretrace_wgl_font.cpp
glretrace_egl.cpp
glretrace_main.cpp
glretrace_ws.cpp
glstate.cpp
+ glstate_formats.cpp
glstate_images.cpp
glstate_params.cpp
glstate_shaders.cpp
glws.cpp
+ metric_helper.cpp
+ metric_writer.cpp
+ metric_backend_amd_perfmon.cpp
+ metric_backend_intel_perfquery.cpp
+ metric_backend_opengl.cpp
)
add_dependencies (glretrace_common glproc)
target_link_libraries (glretrace_common
retrace_common
)
+if (PROCPS_FOUND)
+ target_link_libraries (glretrace_common ${PROCPS_LIBRARY})
+endif ()
if (WIN32)
@@ -90,6 +115,7 @@ if (WIN32 OR APPLE OR X11_FOUND)
target_link_libraries (glretrace
retrace_common
glretrace_common
+ glhelpers
glproc_gl
)
@@ -110,19 +136,12 @@ if (WIN32 OR APPLE OR X11_FOUND)
# when dlopen'ing libGL), so link pthreads to avoid this issue. See also
# http://stackoverflow.com/questions/2702628/gdb-cannot-find-new-threads-generic-error
${CMAKE_THREAD_LIBS_INIT}
- dl
+ ${CMAKE_DL_LIBS}
)
-
- if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- target_link_libraries (glretrace rt)
- if (READPROC_H_FOUND)
- target_link_libraries (glretrace ${proc_LIBRARY})
- endif ()
- endif ()
-
endif ()
install (TARGETS glretrace RUNTIME DESTINATION bin)
+ install_pdb (glretrace DESTINATION bin)
endif ()
if (ENABLE_EGL AND X11_FOUND AND NOT WIN32 AND NOT APPLE AND NOT ENABLE_WAFFLE)
@@ -136,45 +155,109 @@ if (ENABLE_EGL AND X11_FOUND AND NOT WIN32 AND NOT APPLE AND NOT ENABLE_WAFFLE)
target_link_libraries (eglretrace
retrace_common
glretrace_common
+ glhelpers
glproc_egl
${X11_X11_LIB}
${CMAKE_THREAD_LIBS_INIT}
- dl
+ ${CMAKE_DL_LIBS}
)
-
- if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- target_link_libraries (eglretrace rt)
- if (READPROC_H_FOUND)
- target_link_libraries (eglretrace ${proc_LIBRARY})
- endif ()
- endif ()
-
install (TARGETS eglretrace RUNTIME DESTINATION bin)
endif ()
-if (ENABLE_EGL AND (ANDROID OR ENABLE_WAFFLE) AND Waffle_FOUND)
- add_executable (eglretrace
- glws_waffle.cpp
- )
+if (ENABLE_EGL)
+ if (ENABLE_WAFFLE)
+ add_executable (eglretrace
+ glws_waffle.cpp
+ )
- add_dependencies (eglretrace glproc)
- include_directories (${Waffle_INCLUDE_DIR})
+ add_dependencies (eglretrace glproc)
+ include_directories (${Waffle_INCLUDE_DIRS})
- target_link_libraries (eglretrace
- retrace_common
- glretrace_common
- glproc_egl
- ${Waffle_LIBRARY}
- ${X11_X11_LIB}
- ${CMAKE_THREAD_LIBS_INIT}
- dl
- )
- target_link_libraries (eglretrace ${proc_LIBRARY})
- install (TARGETS eglretrace RUNTIME DESTINATION bin)
+ target_link_libraries (eglretrace
+ retrace_common
+ glretrace_common
+ glhelpers
+ glproc_egl
+ ${Waffle_LIBRARIES}
+ ${X11_X11_LIB}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${CMAKE_DL_LIBS}
+ )
+ install (TARGETS eglretrace RUNTIME DESTINATION bin)
+ elseif (ANDROID AND (DEFINED ANDROID_SDK))
+ add_library(retrace SHARED glws_egl_android.cpp)
+
+ target_link_libraries (retrace
+ retrace_common
+ glretrace_common
+ glhelpers
+ glproc_egl
+ android
+ )
+ set (ANDROID_BUILD_DIR "${CMAKE_BINARY_DIR}/android-build")
+
+ configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/android/local.properties.in" "${CMAKE_BINARY_DIR}/local.properties")
+
+ add_custom_target (copyAndroidStuff
+ COMMAND ${CMAKE_COMMAND} -E remove_directory "${ANDROID_BUILD_DIR}"
+ COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/android" "${ANDROID_BUILD_DIR}"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${ANDROID_BUILD_DIR}/libs/${ANDROID_NDK_ABI_NAME}"
+
+ # FIXME According to android.toolchain.cmake decumentation the
+ # android libs should be putted to
+ # ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME} but
+ # android.toolchain.cmake sees LIBRARY_OUTPUT_PATH_ROOT as
+ # CMAKE_SOURCE_DIR and this CMakeLists.txt file sees it as
+ # ANDROID_BUILD_DIR ;-( so, I must use
+ # ${CMAKE_SOURCE_DIR}/libs/${ANDROID_NDK_ABI_NAME} insted of
+ # ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME} ...
+
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_shared.so" "${ANDROID_BUILD_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/libretrace.so" "${ANDROID_BUILD_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
+ DEPENDS retrace
+ )
+
+ add_custom_target (retraceAPK
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/local.properties" "${ANDROID_BUILD_DIR}/local.properties"
+ COMMAND "${CMAKE_SOURCE_DIR}/thirdparty/gradlew/gradlew" "assembleDebug"
+ DEPENDS copyAndroidStuff
+ DEPENDS "${CMAKE_BINARY_DIR}/local.properties"
+ WORKING_DIRECTORY "${ANDROID_BUILD_DIR}")
+
+ add_custom_target (installRetraceAPK
+ COMMAND "${CMAKE_SOURCE_DIR}/thirdparty/gradlew/gradlew" "installDebug"
+ DEPENDS retraceAPK
+ WORKING_DIRECTORY "${ANDROID_BUILD_DIR}")
+ endif ()
endif ()
if (WIN32)
- if (DirectX_D3D8_INCLUDE_DIR)
+ if (DirectX_D3D_INCLUDE_FOUND)
+ include_directories (BEFORE SYSTEM ${DirectX_D3D_INCLUDE_DIR})
+ add_custom_command (
+ OUTPUT d3dretrace_ddraw.cpp
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/ddrawretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_ddraw.cpp
+ DEPENDS
+ ddrawretrace.py
+ dllretrace.py
+ retrace.py
+ ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
+ ${CMAKE_SOURCE_DIR}/specs/ddraw.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d.py
+ ${CMAKE_SOURCE_DIR}/specs/d3dtypes.py
+ ${CMAKE_SOURCE_DIR}/specs/d3dcaps.py
+ ${CMAKE_SOURCE_DIR}/specs/winapi.py
+ ${CMAKE_SOURCE_DIR}/specs/stdapi.py
+ )
+ set (D3DSTATE_SOURCES ${D3DSTATE_SOURCES}
+ d3d7state.cpp
+ d3d7state_images.cpp
+ )
+ else ()
+ message (FATAL_ERROR "d3d.h is required.")
+ endif ()
+
+ if (DirectX_D3D8_INCLUDE_FOUND)
include_directories (BEFORE SYSTEM ${DirectX_D3D8_INCLUDE_DIR})
set (HAVE_D3D8 1)
set (D3DSTATE_SOURCES ${D3DSTATE_SOURCES}
@@ -188,18 +271,18 @@ if (WIN32)
OUTPUT d3dretrace_d3d8.cpp
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9retrace.py d3d8 ${HAVE_D3D8} > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d8.cpp
DEPENDS
- d3d9retrace.py
- dllretrace.py
- retrace.py
- ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
- ${CMAKE_SOURCE_DIR}/specs/d3d8.py
- ${CMAKE_SOURCE_DIR}/specs/d3d8types.py
- ${CMAKE_SOURCE_DIR}/specs/d3d8caps.py
- ${CMAKE_SOURCE_DIR}/specs/winapi.py
- ${CMAKE_SOURCE_DIR}/specs/stdapi.py
+ d3d9retrace.py
+ dllretrace.py
+ retrace.py
+ ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d8.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d8types.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d8caps.py
+ ${CMAKE_SOURCE_DIR}/specs/winapi.py
+ ${CMAKE_SOURCE_DIR}/specs/stdapi.py
)
- if (DirectX_D3D9_INCLUDE_DIR)
+ if (DirectX_D3D9_INCLUDE_FOUND)
include_directories (BEFORE SYSTEM ${DirectX_D3D9_INCLUDE_DIR})
set (HAVE_D3D9 1)
else ()
@@ -209,78 +292,74 @@ if (WIN32)
OUTPUT d3dretrace_d3d9.cpp
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9retrace.py d3d9 ${HAVE_D3D9} > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d9.cpp
DEPENDS
- d3d9retrace.py
- dllretrace.py
- retrace.py
- ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
- ${CMAKE_SOURCE_DIR}/specs/d3d9.py
- ${CMAKE_SOURCE_DIR}/specs/d3d9types.py
- ${CMAKE_SOURCE_DIR}/specs/d3d9caps.py
- ${CMAKE_SOURCE_DIR}/specs/winapi.py
- ${CMAKE_SOURCE_DIR}/specs/stdapi.py
+ d3d9retrace.py
+ dllretrace.py
+ retrace.py
+ ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d9.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d9types.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d9caps.py
+ ${CMAKE_SOURCE_DIR}/specs/dxva2.py
+ ${CMAKE_SOURCE_DIR}/specs/winapi.py
+ ${CMAKE_SOURCE_DIR}/specs/stdapi.py
)
- if (DirectX_D3D10_INCLUDE_DIR)
- include_directories (BEFORE SYSTEM ${DirectX_D3D10_INCLUDE_DIR})
- set (DXGI_MODULES d3d10)
- if (DirectX_D3D10_1_INCLUDE_DIR)
- include_directories (BEFORE SYSTEM ${DirectX_D3D10_1_INCLUDE_DIR})
- set (DXGI_MODULES ${DXGI_MODULES} d3d10_1)
- endif ()
- set (D3DSTATE_SOURCES ${D3DSTATE_SOURCES}
- dxgistate.cpp
- d3d10state.cpp
- d3d10state_images.cpp
- )
- endif ()
-
- if (DirectX_D3D11_INCLUDE_DIR)
+ if (DirectX_D3D11_3_INCLUDE_FOUND)
+ add_definitions (-DHAVE_DXGI)
include_directories (BEFORE SYSTEM
- ${DirectX_D3D11_INCLUDE_DIR}
+ ${DirectX_D3D11_3_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/thirdparty/directxtex/DirectXTex
)
- set (DXGI_MODULES ${DXGI_MODULES} d3d11)
- if (DirectX_D3D11_1_INCLUDE_DIR)
- include_directories (BEFORE SYSTEM ${DirectX_D3D11_1_INCLUDE_DIR})
- set (DXGI_MODULES ${DXGI_MODULES} d3d11_1)
- endif ()
set (D3DSTATE_SOURCES ${D3DSTATE_SOURCES}
+ dxgistate.cpp
+ dxgistate_so.cpp
+ d3d10state.cpp
+ d3d10state_images.cpp
d3d11state.cpp
d3d11state_images.cpp
+ d3dretrace_dxgi.cpp
+ d3dretrace_dxgi_misc.cpp
)
- endif ()
-
- add_custom_command (
- OUTPUT d3dretrace_dxgi.cpp
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgiretrace.py ${DXGI_MODULES} > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_dxgi.cpp
- DEPENDS
+ add_custom_command (
+ OUTPUT dxgistate_so.cpp
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgistate_so.py > ${CMAKE_CURRENT_BINARY_DIR}/dxgistate_so.cpp
+ DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/dxgistate_so.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d11.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d11sdklayers.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d10.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d10sdklayers.py
+ ${CMAKE_SOURCE_DIR}/specs/dxgi.py
+ ${CMAKE_SOURCE_DIR}/specs/winapi.py
+ ${CMAKE_SOURCE_DIR}/specs/stdapi.py
+ )
+ add_custom_command (
+ OUTPUT d3dretrace_dxgi.cpp
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgiretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_dxgi.cpp
+ DEPENDS
dxgiretrace.py
dllretrace.py
retrace.py
${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
- ${CMAKE_SOURCE_DIR}/specs/d3d11_1.py
${CMAKE_SOURCE_DIR}/specs/d3d11.py
${CMAKE_SOURCE_DIR}/specs/d3d11sdklayers.py
- ${CMAKE_SOURCE_DIR}/specs/d3d10_1.py
${CMAKE_SOURCE_DIR}/specs/d3d10.py
- ${CMAKE_SOURCE_DIR}/specs/d3d10misc.py
${CMAKE_SOURCE_DIR}/specs/d3d10sdklayers.py
- ${CMAKE_SOURCE_DIR}/specs/d3dcommon.py
- ${CMAKE_SOURCE_DIR}/specs/dxgi1_2.py
${CMAKE_SOURCE_DIR}/specs/dxgi.py
- ${CMAKE_SOURCE_DIR}/specs/dxgitype.py
- ${CMAKE_SOURCE_DIR}/specs/dxgiformat.py
${CMAKE_SOURCE_DIR}/specs/winapi.py
${CMAKE_SOURCE_DIR}/specs/stdapi.py
- )
+ )
+ endif ()
add_executable (d3dretrace
d3dretrace_main.cpp
+ d3dretrace_ddraw.cpp
d3dretrace_d3d8.cpp
d3dretrace_d3d9.cpp
- d3dretrace_dxgi.cpp
+ d3dretrace_dxgi_priv.cpp
d3dretrace_ws.cpp
d3d9state.cpp
+ d3d9state_formats.cpp
d3d9state_images.cpp
${D3DSTATE_SOURCES}
)
@@ -288,9 +367,10 @@ if (WIN32)
retrace_common
d3dhelpers
)
- if (DirectX_D3D11_INCLUDE_DIR)
+ if (DirectX_D3D11_3_INCLUDE_FOUND)
target_link_libraries (d3dretrace directxtex)
endif ()
install (TARGETS d3dretrace RUNTIME DESTINATION bin)
+ install_pdb (d3dretrace DESTINATION bin)
endif ()
diff --git a/retrace/android/AndroidManifest.xml b/retrace/android/AndroidManifest.xml
new file mode 100644
index 00000000..c7a12db1
--- /dev/null
+++ b/retrace/android/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="apitrace.github.io.eglretrace" >
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" >
+ <activity
+ android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation"
+ android:screenOrientation="unspecified"
+ android:launchMode="singleTop"
+ android:name=".RetraceActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+</manifest>
diff --git a/retrace/android/build.gradle b/retrace/android/build.gradle
new file mode 100644
index 00000000..4afe4b56
--- /dev/null
+++ b/retrace/android/build.gradle
@@ -0,0 +1,46 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.0.0'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 19
+ buildToolsVersion "21.1.2"
+
+ defaultConfig {
+ applicationId "apitrace.github.io.eglretrace"
+ minSdkVersion 12
+ targetSdkVersion 19
+ versionCode 1
+ versionName "1.0"
+ }
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['java']
+ aidl.srcDirs = ['aidl']
+ res.srcDirs = ['res']
+ resources.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ assets.srcDirs = ['assets']
+ jniLibs.srcDirs = ['libs']
+ }
+ }
+}
diff --git a/retrace/android/java/apitrace/github/io/eglretrace/AbstractServer.java b/retrace/android/java/apitrace/github/io/eglretrace/AbstractServer.java
new file mode 100644
index 00000000..04933c3c
--- /dev/null
+++ b/retrace/android/java/apitrace/github/io/eglretrace/AbstractServer.java
@@ -0,0 +1,31 @@
+package apitrace.github.io.eglretrace;
+
+import android.net.LocalServerSocket;
+import android.net.LocalSocket;
+
+import java.io.IOException;
+
+public abstract class AbstractServer extends Thread {
+ public AbstractServer(String name) throws IOException {
+ m_localServer = new LocalServerSocket(name);
+ }
+
+ private LocalServerSocket m_localServer;
+
+ public void close() throws IOException {
+ m_localServer.close();
+ }
+
+ @Override
+ public void run() {
+ while(true) {
+ try {
+ accepted(m_localServer.accept());
+ } catch (Exception e) {
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
+ protected abstract void accepted(LocalSocket socket);
+}
diff --git a/retrace/android/java/apitrace/github/io/eglretrace/QtCreatorDebugger.java b/retrace/android/java/apitrace/github/io/eglretrace/QtCreatorDebugger.java
new file mode 100644
index 00000000..dee54b4b
--- /dev/null
+++ b/retrace/android/java/apitrace/github/io/eglretrace/QtCreatorDebugger.java
@@ -0,0 +1,242 @@
+package apitrace.github.io.eglretrace;
+
+import android.app.Activity;
+import android.net.LocalServerSocket;
+import android.net.LocalSocket;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+public class QtCreatorDebugger {
+
+ QtCreatorDebugger(){}
+
+ QtCreatorDebugger(String TAG) {
+ this.TAG =TAG;
+ }
+
+ private String TAG = "QtCreator";
+
+ private Process m_debuggerProcess = null; // debugger process
+
+ public boolean connect(Activity activity) {
+ try {
+ Bundle extras = activity.getIntent().getExtras();
+
+ if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0
+ &&*/ extras.containsKey("debug_ping")
+ && extras.getString("debug_ping").equals("true")) {
+ try {
+ debugLog("extra parameters: " + extras);
+ String packageName = activity.getPackageName();
+ String pingFile = extras.getString("ping_file");
+ String pongFile = extras.getString("pong_file");
+ String gdbserverSocket = extras.getString("gdbserver_socket");
+ String gdbserverCommand = extras.getString("gdbserver_command");
+ String pingSocket = extras.getString("ping_socket");
+ boolean usePing = pingFile != null;
+ boolean usePong = pongFile != null;
+ boolean useSocket = gdbserverSocket != null;
+ boolean usePingSocket = pingSocket != null;
+ int napTime = 200; // milliseconds between file accesses
+ int timeOut = 30000; // ms until we give up on ping and pong
+ int maxAttempts = timeOut / napTime;
+
+ if (gdbserverSocket != null) {
+ debugLog("removing gdb socket " + gdbserverSocket);
+ new File(gdbserverSocket).delete();
+ }
+
+ if (usePing) {
+ debugLog("removing ping file " + pingFile);
+ File ping = new File(pingFile);
+ if (ping.exists()) {
+ if (!ping.delete())
+ debugLog("ping file cannot be deleted");
+ }
+ }
+
+ if (usePong) {
+ debugLog("removing pong file " + pongFile);
+ File pong = new File(pongFile);
+ if (pong.exists()) {
+ if (!pong.delete())
+ debugLog("pong file cannot be deleted");
+ }
+ }
+
+ debugLog("starting " + gdbserverCommand);
+ m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand);
+ debugLog("gdbserver started");
+
+ if (useSocket) {
+ int i;
+ for (i = 0; i < maxAttempts; ++i) {
+ debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i);
+ File file = new File(gdbserverSocket);
+ if (file.exists()) {
+ file.setReadable(true, false);
+ file.setWritable(true, false);
+ file.setExecutable(true, false);
+ break;
+ }
+ Thread.sleep(napTime);
+ }
+
+ if (i == maxAttempts) {
+ debugLog("time out when waiting for debug socket");
+ return false;
+ }
+
+ debugLog("socket ok");
+ } else {
+ debugLog("socket not used");
+ }
+
+ if (usePingSocket) {
+ DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket);
+ Thread waitThread = new Thread(runnable);
+ waitThread.start();
+
+ int i;
+ for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) {
+ debugLog("Waiting for debug socket connect");
+ debugLog("go to sleep");
+ Thread.sleep(napTime);
+ }
+
+ if (i == maxAttempts) {
+ debugLog("time out when waiting for ping socket");
+ runnable.shutdown();
+ return false;
+ }
+
+ if (runnable.wasFailure) {
+ debugLog("Could not connect to debug client");
+ return false;
+ } else {
+ debugLog("Got pid acknowledgment");
+ }
+ }
+
+ if (usePing) {
+ // Tell we are ready.
+ debugLog("writing ping at " + pingFile);
+ FileWriter writer = new FileWriter(pingFile);
+ writer.write("" + android.os.Process.myPid());
+ writer.close();
+ File file = new File(pingFile);
+ file.setReadable(true, false);
+ file.setWritable(true, false);
+ file.setExecutable(true, false);
+ debugLog("wrote ping");
+ } else {
+ debugLog("ping not requested");
+ }
+
+ // Wait until other side is ready.
+ if (usePong) {
+ int i;
+ for (i = 0; i < maxAttempts; ++i) {
+ debugLog("waiting for pong at " + pongFile + ", attempt " + i);
+ File file = new File(pongFile);
+ if (file.exists()) {
+ file.delete();
+ break;
+ }
+ debugLog("go to sleep");
+ Thread.sleep(napTime);
+ }
+ debugLog("Removing pingFile " + pingFile);
+ new File(pingFile).delete();
+
+ if (i == maxAttempts) {
+ debugLog("time out when waiting for pong file");
+ return false;
+ }
+
+ debugLog("got pong " + pongFile);
+ } else {
+ debugLog("pong not requested");
+ }
+
+ } catch (Exception e) {
+ debugLog("Can't start debugger" + e.getMessage());
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
+
+ void close()
+ {
+ if (m_debuggerProcess != null)
+ m_debuggerProcess.destroy();
+ }
+
+ private void debugLog(String msg)
+ {
+ Log.i(TAG, "DEBUGGER: " + msg);
+ }
+
+ private class DebugWaitRunnable implements Runnable {
+
+ public DebugWaitRunnable(String pingPongSocket) throws IOException {
+ socket = new LocalServerSocket(pingPongSocket);
+ }
+
+ public boolean wasFailure;
+ private LocalServerSocket socket;
+
+ public void run() {
+ final int napTime = 200; // milliseconds between file accesses
+ final int timeOut = 30000; // ms until we give up on ping and pong
+ final int maxAttempts = timeOut / napTime;
+
+ try {
+ LocalSocket connectionFromClient = socket.accept();
+ debugLog("Debug socket accepted");
+ BufferedReader inFromClient =
+ new BufferedReader(new InputStreamReader(connectionFromClient.getInputStream()));
+ DataOutputStream outToClient = new DataOutputStream(connectionFromClient.getOutputStream());
+ outToClient.writeBytes("" + android.os.Process.myPid());
+
+ for (int i = 0; i < maxAttempts; i++) {
+ String clientData = inFromClient.readLine();
+ debugLog("Incoming socket " + clientData);
+ if (!clientData.isEmpty())
+ break;
+
+ if (connectionFromClient.isClosed()) {
+ wasFailure = true;
+ break;
+ }
+ Thread.sleep(napTime);
+ }
+ } catch (IOException ioEx) {
+ ioEx.printStackTrace();
+ wasFailure = true;
+ debugLog("Can't start debugger" + ioEx.getMessage());
+ } catch (InterruptedException interruptEx) {
+ wasFailure = true;
+ debugLog("Can't start debugger" + interruptEx.getMessage());
+ }
+ }
+
+ public void shutdown() throws IOException
+ {
+ wasFailure = true;
+ try {
+ socket.close();
+ } catch (IOException ignored) { }
+ }
+ };
+}
diff --git a/retrace/android/java/apitrace/github/io/eglretrace/RetraceActivity.java b/retrace/android/java/apitrace/github/io/eglretrace/RetraceActivity.java
new file mode 100644
index 00000000..9d002421
--- /dev/null
+++ b/retrace/android/java/apitrace/github/io/eglretrace/RetraceActivity.java
@@ -0,0 +1,114 @@
+package apitrace.github.io.eglretrace;
+
+import android.app.Activity;
+import android.content.pm.ActivityInfo;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.RelativeLayout;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+public class RetraceActivity extends Activity implements SurfaceHolder.Callback2{
+
+ private SurfaceView m_surface;
+ private Servers m_servers;
+ private QtCreatorDebugger m_debugger = new QtCreatorDebugger("eglretrace");
+
+ public void setSurfaceSize(final int width, final int height) {
+ synchronized (this) {
+ runOnUiThread( new Runnable() {
+ @Override
+ public void run() {
+ if (width < height)
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ else
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ m_surface.getHolder().setFixedSize(width, height);
+ }
+ });
+ }
+ }
+
+ public static native boolean setStdoutFileDescriptor(FileDescriptor fd);
+ public static native boolean setStderrFileDescriptor(FileDescriptor fd);
+
+ public static native void onActivityCreatedNative(RetraceActivity activity);
+ public static native void onSurfaceCreatedNative(Surface surface);
+ public static native void onSurfaceChangedNative(Surface surface, int format, int width, int height);
+ public static native void onSurfaceRedrawNeededNative(Surface surface);
+ public static native void onSurfaceDestroyedNative();
+ public static native void onActivityDestroyedNative();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (Build.VERSION.SDK_INT > 13) {
+ int systemVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ if (Build.VERSION.SDK_INT > 15) {
+ systemVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_FULLSCREEN;
+ if (Build.VERSION.SDK_INT > 18)
+ systemVisibility |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ }
+ getWindow().getDecorView().setSystemUiVisibility(systemVisibility);
+ }
+
+ if (savedInstanceState == null) {
+ System.loadLibrary("gnustl_shared");
+ System.loadLibrary("retrace");
+ m_debugger.connect(this);
+ }
+ onActivityCreatedNative(this);
+ try {
+ m_servers = new Servers("apitrace.github.io.eglretrace.stdout", "apitrace.github.io.eglretrace.stderr");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ RelativeLayout layout = new RelativeLayout(this);
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
+ m_surface = new SurfaceView(this);
+ m_surface.getHolder().addCallback(this);
+ layout.addView(m_surface, params);
+ setContentView(layout);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ onSurfaceCreatedNative(holder.getSurface());
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ onSurfaceChangedNative(holder.getSurface(), format, width, height);
+ }
+
+ @Override
+ public void surfaceRedrawNeeded(SurfaceHolder holder) {
+ onSurfaceRedrawNeededNative(holder.getSurface());
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ onSurfaceDestroyedNative();
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (m_servers != null)
+ m_servers.close();
+ m_debugger.close();
+ onActivityDestroyedNative();
+ super.onDestroy();
+ System.exit(1);
+ }
+}
diff --git a/retrace/android/java/apitrace/github/io/eglretrace/Servers.java b/retrace/android/java/apitrace/github/io/eglretrace/Servers.java
new file mode 100644
index 00000000..8ba2d7fe
--- /dev/null
+++ b/retrace/android/java/apitrace/github/io/eglretrace/Servers.java
@@ -0,0 +1,54 @@
+package apitrace.github.io.eglretrace;
+
+import android.net.LocalSocket;
+
+import java.io.IOException;
+
+public class Servers {
+ private AbstractServer m_stdout, m_stderr;
+ Servers(String stdoutServerName, String stderrServerName) throws IOException {
+ m_stdout = new AbstractServer(stdoutServerName) {
+ @Override
+ protected void accepted(LocalSocket socket) {
+ if (!RetraceActivity.setStdoutFileDescriptor(socket.getFileDescriptor())) {
+ try {
+ // close socket if we are busy
+ socket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+ m_stdout.start();
+ m_stderr = new AbstractServer(stderrServerName) {
+ @Override
+ protected void accepted(LocalSocket socket) {
+ if (!RetraceActivity.setStderrFileDescriptor(socket.getFileDescriptor())) {
+ try {
+ // close socket if we are busy
+ socket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+ m_stderr.start();
+ }
+
+ public void close() {
+ try {
+ m_stdout.close();
+ m_stdout.join();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ try {
+ m_stderr.close();
+ m_stderr.join();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/retrace/android/local.properties.in b/retrace/android/local.properties.in
new file mode 100644
index 00000000..c6ba37c4
--- /dev/null
+++ b/retrace/android/local.properties.in
@@ -0,0 +1,7 @@
+## This file is automatically generated by QtCreator.
+#
+# This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+
+sdk.dir=@ANDROID_SDK@
+
diff --git a/retrace/android/res/drawable-hdpi/ic_launcher.png b/retrace/android/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..96a442e5
--- /dev/null
+++ b/retrace/android/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/retrace/android/res/drawable-mdpi/ic_launcher.png b/retrace/android/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..359047df
--- /dev/null
+++ b/retrace/android/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/retrace/android/res/drawable-xhdpi/ic_launcher.png b/retrace/android/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..71c6d760
--- /dev/null
+++ b/retrace/android/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/retrace/android/res/drawable-xxhdpi/ic_launcher.png b/retrace/android/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..4df18946
--- /dev/null
+++ b/retrace/android/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/retrace/android/res/values/strings.xml b/retrace/android/res/values/strings.xml
new file mode 100644
index 00000000..d5975fd7
--- /dev/null
+++ b/retrace/android/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">EGLRetrace</string>
+</resources>
diff --git a/retrace/d3d10state.cpp b/retrace/d3d10state.cpp
index 0f6cf805..d17fbf1f 100644
--- a/retrace/d3d10state.cpp
+++ b/retrace/d3d10state.cpp
@@ -28,8 +28,10 @@
#include <iostream>
+#include "com_ptr.hpp"
#include "d3d10imports.hpp"
#include "d3d10state.hpp"
+#include "dxgistate_so.hpp"
namespace d3dstate {
@@ -40,52 +42,152 @@ GUID_D3DSTATE = {0x7D71CAC9,0x7F58,0x432C,{0xA9,0x75,0xA1,0x9F,0xCF,0xCE,0xFD,0x
static void
-dumpShaders(JSONWriter &json, ID3D10Device *pDevice)
+dumpRasterizerState(StateWriter &writer, ID3D10Device *pDevice)
{
- json.beginMember("shaders");
- json.beginObject();
+ com_ptr<ID3D10RasterizerState> pRasterizerState;
- ID3D10VertexShader *pVertexShader = NULL;
+ pDevice->RSGetState(&pRasterizerState);
+ writer.beginMember("RasterizerState");
+ dumpStateObjectDesc(writer, pRasterizerState);
+ writer.endMember(); // RasterizerState
+}
+
+
+static void
+dumpBlendState(StateWriter &writer, ID3D10Device *pDevice)
+{
+ com_ptr<ID3D10BlendState> pBlendState;
+ FLOAT BlendFactor[4];
+ UINT SampleMask;
+
+ pDevice->OMGetBlendState(&pBlendState, BlendFactor, &SampleMask);
+
+ writer.beginMember("BlendState");
+ dumpStateObjectDesc(writer, pBlendState);
+ writer.endMember(); // BlendState
+
+ writer.beginMember("BlendFactor");
+ writer.beginArray();
+ writer.writeFloat(BlendFactor[0]);
+ writer.writeFloat(BlendFactor[1]);
+ writer.writeFloat(BlendFactor[2]);
+ writer.writeFloat(BlendFactor[3]);
+ writer.endArray();
+ writer.endMember(); // BlendFactor
+
+ writer.writeIntMember("SampleMask", SampleMask);
+}
+
+
+static void
+dumpDepthStencilState(StateWriter &writer, ID3D10Device *pDevice)
+{
+ com_ptr<ID3D10DepthStencilState> pDepthStencilState;
+ UINT stencilRef;
+
+ pDevice->OMGetDepthStencilState(&pDepthStencilState, &stencilRef);
+ writer.beginMember("DepthStencilState");
+ dumpStateObjectDesc(writer, pDepthStencilState);
+ writer.endMember(); // DepthStencilState
+ writer.writeIntMember("StencilRef", stencilRef);
+}
+
+
+static void
+dumpViewports(StateWriter &writer, ID3D10Device *pDevice)
+{
+ D3D10_VIEWPORT vps[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ UINT numViewports = 0, i;
+
+ pDevice->RSGetViewports(&numViewports, NULL);
+ pDevice->RSGetViewports(&numViewports, vps);
+
+ writer.beginMember("Viewports");
+ writer.beginArray();
+ for (i = 0; i < numViewports; ++i) {
+ dumpStateObject(writer, vps[i]);
+ }
+ writer.endArray();
+ writer.endMember();
+}
+
+
+static void
+dumpScissors(StateWriter &writer, ID3D10Device *pDevice)
+{
+ D3D10_RECT rects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ UINT numRects = 0, i;
+
+ pDevice->RSGetScissorRects(&numRects, NULL);
+ pDevice->RSGetScissorRects(&numRects, rects);
+
+ writer.beginMember("Scissors");
+ writer.beginArray();
+ for (i = 0; i < numRects; ++i) {
+ dumpStateObject(writer, rects[i]);
+ }
+ writer.endArray();
+ writer.endMember();
+}
+
+
+static void
+dumpParameters(StateWriter &writer, ID3D10Device *pDevice)
+{
+ // TODO: dump description of current bound state
+ writer.beginMember("parameters");
+ writer.beginObject();
+
+ dumpRasterizerState(writer, pDevice);
+ dumpBlendState(writer, pDevice);
+ dumpDepthStencilState(writer, pDevice);
+ dumpViewports(writer, pDevice);
+ dumpScissors(writer, pDevice);
+
+ writer.endObject();
+ writer.endMember(); // parameters
+}
+
+
+static void
+dumpShaders(StateWriter &writer, ID3D10Device *pDevice)
+{
+ writer.beginMember("shaders");
+ writer.beginObject();
+
+ com_ptr<ID3D10VertexShader> pVertexShader;
pDevice->VSGetShader(&pVertexShader);
if (pVertexShader) {
- dumpShader<ID3D10DeviceChild>(json, "VS", pVertexShader);
- pVertexShader->Release();
+ dumpShader<ID3D10DeviceChild>(writer, "VS", pVertexShader);
}
- ID3D10GeometryShader *pGeometryShader = NULL;
+ com_ptr<ID3D10GeometryShader> pGeometryShader;
pDevice->GSGetShader(&pGeometryShader);
if (pGeometryShader) {
- dumpShader<ID3D10DeviceChild>(json, "GS", pGeometryShader);
- pGeometryShader->Release();
+ dumpShader<ID3D10DeviceChild>(writer, "GS", pGeometryShader);
}
- ID3D10PixelShader *pPixelShader = NULL;
+ com_ptr<ID3D10PixelShader> pPixelShader;
pDevice->PSGetShader(&pPixelShader);
if (pPixelShader) {
- dumpShader<ID3D10DeviceChild>(json, "PS", pPixelShader);
+ dumpShader<ID3D10DeviceChild>(writer, "PS", pPixelShader);
}
- json.endObject();
- json.endMember(); // shaders
+ writer.endObject();
+ writer.endMember(); // shaders
}
void
-dumpDevice(std::ostream &os, ID3D10Device *pDevice)
+dumpDevice(StateWriter &writer, ID3D10Device *pDevice)
{
- JSONWriter json(os);
-
- /* TODO */
- json.beginMember("parameters");
- json.beginObject();
- json.endObject();
- json.endMember(); // parameters
+ dumpParameters(writer, pDevice);
- dumpShaders(json, pDevice);
+ dumpShaders(writer, pDevice);
- dumpTextures(json, pDevice);
+ dumpTextures(writer, pDevice);
- dumpFramebuffer(json, pDevice);
+ dumpFramebuffer(writer, pDevice);
}
diff --git a/retrace/d3d10state.hpp b/retrace/d3d10state.hpp
index 2b6fc986..87fcd946 100644
--- a/retrace/d3d10state.hpp
+++ b/retrace/d3d10state.hpp
@@ -23,62 +23,102 @@
*
**************************************************************************/
-#ifndef _D3D10STATE_HPP_
-#define _D3D10STATE_HPP_
+#pragma once
+#include <assert.h>
+
#include <windows.h>
+#include <vector>
+#include <string>
-#include "json.hpp"
+#include "state_writer.hpp"
+#include "com_ptr.hpp"
#include "d3dshader.hpp"
#include "d3dstate.hpp"
+#include "d3d10imports.hpp"
+
namespace d3dstate {
-template< class T >
+template< typename T >
+inline std::vector<BYTE>
+getPrivateData(T *pObject, REFGUID guid)
+{
+ std::vector<BYTE> Data;
+
+ if (!pObject) {
+ return Data;
+ }
+
+ UINT DataLength = 0;
+ HRESULT hr;
+ hr = pObject->GetPrivateData(guid, &DataLength, NULL);
+ if (hr != S_OK) {
+ assert(hr == DXGI_ERROR_NOT_FOUND);
+ return Data;
+ }
+
+ Data.resize(DataLength);
+
+ hr = pObject->GetPrivateData(guid, &DataLength, &Data[0]);
+ assert(hr == S_OK);
+ if (FAILED(hr)) {
+ Data.clear();
+ }
+
+ return Data;
+}
+
+
+template< typename T >
inline void
-dumpShader(JSONWriter &json, const char *name, T *pShader) {
+dumpShader(StateWriter &writer, const char *name, T *pShader) {
if (!pShader) {
return;
}
- HRESULT hr;
-
/*
* There is no method to get the shader byte code, so the creator is supposed to
* attach it via the SetPrivateData method.
*/
- UINT BytecodeLength = 0;
- char dummy;
- hr = pShader->GetPrivateData(GUID_D3DSTATE, &BytecodeLength, &dummy);
- if (hr != DXGI_ERROR_MORE_DATA) {
- return;
- }
- void *pShaderBytecode = malloc(BytecodeLength);
- if (!pShaderBytecode) {
+
+ std::vector<BYTE> ShaderBytecode = getPrivateData(pShader, GUID_D3DSTATE);
+ if (ShaderBytecode.empty()) {
return;
}
- hr = pShader->GetPrivateData(GUID_D3DSTATE, &BytecodeLength, pShaderBytecode);
+ com_ptr<IDisassemblyBuffer> pDisassembly;
+ HRESULT hr;
+ hr = DisassembleShader(&ShaderBytecode[0], ShaderBytecode.size(), &pDisassembly);
if (SUCCEEDED(hr)) {
- IDisassemblyBuffer *pDisassembly = NULL;
- hr = DisassembleShader(pShaderBytecode, BytecodeLength, &pDisassembly);
- if (SUCCEEDED(hr)) {
- json.beginMember(name);
- json.writeString((const char *)pDisassembly->GetBufferPointer() /*, pDisassembly->GetBufferSize() */);
- json.endMember();
- pDisassembly->Release();
- }
+ writer.beginMember(name);
+ writer.writeString((const char *)pDisassembly->GetBufferPointer() /*, pDisassembly->GetBufferSize() */);
+ writer.endMember();
}
+}
- free(pShaderBytecode);
+
+template< typename T >
+inline std::string
+getObjectName(T *pObject)
+{
+ std::vector<BYTE> ObjectName = getPrivateData(pObject, WKPDID_D3DDebugObjectName);
+ return std::string(ObjectName.begin(), ObjectName.end());
}
+image::Image *
+getSubResourceImage(ID3D10Device *pDevice,
+ ID3D10Resource *pResource,
+ DXGI_FORMAT Format,
+ UINT ArraySlice,
+ UINT MipSlice);
+
+
} /* namespace d3dstate */
-#endif // _D3D10STATE_HPP_
diff --git a/retrace/d3d10state_images.cpp b/retrace/d3d10state_images.cpp
index bae0178e..b6dc3eac 100644
--- a/retrace/d3d10state_images.cpp
+++ b/retrace/d3d10state_images.cpp
@@ -1,5 +1,6 @@
/**************************************************************************
*
+ * Copyright 2014 VMware, Inc.
* Copyright 2011 Jose Fonseca
* All Rights Reserved.
*
@@ -30,119 +31,181 @@
#include <algorithm>
#include "os.hpp"
-#include "json.hpp"
+#include "state_writer.hpp"
#include "image.hpp"
+#include "com_ptr.hpp"
#include "d3d10imports.hpp"
#include "d3dstate.hpp"
+#include "d3d10state.hpp"
#include "dxgistate.hpp"
namespace d3dstate {
-static HRESULT
-stageResource(ID3D10Device *pDevice,
- ID3D10Resource *pResource,
- ID3D10Resource **ppStagingResource,
- UINT *pWidth, UINT *pHeight, UINT *pDepth,
- UINT *pMipLevels) {
- D3D10_USAGE Usage = D3D10_USAGE_STAGING;
- UINT BindFlags = 0;
- UINT CPUAccessFlags = D3D10_CPU_ACCESS_READ;
- UINT MiscFlags = 0;
- union {
- ID3D10Resource *pStagingResource;
- ID3D10Buffer *pStagingBuffer;
- ID3D10Texture1D *pStagingTexture1D;
- ID3D10Texture2D *pStagingTexture2D;
- ID3D10Texture3D *pStagingTexture3D;
- };
- HRESULT hr;
- D3D10_RESOURCE_DIMENSION Type = D3D10_RESOURCE_DIMENSION_UNKNOWN;
- pResource->GetType(&Type);
- switch (Type) {
+struct ResourceDesc
+{
+ D3D10_RESOURCE_DIMENSION Type;
+ UINT Width;
+ UINT Height;
+ UINT Depth;
+ UINT MipLevels;
+ UINT ArraySize;
+ DXGI_FORMAT Format;
+ DXGI_SAMPLE_DESC SampleDesc;
+ D3D10_USAGE Usage;
+ UINT BindFlags;
+ UINT CPUAccessFlags;
+ UINT MiscFlags;
+};
+
+
+static void
+getResourceDesc(ID3D10Resource *pResource, ResourceDesc *pDesc)
+{
+ pDesc->Type = D3D10_RESOURCE_DIMENSION_UNKNOWN;
+ pDesc->Width = 0;
+ pDesc->Height = 1;
+ pDesc->Depth = 1;
+ pDesc->MipLevels = 1;
+ pDesc->ArraySize = 1;
+ pDesc->Format = DXGI_FORMAT_UNKNOWN;
+ pDesc->SampleDesc.Count = 1;
+ pDesc->SampleDesc.Quality = 0;
+ pDesc->Usage = D3D10_USAGE_DEFAULT;
+ pDesc->BindFlags = 0;
+ pDesc->CPUAccessFlags = 0;
+ pDesc->MiscFlags = 0;
+
+ pResource->GetType(&pDesc->Type);
+ switch (pDesc->Type) {
case D3D10_RESOURCE_DIMENSION_BUFFER:
{
D3D10_BUFFER_DESC Desc;
static_cast<ID3D10Buffer *>(pResource)->GetDesc(&Desc);
- Desc.Usage = Usage;
- Desc.BindFlags = BindFlags;
- Desc.CPUAccessFlags = CPUAccessFlags;
- Desc.MiscFlags = MiscFlags;
-
- *pWidth = Desc.ByteWidth;
- *pHeight = 1;
- *pDepth = 1;
- *pMipLevels = 1;
-
- hr = pDevice->CreateBuffer(&Desc, NULL, &pStagingBuffer);
+ pDesc->Width = Desc.ByteWidth;
+ pDesc->Usage = Desc.Usage;
+ pDesc->BindFlags = Desc.BindFlags;
+ pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
+ pDesc->MiscFlags = Desc.MiscFlags;
}
break;
case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
{
D3D10_TEXTURE1D_DESC Desc;
static_cast<ID3D10Texture1D *>(pResource)->GetDesc(&Desc);
- Desc.Usage = Usage;
- Desc.BindFlags = BindFlags;
- Desc.CPUAccessFlags = CPUAccessFlags;
- Desc.MiscFlags = MiscFlags;
-
- *pWidth = Desc.Width;
- *pHeight = 1;
- *pDepth = 1;
- *pMipLevels = Desc.MipLevels;
-
- hr = pDevice->CreateTexture1D(&Desc, NULL, &pStagingTexture1D);
+ pDesc->Width = Desc.Width;
+ pDesc->MipLevels = Desc.MipLevels;
+ pDesc->ArraySize = Desc.ArraySize;
+ pDesc->Format = Desc.Format;
+ pDesc->Usage = Desc.Usage;
+ pDesc->BindFlags = Desc.BindFlags;
+ pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
+ pDesc->MiscFlags = Desc.MiscFlags;
}
break;
case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
{
D3D10_TEXTURE2D_DESC Desc;
static_cast<ID3D10Texture2D *>(pResource)->GetDesc(&Desc);
- Desc.Usage = Usage;
- Desc.BindFlags = BindFlags;
- Desc.CPUAccessFlags = CPUAccessFlags;
- Desc.MiscFlags &= D3D10_RESOURCE_MISC_TEXTURECUBE;
-
- *pWidth = Desc.Width;
- *pHeight = Desc.Height;
- *pDepth = 1;
- *pMipLevels = Desc.MipLevels;
-
- hr = pDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture2D);
+ pDesc->Width = Desc.Width;
+ pDesc->Height = Desc.Height;
+ pDesc->MipLevels = Desc.MipLevels;
+ pDesc->ArraySize = Desc.ArraySize;
+ pDesc->Format = Desc.Format;
+ pDesc->SampleDesc = Desc.SampleDesc;
+ pDesc->Usage = Desc.Usage;
+ pDesc->BindFlags = Desc.BindFlags;
+ pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
+ pDesc->MiscFlags = Desc.MiscFlags;
}
break;
case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
{
D3D10_TEXTURE3D_DESC Desc;
static_cast<ID3D10Texture3D *>(pResource)->GetDesc(&Desc);
- Desc.Usage = Usage;
- Desc.BindFlags = BindFlags;
- Desc.CPUAccessFlags = CPUAccessFlags;
- Desc.MiscFlags = MiscFlags;
-
- *pWidth = Desc.Width;
- *pHeight = Desc.Height;
- *pDepth = Desc.Depth;
- *pMipLevels = Desc.MipLevels;
-
- hr = pDevice->CreateTexture3D(&Desc, NULL, &pStagingTexture3D);
+ pDesc->Width = Desc.Width;
+ pDesc->Height = Desc.Height;
+ pDesc->Depth = Desc.Depth;
+ pDesc->MipLevels = Desc.MipLevels;
+ pDesc->Format = Desc.Format;
+ pDesc->Usage = Desc.Usage;
+ pDesc->BindFlags = Desc.BindFlags;
+ pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
+ pDesc->MiscFlags = Desc.MiscFlags;
}
break;
default:
assert(0);
- hr = E_NOTIMPL;
break;
}
+}
+
- if (SUCCEEDED(hr)) {
- *ppStagingResource = pStagingResource;
- pDevice->CopyResource(pStagingResource, pResource);
+static HRESULT
+createResource(ID3D10Device *pDevice, const ResourceDesc *pDesc, ID3D10Resource **ppResource)
+{
+ switch (pDesc->Type) {
+ case D3D10_RESOURCE_DIMENSION_BUFFER:
+ {
+ D3D10_BUFFER_DESC Desc;
+ Desc.ByteWidth = pDesc->Width;
+ Desc.Usage = pDesc->Usage;
+ Desc.BindFlags = pDesc->BindFlags;
+ Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ Desc.MiscFlags = pDesc->MiscFlags;
+ return pDevice->CreateBuffer(&Desc, NULL, reinterpret_cast<ID3D10Buffer **>(ppResource));
+ }
+ case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
+ {
+ D3D10_TEXTURE1D_DESC Desc;
+ Desc.Width = pDesc->Width;
+ Desc.MipLevels = pDesc->MipLevels;
+ Desc.ArraySize = pDesc->ArraySize;
+ Desc.Format = pDesc->Format;
+ Desc.Usage = pDesc->Usage;
+ Desc.BindFlags = pDesc->BindFlags;
+ Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ Desc.MiscFlags = pDesc->MiscFlags;
+ return pDevice->CreateTexture1D(&Desc, NULL, reinterpret_cast<ID3D10Texture1D **>(ppResource));
+ }
+ case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
+ {
+ D3D10_TEXTURE2D_DESC Desc;
+ Desc.Width = pDesc->Width;
+ Desc.Height = pDesc->Height;
+ Desc.MipLevels = pDesc->MipLevels;
+ Desc.ArraySize = pDesc->ArraySize;
+ Desc.Format = pDesc->Format;
+ Desc.SampleDesc = pDesc->SampleDesc;
+ Desc.Usage = pDesc->Usage;
+ Desc.BindFlags = pDesc->BindFlags;
+ Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ Desc.MiscFlags = pDesc->MiscFlags;
+ return pDevice->CreateTexture2D(&Desc, NULL, reinterpret_cast<ID3D10Texture2D **>(ppResource));
+ }
+ case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
+ {
+ D3D10_TEXTURE3D_DESC Desc;
+ Desc.Width = pDesc->Width;
+ Desc.Height = pDesc->Height;
+ Desc.Depth = pDesc->Depth;
+ Desc.MipLevels = pDesc->MipLevels;
+ Desc.Format = pDesc->Format;
+ Desc.Usage = pDesc->Usage;
+ Desc.BindFlags = pDesc->BindFlags;
+ Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ Desc.MiscFlags = pDesc->MiscFlags;
+ return pDevice->CreateTexture3D(&Desc, NULL, reinterpret_cast<ID3D10Texture3D **>(ppResource));
+ }
+ default:
+ assert(0);
+ *ppResource = NULL;
+ return E_NOTIMPL;
}
-
- return hr;
}
+
static HRESULT
mapResource(ID3D10Resource *pResource,
UINT SubResource, D3D10_MAP MapType, UINT MapFlags,
@@ -165,6 +228,7 @@ mapResource(ID3D10Resource *pResource,
}
}
+
static void
unmapResource(ID3D10Resource *pResource, UINT SubResource) {
D3D10_RESOURCE_DIMENSION Type = D3D10_RESOURCE_DIMENSION_UNKNOWN;
@@ -189,7 +253,7 @@ unmapResource(ID3D10Resource *pResource, UINT SubResource) {
}
-static image::Image *
+image::Image *
getSubResourceImage(ID3D10Device *pDevice,
ID3D10Resource *pResource,
DXGI_FORMAT Format,
@@ -197,9 +261,6 @@ getSubResourceImage(ID3D10Device *pDevice,
UINT MipSlice)
{
image::Image *image = NULL;
- ID3D10Resource *pStagingResource = NULL;
- UINT Width, Height, Depth;
- UINT MipLevels;
UINT SubResource;
D3D10_MAPPED_TEXTURE3D MappedSubResource;
HRESULT hr;
@@ -208,18 +269,65 @@ getSubResourceImage(ID3D10Device *pDevice,
return NULL;
}
- hr = stageResource(pDevice, pResource, &pStagingResource, &Width, &Height, &Depth, &MipLevels);
+ ResourceDesc Desc;
+ getResourceDesc(pResource, &Desc);
+ assert(ArraySlice < Desc.ArraySize);
+ assert(MipSlice < Desc.MipLevels);
+ assert(Desc.SampleDesc.Count > 0);
+
+ SubResource = ArraySlice*Desc.MipLevels + MipSlice;
+
+ /*
+ * Resolve the subresource.
+ */
+
+ ResourceDesc ResolvedDesc = Desc;
+ ResolvedDesc.Width = std::max(Desc.Width >> MipSlice, 1U);
+ ResolvedDesc.Height = std::max(Desc.Height >> MipSlice, 1U);
+ ResolvedDesc.Depth = std::max(Desc.Depth >> MipSlice, 1U);
+ ResolvedDesc.ArraySize = 1;
+ ResolvedDesc.MipLevels = 1;
+ ResolvedDesc.SampleDesc.Count = 1;
+ ResolvedDesc.SampleDesc.Quality = 0;
+ ResolvedDesc.Usage = D3D10_USAGE_DEFAULT;
+ ResolvedDesc.BindFlags = 0;
+ ResolvedDesc.CPUAccessFlags = 0;
+ ResolvedDesc.MiscFlags = 0;
+
+ com_ptr<ID3D10Resource> pResolvedResource;
+ if (Desc.SampleDesc.Count == 1) {
+ pResolvedResource = pResource;
+ } else {
+ hr = createResource(pDevice, &ResolvedDesc, &pResolvedResource);
+ if (FAILED(hr)) {
+ return NULL;
+ }
+
+ pDevice->ResolveSubresource(pResolvedResource, 0, pResource, SubResource, Format);
+ SubResource = 0;
+ }
+
+ /*
+ * Stage the subresource.
+ */
+
+ ResourceDesc StagingDesc = ResolvedDesc;
+ StagingDesc.Usage = D3D10_USAGE_STAGING;
+ StagingDesc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
+
+ com_ptr<ID3D10Resource> pStagingResource;
+ hr = createResource(pDevice, &StagingDesc, &pStagingResource);
if (FAILED(hr)) {
- goto no_staging;
+ return NULL;
}
- SubResource = ArraySlice*MipLevels + MipSlice;
+ pDevice->CopySubresourceRegion(pStagingResource, 0, 0, 0, 0, pResolvedResource, SubResource, NULL);
- Width = std::max(Width >> MipSlice, 1U);
- Height = std::max(Height >> MipSlice, 1U);
- Depth = std::max(Depth >> MipSlice, 1U);
+ /*
+ * Map and read the subresource.
+ */
- hr = mapResource(pStagingResource, SubResource, D3D10_MAP_READ, 0, &MappedSubResource);
+ hr = mapResource(pStagingResource, 0, D3D10_MAP_READ, 0, &MappedSubResource);
if (FAILED(hr)) {
goto no_map;
}
@@ -227,44 +335,42 @@ getSubResourceImage(ID3D10Device *pDevice,
image = ConvertImage(Format,
MappedSubResource.pData,
MappedSubResource.RowPitch,
- Width, Height);
+ StagingDesc.Width, StagingDesc.Height);
- unmapResource(pStagingResource, SubResource);
-no_map:
- if (pStagingResource) {
- pStagingResource->Release();
- }
-no_staging:
- if (pResource) {
- pResource->Release();
+ unmapResource(pStagingResource, 0);
+
+ if (image) {
+ image->label = getObjectName(pResource);
+ std::cerr << image->label << "\n";
}
+
+no_map:
return image;
}
static void
-dumpShaderResourceViewImage(JSONWriter &json,
+dumpShaderResourceViewImage(StateWriter &writer,
ID3D10Device *pDevice,
ID3D10ShaderResourceView *pShaderResourceView,
const char *shader,
- UINT stage) {
- D3D10_SHADER_RESOURCE_VIEW_DESC Desc;
- ID3D10Resource *pResource = NULL;
-
+ UINT stage)
+{
if (!pShaderResourceView) {
return;
}
+ com_ptr<ID3D10Resource> pResource;
pShaderResourceView->GetResource(&pResource);
assert(pResource);
+ D3D10_SHADER_RESOURCE_VIEW_DESC Desc;
pShaderResourceView->GetDesc(&Desc);
UINT MipSlice = 0;
UINT FirstArraySlice = 0;
UINT ArraySize = 1;
- // TODO: Take the slice in consideration
switch (Desc.ViewDimension) {
case D3D10_SRV_DIMENSION_BUFFER:
break;
@@ -273,16 +379,22 @@ dumpShaderResourceViewImage(JSONWriter &json,
break;
case D3D10_SRV_DIMENSION_TEXTURE1DARRAY:
MipSlice = Desc.Texture1DArray.MostDetailedMip;
+ FirstArraySlice = Desc.Texture1DArray.FirstArraySlice;
+ ArraySize = Desc.Texture1DArray.ArraySize;
break;
case D3D10_SRV_DIMENSION_TEXTURE2D:
MipSlice = Desc.Texture2D.MostDetailedMip;
break;
case D3D10_SRV_DIMENSION_TEXTURE2DARRAY:
MipSlice = Desc.Texture2DArray.MostDetailedMip;
+ FirstArraySlice = Desc.Texture2DArray.FirstArraySlice;
+ ArraySize = Desc.Texture2DArray.ArraySize;
break;
case D3D10_SRV_DIMENSION_TEXTURE2DMS:
break;
case D3D10_SRV_DIMENSION_TEXTURE2DMSARRAY:
+ FirstArraySlice = Desc.Texture2DMSArray.FirstArraySlice;
+ ArraySize = Desc.Texture2DMSArray.ArraySize;
break;
case D3D10_SRV_DIMENSION_TEXTURE3D:
MipSlice = Desc.Texture3D.MostDetailedMip;
@@ -306,9 +418,12 @@ dumpShaderResourceViewImage(JSONWriter &json,
_snprintf(label, sizeof label,
"%s_RESOURCE_%u_ARRAY_%u_LEVEL_%u",
shader, stage, ArraySlice, MipSlice);
- json.beginMember(label);
- json.writeImage(image, "UNKNOWN");
- json.endMember(); // *_RESOURCE_*
+ StateWriter::ImageDesc imgDesc;
+ imgDesc.depth = 1;
+ imgDesc.format = getDXGIFormatName(Desc.Format);
+ writer.beginMember(label);
+ writer.writeImage(image, imgDesc);
+ writer.endMember(); // *_RESOURCE_*
delete image;
}
@@ -318,21 +433,26 @@ dumpShaderResourceViewImage(JSONWriter &json,
static image::Image *
getRenderTargetViewImage(ID3D10Device *pDevice,
- ID3D10RenderTargetView *pRenderTargetView) {
- D3D10_RENDER_TARGET_VIEW_DESC Desc;
- ID3D10Resource *pResource = NULL;
- UINT MipSlice;
-
+ ID3D10RenderTargetView *pRenderTargetView,
+ DXGI_FORMAT *dxgiFormat)
+{
if (!pRenderTargetView) {
return NULL;
}
+ com_ptr<ID3D10Resource> pResource;
pRenderTargetView->GetResource(&pResource);
assert(pResource);
+ D3D10_RENDER_TARGET_VIEW_DESC Desc;
pRenderTargetView->GetDesc(&Desc);
+ if (dxgiFormat) {
+ *dxgiFormat = Desc.Format;
+ }
+
// TODO: Take the slice in consideration
+ UINT MipSlice;
switch (Desc.ViewDimension) {
case D3D10_RTV_DIMENSION_BUFFER:
MipSlice = 0;
@@ -370,21 +490,26 @@ getRenderTargetViewImage(ID3D10Device *pDevice,
static image::Image *
getDepthStencilViewImage(ID3D10Device *pDevice,
- ID3D10DepthStencilView *pDepthStencilView) {
- D3D10_DEPTH_STENCIL_VIEW_DESC Desc;
- ID3D10Resource *pResource = NULL;
- UINT MipSlice;
-
+ ID3D10DepthStencilView *pDepthStencilView,
+ DXGI_FORMAT *dxgiFormat)
+{
if (!pDepthStencilView) {
return NULL;
}
+ com_ptr<ID3D10Resource> pResource;
pDepthStencilView->GetResource(&pResource);
assert(pResource);
+ D3D10_DEPTH_STENCIL_VIEW_DESC Desc;
pDepthStencilView->GetDesc(&Desc);
+ if (dxgiFormat) {
+ *dxgiFormat = Desc.Format;
+ }
+
// TODO: Take the slice in consideration
+ UINT MipSlice;
switch (Desc.ViewDimension) {
case D3D10_DSV_DIMENSION_TEXTURE1D:
MipSlice = Desc.Texture1D.MipSlice;
@@ -415,7 +540,7 @@ getDepthStencilViewImage(ID3D10Device *pDevice,
static void
-dumpStageTextures(JSONWriter &json, ID3D10Device *pDevice, const char *stageName,
+dumpStageTextures(StateWriter &writer, ID3D10Device *pDevice, const char *stageName,
UINT NumViews,
ID3D10ShaderResourceView **ppShaderResourceViews)
{
@@ -424,7 +549,7 @@ dumpStageTextures(JSONWriter &json, ID3D10Device *pDevice, const char *stageName
continue;
}
- dumpShaderResourceViewImage(json, pDevice, ppShaderResourceViews[i], stageName, i);
+ dumpShaderResourceViewImage(writer, pDevice, ppShaderResourceViews[i], stageName, i);
ppShaderResourceViews[i]->Release();
}
@@ -432,36 +557,36 @@ dumpStageTextures(JSONWriter &json, ID3D10Device *pDevice, const char *stageName
void
-dumpTextures(JSONWriter &json, ID3D10Device *pDevice)
+dumpTextures(StateWriter &writer, ID3D10Device *pDevice)
{
- json.beginMember("textures");
- json.beginObject();
+ writer.beginMember("textures");
+ writer.beginObject();
ID3D10ShaderResourceView *pShaderResourceViews[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT];
pDevice->PSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
- dumpStageTextures(json, pDevice, "PS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+ dumpStageTextures(writer, pDevice, "PS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
pDevice->VSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
- dumpStageTextures(json, pDevice, "VS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+ dumpStageTextures(writer, pDevice, "VS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
pDevice->GSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
- dumpStageTextures(json, pDevice, "GS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+ dumpStageTextures(writer, pDevice, "GS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
- json.endObject();
- json.endMember(); // textures
+ writer.endObject();
+ writer.endMember(); // textures
}
image::Image *
-getRenderTargetImage(ID3D10Device *pDevice) {
- ID3D10RenderTargetView *pRenderTargetView = NULL;
+getRenderTargetImage(ID3D10Device *pDevice,
+ DXGI_FORMAT *dxgiFormat) {
+ com_ptr<ID3D10RenderTargetView> pRenderTargetView;
pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL);
image::Image *image = NULL;
if (pRenderTargetView) {
- image = getRenderTargetViewImage(pDevice, pRenderTargetView);
- pRenderTargetView->Release();
+ image = getRenderTargetViewImage(pDevice, pRenderTargetView, dxgiFormat);
}
return image;
@@ -469,10 +594,10 @@ getRenderTargetImage(ID3D10Device *pDevice) {
void
-dumpFramebuffer(JSONWriter &json, ID3D10Device *pDevice)
+dumpFramebuffer(StateWriter &writer, ID3D10Device *pDevice)
{
- json.beginMember("framebuffer");
- json.beginObject();
+ writer.beginMember("framebuffer");
+ writer.beginObject();
ID3D10RenderTargetView *pRenderTargetViews[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT];
ID3D10DepthStencilView *pDepthStencilView;
@@ -485,13 +610,18 @@ dumpFramebuffer(JSONWriter &json, ID3D10Device *pDevice)
}
image::Image *image;
- image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i]);
+ DXGI_FORMAT dxgiFormat;
+ image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i],
+ &dxgiFormat);
if (image) {
char label[64];
_snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
- json.beginMember(label);
- json.writeImage(image, "UNKNOWN");
- json.endMember(); // RENDER_TARGET_*
+ StateWriter::ImageDesc imgDesc;
+ imgDesc.depth = 1;
+ imgDesc.format = getDXGIFormatName(dxgiFormat);
+ writer.beginMember(label);
+ writer.writeImage(image, imgDesc);
+ writer.endMember(); // RENDER_TARGET_*
delete image;
}
@@ -500,20 +630,24 @@ dumpFramebuffer(JSONWriter &json, ID3D10Device *pDevice)
if (pDepthStencilView) {
image::Image *image;
- image = getDepthStencilViewImage(pDevice, pDepthStencilView);
+ DXGI_FORMAT dxgiFormat;
+ image = getDepthStencilViewImage(pDevice, pDepthStencilView,
+ &dxgiFormat);
if (image) {
- json.beginMember("DEPTH_STENCIL");
- json.writeImage(image, "UNKNOWN");
- json.endMember();
+ StateWriter::ImageDesc imgDesc;
+ imgDesc.depth = 1;
+ imgDesc.format = getDXGIFormatName(dxgiFormat);
+ writer.beginMember("DEPTH_STENCIL");
+ writer.writeImage(image, imgDesc);
+ writer.endMember();
delete image;
}
pDepthStencilView->Release();
-
}
- json.endObject();
- json.endMember(); // framebuffer
+ writer.endObject();
+ writer.endMember(); // framebuffer
}
diff --git a/retrace/d3d11state.cpp b/retrace/d3d11state.cpp
index cc1f6c72..737e306f 100644
--- a/retrace/d3d11state.cpp
+++ b/retrace/d3d11state.cpp
@@ -27,61 +27,192 @@
#include <stdio.h>
#include <iostream>
+#include <type_traits>
+#include "com_ptr.hpp"
#include "d3d11imports.hpp"
#include "d3d10state.hpp"
+#include "dxgistate_so.hpp"
namespace d3dstate {
+// Ensure ExtractDescType template is sane
+static_assert( std::is_same< ExtractDescType< decltype( &ID3D11BlendState::GetDesc ) >::type, D3D11_BLEND_DESC >::value, "type mismatch" );
+
+
+static void
+dumpRasterizerState(StateWriter &writer, ID3D11DeviceContext *pDeviceContext)
+{
+ com_ptr<ID3D11RasterizerState> pRasterizerState;
+
+ pDeviceContext->RSGetState(&pRasterizerState);
+ writer.beginMember("RasterizerState");
+ dumpStateObjectDesc(writer, pRasterizerState);
+ writer.endMember(); // RasterizerState
+}
+
+
+static void
+dumpBlendState(StateWriter &writer, ID3D11DeviceContext *pDeviceContext)
+{
+ com_ptr<ID3D11BlendState> pBlendState;
+ FLOAT BlendFactor[4];
+ UINT SampleMask;
+
+ pDeviceContext->OMGetBlendState(&pBlendState, BlendFactor, &SampleMask);
+
+ writer.beginMember("BlendState");
+ dumpStateObjectDesc(writer, pBlendState);
+ writer.endMember(); // BlendState
+
+ writer.beginMember("BlendFactor");
+ writer.beginArray();
+ writer.writeFloat(BlendFactor[0]);
+ writer.writeFloat(BlendFactor[1]);
+ writer.writeFloat(BlendFactor[2]);
+ writer.writeFloat(BlendFactor[3]);
+ writer.endArray();
+ writer.endMember(); // BlendFactor
+
+ writer.writeIntMember("SampleMask", SampleMask);
+}
+
+
+static void
+dumpDepthStencilState(StateWriter &writer, ID3D11DeviceContext *pDeviceContext)
+{
+ com_ptr<ID3D11DepthStencilState> pDepthStencilState;
+ UINT stencilRef;
+
+ pDeviceContext->OMGetDepthStencilState(&pDepthStencilState, &stencilRef);
+ writer.beginMember("DepthStencilState");
+ dumpStateObjectDesc(writer, pDepthStencilState);
+ writer.endMember(); // DepthStencilState
+ writer.writeIntMember("StencilRef", stencilRef);
+}
+
+
+static void
+dumpViewports(StateWriter &writer, ID3D11DeviceContext *pDeviceContext)
+{
+ D3D11_VIEWPORT vps[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ UINT numViewports = 0, i;
+
+ pDeviceContext->RSGetViewports(&numViewports, NULL);
+ pDeviceContext->RSGetViewports(&numViewports, vps);
+
+ writer.beginMember("Viewports");
+ writer.beginArray();
+ for (i = 0; i < numViewports; ++i) {
+ dumpStateObject(writer, vps[i]);
+ }
+ writer.endArray();
+ writer.endMember();
+}
+
+
+static void
+dumpScissors(StateWriter &writer, ID3D11DeviceContext *pDeviceContext)
+{
+ D3D11_RECT rects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ UINT numRects = 0, i;
+
+ pDeviceContext->RSGetScissorRects(&numRects, NULL);
+ pDeviceContext->RSGetScissorRects(&numRects, rects);
+
+ writer.beginMember("Scissors");
+ writer.beginArray();
+ for (i = 0; i < numRects; ++i) {
+ dumpStateObject(writer, rects[i]);
+ }
+ writer.endArray();
+ writer.endMember();
+}
+
+
static void
-dumpShaders(JSONWriter &json, ID3D11DeviceContext *pDeviceContext)
+dumpParameters(StateWriter &writer, ID3D11DeviceContext *pDeviceContext)
{
- json.beginMember("shaders");
- json.beginObject();
+ // TODO: dump description of current bound state
+ writer.beginMember("parameters");
+ writer.beginObject();
+
+ dumpRasterizerState(writer, pDeviceContext);
+ dumpBlendState(writer, pDeviceContext);
+ dumpDepthStencilState(writer, pDeviceContext);
+ dumpViewports(writer, pDeviceContext);
+ dumpScissors(writer, pDeviceContext);
+
+ writer.endObject();
+ writer.endMember(); // parameters
+}
- ID3D11VertexShader *pVertexShader = NULL;
+
+static void
+dumpShaders(StateWriter &writer, ID3D11DeviceContext *pDeviceContext)
+{
+ writer.beginMember("shaders");
+ writer.beginObject();
+
+ com_ptr<ID3D11VertexShader> pVertexShader;
pDeviceContext->VSGetShader(&pVertexShader, NULL, NULL);
if (pVertexShader) {
- dumpShader<ID3D11DeviceChild>(json, "VS", pVertexShader);
- pVertexShader->Release();
+ dumpShader<ID3D11DeviceChild>(writer, "VS", pVertexShader);
}
- ID3D11GeometryShader *pGeometryShader = NULL;
+ com_ptr<ID3D11HullShader> pHullShader;
+ pDeviceContext->HSGetShader(&pHullShader, NULL, NULL);
+ if (pHullShader) {
+ dumpShader<ID3D11DeviceChild>(writer, "HS", pHullShader);
+ }
+
+ com_ptr<ID3D11DomainShader> pDomainShader;
+ pDeviceContext->DSGetShader(&pDomainShader, NULL, NULL);
+ if (pDomainShader) {
+ dumpShader<ID3D11DeviceChild>(writer, "DS", pDomainShader);
+ }
+
+ com_ptr<ID3D11GeometryShader> pGeometryShader;
pDeviceContext->GSGetShader(&pGeometryShader, NULL, NULL);
if (pGeometryShader) {
- dumpShader<ID3D11DeviceChild>(json, "GS", pGeometryShader);
- pGeometryShader->Release();
+ dumpShader<ID3D11DeviceChild>(writer, "GS", pGeometryShader);
}
- ID3D11PixelShader *pPixelShader = NULL;
+ com_ptr<ID3D11PixelShader> pPixelShader;
pDeviceContext->PSGetShader(&pPixelShader, NULL, NULL);
if (pPixelShader) {
- dumpShader<ID3D11DeviceChild>(json, "PS", pPixelShader);
+ dumpShader<ID3D11DeviceChild>(writer, "PS", pPixelShader);
}
- json.endObject();
- json.endMember(); // shaders
+ writer.endObject();
+ writer.endMember(); // shaders
}
void
-dumpDevice(std::ostream &os, ID3D11DeviceContext *pDeviceContext)
+dumpDevice(StateWriter &writer, ID3D11DeviceContext *pDeviceContext)
{
- JSONWriter json(os);
+ dumpParameters(writer, pDeviceContext);
+
+ dumpShaders(writer, pDeviceContext);
- /* TODO */
- json.beginMember("parameters");
- json.beginObject();
- json.endObject();
- json.endMember(); // parameters
+ // TODO: dump constant buffers
+ writer.beginMember("uniforms");
+ writer.beginObject();
+ writer.endObject();
+ writer.endMember(); // uniforms
- dumpShaders(json, pDeviceContext);
+ // TODO: dump stream-out buffer, vertex buffer
+ writer.beginMember("buffers");
+ writer.beginObject();
+ writer.endObject();
+ writer.endMember(); // buffers
- dumpTextures(json, pDeviceContext);
+ dumpTextures(writer, pDeviceContext);
- dumpFramebuffer(json, pDeviceContext);
+ dumpFramebuffer(writer, pDeviceContext);
}
diff --git a/common/trace_file_write.cpp b/retrace/d3d11state.hpp
index 4cc8984e..9438b658 100644
--- a/common/trace_file_write.cpp
+++ b/retrace/d3d11state.hpp
@@ -23,28 +23,25 @@
*
**************************************************************************/
+#pragma once
-#include "os.hpp"
-#include "trace_file.hpp"
+#include <windows.h>
-using namespace trace;
+#include "d3dstate.hpp"
-File *
-File::createForWrite(const char *filename)
-{
- File *file;
- file = File::createSnappy();
- if (!file) {
- return NULL;
- }
- if (!file->open(filename, File::Write)) {
- os::log("error: could not open %s for writing\n", filename);
- delete file;
- return NULL;
- }
+namespace d3dstate {
+
+
+image::Image *
+getSubResourceImage(ID3D11DeviceContext *pDevice,
+ ID3D11Resource *pResource,
+ DXGI_FORMAT Format,
+ UINT ArraySlice,
+ UINT MipSlice);
+
+
+} /* namespace d3dstate */
- return file;
-}
diff --git a/retrace/d3d11state_images.cpp b/retrace/d3d11state_images.cpp
index b8dfc3a9..8bc1d0fa 100644
--- a/retrace/d3d11state_images.cpp
+++ b/retrace/d3d11state_images.cpp
@@ -1,5 +1,6 @@
/**************************************************************************
*
+ * Copyright 2014 VMware, Inc.
* Copyright 2011 Jose Fonseca
* All Rights Reserved.
*
@@ -30,135 +31,189 @@
#include <algorithm>
#include "os.hpp"
-#include "json.hpp"
+#include "state_writer.hpp"
#include "image.hpp"
+#include "com_ptr.hpp"
#include "d3d11imports.hpp"
+#include "d3d11state.hpp"
#include "d3d10state.hpp"
#include "dxgistate.hpp"
namespace d3dstate {
-static HRESULT
-stageResource(ID3D11DeviceContext *pDeviceContext,
- ID3D11Resource *pResource,
- ID3D11Resource **ppStagingResource,
- UINT *pWidth, UINT *pHeight, UINT *pDepth,
- UINT *pMipLevels) {
- D3D11_USAGE Usage = D3D11_USAGE_STAGING;
- UINT BindFlags = 0;
- UINT CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- UINT MiscFlags = 0;
- union {
- ID3D11Resource *pStagingResource;
- ID3D11Buffer *pStagingBuffer;
- ID3D11Texture1D *pStagingTexture1D;
- ID3D11Texture2D *pStagingTexture2D;
- ID3D11Texture3D *pStagingTexture3D;
- };
- HRESULT hr;
- ID3D11Device *pDevice = NULL;
- pDeviceContext->GetDevice(&pDevice);
+struct ResourceDesc
+{
+ D3D11_RESOURCE_DIMENSION Type;
+ UINT Width;
+ UINT Height;
+ UINT Depth;
+ UINT MipLevels;
+ UINT ArraySize;
+ DXGI_FORMAT Format;
+ DXGI_SAMPLE_DESC SampleDesc;
+ D3D11_USAGE Usage;
+ UINT BindFlags;
+ UINT CPUAccessFlags;
+ UINT MiscFlags;
+};
+
- D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
- pResource->GetType(&Type);
- switch (Type) {
+static void
+getResourceDesc(ID3D11Resource *pResource, ResourceDesc *pDesc)
+{
+ pDesc->Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
+ pDesc->Width = 0;
+ pDesc->Height = 1;
+ pDesc->Depth = 1;
+ pDesc->MipLevels = 1;
+ pDesc->ArraySize = 1;
+ pDesc->Format = DXGI_FORMAT_UNKNOWN;
+ pDesc->SampleDesc.Count = 1;
+ pDesc->SampleDesc.Quality = 0;
+ pDesc->Usage = D3D11_USAGE_DEFAULT;
+ pDesc->BindFlags = 0;
+ pDesc->CPUAccessFlags = 0;
+ pDesc->MiscFlags = 0;
+
+ pResource->GetType(&pDesc->Type);
+ switch (pDesc->Type) {
case D3D11_RESOURCE_DIMENSION_BUFFER:
{
D3D11_BUFFER_DESC Desc;
static_cast<ID3D11Buffer *>(pResource)->GetDesc(&Desc);
- Desc.Usage = Usage;
- Desc.BindFlags = BindFlags;
- Desc.CPUAccessFlags = CPUAccessFlags;
- Desc.MiscFlags = MiscFlags;
-
- *pWidth = Desc.ByteWidth;
- *pHeight = 1;
- *pDepth = 1;
- *pMipLevels = 1;
-
- hr = pDevice->CreateBuffer(&Desc, NULL, &pStagingBuffer);
+ pDesc->Width = Desc.ByteWidth;
+ pDesc->Usage = Desc.Usage;
+ pDesc->BindFlags = Desc.BindFlags;
+ pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
+ pDesc->MiscFlags = Desc.MiscFlags;
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
{
D3D11_TEXTURE1D_DESC Desc;
static_cast<ID3D11Texture1D *>(pResource)->GetDesc(&Desc);
- Desc.Usage = Usage;
- Desc.BindFlags = BindFlags;
- Desc.CPUAccessFlags = CPUAccessFlags;
- Desc.MiscFlags = MiscFlags;
-
- *pWidth = Desc.Width;
- *pHeight = 1;
- *pDepth = 1;
- *pMipLevels = Desc.MipLevels;
-
- hr = pDevice->CreateTexture1D(&Desc, NULL, &pStagingTexture1D);
+ pDesc->Width = Desc.Width;
+ pDesc->MipLevels = Desc.MipLevels;
+ pDesc->ArraySize = Desc.ArraySize;
+ pDesc->Format = Desc.Format;
+ pDesc->Usage = Desc.Usage;
+ pDesc->BindFlags = Desc.BindFlags;
+ pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
+ pDesc->MiscFlags = Desc.MiscFlags;
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
{
D3D11_TEXTURE2D_DESC Desc;
static_cast<ID3D11Texture2D *>(pResource)->GetDesc(&Desc);
- Desc.Usage = Usage;
- Desc.BindFlags = BindFlags;
- Desc.CPUAccessFlags = CPUAccessFlags;
- Desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;
-
- *pWidth = Desc.Width;
- *pHeight = Desc.Height;
- *pDepth = 1;
- *pMipLevels = Desc.MipLevels;
-
- hr = pDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture2D);
+ pDesc->Width = Desc.Width;
+ pDesc->Height = Desc.Height;
+ pDesc->MipLevels = Desc.MipLevels;
+ pDesc->ArraySize = Desc.ArraySize;
+ pDesc->Format = Desc.Format;
+ pDesc->SampleDesc = Desc.SampleDesc;
+ pDesc->Usage = Desc.Usage;
+ pDesc->BindFlags = Desc.BindFlags;
+ pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
+ pDesc->MiscFlags = Desc.MiscFlags;
}
break;
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
{
D3D11_TEXTURE3D_DESC Desc;
static_cast<ID3D11Texture3D *>(pResource)->GetDesc(&Desc);
- Desc.Usage = Usage;
- Desc.BindFlags = BindFlags;
- Desc.CPUAccessFlags = CPUAccessFlags;
- Desc.MiscFlags = MiscFlags;
-
- *pWidth = Desc.Width;
- *pHeight = Desc.Height;
- *pDepth = Desc.Depth;
- *pMipLevels = Desc.MipLevels;
-
- hr = pDevice->CreateTexture3D(&Desc, NULL, &pStagingTexture3D);
+ pDesc->Width = Desc.Width;
+ pDesc->Height = Desc.Height;
+ pDesc->Depth = Desc.Depth;
+ pDesc->MipLevels = Desc.MipLevels;
+ pDesc->Format = Desc.Format;
+ pDesc->Usage = Desc.Usage;
+ pDesc->BindFlags = Desc.BindFlags;
+ pDesc->CPUAccessFlags = Desc.CPUAccessFlags;
+ pDesc->MiscFlags = Desc.MiscFlags;
}
break;
default:
assert(0);
- hr = E_NOTIMPL;
break;
}
+}
- if (SUCCEEDED(hr)) {
- *ppStagingResource = pStagingResource;
- pDeviceContext->CopyResource(pStagingResource, pResource);
- }
-
- pDevice->Release();
- return hr;
+static HRESULT
+createResource(ID3D11Device *pDevice, const ResourceDesc *pDesc, ID3D11Resource **ppResource)
+{
+ switch (pDesc->Type) {
+ case D3D11_RESOURCE_DIMENSION_BUFFER:
+ {
+ D3D11_BUFFER_DESC Desc;
+ Desc.ByteWidth = pDesc->Width;
+ Desc.Usage = pDesc->Usage;
+ Desc.BindFlags = pDesc->BindFlags;
+ Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ Desc.MiscFlags = pDesc->MiscFlags;
+ return pDevice->CreateBuffer(&Desc, NULL, reinterpret_cast<ID3D11Buffer **>(ppResource));
+ }
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ {
+ D3D11_TEXTURE1D_DESC Desc;
+ Desc.Width = pDesc->Width;
+ Desc.MipLevels = pDesc->MipLevels;
+ Desc.ArraySize = pDesc->ArraySize;
+ Desc.Format = pDesc->Format;
+ Desc.Usage = pDesc->Usage;
+ Desc.BindFlags = pDesc->BindFlags;
+ Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ Desc.MiscFlags = pDesc->MiscFlags;
+ return pDevice->CreateTexture1D(&Desc, NULL, reinterpret_cast<ID3D11Texture1D **>(ppResource));
+ }
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ {
+ D3D11_TEXTURE2D_DESC Desc;
+ Desc.Width = pDesc->Width;
+ Desc.Height = pDesc->Height;
+ Desc.MipLevels = pDesc->MipLevels;
+ Desc.ArraySize = pDesc->ArraySize;
+ Desc.Format = pDesc->Format;
+ Desc.SampleDesc = pDesc->SampleDesc;
+ Desc.Usage = pDesc->Usage;
+ Desc.BindFlags = pDesc->BindFlags;
+ Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ Desc.MiscFlags = pDesc->MiscFlags;
+ return pDevice->CreateTexture2D(&Desc, NULL, reinterpret_cast<ID3D11Texture2D **>(ppResource));
+ }
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ {
+ D3D11_TEXTURE3D_DESC Desc;
+ Desc.Width = pDesc->Width;
+ Desc.Height = pDesc->Height;
+ Desc.Depth = pDesc->Depth;
+ Desc.MipLevels = pDesc->MipLevels;
+ Desc.Format = pDesc->Format;
+ Desc.Usage = pDesc->Usage;
+ Desc.BindFlags = pDesc->BindFlags;
+ Desc.CPUAccessFlags = pDesc->CPUAccessFlags;
+ Desc.MiscFlags = pDesc->MiscFlags;
+ return pDevice->CreateTexture3D(&Desc, NULL, reinterpret_cast<ID3D11Texture3D **>(ppResource));
+ }
+ default:
+ assert(0);
+ *ppResource = NULL;
+ return E_NOTIMPL;
+ }
}
-static image::Image *
-getSubResourceImage(ID3D11DeviceContext *pDevice,
+
+image::Image *
+getSubResourceImage(ID3D11DeviceContext *pDeviceContext,
ID3D11Resource *pResource,
DXGI_FORMAT Format,
UINT ArraySlice,
UINT MipSlice)
{
image::Image *image = NULL;
- ID3D11Resource *pStagingResource = NULL;
- UINT Width, Height, Depth;
- UINT MipLevels;
UINT SubResource;
D3D11_MAPPED_SUBRESOURCE MappedSubResource;
HRESULT hr;
@@ -167,18 +222,68 @@ getSubResourceImage(ID3D11DeviceContext *pDevice,
return NULL;
}
- hr = stageResource(pDevice, pResource, &pStagingResource, &Width, &Height, &Depth, &MipLevels);
+ com_ptr<ID3D11Device> pDevice;
+ pDeviceContext->GetDevice(&pDevice);
+
+ ResourceDesc Desc;
+ getResourceDesc(pResource, &Desc);
+ assert(ArraySlice < Desc.ArraySize);
+ assert(MipSlice < Desc.MipLevels);
+ assert(Desc.SampleDesc.Count > 0);
+
+ SubResource = ArraySlice*Desc.MipLevels + MipSlice;
+
+ /*
+ * Resolve the subresource.
+ */
+
+ ResourceDesc ResolvedDesc = Desc;
+ ResolvedDesc.Width = std::max(Desc.Width >> MipSlice, 1U);
+ ResolvedDesc.Height = std::max(Desc.Height >> MipSlice, 1U);
+ ResolvedDesc.Depth = std::max(Desc.Depth >> MipSlice, 1U);
+ ResolvedDesc.ArraySize = 1;
+ ResolvedDesc.MipLevels = 1;
+ ResolvedDesc.SampleDesc.Count = 1;
+ ResolvedDesc.SampleDesc.Quality = 0;
+ ResolvedDesc.Usage = D3D11_USAGE_DEFAULT;
+ ResolvedDesc.BindFlags = 0;
+ ResolvedDesc.CPUAccessFlags = 0;
+ ResolvedDesc.MiscFlags = 0;
+
+ com_ptr<ID3D11Resource> pResolvedResource;
+ if (Desc.SampleDesc.Count == 1) {
+ pResolvedResource = pResource;
+ } else {
+ hr = createResource(pDevice, &ResolvedDesc, &pResolvedResource);
+ if (FAILED(hr)) {
+ return NULL;
+ }
+
+ pDeviceContext->ResolveSubresource(pResolvedResource, 0, pResource, SubResource, Format);
+ SubResource = 0;
+ }
+
+ /*
+ * Stage the subresource.
+ */
+
+ ResourceDesc StagingDesc = ResolvedDesc;
+ StagingDesc.Usage = D3D11_USAGE_STAGING;
+ StagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+
+ com_ptr<ID3D11Resource> pStagingResource;
+ hr = createResource(pDevice, &StagingDesc, &pStagingResource);
if (FAILED(hr)) {
- goto no_staging;
+ return NULL;
}
- SubResource = ArraySlice*MipLevels + MipSlice;
+ pDeviceContext->CopySubresourceRegion(pStagingResource, 0, 0, 0, 0, pResolvedResource, SubResource, NULL);
- Width = std::max(Width >> MipSlice, 1U);
- Height = std::max(Height >> MipSlice, 1U);
- Depth = std::max(Depth >> MipSlice, 1U);
+ /*
+ * Map and read the subresource.
+ */
- hr = pDevice->Map(pStagingResource, SubResource, D3D11_MAP_READ, 0, &MappedSubResource);
+ hr = pDeviceContext->Map(pStagingResource, 0, D3D11_MAP_READ, 0, &MappedSubResource);
if (FAILED(hr)) {
goto no_map;
}
@@ -186,62 +291,67 @@ getSubResourceImage(ID3D11DeviceContext *pDevice,
image = ConvertImage(Format,
MappedSubResource.pData,
MappedSubResource.RowPitch,
- Width, Height);
+ StagingDesc.Width, StagingDesc.Height);
- pDevice->Unmap(pStagingResource, SubResource);
-no_map:
- if (pStagingResource) {
- pStagingResource->Release();
- }
-no_staging:
- if (pResource) {
- pResource->Release();
+ pDeviceContext->Unmap(pStagingResource, 0);
+
+ if (image) {
+ image->label = getObjectName(pResource);
+ std::cerr << image->label << "\n";
}
+
+no_map:
return image;
}
static void
-dumpShaderResourceViewImage(JSONWriter &json,
+dumpShaderResourceViewImage(StateWriter &writer,
ID3D11DeviceContext *pDevice,
ID3D11ShaderResourceView *pShaderResourceView,
const char *shader,
- UINT stage) {
- D3D11_SHADER_RESOURCE_VIEW_DESC Desc;
- ID3D11Resource *pResource = NULL;
-
+ UINT stage)
+{
if (!pShaderResourceView) {
return;
}
+ com_ptr<ID3D11Resource> pResource;
pShaderResourceView->GetResource(&pResource);
assert(pResource);
+ D3D11_SHADER_RESOURCE_VIEW_DESC Desc;
pShaderResourceView->GetDesc(&Desc);
UINT MipSlice = 0;
UINT FirstArraySlice = 0;
UINT ArraySize = 1;
- // TODO: Take the slice in consideration
switch (Desc.ViewDimension) {
case D3D11_SRV_DIMENSION_BUFFER:
+ case D3D11_SRV_DIMENSION_BUFFEREX:
break;
case D3D11_SRV_DIMENSION_TEXTURE1D:
MipSlice = Desc.Texture1D.MostDetailedMip;
break;
case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
MipSlice = Desc.Texture1DArray.MostDetailedMip;
+ FirstArraySlice = Desc.Texture1DArray.FirstArraySlice;
+ ArraySize = Desc.Texture1DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2D:
MipSlice = Desc.Texture2D.MostDetailedMip;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
MipSlice = Desc.Texture2DArray.MostDetailedMip;
+ FirstArraySlice = Desc.Texture2DArray.FirstArraySlice;
+ ArraySize = Desc.Texture2DArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMS:
break;
case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
+ FirstArraySlice = Desc.Texture2DMSArray.FirstArraySlice;
+ ArraySize = Desc.Texture2DMSArray.ArraySize;
break;
case D3D11_SRV_DIMENSION_TEXTURE3D:
MipSlice = Desc.Texture3D.MostDetailedMip;
@@ -250,6 +360,11 @@ dumpShaderResourceViewImage(JSONWriter &json,
MipSlice = Desc.TextureCube.MostDetailedMip;
ArraySize = 6;
break;
+ case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
+ MipSlice = Desc.TextureCubeArray.MostDetailedMip;
+ FirstArraySlice = Desc.TextureCubeArray.First2DArrayFace;
+ ArraySize = 6 * Desc.TextureCubeArray.NumCubes;
+ break;
case D3D11_SRV_DIMENSION_UNKNOWN:
default:
assert(0);
@@ -265,9 +380,12 @@ dumpShaderResourceViewImage(JSONWriter &json,
_snprintf(label, sizeof label,
"%s_RESOURCE_%u_ARRAY_%u_LEVEL_%u",
shader, stage, ArraySlice, MipSlice);
- json.beginMember(label);
- json.writeImage(image, "UNKNOWN");
- json.endMember(); // *_RESOURCE_*
+ StateWriter::ImageDesc imgDesc;
+ imgDesc.depth = 1;
+ imgDesc.format = getDXGIFormatName(Desc.Format);
+ writer.beginMember(label);
+ writer.writeImage(image, imgDesc);
+ writer.endMember(); // *_RESOURCE_*
delete image;
}
@@ -277,21 +395,26 @@ dumpShaderResourceViewImage(JSONWriter &json,
static image::Image *
getRenderTargetViewImage(ID3D11DeviceContext *pDevice,
- ID3D11RenderTargetView *pRenderTargetView) {
- D3D11_RENDER_TARGET_VIEW_DESC Desc;
- ID3D11Resource *pResource = NULL;
- UINT MipSlice;
-
+ ID3D11RenderTargetView *pRenderTargetView,
+ DXGI_FORMAT *dxgiFormat)
+{
if (!pRenderTargetView) {
return NULL;
}
+ com_ptr<ID3D11Resource> pResource;
pRenderTargetView->GetResource(&pResource);
assert(pResource);
+ D3D11_RENDER_TARGET_VIEW_DESC Desc;
pRenderTargetView->GetDesc(&Desc);
+ if (dxgiFormat) {
+ *dxgiFormat = Desc.Format;
+ }
+
// TODO: Take the slice in consideration
+ UINT MipSlice;
switch (Desc.ViewDimension) {
case D3D11_RTV_DIMENSION_BUFFER:
MipSlice = 0;
@@ -329,21 +452,26 @@ getRenderTargetViewImage(ID3D11DeviceContext *pDevice,
static image::Image *
getDepthStencilViewImage(ID3D11DeviceContext *pDevice,
- ID3D11DepthStencilView *pDepthStencilView) {
- D3D11_DEPTH_STENCIL_VIEW_DESC Desc;
- ID3D11Resource *pResource = NULL;
- UINT MipSlice;
-
+ ID3D11DepthStencilView *pDepthStencilView,
+ DXGI_FORMAT *dxgiFormat)
+{
if (!pDepthStencilView) {
return NULL;
}
+ com_ptr<ID3D11Resource> pResource;
pDepthStencilView->GetResource(&pResource);
assert(pResource);
+ D3D11_DEPTH_STENCIL_VIEW_DESC Desc;
pDepthStencilView->GetDesc(&Desc);
+ if (dxgiFormat) {
+ *dxgiFormat = Desc.Format;
+ }
+
// TODO: Take the slice in consideration
+ UINT MipSlice;
switch (Desc.ViewDimension) {
case D3D11_DSV_DIMENSION_TEXTURE1D:
MipSlice = Desc.Texture1D.MipSlice;
@@ -374,7 +502,7 @@ getDepthStencilViewImage(ID3D11DeviceContext *pDevice,
static void
-dumpStageTextures(JSONWriter &json, ID3D11DeviceContext *pDevice, const char *stageName,
+dumpStageTextures(StateWriter &writer, ID3D11DeviceContext *pDevice, const char *stageName,
UINT NumViews,
ID3D11ShaderResourceView **ppShaderResourceViews)
{
@@ -383,7 +511,7 @@ dumpStageTextures(JSONWriter &json, ID3D11DeviceContext *pDevice, const char *st
continue;
}
- dumpShaderResourceViewImage(json, pDevice, ppShaderResourceViews[i], stageName, i);
+ dumpShaderResourceViewImage(writer, pDevice, ppShaderResourceViews[i], stageName, i);
ppShaderResourceViews[i]->Release();
}
@@ -391,36 +519,42 @@ dumpStageTextures(JSONWriter &json, ID3D11DeviceContext *pDevice, const char *st
void
-dumpTextures(JSONWriter &json, ID3D11DeviceContext *pDevice)
+dumpTextures(StateWriter &writer, ID3D11DeviceContext *pDevice)
{
- json.beginMember("textures");
- json.beginObject();
+ writer.beginMember("textures");
+ writer.beginObject();
ID3D11ShaderResourceView *pShaderResourceViews[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
- pDevice->PSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
- dumpStageTextures(json, pDevice, "PS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
-
pDevice->VSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
- dumpStageTextures(json, pDevice, "VS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+ dumpStageTextures(writer, pDevice, "VS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+
+ pDevice->HSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+ dumpStageTextures(writer, pDevice, "HS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+
+ pDevice->DSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+ dumpStageTextures(writer, pDevice, "DS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
pDevice->GSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
- dumpStageTextures(json, pDevice, "GS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+ dumpStageTextures(writer, pDevice, "GS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
- json.endObject();
- json.endMember(); // textures
+ pDevice->PSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+ dumpStageTextures(writer, pDevice, "PS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
+
+ writer.endObject();
+ writer.endMember(); // textures
}
image::Image *
-getRenderTargetImage(ID3D11DeviceContext *pDevice) {
- ID3D11RenderTargetView *pRenderTargetView = NULL;
+getRenderTargetImage(ID3D11DeviceContext *pDevice,
+ DXGI_FORMAT *dxgiFormat) {
+ com_ptr<ID3D11RenderTargetView> pRenderTargetView;
pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL);
image::Image *image = NULL;
if (pRenderTargetView) {
- image = getRenderTargetViewImage(pDevice, pRenderTargetView);
- pRenderTargetView->Release();
+ image = getRenderTargetViewImage(pDevice, pRenderTargetView, dxgiFormat);
}
return image;
@@ -428,10 +562,10 @@ getRenderTargetImage(ID3D11DeviceContext *pDevice) {
void
-dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDevice)
+dumpFramebuffer(StateWriter &writer, ID3D11DeviceContext *pDevice)
{
- json.beginMember("framebuffer");
- json.beginObject();
+ writer.beginMember("framebuffer");
+ writer.beginObject();
ID3D11RenderTargetView *pRenderTargetViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
ID3D11DepthStencilView *pDepthStencilView;
@@ -444,13 +578,18 @@ dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDevice)
}
image::Image *image;
- image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i]);
+ DXGI_FORMAT dxgiFormat;
+ image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i],
+ &dxgiFormat);
if (image) {
char label[64];
_snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
- json.beginMember(label);
- json.writeImage(image, "UNKNOWN");
- json.endMember(); // RENDER_TARGET_*
+ StateWriter::ImageDesc imgDesc;
+ imgDesc.depth = 1;
+ imgDesc.format = getDXGIFormatName(dxgiFormat);
+ writer.beginMember(label);
+ writer.writeImage(image, imgDesc);
+ writer.endMember(); // RENDER_TARGET_*
delete image;
}
@@ -459,20 +598,24 @@ dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDevice)
if (pDepthStencilView) {
image::Image *image;
- image = getDepthStencilViewImage(pDevice, pDepthStencilView);
+ DXGI_FORMAT dxgiFormat;
+ image = getDepthStencilViewImage(pDevice, pDepthStencilView,
+ &dxgiFormat);
if (image) {
- json.beginMember("DEPTH_STENCIL");
- json.writeImage(image, "UNKNOWN");
- json.endMember();
+ StateWriter::ImageDesc imgDesc;
+ imgDesc.depth = 1;
+ imgDesc.format = getDXGIFormatName(dxgiFormat);
+ writer.beginMember("DEPTH_STENCIL");
+ writer.writeImage(image, imgDesc);
+ writer.endMember();
delete image;
}
pDepthStencilView->Release();
-
}
- json.endObject();
- json.endMember(); // framebuffer
+ writer.endObject();
+ writer.endMember(); // framebuffer
}
diff --git a/retrace/d3d7state.cpp b/retrace/d3d7state.cpp
new file mode 100644
index 00000000..86116702
--- /dev/null
+++ b/retrace/d3d7state.cpp
@@ -0,0 +1,62 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <stdio.h>
+
+#include <iostream>
+
+#include "state_writer.hpp"
+#include "d3dimports.hpp"
+#include "d3dstate.hpp"
+
+
+namespace d3dstate {
+
+
+void
+dumpDevice(StateWriter &writer, IDirect3DDevice7 *pDevice)
+{
+ /* TODO */
+ writer.beginMember("parameters");
+ writer.beginObject();
+ writer.endObject();
+ writer.endMember(); // parameters
+
+ writer.beginMember("shaders");
+ writer.beginObject();
+ writer.endObject();
+ writer.endMember(); // shaders
+
+ writer.beginMember("textures");
+ writer.beginObject();
+ writer.endObject();
+ writer.endMember(); // textures
+
+ dumpFramebuffer(writer, pDevice);
+}
+
+
+} /* namespace d3dstate */
diff --git a/retrace/d3d7state_images.cpp b/retrace/d3d7state_images.cpp
new file mode 100644
index 00000000..30990902
--- /dev/null
+++ b/retrace/d3d7state_images.cpp
@@ -0,0 +1,216 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "image.hpp"
+#include "state_writer.hpp"
+#include "com_ptr.hpp"
+#include "d3dimports.hpp"
+#include "d3dstate.hpp"
+
+
+typedef enum _D3DFORMAT
+{
+ D3DFMT_UNKNOWN = 0,
+
+ D3DFMT_R8G8B8 = 20,
+ D3DFMT_A8R8G8B8 = 21,
+ D3DFMT_X8R8G8B8 = 22,
+ D3DFMT_R5G6B5 = 23,
+ D3DFMT_X1R5G5B5 = 24,
+ D3DFMT_A1R5G5B5 = 25,
+ D3DFMT_A4R4G4B4 = 26,
+ D3DFMT_R3G3B2 = 27,
+ D3DFMT_A8 = 28,
+ D3DFMT_A8R3G3B2 = 29,
+ D3DFMT_X4R4G4B4 = 30,
+ D3DFMT_A2B10G10R10 = 31,
+
+ D3DFMT_D16_LOCKABLE = 70,
+ D3DFMT_D32 = 71,
+ D3DFMT_D15S1 = 73,
+ D3DFMT_D24S8 = 75,
+ D3DFMT_D24X8 = 77,
+ D3DFMT_D24X4S4 = 79,
+ D3DFMT_D16 = 80,
+
+ D3DFMT_D32F_LOCKABLE = 82,
+ D3DFMT_D24FS8 = 83,
+
+ D3DFMT_FORCE_DWORD = 0x7fffffff
+} D3DFORMAT;
+
+
+namespace d3dstate {
+
+
+image::Image *
+ConvertImage(D3DFORMAT SrcFormat,
+ void *SrcData,
+ INT SrcPitch,
+ UINT Width, UINT Height);
+
+
+static D3DFORMAT
+convertFormat(const DDPIXELFORMAT & ddpfPixelFormat)
+{
+ if (ddpfPixelFormat.dwSize != sizeof ddpfPixelFormat) {
+ return D3DFMT_UNKNOWN;
+ }
+
+ switch (ddpfPixelFormat.dwFlags) {
+ case DDPF_RGB:
+ switch (ddpfPixelFormat.dwRGBBitCount) {
+ case 32:
+ if (ddpfPixelFormat.dwRBitMask == 0xff0000 &&
+ ddpfPixelFormat.dwGBitMask == 0x00ff00 &&
+ ddpfPixelFormat.dwBBitMask == 0x0000ff) {
+ return D3DFMT_X8R8G8B8;
+ }
+ break;
+ }
+ break;
+ case DDPF_ZBUFFER:
+ case DDPF_ZBUFFER | DDPF_STENCILBUFFER:
+ switch (ddpfPixelFormat.dwZBufferBitDepth) {
+ case 16:
+ if (ddpfPixelFormat.dwZBitMask == 0x0000ffff) {
+ return D3DFMT_D16;
+ }
+ break;
+ case 32:
+ if (ddpfPixelFormat.dwZBitMask == 0x00ffffff) {
+ return D3DFMT_D24X8;
+ }
+ break;
+ }
+ break;
+ }
+
+ return D3DFMT_UNKNOWN;
+}
+
+static image::Image *
+getSurfaceImage(IDirect3DDevice7 *pDevice,
+ IDirectDrawSurface7 *pSurface)
+{
+ HRESULT hr;
+
+ DDSURFACEDESC2 Desc;
+ ZeroMemory(&Desc, sizeof Desc);
+ Desc.dwSize = sizeof Desc;
+
+ hr = pSurface->Lock(NULL, &Desc, DDLOCK_WAIT | DDLOCK_READONLY | DDLOCK_SURFACEMEMORYPTR | DDLOCK_NOSYSLOCK, NULL);
+ if (FAILED(hr)) {
+ std::cerr << "warning: IDirectDrawSurface7::Lock failed\n";
+ return NULL;
+ }
+
+ image::Image *image = NULL;
+ D3DFORMAT Format = convertFormat(Desc.ddpfPixelFormat);
+ if (Format == D3DFMT_UNKNOWN) {
+ std::cerr << "warning: unsupported DDPIXELFORMAT\n";
+ } else {
+ image = ConvertImage(Format, Desc.lpSurface, Desc.lPitch, Desc.dwWidth, Desc.dwHeight);
+ }
+
+ pSurface->Unlock(NULL);
+
+ return image;
+}
+
+
+image::Image *
+getRenderTargetImage(IDirect3DDevice7 *pDevice) {
+ HRESULT hr;
+
+ com_ptr<IDirectDrawSurface7> pRenderTarget;
+ hr = pDevice->GetRenderTarget(&pRenderTarget);
+ if (FAILED(hr)) {
+ return NULL;
+ }
+ assert(pRenderTarget);
+
+ return getSurfaceImage(pDevice, pRenderTarget);
+}
+
+
+void
+dumpTextures(StateWriter &writer, IDirect3DDevice7 *pDevice)
+{
+ writer.beginMember("textures");
+ writer.beginObject();
+ writer.endObject();
+ writer.endMember(); // textures
+}
+
+
+void
+dumpFramebuffer(StateWriter &writer, IDirect3DDevice7 *pDevice)
+{
+ HRESULT hr;
+
+ writer.beginMember("framebuffer");
+ writer.beginObject();
+
+ com_ptr<IDirectDrawSurface7> pRenderTarget;
+ hr = pDevice->GetRenderTarget(&pRenderTarget);
+ if (SUCCEEDED(hr) && pRenderTarget) {
+ image::Image *image;
+ image = getSurfaceImage(pDevice, pRenderTarget);
+ if (image) {
+ writer.beginMember("RENDER_TARGET_0");
+ writer.writeImage(image);
+ writer.endMember(); // RENDER_TARGET_*
+ delete image;
+ }
+
+ // Search for a depth-stencil attachment
+ DDSCAPS2 ddsCaps;
+ ZeroMemory(&ddsCaps, sizeof ddsCaps);
+ ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
+ com_ptr<IDirectDrawSurface7> pDepthStencil;
+ hr = pRenderTarget->GetAttachedSurface(&ddsCaps, &pDepthStencil);
+ if (SUCCEEDED(hr) && pDepthStencil) {
+ std::cerr << "found ZS!!\n";
+ image = getSurfaceImage(pDevice, pDepthStencil);
+ if (image) {
+ writer.beginMember("DEPTH_STENCIL");
+ writer.writeImage(image);
+ writer.endMember(); // DEPTH_STENCIL
+ delete image;
+ }
+ }
+ }
+
+ writer.endObject();
+ writer.endMember(); // framebuffer
+}
+
+
+} /* namespace d3dstate */
diff --git a/retrace/d3d8state.cpp b/retrace/d3d8state.cpp
index 60bdb6d2..77be00b5 100644
--- a/retrace/d3d8state.cpp
+++ b/retrace/d3d8state.cpp
@@ -28,10 +28,11 @@
#include <iostream>
+#include "state_writer.hpp"
+#include "com_ptr.hpp"
#include "d3d8imports.hpp"
#include "d3dshader.hpp"
#include "d3dstate.hpp"
-#include "json.hpp"
namespace d3dstate {
@@ -62,7 +63,7 @@ struct PixelShaderGetter
template<class Getter>
inline void
-dumpShader(JSONWriter &json, IDirect3DDevice8 *pDevice, const char *name) {
+dumpShader(StateWriter &writer, IDirect3DDevice8 *pDevice, const char *name) {
Getter getter;
HRESULT hr;
@@ -81,15 +82,13 @@ dumpShader(JSONWriter &json, IDirect3DDevice8 *pDevice, const char *name) {
if (pData) {
hr = getter.GetShaderFunction(pDevice, dwShader, pData, &SizeOfData);
if (SUCCEEDED(hr)) {
- IDisassemblyBuffer *pDisassembly = NULL;
+ com_ptr<IDisassemblyBuffer> pDisassembly;
hr = DisassembleShader((const DWORD *)pData, &pDisassembly);
if (SUCCEEDED(hr)) {
- json.beginMember(name);
- json.writeString((const char *)pDisassembly->GetBufferPointer() /*, pDisassembly->GetBufferSize() */);
- json.endMember();
- pDisassembly->Release();
+ writer.beginMember(name);
+ writer.writeString((const char *)pDisassembly->GetBufferPointer() /*, pDisassembly->GetBufferSize() */);
+ writer.endMember();
}
-
}
free(pData);
}
@@ -97,37 +96,35 @@ dumpShader(JSONWriter &json, IDirect3DDevice8 *pDevice, const char *name) {
}
static void
-dumpShaders(JSONWriter &json, IDirect3DDevice8 *pDevice)
+dumpShaders(StateWriter &writer, IDirect3DDevice8 *pDevice)
{
- json.beginMember("shaders");
- json.beginObject();
+ writer.beginMember("shaders");
+ writer.beginObject();
- dumpShader<VertexShaderGetter>(json, pDevice, "vertex");
- dumpShader<PixelShaderGetter>(json, pDevice, "pixel");
+ dumpShader<VertexShaderGetter>(writer, pDevice, "vertex");
+ dumpShader<PixelShaderGetter>(writer, pDevice, "pixel");
- json.endObject();
- json.endMember(); // shaders
+ writer.endObject();
+ writer.endMember(); // shaders
}
void
-dumpDevice(std::ostream &os, IDirect3DDevice8 *pDevice)
+dumpDevice(StateWriter &writer, IDirect3DDevice8 *pDevice)
{
- JSONWriter json(os);
-
/* TODO */
- json.beginMember("parameters");
- json.beginObject();
- json.endObject();
- json.endMember(); // parameters
+ writer.beginMember("parameters");
+ writer.beginObject();
+ writer.endObject();
+ writer.endMember(); // parameters
- dumpShaders(json, pDevice);
+ dumpShaders(writer, pDevice);
- json.beginMember("textures");
- json.beginObject();
- json.endObject();
- json.endMember(); // textures
+ writer.beginMember("textures");
+ writer.beginObject();
+ writer.endObject();
+ writer.endMember(); // textures
- dumpFramebuffer(json, pDevice);
+ dumpFramebuffer(writer, pDevice);
}
diff --git a/retrace/d3d8state_images.cpp b/retrace/d3d8state_images.cpp
index 89d4e06d..ad23bd6c 100644
--- a/retrace/d3d8state_images.cpp
+++ b/retrace/d3d8state_images.cpp
@@ -26,9 +26,11 @@
#include <assert.h>
#include <stdint.h>
+#include <stdio.h>
#include "image.hpp"
-#include "json.hpp"
+#include "state_writer.hpp"
+#include "com_ptr.hpp"
#include "d3d8imports.hpp"
#include "d3dstate.hpp"
@@ -36,128 +38,219 @@
namespace d3dstate {
+image::Image *
+ConvertImage(D3DFORMAT SrcFormat,
+ void *SrcData,
+ INT SrcPitch,
+ UINT Width, UINT Height);
+
+
static image::Image *
-getRenderTargetImage(IDirect3DDevice8 *pDevice,
- IDirect3DSurface8 *pRenderTarget) {
+getSurfaceImage(IDirect3DDevice8 *pDevice,
+ IDirect3DSurface8 *pSurface) {
image::Image *image = NULL;
+ HRESULT hr;
+
+ if (!pSurface) {
+ return NULL;
+ }
+
D3DSURFACE_DESC Desc;
- IDirect3DSurface8 *pStagingSurface = NULL;
+ hr = pSurface->GetDesc(&Desc);
+ assert(SUCCEEDED(hr));
+
D3DLOCKED_RECT LockedRect;
- const unsigned char *src;
- unsigned char *dst;
+ hr = pSurface->LockRect(&LockedRect, NULL, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
+ if (FAILED(hr)) {
+ return NULL;
+ }
+
+ image = ConvertImage(Desc.Format, LockedRect.pBits, LockedRect.Pitch, Desc.Width, Desc.Height);
+
+ pSurface->UnlockRect();
+
+ return image;
+}
+
+
+static image::Image *
+getRenderTargetImage(IDirect3DDevice8 *pDevice,
+ IDirect3DSurface8 *pRenderTarget) {
HRESULT hr;
if (!pRenderTarget) {
return NULL;
}
+ D3DSURFACE_DESC Desc;
hr = pRenderTarget->GetDesc(&Desc);
assert(SUCCEEDED(hr));
- if (Desc.Format != D3DFMT_X8R8G8B8 &&
- Desc.Format != D3DFMT_A8R8G8B8 &&
- Desc.Format != D3DFMT_R5G6B5) {
- std::cerr << "warning: unsupported D3DFORMAT " << Desc.Format << "\n";
- goto no_staging;
- }
-
+ com_ptr<IDirect3DSurface8> pStagingSurface;
hr = pDevice->CreateImageSurface(Desc.Width, Desc.Height, Desc.Format, &pStagingSurface);
if (FAILED(hr)) {
- goto no_staging;
+ return NULL;
}
hr = pDevice->CopyRects(pRenderTarget, NULL, 0, pStagingSurface, NULL);
if (FAILED(hr)) {
- goto no_rendertargetdata;
+ std::cerr << "warning: GetRenderTargetData failed\n";
+ return NULL;
}
- hr = pStagingSurface->LockRect(&LockedRect, NULL, D3DLOCK_READONLY);
+ return getSurfaceImage(pDevice, pStagingSurface);
+}
+
+
+image::Image *
+getRenderTargetImage(IDirect3DDevice8 *pDevice) {
+ HRESULT hr;
+
+ com_ptr<IDirect3DSurface8> pRenderTarget;
+ hr = pDevice->GetRenderTarget(&pRenderTarget);
if (FAILED(hr)) {
- goto no_rendertargetdata;
+ return NULL;
}
+ assert(pRenderTarget);
+
+ return getRenderTargetImage(pDevice, pRenderTarget);
+}
- image = new image::Image(Desc.Width, Desc.Height, 3, true);
- if (!image) {
- goto no_image;
+
+static image::Image *
+getTextureImage(IDirect3DDevice8 *pDevice,
+ IDirect3DBaseTexture8 *pTexture,
+ D3DCUBEMAP_FACES FaceType,
+ UINT Level)
+{
+ HRESULT hr;
+
+ if (!pTexture) {
+ return NULL;
}
- dst = image->start();
- src = (const unsigned char *)LockedRect.pBits;
- for (unsigned y = 0; y < Desc.Height; ++y) {
- if (Desc.Format == D3DFMT_R5G6B5) {
- for (unsigned x = 0; x < Desc.Width; ++x) {
- uint32_t pixel = ((const uint16_t *)src)[x];
- dst[3*x + 0] = (( pixel & 0x1f) * (2*0xff) + 0x1f) / (2*0x1f);
- dst[3*x + 1] = (((pixel >> 5) & 0x3f) * (2*0xff) + 0x3f) / (2*0x3f);
- dst[3*x + 2] = (( pixel >> 11 ) * (2*0xff) + 0x1f) / (2*0x1f);
- dst[3*x + 3] = 0xff;
- }
- } else {
- for (unsigned x = 0; x < Desc.Width; ++x) {
- dst[3*x + 0] = src[4*x + 2];
- dst[3*x + 1] = src[4*x + 1];
- dst[3*x + 2] = src[4*x + 0];
- }
- }
+ com_ptr<IDirect3DSurface8> pSurface;
- src += LockedRect.Pitch;
- dst += image->stride();
+ D3DRESOURCETYPE Type = pTexture->GetType();
+ switch (Type) {
+ case D3DRTYPE_TEXTURE:
+ assert(FaceType == D3DCUBEMAP_FACE_POSITIVE_X);
+ hr = reinterpret_cast<IDirect3DTexture8 *>(pTexture)->GetSurfaceLevel(Level, &pSurface);
+ break;
+ case D3DRTYPE_CUBETEXTURE:
+ hr = reinterpret_cast<IDirect3DCubeTexture8 *>(pTexture)->GetCubeMapSurface(FaceType, Level, &pSurface);
+ break;
+ default:
+ /* TODO: support volume textures */
+ return NULL;
+ }
+ if (FAILED(hr) || !pSurface) {
+ return NULL;
}
-no_image:
- pStagingSurface->UnlockRect();
-no_rendertargetdata:
- pStagingSurface->Release();
-no_staging:
- return image;
+ D3DSURFACE_DESC Desc;
+ hr = pSurface->GetDesc(&Desc);
+ assert(SUCCEEDED(hr));
+
+ if (Desc.Pool != D3DPOOL_DEFAULT ||
+ Desc.Usage & D3DUSAGE_DYNAMIC) {
+ // Lockable texture
+ return getSurfaceImage(pDevice, pSurface);
+ } else if (Desc.Usage & D3DUSAGE_RENDERTARGET) {
+ // Rendertarget texture
+ return getRenderTargetImage(pDevice, pSurface);
+ } else {
+ // D3D constraints are such there is not much else that can be done.
+ return NULL;
+ }
}
-image::Image *
-getRenderTargetImage(IDirect3DDevice8 *pDevice) {
+void
+dumpTextures(StateWriter &writer, IDirect3DDevice8 *pDevice)
+{
HRESULT hr;
- IDirect3DSurface8 *pRenderTarget = NULL;
- hr = pDevice->GetRenderTarget(&pRenderTarget);
- if (FAILED(hr)) {
- return NULL;
- }
- assert(pRenderTarget);
+ writer.beginMember("textures");
+ writer.beginObject();
- image::Image *image = NULL;
- if (pRenderTarget) {
- image = getRenderTargetImage(pDevice, pRenderTarget);
- pRenderTarget->Release();
+ for (DWORD Stage = 0; Stage < 8; ++Stage) {
+ com_ptr<IDirect3DBaseTexture8> pTexture;
+ hr = pDevice->GetTexture(Stage, &pTexture);
+ if (FAILED(hr)) {
+ continue;
+ }
+
+ if (!pTexture) {
+ continue;
+ }
+
+ D3DRESOURCETYPE Type = pTexture->GetType();
+
+ DWORD NumFaces = Type == D3DRTYPE_CUBETEXTURE ? 6 : 1;
+ DWORD NumLevels = pTexture->GetLevelCount();
+
+ for (DWORD Face = 0; Face < NumFaces; ++Face) {
+ for (DWORD Level = 0; Level < NumLevels; ++Level) {
+ image::Image *image;
+ image = getTextureImage(pDevice, pTexture, static_cast<D3DCUBEMAP_FACES>(Face), Level);
+ if (image) {
+ char label[128];
+ if (Type == D3DRTYPE_CUBETEXTURE) {
+ _snprintf(label, sizeof label, "PS_RESOURCE_%lu_FACE_%lu_LEVEL_%lu", Stage, Face, Level);
+ } else {
+ _snprintf(label, sizeof label, "PS_RESOURCE_%lu_LEVEL_%lu", Stage, Level);
+ }
+ writer.beginMember(label);
+ writer.writeImage(image);
+ writer.endMember(); // PS_RESOURCE_*
+ delete image;
+ }
+ }
+ }
}
- return image;
+ writer.endObject();
+ writer.endMember(); // textures
}
void
-dumpFramebuffer(JSONWriter &json, IDirect3DDevice8 *pDevice)
+dumpFramebuffer(StateWriter &writer, IDirect3DDevice8 *pDevice)
{
HRESULT hr;
- json.beginMember("framebuffer");
- json.beginObject();
+ writer.beginMember("framebuffer");
+ writer.beginObject();
- IDirect3DSurface8 *pRenderTarget = NULL;
+ com_ptr<IDirect3DSurface8> pRenderTarget;
hr = pDevice->GetRenderTarget(&pRenderTarget);
if (SUCCEEDED(hr) && pRenderTarget) {
image::Image *image;
image = getRenderTargetImage(pDevice, pRenderTarget);
if (image) {
- json.beginMember("RENDER_TARGET_0");
- json.writeImage(image, "UNKNOWN");
- json.endMember(); // RENDER_TARGET_*
+ writer.beginMember("RENDER_TARGET_0");
+ writer.writeImage(image);
+ writer.endMember(); // RENDER_TARGET_*
+ delete image;
}
+ }
- pRenderTarget->Release();
+ com_ptr<IDirect3DSurface8> pDepthStencil;
+ hr = pDevice->GetDepthStencilSurface(&pDepthStencil);
+ if (SUCCEEDED(hr) && pDepthStencil) {
+ image::Image *image;
+ image = getSurfaceImage(pDevice, pDepthStencil);
+ if (image) {
+ writer.beginMember("DEPTH_STENCIL");
+ writer.writeImage(image);
+ writer.endMember(); // RENDER_TARGET_*
+ delete image;
+ }
}
- json.endObject();
- json.endMember(); // framebuffer
+ writer.endObject();
+ writer.endMember(); // framebuffer
}
diff --git a/retrace/d3d9retrace.py b/retrace/d3d9retrace.py
index 4d011ed5..ac6af73b 100644
--- a/retrace/d3d9retrace.py
+++ b/retrace/d3d9retrace.py
@@ -36,7 +36,8 @@ class D3DRetracer(Retracer):
def retraceApi(self, api):
print '// Swizzling mapping for lock addresses'
- print 'static std::map<void *, void *> _maps;'
+ print 'typedef std::pair<void *, UINT> MappingKey;'
+ print 'static std::map<MappingKey, void *> _maps;'
print
Retracer.retraceApi(self, api)
@@ -54,6 +55,13 @@ class D3DRetracer(Retracer):
print ' SDKVersion &= ~0x80000000;'
print '}'
+ # d3d8d.dll can be found in the Aug 2007 DXSDK. It works on XP, but
+ # not on Windows 7.
+ if function.name in ('Direct3DCreate8'):
+ print 'if (retrace::debug >= 2 && !g_szD3D8DllName && LoadLibraryA("d3d8d.dll")) {'
+ print ' g_szD3D8DllName = "d3d8d.dll";'
+ print '}'
+
Retracer.invokeFunction(self, function)
createDeviceMethodNames = [
@@ -80,7 +88,12 @@ class D3DRetracer(Retracer):
# create windows as neccessary
if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'):
- print r' HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);'
+ print r' HWND hWnd = pPresentationParameters->hDeviceWindow;'
+ if 'hFocusWindow' in method.argNames():
+ print r' if (hWnd == NULL) {'
+ print r' hWnd = hFocusWindow;'
+ print r' }'
+ print r' hWnd = d3dretrace::createWindow(hWnd, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);'
print r' pPresentationParameters->hDeviceWindow = hWnd;'
if 'hFocusWindow' in method.argNames():
print r' hFocusWindow = hWnd;'
@@ -89,7 +102,33 @@ class D3DRetracer(Retracer):
print r' if (retrace::forceWindowed) {'
print r' pPresentationParameters->Windowed = TRUE;'
print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;'
+ if interface.name.startswith('IDirect3D8'):
+ print r' pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;'
print r' }'
+ if 'BehaviorFlags' in method.argNames():
+ print r' if (retrace::dumpingState) {'
+ print r' BehaviorFlags &= ~D3DCREATE_PUREDEVICE;'
+ print r' }'
+
+ # On D3D8, ensure we use BackBufferFormat compatible with the
+ # current DisplayFormat.
+ #
+ # TODO: BackBufferFormat doesn't need to be always exectly to
+ # DisplayFormat. For example, if DisplayFormat is D3DFMT_X1R5G5B5,
+ # valid values for BackBufferFormat include D3DFMT_X1R5G5B5 and
+ # D3DFMT_A1R5G5B5, but exclude D3DFMT_R5G6B5.
+ if interface.name.startswith('IDirect3D8'):
+ print r' if (pPresentationParameters->Windowed) {'
+ print r' D3DDISPLAYMODE Mode;'
+ print r' HRESULT hr;'
+ print r' hr = _this->GetAdapterDisplayMode(Adapter, &Mode);'
+ print r' assert(SUCCEEDED(hr));'
+ print r' hr = _this->CheckDeviceType(Adapter, DeviceType, Mode.Format, pPresentationParameters->BackBufferFormat, pPresentationParameters->Windowed);'
+ print r' if (hr == D3DERR_NOTAVAILABLE) {'
+ print r' retrace::warning(call) << "forcing back buffer format to match display mode format\n";'
+ print r' pPresentationParameters->BackBufferFormat = Mode.Format;'
+ print r' }'
+ print r' }'
if method.name in self.createDeviceMethodNames:
# override the device type
@@ -130,15 +169,34 @@ class D3DRetracer(Retracer):
# notify frame has been completed
if method.name in ('Present', 'PresentEx'):
+ if interface.name.startswith('IDirect3DSwapChain9'):
+ print r' d3d9scDumper.bindDevice(_this);'
print r' retrace::frameComplete(call);'
print r' hDestWindowOverride = NULL;'
+ # Ensure textures can be locked when dumping
+ # TODO: Pre-check with CheckDeviceFormat
+ if method.name in ('CreateTexture', 'CreateCubeTexture', 'CreateVolumeTexture'):
+ print r' if (retrace::dumpingState &&'
+ print r' Pool == D3DPOOL_DEFAULT &&'
+ print r' !(Usage & (D3DUSAGE_RENDERTARGET|D3DUSAGE_DEPTHSTENCIL))) {'
+ print r' Usage |= D3DUSAGE_DYNAMIC;'
+ print r' }'
+
if 'pSharedHandle' in method.argNames():
print r' if (pSharedHandle) {'
print r' retrace::warning(call) << "shared surfaces unsupported\n";'
print r' pSharedHandle = NULL;'
print r' }'
+ if method.name in ('Lock', 'LockRect', 'LockBox'):
+ # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no
+ # way to cope with it (other than retry).
+ mapFlagsArg = method.getArgByName('Flags')
+ for flag in mapFlagsArg.type.values:
+ if flag.endswith('_DONOTWAIT'):
+ print r' Flags &= ~%s;' % flag
+
Retracer.invokeInterfaceMethod(self, interface, method)
if method.name in self.createDeviceMethodNames:
@@ -150,22 +208,32 @@ class D3DRetracer(Retracer):
if method.name == 'Present':
print r' d3dretrace::processEvents();'
+ def mapping_subkey():
+ if 'Level' in method.argNames():
+ return ('Level',)
+ else:
+ return ('0',)
+
if method.name in ('Lock', 'LockRect', 'LockBox'):
print ' VOID *_pbData = NULL;'
print ' size_t _MappedSize = 0;'
- print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1])
+ print ' if (!(Flags & D3DLOCK_READONLY)) {'
+ print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1])
+ print ' }'
print ' if (_MappedSize) {'
- print ' _maps[_this] = _pbData;'
+ print ' _maps[MappingKey(_this, %s)] = _pbData;' % mapping_subkey()
+ self.checkPitchMismatch(method)
print ' } else {'
print ' return;'
print ' }'
if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'):
print ' VOID *_pbData = 0;'
- print ' _pbData = _maps[_this];'
+ print ' MappingKey _mappingKey(_this, %s);' % mapping_subkey()
+ print ' _pbData = _maps[_mappingKey];'
print ' if (_pbData) {'
print ' retrace::delRegionByPointer(_pbData);'
- print ' _maps[_this] = 0;'
+ print ' _maps[_mappingKey] = 0;'
print ' }'
@@ -184,12 +252,17 @@ def main():
if support:
if moduleName == 'd3d9':
- from specs.d3d9 import d3d9
+ from specs.d3d9 import d3d9, d3dperf
+ from specs.dxva2 import dxva2
print r'#include "d3d9imports.hpp"'
print r'#include "d3d9size.hpp"'
+ print r'#include "dxva2imports.hpp"'
+ d3d9.mergeModule(d3dperf)
api.addModule(d3d9)
+ api.addModule(dxva2)
print
print '''static d3dretrace::D3DDumper<IDirect3DDevice9> d3d9Dumper;'''
+ print '''static d3dretrace::D3DDumper<IDirect3DSwapChain9> d3d9scDumper;'''
print
elif moduleName == 'd3d8':
from specs.d3d8 import d3d8
diff --git a/retrace/d3d9state.cpp b/retrace/d3d9state.cpp
index 6b355294..0717c102 100644
--- a/retrace/d3d9state.cpp
+++ b/retrace/d3d9state.cpp
@@ -28,10 +28,11 @@
#include <iostream>
+#include "state_writer.hpp"
+#include "com_ptr.hpp"
#include "d3d9imports.hpp"
#include "d3dshader.hpp"
#include "d3dstate.hpp"
-#include "json.hpp"
namespace d3dstate {
@@ -39,7 +40,7 @@ namespace d3dstate {
template< class T >
inline void
-dumpShader(JSONWriter &json, const char *name, T *pShader) {
+dumpShader(StateWriter &writer, const char *name, T *pShader) {
if (!pShader) {
return;
}
@@ -55,63 +56,68 @@ dumpShader(JSONWriter &json, const char *name, T *pShader) {
if (pData) {
hr = pShader->GetFunction(pData, &SizeOfData);
if (SUCCEEDED(hr)) {
- IDisassemblyBuffer *pDisassembly = NULL;
+ com_ptr<IDisassemblyBuffer> pDisassembly;
hr = DisassembleShader((const DWORD *)pData, &pDisassembly);
if (SUCCEEDED(hr)) {
- json.beginMember(name);
- json.writeString((const char *)pDisassembly->GetBufferPointer() /*, pDisassembly->GetBufferSize() */);
- json.endMember();
- pDisassembly->Release();
+ writer.beginMember(name);
+ writer.writeString((const char *)pDisassembly->GetBufferPointer() /*, pDisassembly->GetBufferSize() */);
+ writer.endMember();
}
}
free(pData);
}
}
-
- pShader->Release();
}
static void
-dumpShaders(JSONWriter &json, IDirect3DDevice9 *pDevice)
+dumpShaders(StateWriter &writer, IDirect3DDevice9 *pDevice)
{
- json.beginMember("shaders");
+ writer.beginMember("shaders");
HRESULT hr;
- json.beginObject();
+ writer.beginObject();
- IDirect3DVertexShader9 *pVertexShader = NULL;
+ com_ptr<IDirect3DVertexShader9> pVertexShader;
hr = pDevice->GetVertexShader(&pVertexShader);
if (SUCCEEDED(hr)) {
- dumpShader(json, "vertex", pVertexShader);
+ dumpShader<IDirect3DVertexShader9>(writer, "vertex", pVertexShader);
}
- IDirect3DPixelShader9 *pPixelShader = NULL;
+ com_ptr<IDirect3DPixelShader9> pPixelShader;
hr = pDevice->GetPixelShader(&pPixelShader);
if (SUCCEEDED(hr)) {
- dumpShader(json, "pixel", pPixelShader);
+ dumpShader<IDirect3DPixelShader9>(writer, "pixel", pPixelShader);
}
- json.endObject();
- json.endMember(); // shaders
+ writer.endObject();
+ writer.endMember(); // shaders
}
void
-dumpDevice(std::ostream &os, IDirect3DDevice9 *pDevice)
+dumpDevice(StateWriter &writer, IDirect3DDevice9 *pDevice)
{
- JSONWriter json(os);
-
/* TODO */
- json.beginMember("parameters");
- json.beginObject();
- json.endObject();
- json.endMember(); // parameters
+ writer.beginMember("parameters");
+ writer.beginObject();
+ writer.endObject();
+ writer.endMember(); // parameters
- dumpShaders(json, pDevice);
+ dumpShaders(writer, pDevice);
- dumpTextures(json, pDevice);
+ dumpTextures(writer, pDevice);
+
+ dumpFramebuffer(writer, pDevice);
+}
- dumpFramebuffer(json, pDevice);
+void
+dumpDevice(StateWriter &writer, IDirect3DSwapChain9 *pSwapChain)
+{
+ com_ptr<IDirect3DDevice9> pDevice;
+ HRESULT hr = pSwapChain->GetDevice(&pDevice);
+ if (SUCCEEDED(hr)) {
+ dumpDevice(writer, pDevice);
+ }
}
diff --git a/retrace/d3d9state.hpp b/retrace/d3d9state.hpp
new file mode 100644
index 00000000..affb1221
--- /dev/null
+++ b/retrace/d3d9state.hpp
@@ -0,0 +1,57 @@
+/**************************************************************************
+ *
+ * Copyright 2014 VMware, Inc
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+
+#include <ostream>
+
+#include "d3d9imports.hpp"
+
+
+namespace image {
+ class Image;
+}
+
+std::ostream &
+operator << (std::ostream &os, D3DFORMAT Format);
+
+
+namespace d3dstate {
+
+
+image::Image *
+ConvertImage(D3DFORMAT SrcFormat,
+ void *SrcData,
+ INT SrcPitch,
+ UINT Width, UINT Height);
+
+
+
+} /* namespace d3dstate */
+
+
+
diff --git a/retrace/d3d9state_formats.cpp b/retrace/d3d9state_formats.cpp
new file mode 100644
index 00000000..d73a4170
--- /dev/null
+++ b/retrace/d3d9state_formats.cpp
@@ -0,0 +1,259 @@
+/**************************************************************************
+ *
+ * Copyright 2014 VMware, Inc
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "d3d9state.hpp"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "image.hpp"
+
+#ifdef HAVE_DXGI
+#include "dxgistate.hpp"
+#endif
+
+
+std::ostream &
+operator << (std::ostream &os, D3DFORMAT Format) {
+ if (Format >= 0 && Format < 256) {
+ return os << (unsigned)Format;
+ } else {
+ char ch0 = Format;
+ char ch1 = Format >> 8;
+ char ch2 = Format >> 16;
+ char ch3 = Format >> 24;
+ return os << "'" << ch0 << ch1 << ch2 << ch3 << "'";
+ }
+ return os;
+}
+
+
+namespace d3dstate {
+
+
+#ifdef HAVE_DXGI
+
+/**
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/cc308051.aspx
+ */
+static DXGI_FORMAT
+convertFormatDXGI(D3DFORMAT Format)
+{
+ switch ((int)Format) {
+ case D3DFMT_UNKNOWN:
+ return DXGI_FORMAT_UNKNOWN;
+ case D3DFMT_A8R8G8B8:
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
+ case D3DFMT_X8R8G8B8:
+ return DXGI_FORMAT_B8G8R8X8_UNORM;
+ case D3DFMT_R5G6B5:
+ return DXGI_FORMAT_B5G6R5_UNORM;
+ case D3DFMT_A1R5G5B5:
+ return DXGI_FORMAT_B5G5R5A1_UNORM;
+ case D3DFMT_A4R4G4B4:
+ return DXGI_FORMAT_B4G4R4A4_UNORM;
+ case D3DFMT_A8:
+ return DXGI_FORMAT_A8_UNORM;
+ case D3DFMT_A2B10G10R10:
+ return DXGI_FORMAT_R10G10B10A2_UNORM;
+ case D3DFMT_A8B8G8R8:
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ case D3DFMT_G16R16:
+ return DXGI_FORMAT_R16G16_UNORM;
+ case D3DFMT_A16B16G16R16:
+ return DXGI_FORMAT_R16G16B16A16_UNORM;
+ case D3DFMT_L8:
+ return DXGI_FORMAT_R8_UNORM;
+ case D3DFMT_V8U8:
+ return DXGI_FORMAT_R8G8_SNORM;
+ case D3DFMT_Q8W8V8U8:
+ return DXGI_FORMAT_R8G8B8A8_SNORM;
+ case D3DFMT_V16U16:
+ return DXGI_FORMAT_R16G16_SNORM;
+ case D3DFMT_R8G8_B8G8:
+ return DXGI_FORMAT_G8R8_G8B8_UNORM;
+ case D3DFMT_G8R8_G8B8:
+ return DXGI_FORMAT_R8G8_B8G8_UNORM;
+ case D3DFMT_DXT1:
+ return DXGI_FORMAT_BC1_UNORM;
+ case D3DFMT_DXT2:
+ return DXGI_FORMAT_BC2_UNORM;
+ case D3DFMT_DXT3:
+ return DXGI_FORMAT_BC2_UNORM;
+ case D3DFMT_DXT4:
+ return DXGI_FORMAT_BC3_UNORM;
+ case D3DFMT_DXT5:
+ return DXGI_FORMAT_BC3_UNORM;
+ case D3DFMT_D16:
+ case D3DFMT_D16_LOCKABLE:
+ return DXGI_FORMAT_D16_UNORM;
+ case D3DFMT_D32F_LOCKABLE:
+ return DXGI_FORMAT_D32_FLOAT;
+ case D3DFMT_D24S8:
+ return DXGI_FORMAT_D24_UNORM_S8_UINT;
+ case D3DFMT_L16:
+ return DXGI_FORMAT_R16_UNORM;
+ case D3DFMT_INDEX16:
+ return DXGI_FORMAT_R16_UINT;
+ case D3DFMT_INDEX32:
+ return DXGI_FORMAT_R32_UINT;
+ case D3DFMT_Q16W16V16U16:
+ return DXGI_FORMAT_R16G16B16A16_SNORM;
+ case D3DFMT_R16F:
+ return DXGI_FORMAT_R16_FLOAT;
+ case D3DFMT_G16R16F:
+ return DXGI_FORMAT_R16G16_FLOAT;
+ case D3DFMT_A16B16G16R16F:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+ case D3DFMT_R32F:
+ return DXGI_FORMAT_R32_FLOAT;
+ case D3DFMT_G32R32F:
+ return DXGI_FORMAT_R32G32_FLOAT;
+ case D3DFMT_A32B32G32R32F:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ case D3DFMT_ATI1N:
+ return DXGI_FORMAT_BC4_UNORM;
+ case D3DFMT_ATI2N:
+ return DXGI_FORMAT_BC5_UNORM;
+ default:
+ return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+
+image::Image *
+ConvertImageDXGI(D3DFORMAT SrcFormat,
+ void *SrcData,
+ INT SrcPitch,
+ UINT Width, UINT Height)
+{
+ DXGI_FORMAT Format = convertFormatDXGI(SrcFormat);
+ if (Format == DXGI_FORMAT_UNKNOWN) {
+ return NULL;
+ }
+
+ assert(SrcPitch >= 0);
+
+ return ConvertImage(Format, SrcData, SrcPitch, Width, Height);
+}
+
+#endif /* HAVE_DXGI */
+
+
+image::Image *
+ConvertImage(D3DFORMAT SrcFormat,
+ void *SrcData,
+ INT SrcPitch,
+ UINT Width, UINT Height)
+{
+ image::Image *image;
+
+ unsigned numChannels;
+ image::ChannelType channelType;
+ switch (SrcFormat) {
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_R5G6B5:
+ numChannels = 3;
+ channelType = image::TYPE_UNORM8;
+ break;
+ case D3DFMT_D16:
+ case D3DFMT_D16_LOCKABLE:
+ case D3DFMT_D24S8:
+ case D3DFMT_D24X8:
+ case D3DFMT_D32F_LOCKABLE:
+ numChannels = 1;
+ channelType = image::TYPE_FLOAT;
+ break;
+ default:
+#ifdef HAVE_DXGI
+ image = ConvertImageDXGI(SrcFormat, SrcData, SrcPitch, Width, Height);
+ if (image) {
+ return image;
+ }
+#endif
+
+ std::cerr << "warning: unsupported D3DFORMAT " << SrcFormat << "\n";
+ return NULL;
+ }
+
+ image = new image::Image(Width, Height, numChannels, true, channelType);
+ if (!image) {
+ return NULL;
+ }
+
+ const unsigned char *src;
+ unsigned char *dst;
+
+ dst = image->start();
+ src = (const unsigned char *)SrcData;
+ for (unsigned y = 0; y < Height; ++y) {
+ switch (SrcFormat) {
+ case D3DFMT_R5G6B5:
+ for (unsigned x = 0; x < Width; ++x) {
+ uint32_t pixel = ((const uint16_t *)src)[x];
+ dst[3*x + 0] = (( pixel & 0x1f) * (2*0xff) + 0x1f) / (2*0x1f);
+ dst[3*x + 1] = (((pixel >> 5) & 0x3f) * (2*0xff) + 0x3f) / (2*0x3f);
+ dst[3*x + 2] = (( pixel >> 11 ) * (2*0xff) + 0x1f) / (2*0x1f);
+ }
+ break;
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ for (unsigned x = 0; x < Width; ++x) {
+ dst[3*x + 0] = src[4*x + 2];
+ dst[3*x + 1] = src[4*x + 1];
+ dst[3*x + 2] = src[4*x + 0];
+ }
+ break;
+ case D3DFMT_D16:
+ case D3DFMT_D16_LOCKABLE:
+ for (unsigned x = 0; x < Width; ++x) {
+ ((float *)dst)[x] = ((const uint16_t *)src)[x] * (1.0f / 0xffff);
+ }
+ break;
+ case D3DFMT_D24S8:
+ case D3DFMT_D24X8:
+ for (unsigned x = 0; x < Width; ++x) {
+ ((float *)dst)[x] = ((const uint32_t *)src)[x] * (1.0 / 0xffffff);
+ }
+ break;
+ case D3DFMT_D32F_LOCKABLE:
+ memcpy(dst, src, Width * sizeof(float));
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ src += SrcPitch;
+ dst += image->stride();
+ }
+
+ return image;
+}
+
+
+} /* namespace d3dstate */
diff --git a/retrace/d3d9state_images.cpp b/retrace/d3d9state_images.cpp
index e2ef0350..79ad0744 100644
--- a/retrace/d3d9state_images.cpp
+++ b/retrace/d3d9state_images.cpp
@@ -29,8 +29,9 @@
#include <stdio.h>
#include "image.hpp"
-#include "json.hpp"
-#include "d3d9imports.hpp"
+#include "state_writer.hpp"
+#include "com_ptr.hpp"
+#include "d3d9state.hpp"
#include "d3dstate.hpp"
@@ -41,90 +42,26 @@ static image::Image *
getSurfaceImage(IDirect3DDevice9 *pDevice,
IDirect3DSurface9 *pSurface) {
image::Image *image = NULL;
- D3DSURFACE_DESC Desc;
- D3DLOCKED_RECT LockedRect;
- const unsigned char *src;
- unsigned char *dst;
HRESULT hr;
if (!pSurface) {
return NULL;
}
+ D3DSURFACE_DESC Desc;
hr = pSurface->GetDesc(&Desc);
assert(SUCCEEDED(hr));
- unsigned numChannels;
- image::ChannelType channelType;
- switch (Desc.Format) {
- case D3DFMT_X8R8G8B8:
- case D3DFMT_A8R8G8B8:
- case D3DFMT_R5G6B5:
- numChannels = 3;
- channelType = image::TYPE_UNORM8;
- break;
- case D3DFMT_D16:
- case D3DFMT_D16_LOCKABLE:
- case D3DFMT_D32F_LOCKABLE:
- numChannels = 1;
- channelType = image::TYPE_FLOAT;
- break;
- default:
- std::cerr << "warning: unsupported D3DFORMAT " << Desc.Format << "\n";
- goto no_lock;
- }
-
+ D3DLOCKED_RECT LockedRect;
hr = pSurface->LockRect(&LockedRect, NULL, D3DLOCK_READONLY);
if (FAILED(hr)) {
- goto no_lock;
+ return NULL;
}
- image = new image::Image(Desc.Width, Desc.Height, numChannels, true, channelType);
- if (!image) {
- goto no_image;
- }
+ image = ConvertImage(Desc.Format, LockedRect.pBits, LockedRect.Pitch, Desc.Width, Desc.Height);
- dst = image->start();
- src = (const unsigned char *)LockedRect.pBits;
- for (unsigned y = 0; y < Desc.Height; ++y) {
- switch (Desc.Format) {
- case D3DFMT_R5G6B5:
- for (unsigned x = 0; x < Desc.Width; ++x) {
- uint32_t pixel = ((const uint16_t *)src)[x];
- dst[3*x + 0] = (( pixel & 0x1f) * (2*0xff) + 0x1f) / (2*0x1f);
- dst[3*x + 1] = (((pixel >> 5) & 0x3f) * (2*0xff) + 0x3f) / (2*0x3f);
- dst[3*x + 2] = (( pixel >> 11 ) * (2*0xff) + 0x1f) / (2*0x1f);
- }
- break;
- case D3DFMT_X8R8G8B8:
- case D3DFMT_A8R8G8B8:
- for (unsigned x = 0; x < Desc.Width; ++x) {
- dst[3*x + 0] = src[4*x + 2];
- dst[3*x + 1] = src[4*x + 1];
- dst[3*x + 2] = src[4*x + 0];
- }
- break;
- case D3DFMT_D16:
- case D3DFMT_D16_LOCKABLE:
- for (unsigned x = 0; x < Desc.Width; ++x) {
- ((float *)dst)[x] = ((const uint16_t *)src)[x] * (1.0f / 0xffff);
- }
- break;
- case D3DFMT_D32F_LOCKABLE:
- memcpy(dst, src, Desc.Width * sizeof(float));
- break;
- default:
- assert(0);
- break;
- }
-
- src += LockedRect.Pitch;
- dst += image->stride();
- }
-
-no_image:
pSurface->UnlockRect();
-no_lock:
+
return image;
}
@@ -132,35 +69,29 @@ no_lock:
static image::Image *
getRenderTargetImage(IDirect3DDevice9 *pDevice,
IDirect3DSurface9 *pRenderTarget) {
- image::Image *image = NULL;
- D3DSURFACE_DESC Desc;
- IDirect3DSurface9 *pStagingSurface = NULL;
HRESULT hr;
if (!pRenderTarget) {
return NULL;
}
+ D3DSURFACE_DESC Desc;
hr = pRenderTarget->GetDesc(&Desc);
assert(SUCCEEDED(hr));
+ com_ptr<IDirect3DSurface9> pStagingSurface;
hr = pDevice->CreateOffscreenPlainSurface(Desc.Width, Desc.Height, Desc.Format, D3DPOOL_SYSTEMMEM, &pStagingSurface, NULL);
if (FAILED(hr)) {
- goto no_staging;
+ return NULL;
}
hr = pDevice->GetRenderTargetData(pRenderTarget, pStagingSurface);
if (FAILED(hr)) {
std::cerr << "warning: GetRenderTargetData failed\n";
- goto no_rendertargetdata;
+ return NULL;
}
- image = getSurfaceImage(pDevice, pStagingSurface);
-
-no_rendertargetdata:
- pStagingSurface->Release();
-no_staging:
- return image;
+ return getSurfaceImage(pDevice, pStagingSurface);
}
@@ -168,20 +99,36 @@ image::Image *
getRenderTargetImage(IDirect3DDevice9 *pDevice) {
HRESULT hr;
- IDirect3DSurface9 *pRenderTarget = NULL;
+ com_ptr<IDirect3DSurface9> pRenderTarget;
hr = pDevice->GetRenderTarget(0, &pRenderTarget);
if (FAILED(hr)) {
return NULL;
}
assert(pRenderTarget);
- image::Image *image = NULL;
- if (pRenderTarget) {
- image = getRenderTargetImage(pDevice, pRenderTarget);
- pRenderTarget->Release();
+ return getRenderTargetImage(pDevice, pRenderTarget);
+}
+
+
+image::Image *
+getRenderTargetImage(IDirect3DSwapChain9 *pSwapChain) {
+ HRESULT hr;
+
+ com_ptr<IDirect3DDevice9> pDevice;
+ hr = pSwapChain->GetDevice(&pDevice);
+ if (FAILED(hr)) {
+ return NULL;
}
- return image;
+ // TODO: Use GetFrontBufferData instead??
+ com_ptr<IDirect3DSurface9> pBackBuffer;
+ hr = pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
+ if (FAILED(hr)) {
+ return NULL;
+ }
+ assert(pBackBuffer);
+
+ return getRenderTargetImage(pDevice, pBackBuffer);
}
@@ -191,14 +138,13 @@ getTextureImage(IDirect3DDevice9 *pDevice,
D3DCUBEMAP_FACES FaceType,
UINT Level)
{
- image::Image *image = NULL;
HRESULT hr;
if (!pTexture) {
return NULL;
}
- IDirect3DSurface9 *pSurface = NULL;
+ com_ptr<IDirect3DSurface9> pSurface;
D3DRESOURCETYPE Type = pTexture->GetType();
switch (Type) {
@@ -221,41 +167,30 @@ getTextureImage(IDirect3DDevice9 *pDevice,
hr = pSurface->GetDesc(&Desc);
assert(SUCCEEDED(hr));
- if (Desc.Pool == D3DPOOL_DEFAULT) {
- IDirect3DSurface9 *pRenderTarget = NULL;
- hr = pDevice->CreateRenderTarget(Desc.Width, Desc.Height, Desc.Format,
- D3DMULTISAMPLE_NONE, 0, FALSE,
- &pRenderTarget, NULL);
- if (FAILED(hr)) {
- std::cerr << "warning: CreateRenderTarget failed\n";
- } else {
- hr = pDevice->StretchRect(pSurface, NULL, pRenderTarget, NULL, D3DTEXF_NONE);
- if (FAILED(hr)) {
- std::cerr << "warning: StretchRect failed\n";
- } else {
- image = getRenderTargetImage(pDevice, pRenderTarget);
- }
- pRenderTarget->Release();
- }
+ if (Desc.Pool != D3DPOOL_DEFAULT ||
+ Desc.Usage & D3DUSAGE_DYNAMIC) {
+ // Lockable texture
+ return getSurfaceImage(pDevice, pSurface);
+ } else if (Desc.Usage & D3DUSAGE_RENDERTARGET) {
+ // Rendertarget texture
+ return getRenderTargetImage(pDevice, pSurface);
} else {
- image = getSurfaceImage(pDevice, pSurface);
+ // D3D constraints are such there is not much else that can be done.
+ return NULL;
}
-
- pSurface->Release();
-
- return image;
}
+
void
-dumpTextures(JSONWriter &json, IDirect3DDevice9 *pDevice)
+dumpTextures(StateWriter &writer, IDirect3DDevice9 *pDevice)
{
HRESULT hr;
- json.beginMember("textures");
- json.beginObject();
+ writer.beginMember("textures");
+ writer.beginObject();
for (DWORD Stage = 0; Stage < 16; ++Stage) {
- IDirect3DBaseTexture9 *pTexture = NULL;
+ com_ptr<IDirect3DBaseTexture9> pTexture;
hr = pDevice->GetTexture(Stage, &pTexture);
if (FAILED(hr)) {
continue;
@@ -281,34 +216,33 @@ dumpTextures(JSONWriter &json, IDirect3DDevice9 *pDevice)
} else {
_snprintf(label, sizeof label, "PS_RESOURCE_%lu_LEVEL_%lu", Stage, Level);
}
- json.beginMember(label);
- json.writeImage(image, "UNKNOWN");
- json.endMember(); // PS_RESOURCE_*
+ writer.beginMember(label);
+ writer.writeImage(image);
+ writer.endMember(); // PS_RESOURCE_*
+ delete image;
}
}
}
-
- pTexture->Release();
}
- json.endObject();
- json.endMember(); // textures
+ writer.endObject();
+ writer.endMember(); // textures
}
void
-dumpFramebuffer(JSONWriter &json, IDirect3DDevice9 *pDevice)
+dumpFramebuffer(StateWriter &writer, IDirect3DDevice9 *pDevice)
{
HRESULT hr;
- json.beginMember("framebuffer");
- json.beginObject();
+ writer.beginMember("framebuffer");
+ writer.beginObject();
D3DCAPS9 Caps;
pDevice->GetDeviceCaps(&Caps);
for (UINT i = 0; i < Caps.NumSimultaneousRTs; ++i) {
- IDirect3DSurface9 *pRenderTarget = NULL;
+ com_ptr<IDirect3DSurface9> pRenderTarget;
hr = pDevice->GetRenderTarget(i, &pRenderTarget);
if (FAILED(hr)) {
continue;
@@ -323,29 +257,28 @@ dumpFramebuffer(JSONWriter &json, IDirect3DDevice9 *pDevice)
if (image) {
char label[64];
_snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
- json.beginMember(label);
- json.writeImage(image, "UNKNOWN");
- json.endMember(); // RENDER_TARGET_*
+ writer.beginMember(label);
+ writer.writeImage(image);
+ writer.endMember(); // RENDER_TARGET_*
+ delete image;
}
-
- pRenderTarget->Release();
}
- IDirect3DSurface9 *pDepthStencil = NULL;
+ com_ptr<IDirect3DSurface9> pDepthStencil;
hr = pDevice->GetDepthStencilSurface(&pDepthStencil);
if (SUCCEEDED(hr) && pDepthStencil) {
image::Image *image;
image = getSurfaceImage(pDevice, pDepthStencil);
if (image) {
- json.beginMember("DEPTH_STENCIL");
- json.writeImage(image, "UNKNOWN");
- json.endMember(); // RENDER_TARGET_*
+ writer.beginMember("DEPTH_STENCIL");
+ writer.writeImage(image);
+ writer.endMember(); // RENDER_TARGET_*
+ delete image;
}
}
-
- json.endObject();
- json.endMember(); // framebuffer
+ writer.endObject();
+ writer.endMember(); // framebuffer
}
diff --git a/retrace/d3dretrace.hpp b/retrace/d3dretrace.hpp
index 41cc1c51..d0be5773 100644
--- a/retrace/d3dretrace.hpp
+++ b/retrace/d3dretrace.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _D3DRETRACE_HPP_
-#define _D3DRETRACE_HPP_
+#pragma once
#include <windows.h>
@@ -36,6 +35,7 @@
namespace d3dretrace {
+extern const retrace::Entry ddraw_callbacks[];
extern const retrace::Entry d3d8_callbacks[];
extern const retrace::Entry d3d9_callbacks[];
extern const retrace::Entry dxgi_callbacks[];
@@ -59,12 +59,13 @@ public:
}
bool
- dumpState(std::ostream &os) {
- if (!pLastDevice) {
- return false;
- }
- d3dstate::dumpDevice(os, pLastDevice);
- return true;
+ canDump(void) {
+ return pLastDevice;
+ }
+
+ void
+ dumpState(StateWriter &writer) {
+ d3dstate::dumpDevice(writer, pLastDevice);
}
inline void
@@ -85,6 +86,9 @@ public:
HWND
createWindow(int width, int height);
+HWND
+createWindow(HWND hWnd, int width, int height);
+
void
resizeWindow(HWND hWnd, int width, int height);
@@ -95,4 +99,3 @@ processEvents(void);
} /* namespace d3dretrace */
-#endif /* _D3DRETRACE_HPP_ */
diff --git a/retrace/d3dretrace_dxgi.hpp b/retrace/d3dretrace_dxgi.hpp
index fc5fee92..4c1c6f68 100644
--- a/retrace/d3dretrace_dxgi.hpp
+++ b/retrace/d3dretrace_dxgi.hpp
@@ -23,13 +23,13 @@
*
**************************************************************************/
-#ifndef _D3DRETRACE_DXGI_HPP_
-#define _D3DRETRACE_DXGI_HPP_
+#pragma once
#include "dxgiint.h"
#include "retrace.hpp"
+#include "d3dretrace.hpp"
/*
@@ -41,208 +41,41 @@
*/
-namespace d3dretrace {
-
-
-class CDXGISwapChainDWM : public IDXGISwapChainDWM
-{
-private:
- IDXGISwapChain *m_pSwapChain;
-
-public:
- CDXGISwapChainDWM(IDXGISwapChain *pSwapChain);
- ~CDXGISwapChainDWM();
-
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj);
- ULONG STDMETHODCALLTYPE AddRef(void);
- ULONG STDMETHODCALLTYPE Release(void);
- HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID Name, UINT DataSize, const void *pData);
- HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(REFGUID Name, const IUnknown *pUnknown);
- HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID Name, UINT *pDataSize, void *pData);
- HRESULT STDMETHODCALLTYPE GetParent(REFIID riid, void **ppParent);
- HRESULT STDMETHODCALLTYPE GetDevice(REFIID riid, void **ppDevice);
-
- HRESULT STDMETHODCALLTYPE Present(UINT SyncInterval, UINT Flags);
- HRESULT STDMETHODCALLTYPE GetBuffer(UINT Buffer, REFIID riid, void **ppSurface);
- HRESULT STDMETHODCALLTYPE GetDesc(DXGI_SWAP_CHAIN_DESC *pDesc);
- HRESULT STDMETHODCALLTYPE ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags);
- HRESULT STDMETHODCALLTYPE ResizeTarget(const DXGI_MODE_DESC *pNewTargetParameters);
- HRESULT STDMETHODCALLTYPE GetContainingOutput(IDXGIOutput **ppOutput);
- HRESULT STDMETHODCALLTYPE GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats);
- HRESULT STDMETHODCALLTYPE GetLastPresentCount(UINT *pLastPresentCount);
- HRESULT STDMETHODCALLTYPE SetFullscreenState(BOOL Fullscreen, IDXGIOutput *pTarget);
- HRESULT STDMETHODCALLTYPE GetFullscreenState(BOOL *pFullscreen, IDXGIOutput **ppTarget);
-};
-
-CDXGISwapChainDWM::CDXGISwapChainDWM(IDXGISwapChain *pSwapChain) :
- m_pSwapChain(pSwapChain)
-{
-}
-
-CDXGISwapChainDWM::~CDXGISwapChainDWM()
-{
- m_pSwapChain->SetFullscreenState(FALSE, NULL);
- m_pSwapChain->Release();
-}
-
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::QueryInterface(REFIID riid, void **ppvObj)
-{
- return m_pSwapChain->QueryInterface(riid, ppvObj);
-}
-
-ULONG STDMETHODCALLTYPE CDXGISwapChainDWM::AddRef(void)
-{
- // FIXME
- return 1;
-}
-
-ULONG STDMETHODCALLTYPE CDXGISwapChainDWM::Release(void)
-{
- // FIXME
- return 1;
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::SetPrivateData(REFGUID Name, UINT DataSize, const void *pData)
-{
- return m_pSwapChain->SetPrivateData(Name, DataSize, pData);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::SetPrivateDataInterface(REFGUID Name, const IUnknown *pUnknown)
-{
- return m_pSwapChain->SetPrivateDataInterface(Name, pUnknown);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetPrivateData(REFGUID Name, UINT *pDataSize, void *pData)
-{
- return m_pSwapChain->GetPrivateData(Name, pDataSize, pData);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetParent(REFIID riid, void **ppParent)
-{
- return m_pSwapChain->GetParent(riid, ppParent);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetDevice(REFIID riid, void **ppDevice)
-{
- return m_pSwapChain->GetDevice(riid, ppDevice);
-}
+struct ID3D10Device;
+struct ID3D11Device;
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::Present(UINT SyncInterval, UINT Flags)
-{
- return m_pSwapChain->Present(SyncInterval, Flags);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetBuffer(UINT Buffer, REFIID riid, void **ppSurface)
-{
- return m_pSwapChain->GetBuffer(Buffer, riid, ppSurface);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetDesc(DXGI_SWAP_CHAIN_DESC *pDesc)
-{
- return m_pSwapChain->GetDesc(pDesc);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags)
-{
- return m_pSwapChain->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::ResizeTarget(const DXGI_MODE_DESC *pNewTargetParameters)
-{
- return m_pSwapChain->ResizeTarget(pNewTargetParameters);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetContainingOutput(IDXGIOutput **ppOutput)
-{
- return m_pSwapChain->GetContainingOutput(ppOutput);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats)
-{
- return m_pSwapChain->GetFrameStatistics(pStats);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetLastPresentCount(UINT *pLastPresentCount)
-{
- return m_pSwapChain->GetLastPresentCount(pLastPresentCount);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::SetFullscreenState(BOOL Fullscreen, IDXGIOutput *pTarget)
-{
- return m_pSwapChain->SetFullscreenState(Fullscreen, pTarget);
-}
-
-HRESULT STDMETHODCALLTYPE CDXGISwapChainDWM::GetFullscreenState(BOOL *pFullscreen, IDXGIOutput **ppTarget)
-{
- return m_pSwapChain->GetFullscreenState(pFullscreen, ppTarget);
-}
-
-
-
-class CDXGIFactoryDWM : public IDXGIFactoryDWM
-{
-private:
- IDXGIFactory *m_pFactory;
-
- ~CDXGIFactoryDWM();
-
-public:
- CDXGIFactoryDWM(IDXGIFactory *pFactory);
-
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj);
- ULONG STDMETHODCALLTYPE AddRef(void);
- ULONG STDMETHODCALLTYPE Release(void);
- HRESULT STDMETHODCALLTYPE CreateSwapChain(IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGIOutput *pOutput, IDXGISwapChainDWM **ppSwapChain);
-};
+namespace d3dretrace {
-CDXGIFactoryDWM::CDXGIFactoryDWM(IDXGIFactory *pFactory) :
- m_pFactory(pFactory)
-{}
-CDXGIFactoryDWM::~CDXGIFactoryDWM()
-{
- m_pFactory->Release();
+static inline void
+createWindowForSwapChain(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
+ UINT Width = pSwapChainDesc->BufferDesc.Width;
+ UINT Height = pSwapChainDesc->BufferDesc.Height;
+ if (!Width) Width = 1024;
+ if (!Height) Height = 768;
+ if (retrace::forceWindowed) {
+ pSwapChainDesc->Windowed = TRUE;
+ pSwapChainDesc->Flags &= ~DXGI_SWAP_CHAIN_FLAG_NONPREROTATED;
+ }
+ if (pSwapChainDesc->OutputWindow) {
+ pSwapChainDesc->OutputWindow = d3dretrace::createWindow(Width, Height);
+ }
}
-HRESULT STDMETHODCALLTYPE CDXGIFactoryDWM::QueryInterface(REFIID riid, void **ppvObj)
-{
- return m_pFactory->QueryInterface(riid, ppvObj);
-}
+BOOL
+overrideQueryInterface(IUnknown *pThis, REFIID riid, void **ppvObj, HRESULT *pResult);
-ULONG STDMETHODCALLTYPE CDXGIFactoryDWM::AddRef(void)
-{
- // FIXME
- return 1;
-}
-ULONG STDMETHODCALLTYPE CDXGIFactoryDWM::Release(void)
-{
- // FIXME
- return 1;
-}
+HRESULT
+createSharedResource(ID3D10Device *pDevice, REFIID ReturnedInterface, void **ppResource);
-HRESULT STDMETHODCALLTYPE CDXGIFactoryDWM::CreateSwapChain(IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGIOutput *pOutput, IDXGISwapChainDWM **ppSwapChain)
-{
- IDXGISwapChain *pSwapChain = NULL;
- if (retrace::forceWindowed) {
- pDesc->Windowed = TRUE;
- }
- HRESULT hr = m_pFactory->CreateSwapChain(pDevice, pDesc, &pSwapChain);
- if (SUCCEEDED(hr)) {
- if (!retrace::forceWindowed) {
- pSwapChain->SetFullscreenState(TRUE, pOutput);
- }
- *ppSwapChain = new CDXGISwapChainDWM(pSwapChain);
- }
- return hr;
-}
+HRESULT
+createSharedResource(ID3D11Device *pDevice, REFIID ReturnedInterface, void **ppResource);
} /* namespace d3dretrace */
-#endif /* _D3DRETRACE_DXGI_HPP_ */
diff --git a/retrace/d3dretrace_dxgi_misc.cpp b/retrace/d3dretrace_dxgi_misc.cpp
new file mode 100644
index 00000000..562f0db2
--- /dev/null
+++ b/retrace/d3dretrace_dxgi_misc.cpp
@@ -0,0 +1,113 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware Inc
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "d3dretrace_dxgi.hpp"
+
+#include "d3d10imports.hpp"
+#include "d3d11imports.hpp"
+
+#include "com_ptr.hpp"
+
+
+namespace d3dretrace {
+
+
+static const DWORD
+Checker[8][8] = {
+ { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U },
+ { ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U },
+ { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U },
+ { ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U },
+ { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U },
+ { ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U },
+ { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U },
+ { ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }
+};
+
+
+HRESULT
+createSharedResource(ID3D10Device *pDevice, REFIID ReturnedInterface, void **ppResource)
+{
+ D3D10_TEXTURE2D_DESC Desc;
+ memset(&Desc, 0, sizeof Desc);
+ Desc.Width = 8;
+ Desc.Height = 8;
+ Desc.MipLevels = 1;
+ Desc.ArraySize = 1;
+ Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ Desc.SampleDesc.Count = 1;
+ Desc.SampleDesc.Quality = 0;
+ Desc.Usage = D3D10_USAGE_DEFAULT;
+ Desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;
+ Desc.CPUAccessFlags = 0x0;
+ Desc.MiscFlags = 0 /* D3D10_RESOURCE_MISC_SHARED */;
+
+ static const D3D10_SUBRESOURCE_DATA InitialData = {
+ Checker, sizeof Checker[0], sizeof Checker
+ };
+
+ com_ptr<ID3D10Texture2D> pResource;
+ HRESULT hr = pDevice->CreateTexture2D(&Desc, &InitialData, &pResource);
+ if (SUCCEEDED(hr)) {
+ hr = pResource->QueryInterface(ReturnedInterface, ppResource);
+ }
+
+ return hr;
+}
+
+
+HRESULT
+createSharedResource(ID3D11Device *pDevice, REFIID ReturnedInterface, void **ppResource)
+{
+ D3D11_TEXTURE2D_DESC Desc;
+ memset(&Desc, 0, sizeof Desc);
+ Desc.Width = 8;
+ Desc.Height = 8;
+ Desc.MipLevels = 1;
+ Desc.ArraySize = 1;
+ Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ Desc.SampleDesc.Count = 1;
+ Desc.SampleDesc.Quality = 0;
+ Desc.Usage = D3D11_USAGE_DEFAULT;
+ Desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ Desc.CPUAccessFlags = 0x0;
+ Desc.MiscFlags = 0 /* D3D11_RESOURCE_MISC_SHARED */;
+ //Desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
+
+ static const D3D11_SUBRESOURCE_DATA InitialData = {
+ Checker, sizeof Checker[0], sizeof Checker
+ };
+
+ com_ptr<ID3D11Texture2D> pResource;
+ HRESULT hr = pDevice->CreateTexture2D(&Desc, &InitialData, &pResource);
+ if (SUCCEEDED(hr)) {
+ hr = pResource->QueryInterface(ReturnedInterface, ppResource);
+ }
+
+ return hr;
+}
+
+
+} /* namespace d3dretrace */
diff --git a/retrace/d3dretrace_dxgi_priv.cpp b/retrace/d3dretrace_dxgi_priv.cpp
new file mode 100644
index 00000000..a32e0205
--- /dev/null
+++ b/retrace/d3dretrace_dxgi_priv.cpp
@@ -0,0 +1,283 @@
+/**************************************************************************
+ *
+ * Copyright 2012 VMware Inc
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifdef HAVE_DXGI
+
+
+#include "d3dretrace_dxgi.hpp"
+
+
+/*
+ * This module implements the IDXGIFactoryDWM and IDXGISwapChainDWM
+ * undocumented interfaces used by DWM, in terms of the standard IDXGIFactory
+ * and IDXGISwapChain interfaces, just for sake of d3dretrace. Retracing on
+ * top of the undocumented interfaces works, but it may interfere with running
+ * DWM and causes corruption of the desktop upon exit.
+ *
+ * Note that we don't maintain our own reference counts in these
+ * implementations, as there should only be one reference count for all
+ * interfaces. See http://msdn.microsoft.com/en-us/library/ms686590.aspx
+ */
+
+
+namespace d3dretrace {
+
+
+static HRESULT __stdcall
+GetInterface(IUnknown *pUnknown, void **ppvObj) {
+ if (!ppvObj) {
+ return E_POINTER;
+ }
+ *ppvObj = (LPVOID)pUnknown;
+ pUnknown->AddRef();
+ return S_OK;
+}
+
+
+class CDXGISwapChainDWM : public IDXGISwapChainDWM
+{
+protected:
+ IDXGISwapChain *m_pSwapChain;
+ IDXGIOutput *m_pOutput;
+
+ virtual ~CDXGISwapChainDWM() {
+ m_pSwapChain->SetFullscreenState(FALSE, NULL);
+ m_pOutput->Release();
+ }
+
+public:
+ CDXGISwapChainDWM(IDXGISwapChain *pSwapChain, IDXGIOutput *pOutput) :
+ m_pSwapChain(pSwapChain),
+ m_pOutput(pOutput)
+ {
+ m_pOutput->AddRef();
+ if (!retrace::forceWindowed) {
+ pSwapChain->SetFullscreenState(TRUE, pOutput);
+ }
+ }
+
+ /*
+ * IUnknown
+ */
+
+ HRESULT STDMETHODCALLTYPE
+ QueryInterface(REFIID riid, void **ppvObj)
+ {
+ if (riid == IID_IDXGISwapChainDWM) {
+ return GetInterface(this, ppvObj);
+ }
+ return m_pSwapChain->QueryInterface(riid, ppvObj);
+ }
+
+ ULONG STDMETHODCALLTYPE
+ AddRef(void) {
+ return m_pSwapChain->AddRef();
+ }
+
+ ULONG STDMETHODCALLTYPE
+ Release(void) {
+ ULONG cRef = m_pSwapChain->Release();
+ if (cRef == 0) {
+ delete this;
+ }
+ return cRef;
+ }
+
+ /*
+ * IDXGIObject
+ */
+
+ HRESULT STDMETHODCALLTYPE
+ SetPrivateData(REFGUID Name, UINT DataSize, const void *pData) {
+ return m_pSwapChain->SetPrivateData(Name, DataSize, pData);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ SetPrivateDataInterface(REFGUID Name, const IUnknown *pUnknown) {
+ return m_pSwapChain->SetPrivateDataInterface(Name, pUnknown);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ GetPrivateData(REFGUID Name, UINT *pDataSize, void *pData) {
+ return m_pSwapChain->GetPrivateData(Name, pDataSize, pData);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ GetParent(REFIID riid, void **ppParent) {
+ return m_pSwapChain->GetParent(riid, ppParent);
+ }
+
+ /*
+ * IDXGIDeviceSubObject
+ */
+
+ HRESULT STDMETHODCALLTYPE
+ GetDevice(REFIID riid, void **ppDevice) {
+ return m_pSwapChain->GetDevice(riid, ppDevice);
+ }
+
+ /*
+ * IDXGISwapChainDWM
+ */
+
+ HRESULT STDMETHODCALLTYPE
+ Present(UINT SyncInterval, UINT Flags) {
+ return m_pSwapChain->Present(SyncInterval, Flags);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ GetBuffer(UINT Buffer, REFIID riid, void **ppSurface) {
+ /* XXX: IDXGISwapChain buffers with indexes greater than zero can only
+ * be read from, per
+ * http://msdn.microsoft.com/en-gb/library/windows/desktop/bb174570.aspx,
+ * but it appears that IDXGISwapChainDWM doesn't have that limitation.
+ */
+ return m_pSwapChain->GetBuffer(Buffer, riid, ppSurface);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ GetDesc(DXGI_SWAP_CHAIN_DESC *pDesc) {
+ return m_pSwapChain->GetDesc(pDesc);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) {
+ return m_pSwapChain->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ ResizeTarget(const DXGI_MODE_DESC *pNewTargetParameters) {
+ return m_pSwapChain->ResizeTarget(pNewTargetParameters);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ GetContainingOutput(IDXGIOutput **ppOutput) {
+ return GetInterface(m_pOutput, (void **) ppOutput);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats) {
+ return m_pSwapChain->GetFrameStatistics(pStats);
+ }
+
+ HRESULT STDMETHODCALLTYPE
+ GetLastPresentCount(UINT *pLastPresentCount) {
+ return m_pSwapChain->GetLastPresentCount(pLastPresentCount);
+ }
+};
+
+
+class CDXGIFactoryDWM : public IDXGIFactoryDWM
+{
+private:
+ IDXGIFactory *m_pFactory;
+
+ virtual ~CDXGIFactoryDWM() {
+ }
+
+public:
+ CDXGIFactoryDWM(IDXGIFactory *pFactory) :
+ m_pFactory(pFactory)
+ {}
+
+ /*
+ * IUnknown
+ */
+
+ HRESULT STDMETHODCALLTYPE
+ QueryInterface(REFIID riid, void **ppvObj)
+ {
+ if (riid == IID_IDXGIFactoryDWM) {
+ return GetInterface(static_cast<IDXGIFactoryDWM *>(this), ppvObj);
+ }
+ return m_pFactory->QueryInterface(riid, ppvObj);
+ }
+
+ ULONG STDMETHODCALLTYPE
+ AddRef(void) {
+ return m_pFactory->AddRef();
+ }
+
+ ULONG STDMETHODCALLTYPE
+ Release(void) {
+ ULONG cRef = m_pFactory->Release();
+ if (cRef == 0) {
+ delete this;
+ }
+ return cRef;
+ }
+
+ /*
+ * IDXGIFactoryDWM
+ */
+
+ HRESULT STDMETHODCALLTYPE
+ CreateSwapChain(IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGIOutput *pOutput, IDXGISwapChainDWM **ppSwapChain)
+ {
+ assert(pOutput);
+ IDXGISwapChain *pSwapChain = NULL;
+ if (retrace::forceWindowed) {
+ assert(pDesc->Windowed);
+ }
+ assert(!pDesc->OutputWindow);
+ pDesc->OutputWindow = d3dretrace::createWindow(pDesc->BufferDesc.Width, pDesc->BufferDesc.Height);
+ HRESULT hr = m_pFactory->CreateSwapChain(pDevice, pDesc, &pSwapChain);
+ if (SUCCEEDED(hr)) {
+ *ppSwapChain = new CDXGISwapChainDWM(pSwapChain, pOutput);
+ }
+ return hr;
+ }
+};
+
+
+BOOL
+overrideQueryInterface(IUnknown *pUnknown, REFIID riid, void **ppvObj, HRESULT *pResult)
+{
+ HRESULT hr;
+
+ if (!ppvObj) {
+ *pResult = E_POINTER;
+ return TRUE;
+ }
+
+ if (riid == IID_IDXGIFactoryDWM) {
+ IDXGIFactory *pFactory = NULL;
+ hr = pUnknown->QueryInterface(IID_IDXGIFactory, (VOID **)&pFactory);
+ if (SUCCEEDED(hr)) {
+ *ppvObj = new d3dretrace::CDXGIFactoryDWM(pFactory);
+ *pResult = S_OK;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+} /* namespace d3dretrace */
+
+
+#endif /* HAVE_DXGI */
diff --git a/retrace/d3dretrace_main.cpp b/retrace/d3dretrace_main.cpp
index 33fb835f..433e0a07 100644
--- a/retrace/d3dretrace_main.cpp
+++ b/retrace/d3dretrace_main.cpp
@@ -47,9 +47,12 @@ retrace::setUp(void) {
void
retrace::addCallbacks(retrace::Retracer &retracer)
{
+ retracer.addCallbacks(d3dretrace::ddraw_callbacks);
retracer.addCallbacks(d3dretrace::d3d8_callbacks);
retracer.addCallbacks(d3dretrace::d3d9_callbacks);
+#ifdef HAVE_DXGI
retracer.addCallbacks(d3dretrace::dxgi_callbacks);
+#endif
}
diff --git a/retrace/d3dretrace_ws.cpp b/retrace/d3dretrace_ws.cpp
index d9f101ab..62f3a9c7 100644
--- a/retrace/d3dretrace_ws.cpp
+++ b/retrace/d3dretrace_ws.cpp
@@ -28,129 +28,58 @@
#include "d3dretrace.hpp"
+#include "ws_win32.hpp"
-namespace d3dretrace {
+namespace d3dretrace {
-// XXX: Don't duplicate this code.
-static LRESULT CALLBACK
-WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+HWND
+createWindow(int width, int height)
{
- MINMAXINFO *pMMI;
- switch (uMsg) {
- case WM_KEYDOWN:
- switch (wParam) {
- case VK_ESCAPE:
- PostMessage(hWnd, WM_CLOSE, 0, 0);
- break;
- }
- break;
- case WM_GETMINMAXINFO:
- // Allow to create a window bigger than the desktop
- pMMI = (MINMAXINFO *)lParam;
- pMMI->ptMaxSize.x = 60000;
- pMMI->ptMaxSize.y = 60000;
- pMMI->ptMaxTrackSize.x = 60000;
- pMMI->ptMaxTrackSize.y = 60000;
- break;
- case WM_CLOSE:
- exit(0);
- break;
- default:
- break;
- }
+ HWND hWnd;
+
+ hWnd = ws::createWindow("d3dretrace", width, height);
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
+ ws::showWindow(hWnd);
+
+ return hWnd;
}
-HWND
-createWindow(int width, int height) {
- static bool first = TRUE;
- RECT rect;
-
- if (first) {
- WNDCLASS wc;
- memset(&wc, 0, sizeof wc);
- wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wc.lpfnWndProc = WndProc;
- wc.lpszClassName = "d3dretrace";
- wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
- RegisterClass(&wc);
- first = FALSE;
- }
+typedef std::map<HWND, HWND> HWND_MAP;
+static HWND_MAP g_hWndMap;
- DWORD dwExStyle;
- DWORD dwStyle;
- HWND hWnd;
- dwExStyle = 0;
- dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
-
- int x = 0, y = 0;
-
- rect.left = x;
- rect.top = y;
- rect.right = rect.left + width;
- rect.bottom = rect.top + height;
-
- AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
-
- hWnd = CreateWindowEx(dwExStyle,
- "d3dretrace", /* wc.lpszClassName */
- NULL,
- dwStyle,
- 0, /* x */
- 0, /* y */
- rect.right - rect.left, /* width */
- rect.bottom - rect.top, /* height */
- NULL,
- NULL,
- NULL,
- NULL);
- ShowWindow(hWnd, SW_SHOW);
+HWND
+createWindow(HWND hWnd, int width, int height)
+{
+ HWND_MAP::iterator it;
+ it = g_hWndMap.find(hWnd);
+ if (it == g_hWndMap.end()) {
+ // Create a new window
+ hWnd = createWindow(width, height);
+ g_hWndMap[hWnd] = hWnd;
+ } else {
+ // Reuse the existing window
+ hWnd = it->second;
+ ws::resizeWindow(hWnd, width, height);
+ }
return hWnd;
}
void
-resizeWindow(HWND hWnd, int width, int height) {
- RECT rClient;
- GetClientRect(hWnd, &rClient);
- if (width == rClient.right - rClient.left &&
- height == rClient.bottom - rClient.top) {
- return;
- }
-
- RECT rWindow;
- GetWindowRect(hWnd, &rWindow);
- width += (rWindow.right - rWindow.left) - rClient.right;
- height += (rWindow.bottom - rWindow.top) - rClient.bottom;
-
- // SetWindowPos will hang if this ever happens.
- assert(GetCurrentThreadId() == GetWindowThreadProcessId(hWnd, NULL));
-
- SetWindowPos(hWnd, NULL, rWindow.left, rWindow.top, width, height, SWP_NOMOVE);
+resizeWindow(HWND hWnd, int width, int height)
+{
+ ws::resizeWindow(hWnd, width, height);
}
bool
-processEvents(void) {
- MSG uMsg;
- while (PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE)) {
- if (uMsg.message == WM_QUIT) {
- return false;
- }
-
- if (!TranslateAccelerator(uMsg.hwnd, NULL, &uMsg)) {
- TranslateMessage(&uMsg);
- DispatchMessage(&uMsg);
- }
- }
- return true;
+processEvents(void)
+{
+ return ws::processEvents();
}
diff --git a/retrace/d3dstate.hpp b/retrace/d3dstate.hpp
index 83727085..fe911d80 100644
--- a/retrace/d3dstate.hpp
+++ b/retrace/d3dstate.hpp
@@ -23,22 +23,30 @@
*
**************************************************************************/
-#ifndef _D3DSTATE_HPP_
-#define _D3DSTATE_HPP_
+#pragma once
#include <iostream>
#include <windows.h>
+#ifdef HAVE_DXGI
+#include <dxgiformat.h>
+#endif
+
+struct IDirect3DDevice7;
struct IDirect3DDevice8;
struct IDirect3DDevice9;
+struct IDirect3DSwapChain9;
+struct IDXGISwapChain;
struct ID3D10Device;
+struct ID3D10Resource;
struct ID3D11DeviceContext;
+struct ID3D11Resource;
-class JSONWriter;
+class StateWriter;
namespace image {
class Image;
@@ -52,6 +60,20 @@ extern const GUID GUID_D3DSTATE;
/*
+ * D3D7
+ */
+
+image::Image *
+getRenderTargetImage(IDirect3DDevice7 *pDevice);
+
+void
+dumpFramebuffer(StateWriter &writer, IDirect3DDevice7 *pDevice);
+
+void
+dumpDevice(StateWriter &writer, IDirect3DDevice7 *pDevice);
+
+
+/*
* D3D8
*/
@@ -59,10 +81,10 @@ image::Image *
getRenderTargetImage(IDirect3DDevice8 *pDevice);
void
-dumpFramebuffer(JSONWriter &json, IDirect3DDevice8 *pDevice);
+dumpFramebuffer(StateWriter &writer, IDirect3DDevice8 *pDevice);
void
-dumpDevice(std::ostream &os, IDirect3DDevice8 *pDevice);
+dumpDevice(StateWriter &writer, IDirect3DDevice8 *pDevice);
/*
@@ -70,16 +92,36 @@ dumpDevice(std::ostream &os, IDirect3DDevice8 *pDevice);
*/
image::Image *
-getRenderTargetImage(IDirect3DDevice9 *pDevice);
+getRenderTargetImage(IDirect3DSwapChain9 *pSwapChain);
void
-dumpTextures(JSONWriter &json, IDirect3DDevice9 *pDevice);
+dumpTextures(StateWriter &writer, IDirect3DDevice9 *pDevice);
void
-dumpFramebuffer(JSONWriter &json, IDirect3DDevice9 *pDevice);
+dumpFramebuffer(StateWriter &writer, IDirect3DDevice9 *pDevice);
void
-dumpDevice(std::ostream &os, IDirect3DDevice9 *pDevice);
+dumpDevice(StateWriter &writer, IDirect3DDevice9 *pDevice);
+
+image::Image *
+getRenderTargetImage(IDirect3DDevice9 *pDevice);
+
+void
+dumpDevice(StateWriter &writer, IDirect3DSwapChain9 *pSwapChain);
+
+
+#ifdef HAVE_DXGI
+
+
+/*
+ * DXGI
+ */
+
+image::Image *
+getRenderTargetImage(IDXGISwapChain *pSwapChain);
+
+void
+dumpDevice(StateWriter &writer, IDXGISwapChain *pSwapChain);
/*
@@ -87,16 +129,17 @@ dumpDevice(std::ostream &os, IDirect3DDevice9 *pDevice);
*/
image::Image *
-getRenderTargetImage(ID3D10Device *pDevice);
+getRenderTargetImage(ID3D10Device *pDevice,
+ DXGI_FORMAT *dxgiFormat = 0);
void
-dumpTextures(JSONWriter &json, ID3D10Device *pDevice);
+dumpTextures(StateWriter &writer, ID3D10Device *pDevice);
void
-dumpFramebuffer(JSONWriter &json, ID3D10Device *pDevice);
+dumpFramebuffer(StateWriter &writer, ID3D10Device *pDevice);
void
-dumpDevice(std::ostream &os, ID3D10Device *pDevice);
+dumpDevice(StateWriter &writer, ID3D10Device *pDevice);
/*
@@ -104,19 +147,22 @@ dumpDevice(std::ostream &os, ID3D10Device *pDevice);
*/
image::Image *
-getRenderTargetImage(ID3D11DeviceContext *pDeviceContext);
+getRenderTargetImage(ID3D11DeviceContext *pDeviceContext,
+ DXGI_FORMAT *dxgiFormat = 0);
void
-dumpTextures(JSONWriter &json, ID3D11DeviceContext *pDeviceContext);
+dumpTextures(StateWriter &writer, ID3D11DeviceContext *pDeviceContext);
void
-dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDeviceContext);
+dumpFramebuffer(StateWriter &writer, ID3D11DeviceContext *pDeviceContext);
void
-dumpDevice(std::ostream &os, ID3D11DeviceContext *pDeviceContext);
+dumpDevice(StateWriter &writer, ID3D11DeviceContext *pDeviceContext);
+
+
+#endif /* HAVE_DXGI */
} /* namespace d3dstate */
-#endif /* _D3DSTATE_HPP_ */
diff --git a/retrace/ddrawretrace.py b/retrace/ddrawretrace.py
new file mode 100644
index 00000000..4f2ff944
--- /dev/null
+++ b/retrace/ddrawretrace.py
@@ -0,0 +1,149 @@
+##########################################################################
+#
+# Copyright 2011 Jose Fonseca
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+##########################################################################/
+
+
+"""D3D retracer generator."""
+
+
+import sys
+from dllretrace import DllRetracer as Retracer
+from specs.stdapi import API
+from specs.d3d import ddraw, HWND
+from specs.ddraw import DDCREATE_LPGUID
+
+
+class D3DRetracer(Retracer):
+
+ def retraceApi(self, api):
+ print '// Swizzling mapping for lock addresses'
+ print 'static std::map<void *, void *> _maps;'
+ print
+ # TODO: Keep a table of windows
+ print 'static HWND g_hWnd;'
+ print
+
+ Retracer.retraceApi(self, api)
+
+ def invokeInterfaceMethod(self, interface, method):
+ # keep track of the last used device for state dumping
+ if interface.name in ('IDirect3DDevice7',):
+ if method.name == 'Release':
+ print r' if (call.ret->toUInt() == 0) {'
+ print r' d3d7Dumper.unbindDevice(_this);'
+ print r' }'
+ else:
+ print r' d3d7Dumper.bindDevice(_this);'
+
+ # create windows as neccessary
+ hWndArg = method.getArgByType(HWND)
+ if hWndArg is not None:
+ # FIXME: Try to guess the window size (e.g., from IDirectDrawSurface7::Blt)
+ print r' if (!g_hWnd) {'
+ print r' g_hWnd = d3dretrace::createWindow(512, 512);'
+ print r' }'
+ print r' %s = g_hWnd;' % hWndArg.name
+
+
+ if method.name == 'Lock':
+ # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no
+ # way to cope with it (other than retry).
+ mapFlagsArg = method.getArgByName('dwFlags')
+ if mapFlagsArg is not None:
+ print r' dwFlags &= DDLOCK_DONOTWAIT;'
+ print r' dwFlags |= DDLOCK_WAIT;'
+
+ Retracer.invokeInterfaceMethod(self, interface, method)
+
+ if method.name == 'CreateDevice':
+ print r' if (FAILED(_result)) {'
+ print r' exit(1);'
+ print r' }'
+
+ # notify frame has been completed
+ # process events after presents
+ if interface.name == 'IDirectDrawSurface7' and method.name == 'Blt':
+ print r' DDSCAPS2 ddsCaps;'
+ print r' if (SUCCEEDED(_this->GetCaps(&ddsCaps)) &&'
+ print r' (ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {'
+ print r' retrace::frameComplete(call);'
+ print r' d3dretrace::processEvents();'
+ print r' }'
+
+ if method.name == 'Lock':
+ print ' VOID *_pbData = NULL;'
+ print ' size_t _MappedSize = 0;'
+ # FIXME: determine the mapping size
+ #print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1])
+ print ' if (_MappedSize) {'
+ print ' _maps[_this] = _pbData;'
+ # TODO: check pitches match
+ print ' } else {'
+ print ' return;'
+ print ' }'
+
+ if method.name == 'Unlock':
+ print ' VOID *_pbData = 0;'
+ print ' _pbData = _maps[_this];'
+ print ' if (_pbData) {'
+ print ' retrace::delRegionByPointer(_pbData);'
+ print ' _maps[_this] = 0;'
+ print ' }'
+
+ def extractArg(self, function, arg, arg_type, lvalue, rvalue):
+ # Handle DDCREATE_* flags
+ if arg.type is DDCREATE_LPGUID:
+ print ' if (%s.toArray()) {' % rvalue
+ Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
+ print ' } else {'
+ print ' %s = static_cast<%s>(%s.toPointer());' % (lvalue, arg_type, rvalue)
+ print ' }'
+ return
+
+ Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
+
+
+def main():
+ print r'#include <string.h>'
+ print
+ print r'#include <iostream>'
+ print
+ print r'#include "d3dretrace.hpp"'
+ print
+
+ api = API()
+
+ print r'#include "d3dimports.hpp"'
+ api.addModule(ddraw)
+ print
+ print '''static d3dretrace::D3DDumper<IDirect3DDevice7> d3d7Dumper;'''
+ print
+
+ retracer = D3DRetracer()
+ retracer.table_name = 'd3dretrace::ddraw_callbacks'
+ retracer.retraceApi(api)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/retrace/dllretrace.py b/retrace/dllretrace.py
index aa7ed45a..c818b0a9 100644
--- a/retrace/dllretrace.py
+++ b/retrace/dllretrace.py
@@ -60,7 +60,6 @@ class DllDispatcher(Dispatcher):
Dispatcher.dispatchModule(self, module)
def getProcAddressName(self, module, function):
- assert self.isFunctionPublic(module, function)
return '_get%sProcAddress' % (module.name.upper())
diff --git a/retrace/dxgiretrace.py b/retrace/dxgiretrace.py
index 48bbec14..799e3df9 100755
--- a/retrace/dxgiretrace.py
+++ b/retrace/dxgiretrace.py
@@ -31,29 +31,19 @@ import sys
from dllretrace import DllRetracer as Retracer
import specs.dxgi
from specs.stdapi import API
+from specs.winapi import LPCSTR
from specs.dxgi import dxgi
-from specs.d3d10 import d3d10
-from specs.d3d10_1 import d3d10_1
+from specs.d3d10 import d3d10, d3d10_1
from specs.d3d11 import d3d11
class D3DRetracer(Retracer):
def retraceApi(self, api):
- print '// Swizzling mapping for lock addresses'
- print 'static std::map<void *, void *> _maps;'
+ print '// Swizzling mapping for lock addresses, mapping a (pDeviceContext, pResource, Subresource) -> void *'
+ print 'typedef std::pair< IUnknown *, UINT > SubresourceKey;'
+ print 'static std::map< IUnknown *, std::map< SubresourceKey, void * > > g_Maps;'
print
- print r'''
-static void
-createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
- UINT Width = pSwapChainDesc->BufferDesc.Width;
- UINT Height = pSwapChainDesc->BufferDesc.Height;
- if (!Width) Width = 1024;
- if (!Height) Height = 768;
- pSwapChainDesc->OutputWindow = d3dretrace::createWindow(Width, Height);
-}
-'''
-
self.table_name = 'd3dretrace::dxgi_callbacks'
Retracer.retraceApi(self, api)
@@ -71,7 +61,7 @@ createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
if function.name in self.createDeviceFunctionNames:
# create windows as neccessary
if 'pSwapChainDesc' in function.argNames():
- print r' createWindow(pSwapChainDesc);'
+ print r' d3dretrace::createWindowForSwapChain(pSwapChainDesc);'
# Compensate for the fact we don't trace DXGI object creation
if function.name.startswith('D3D11CreateDevice'):
@@ -83,8 +73,12 @@ createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
# Toggle debugging
print r' Flags &= ~D3D10_CREATE_DEVICE_DEBUG;'
print r' if (retrace::debug) {'
- print r' if (LoadLibraryA("d3d10sdklayers")) {'
+ print r' HMODULE hD3d10SdkLayers = LoadLibraryA("d3d10sdklayers");'
+ print r' if (hD3d10SdkLayers) {'
+ print r' FreeLibrary(hD3d10SdkLayers);'
print r' Flags |= D3D10_CREATE_DEVICE_DEBUG;'
+ print r' } else {'
+ print r' retrace::warning(call) << "Direct3D 10.x SDK Debug Layer (d3d10sdklayers.dll) not available, continuing without debug output\n";'
print r' }'
print r' }'
@@ -95,17 +89,11 @@ createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
# Toggle debugging
print r' Flags &= ~D3D11_CREATE_DEVICE_DEBUG;'
print r' if (retrace::debug) {'
- print r' OSVERSIONINFO osvi;'
- print r' BOOL bIsWindows8orLater;'
- print r' ZeroMemory(&osvi, sizeof osvi);'
- print r' osvi.dwOSVersionInfoSize = sizeof osvi;'
- print r' GetVersionEx(&osvi);'
- print r' bIsWindows8orLater = '
- print r' (osvi.dwMajorVersion > 6) ||'
- print r' (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 2);'
- print r' const char *szD3d11SdkLayers = bIsWindows8orLater ? "d3d11_1sdklayers" : "d3d11sdklayers";'
- print r' if (LoadLibraryA(szD3d11SdkLayers)) {'
+ print r' HRESULT hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, 0, D3D11_CREATE_DEVICE_DEBUG, NULL, 0, D3D11_SDK_VERSION, NULL, NULL, NULL);'
+ print r' if (SUCCEEDED(hr)) {'
print r' Flags |= D3D11_CREATE_DEVICE_DEBUG;'
+ print r' } else {'
+ print r' retrace::warning(call) << "Direct3D 11.x SDK Debug Layer (d3d11*sdklayers.dll) not available, continuing without debug output\n";'
print r' }'
print r' }'
@@ -114,32 +102,24 @@ createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
Retracer.invokeFunction(self, function)
- # Debug layers with Windows 8 or Windows 7 Platform update are a mess.
- # It's not possible to know before hand whether they are or not
- # available, so always retry with debug flag off..
- if function.name in self.createDeviceFunctionNames:
- print r' if (FAILED(_result)) {'
-
- if function.name.startswith('D3D10CreateDevice'):
- print r' if (_result == E_FAIL && (Flags & D3D10_CREATE_DEVICE_DEBUG)) {'
- print r' retrace::warning(call) << "debug layer (d3d10sdklayers.dll) not installed\n";'
- print r' Flags &= ~D3D10_CREATE_DEVICE_DEBUG;'
- Retracer.invokeFunction(self, function)
- print r' }'
- elif function.name.startswith('D3D11CreateDevice'):
- print r' if (_result == E_FAIL && (Flags & D3D11_CREATE_DEVICE_DEBUG)) {'
- print r' retrace::warning(call) << "debug layer (d3d11sdklayers.dll for Windows 7, d3d11_1sdklayers.dll for Windows 8 or Windows 7 with KB 2670838) not properly installed\n";'
- print r' Flags &= ~D3D11_CREATE_DEVICE_DEBUG;'
- Retracer.invokeFunction(self, function)
- print r' }'
- else:
- assert False
-
- print r' if (FAILED(_result)) {'
- print r' exit(1);'
- print r' }'
-
- print r' }'
+ def checkResult(self, interface, methodOrFunction):
+ # Catch when device is removed, and report the reason.
+ if str(methodOrFunction.type) == 'HRESULT':
+ if interface is not None:
+ getDeviceRemovedReasonMethod = interface.getMethodByName("GetDeviceRemovedReason")
+ if getDeviceRemovedReasonMethod is not None:
+ print r' if (FAILED(_result)) {'
+ print r' retrace::failed(call, _result);'
+ print r' if (_result == DXGI_ERROR_DEVICE_REMOVED) {'
+ print r' HRESULT _reason = _this->GetDeviceRemovedReason();'
+ print r' retrace::failed(call, _reason);'
+ print r' exit(1);'
+ print r' }'
+ print r' return;'
+ print r' }'
+ return
+
+ Retracer.checkResult(self, interface, methodOrFunction)
def forceDriver(self, enum):
# This can only work when pAdapter is NULL. For non-NULL pAdapter we
@@ -194,7 +174,7 @@ createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
print r' }'
else:
print r' d3d10Dumper.bindDevice(_this);'
- if interface.name in ('ID3D11DeviceContext', 'ID3D11DeviceContext1'):
+ if interface.name.startswith('ID3D11DeviceContext'):
if method.name == 'Release':
print r' if (call.ret->toUInt() == 0) {'
print r' d3d11Dumper.unbindDevice(_this);'
@@ -204,22 +184,45 @@ createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
print r' d3d11Dumper.bindDevice(_this);'
print r' }'
- if interface.name == 'IDXGIFactory' and method.name == 'QueryInterface':
- print r' if (riid == IID_IDXGIFactoryDWM) {'
- print r' _this->AddRef();'
- print r' *ppvObj = new d3dretrace::CDXGIFactoryDWM(_this);'
- print r' _result = S_OK;'
- print r' } else {'
+ # intercept private interfaces
+ if method.name == 'QueryInterface':
+ print r' if (!d3dretrace::overrideQueryInterface(_this, riid, ppvObj, &_result)) {'
Retracer.invokeInterfaceMethod(self, interface, method)
print r' }'
return
# create windows as neccessary
if method.name == 'CreateSwapChain':
- print r' createWindow(pDesc);'
+ print r' d3dretrace::createWindowForSwapChain(pDesc);'
+ if method.name == 'CreateSwapChainForHwnd':
+ print r' WindowHandle = d3dretrace::createWindow(pDesc->Width, pDesc->Height);'
+ print r' // DXGI_SCALING_NONE is only supported on Win8 and beyond'
+ print r' if (pDesc->Scaling == DXGI_SCALING_NONE && !IsWindows8OrGreater()) {'
+ print r' pDesc->Scaling = DXGI_SCALING_STRETCH;'
+ print r' }'
+ if method.name == 'CreateSwapChainForComposition':
+ print r' HWND hWnd = d3dretrace::createWindow(pDesc->Width, pDesc->Height);'
+ print r' _result = _this->CreateSwapChainForHwnd(pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);'
+ self.checkResult(interface, method)
+ return
+
+ if method.name == 'SetFullscreenState':
+ print r' if (retrace::forceWindowed) {'
+ print r' Fullscreen = FALSE;'
+ print r' pTarget = NULL;'
+ print r' }'
# notify frame has been completed
- if method.name == 'Present':
+ if interface.name.startswith('IDXGISwapChain') and method.name.startswith('Present'):
+ if interface.name.startswith('IDXGISwapChainDWM'):
+ print r' com_ptr<IDXGISwapChain> pSwapChain;'
+ print r' if (SUCCEEDED(_this->QueryInterface(IID_IDXGISwapChain, (void **) &pSwapChain))) {'
+ print r' dxgiDumper.bindDevice(pSwapChain);'
+ print r' } else {'
+ print r' assert(0);'
+ print r' }'
+ else:
+ print r' dxgiDumper.bindDevice(_this);'
print r' retrace::frameComplete(call);'
if 'pSharedResource' in method.argNames():
@@ -256,36 +259,33 @@ createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
print r' }'
return
- if interface.name.startswith('ID3D10Device') and method.name == 'OpenSharedResource':
+ if interface.name.startswith('ID3D10Device') and method.name.startswith('OpenSharedResource'):
+ print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";'
+ print r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);'
+ self.checkResult(interface, method)
+ return
+ if interface.name.startswith('ID3D11Device') and method.name == 'OpenSharedResource':
+ # Some applications (e.g., video playing in IE11) create shared resources within the same process.
+ # TODO: Generalize to other OpenSharedResource variants
+ print r' retrace::map<HANDLE>::const_iterator it = _shared_handle_map.find(hResource);'
+ print r' if (it == _shared_handle_map.end()) {'
+ print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";'
+ print r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);'
+ self.checkResult(interface, method)
+ print r' } else {'
+ print r' hResource = it->second;'
+ Retracer.invokeInterfaceMethod(self, interface, method)
+ print r' }'
+ return
+ if interface.name.startswith('ID3D11Device') and method.name.startswith('OpenSharedResource'):
print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";'
- print r' D3D10_TEXTURE2D_DESC Desc;'
- print r' memset(&Desc, 0, sizeof Desc);'
- print r' Desc.Width = 8;'
- print r' Desc.Height = 8;'
- print r' Desc.MipLevels = 1;'
- print r' Desc.ArraySize = 1;'
- print r' Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;'
- print r' Desc.SampleDesc.Count = 1;'
- print r' Desc.SampleDesc.Quality = 0;'
- print r' Desc.Usage = D3D10_USAGE_DEFAULT;'
- print r' Desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;'
- print r' Desc.CPUAccessFlags = 0x0;'
- print r' Desc.MiscFlags = 0 /* D3D10_RESOURCE_MISC_SHARED */;'
- print r'''
- static const DWORD Checker[8][8] = {
- { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U },
- {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U },
- { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U },
- {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U },
- { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U },
- {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U },
- { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U },
- {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }
- };
- static const D3D10_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker};
- '''
- print r' _result = _this->CreateTexture2D(&Desc, &InitialData, (ID3D10Texture2D**)ppResource);'
- self.checkResult(method.type)
+ print r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);'
+ if method.name == 'OpenSharedResourceByName':
+ print r' (void)lpName;'
+ print r' (void)dwDesiredAccess;'
+ else:
+ print r' (void)hResource;'
+ self.checkResult(interface, method)
return
if method.name == 'Map':
@@ -296,40 +296,66 @@ createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'):
print r' MapFlags &= ~%s;' % flag
+ if method.name.startswith('UpdateSubresource'):
+ # The D3D10 debug layer is buggy (or at least inconsistent with the
+ # runtime), as it seems to estimate and enforce the data size based on the
+ # SrcDepthPitch, even for non 3D textures, but in some traces
+ # SrcDepthPitch is garbagge for non 3D textures.
+ # XXX: It also seems to expect padding bytes at the end of the last
+ # row, but we never record (or allocate) those...
+ print r' if (retrace::debug && pDstBox && pDstBox->front == 0 && pDstBox->back == 1) {'
+ print r' SrcDepthPitch = 0;'
+ print r' }'
+
+ if method.name == 'SetGammaControl':
+ # This method is only supported while in full-screen mode
+ print r' if (retrace::forceWindowed) {'
+ print r' return;'
+ print r' }'
+
Retracer.invokeInterfaceMethod(self, interface, method)
+ if method.name in ('AcquireSync', 'ReleaseSync'):
+ print r' if (SUCCEEDED(_result) && _result != S_OK) {'
+ print r' retrace::warning(call) << " returned " << _result << "\n";'
+ print r' }'
+
# process events after presents
- if method.name == 'Present':
+ if interface.name.startswith('IDXGISwapChain') and method.name.startswith('Present'):
print r' d3dretrace::processEvents();'
+ if method.name in ('Map', 'Unmap'):
+ if interface.name.startswith('ID3D11DeviceContext'):
+ print ' void * & _pbData = g_Maps[_this][SubresourceKey(pResource, Subresource)];'
+ else:
+ subresourceArg = method.getArgByName('Subresource')
+ if subresourceArg is None:
+ print ' UINT Subresource = 0;'
+ print ' void * & _pbData = g_Maps[0][SubresourceKey(_this, Subresource)];'
+
if method.name == 'Map':
print ' _MAP_DESC _MapDesc;'
print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames())
print ' size_t _MappedSize = _MapDesc.Size;'
print ' if (_MapDesc.Size) {'
+ print ' _pbData = _MapDesc.pData;'
if interface.name.startswith('ID3D11DeviceContext'):
- print ' _maps[pResource] = _MapDesc.pData;'
+ # Prevent false warnings on 1D and 2D resources, since the
+ # pitches are often junk there...
+ print ' _normalizeMap(pResource, pMappedResource);'
+ self.checkPitchMismatch(method)
else:
- print ' _maps[_this] = _MapDesc.pData;'
+ print ' _pbData = _MapDesc.pData;'
+ self.checkPitchMismatch(method)
print ' } else {'
print ' return;'
print ' }'
if method.name == 'Unmap':
- if interface.name.startswith('ID3D11DeviceContext'):
- print ' VOID *_pbData = 0;'
- print ' _pbData = _maps[pResource];'
- print ' if (_pbData) {'
- print ' retrace::delRegionByPointer(_pbData);'
- print ' _maps[pResource] = 0;'
- print ' }'
- else:
- print ' VOID *_pbData = 0;'
- print ' _pbData = _maps[_this];'
- print ' if (_pbData) {'
- print ' retrace::delRegionByPointer(_pbData);'
- print ' _maps[_this] = 0;'
- print ' }'
+ print ' if (_pbData) {'
+ print ' retrace::delRegionByPointer(_pbData);'
+ print ' _pbData = 0;'
+ print ' }'
# Attach shader byte code for lookup
if 'pShaderBytecode' in method.argNames():
@@ -339,6 +365,23 @@ createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
print r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name
print r' }'
+ def extractArg(self, function, arg, arg_type, lvalue, rvalue):
+ # Set object names
+ if function.name == 'SetPrivateData' and arg.name == 'pData':
+ iid = function.args[0].name
+ print r' if (%s != WKPDID_D3DDebugObjectName) {' % iid
+ print r' return;'
+ print r' }'
+ # Interpret argument as string
+ Retracer.extractArg(self, function, arg, LPCSTR, lvalue, rvalue)
+ print r' assert(pData);'
+ print r' assert(DataSize >= strlen((const char *)pData));'
+ print r' // Some applications include the trailing zero terminator in the data'
+ print r' DataSize = strlen((const char *)pData);'
+ return
+
+ Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
+
def main():
print r'#define INITGUID'
@@ -348,40 +391,26 @@ def main():
print r'#include <iostream>'
print
print r'#include "d3dretrace.hpp"'
+ print r'#include "os_version.hpp"'
+ print
+ print r'#include "d3dretrace_dxgi.hpp"'
+ print r'#include "d3d10imports.hpp"'
+ print r'#include "d3d10size.hpp"'
+ print r'#include "d3d10state.hpp"'
+ print r'#include "d3d11imports.hpp"'
+ print r'#include "d3d11size.hpp"'
+ print r'#include "d3dstate.hpp"'
+ print
+ print '''static d3dretrace::D3DDumper<IDXGISwapChain> dxgiDumper;'''
+ print '''static d3dretrace::D3DDumper<ID3D10Device> d3d10Dumper;'''
+ print '''static d3dretrace::D3DDumper<ID3D11DeviceContext> d3d11Dumper;'''
print
-
- moduleNames = sys.argv[1:]
api = API()
-
- if moduleNames:
- print r'#include "d3dretrace_dxgi.hpp"'
- api.addModule(dxgi)
-
- if 'd3d10' in moduleNames:
- if 'd3d10_1' in moduleNames:
- print r'#include "d3d10_1imports.hpp"'
- api.addModule(d3d10_1)
- else:
- print r'#include "d3d10imports.hpp"'
- print r'#include "d3d10size.hpp"'
- api.addModule(d3d10)
- print
- print '''static d3dretrace::D3DDumper<ID3D10Device> d3d10Dumper;'''
- print
-
- if 'd3d11' in moduleNames:
- print r'#include "d3d11imports.hpp"'
- if 'd3d11_1' in moduleNames:
- print '#include <d3d11_1.h>'
- import specs.d3d11_1
- print r'#include "d3d11size.hpp"'
- print r'#include "d3dstate.hpp"'
- api.addModule(d3d11)
-
- print
- print '''static d3dretrace::D3DDumper<ID3D11DeviceContext> d3d11Dumper;'''
- print
+ api.addModule(dxgi)
+ api.addModule(d3d10)
+ api.addModule(d3d10_1)
+ api.addModule(d3d11)
retracer = D3DRetracer()
retracer.retraceApi(api)
diff --git a/retrace/dxgistate.cpp b/retrace/dxgistate.cpp
index 3cf4c746..d69f2421 100644
--- a/retrace/dxgistate.cpp
+++ b/retrace/dxgistate.cpp
@@ -29,8 +29,13 @@
#include <iostream>
#include "image.hpp"
+#include "state_writer.hpp"
+#include "com_ptr.hpp"
#include "dxgistate.hpp"
+#include "d3d10state.hpp"
+#include "d3d11state.hpp"
+#include "d3d11imports.hpp"
#ifdef __MINGW32__
#define nullptr NULL
@@ -252,6 +257,30 @@ ConvertImage(DXGI_FORMAT SrcFormat,
unsigned numChannels;
image::ChannelType channelType;
+ // DirectXTex doesn't support the typeless depth-stencil variants
+ switch (SrcFormat) {
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ SrcFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ break;
+
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ // FIXME: This will dump the depth-channel. It would be more
+ // adequate to dump the stencil channel, but we can't achieve
+ // that with DirectXTex.
+ SrcFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ break;
+
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ SrcFormat = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
+ break;
+
+ default:
+ break;
+ }
+
DXGI_FORMAT DstFormat = ChooseConversionFormat(SrcFormat, numChannels, channelType);
if (DstFormat == DXGI_FORMAT_UNKNOWN) {
return NULL;
@@ -278,4 +307,396 @@ ConvertImage(DXGI_FORMAT SrcFormat,
return image;
}
+
+image::Image *
+getRenderTargetImage(IDXGISwapChain *pSwapChain)
+{
+ HRESULT hr;
+
+ assert(pSwapChain);
+ if (!pSwapChain) {
+ return NULL;
+ }
+
+ DXGI_SWAP_CHAIN_DESC Desc;
+ hr = pSwapChain->GetDesc(&Desc);
+ assert(SUCCEEDED(hr));
+
+ DXGI_FORMAT Format = Desc.BufferDesc.Format;
+
+ /*
+ * There is a IDXGISurface::Map method, but swapchains are not normally mappable,
+ * and there is no way to copy into a staging resource, which effectively means there
+ * is no way to read a IDXGISwapChain using DXGI interfaces alone.
+ *
+ * We must figure out
+ * the appropriate D3D10/D3D11 interfaces, and use them instead.
+ */
+
+ com_ptr<ID3D11Device1> pD3D11Device1;
+ hr = pSwapChain->GetDevice(IID_ID3D11Device1, (void **)&pD3D11Device1);
+ if (SUCCEEDED(hr)) {
+ /*
+ * With D3D11.1 runtime (that comes with Windows 8 and Windows 7
+ * Platform Update), we can no longer guess the device interface based
+ * on the success of GetDevice, since it will always succeed regardless
+ * the requested device interface, but the returned device maight be
+ * inactive/lockedout, and attempt to use it will cause the call to be
+ * ignored, though a debug runtime will issue a
+ * DEVICE_LOCKEDOUT_INTERFACE warning.
+ *
+ * See also:
+ * - https://msdn.microsoft.com/en-us/library/windows/desktop/hh404583.aspx
+ * - https://social.msdn.microsoft.com/Forums/en-US/c482bcec-b094-4df0-9253-9c496b115beb/d3d11-runtime-assertion-when-using-graphics-debugger-and-other-applications-may-be-intercepting?forum=wingameswithdirectx
+ */
+ com_ptr<ID3D11Resource> pD3D11Resource;
+ hr = pSwapChain->GetBuffer(0, IID_ID3D11Resource, (void **)&pD3D11Resource);
+ assert(SUCCEEDED(hr));
+ if (FAILED(hr)) {
+ return NULL;
+ }
+
+ com_ptr<ID3D11DeviceContext1> pD3D11DeviceContext;
+ pD3D11Device1->GetImmediateContext1(&pD3D11DeviceContext);
+
+ UINT Flags = 0;
+ UINT DeviceFlags = pD3D11Device1->GetCreationFlags();
+ if (DeviceFlags & D3D11_CREATE_DEVICE_SINGLETHREADED) {
+ Flags |= D3D11_1_CREATE_DEVICE_CONTEXT_STATE_SINGLETHREADED;
+ }
+ D3D_FEATURE_LEVEL FeatureLevel = pD3D11Device1->GetFeatureLevel();
+
+ com_ptr<ID3DDeviceContextState> pState;
+ hr = pD3D11Device1->CreateDeviceContextState(Flags, &FeatureLevel, 1, D3D11_SDK_VERSION, IID_ID3D11Device1, NULL, &pState);
+ if (SUCCEEDED(hr)) {
+ com_ptr<ID3DDeviceContextState> pPreviousState;
+ pD3D11DeviceContext->SwapDeviceContextState(pState, &pPreviousState);
+
+ image::Image *image;
+ image = getSubResourceImage(pD3D11DeviceContext, pD3D11Resource, Format, 0, 0);
+
+ pD3D11DeviceContext->SwapDeviceContextState(pPreviousState, NULL);
+
+ return image;
+ }
+ }
+
+ com_ptr<ID3D11Device> pD3D11Device;
+ hr = pSwapChain->GetDevice(IID_ID3D11Device, (void **)&pD3D11Device);
+ if (SUCCEEDED(hr)) {
+ com_ptr<ID3D11Resource> pD3D11Resource;
+ hr = pSwapChain->GetBuffer(0, IID_ID3D11Resource, (void **)&pD3D11Resource);
+ assert(SUCCEEDED(hr));
+ if (FAILED(hr)) {
+ return NULL;
+ }
+
+ com_ptr<ID3D11DeviceContext> pD3D11DeviceContext;
+ pD3D11Device->GetImmediateContext(&pD3D11DeviceContext);
+
+ return getSubResourceImage(pD3D11DeviceContext, pD3D11Resource, Format, 0, 0);
+ }
+
+ com_ptr<ID3D10Device> pD3D10Device;
+ hr = pSwapChain->GetDevice(IID_ID3D10Device, (void **)&pD3D10Device);
+ if (SUCCEEDED(hr)) {
+ com_ptr<ID3D10Resource> pD3D10Resource;
+ hr = pSwapChain->GetBuffer(0, IID_ID3D10Resource, (void **)&pD3D10Resource);
+ assert(SUCCEEDED(hr));
+ if (FAILED(hr)) {
+ return NULL;
+ }
+
+ return getSubResourceImage(pD3D10Device, pD3D10Resource, Format, 0, 0);
+ }
+
+ return NULL;
+}
+
+
+void
+dumpDevice(StateWriter &writer, IDXGISwapChain *pSwapChain)
+{
+ HRESULT hr;
+
+ if (pSwapChain) {
+ com_ptr<ID3D10Device> pD3D10Device;
+ hr = pSwapChain->GetDevice(IID_ID3D10Device, (void **)&pD3D10Device);
+ if (SUCCEEDED(hr)) {
+ dumpDevice(writer, pD3D10Device);
+ return;
+ }
+
+ com_ptr<ID3D11Device> pD3D11Device;
+ hr = pSwapChain->GetDevice(IID_ID3D11Device, (void **)&pD3D11Device);
+ if (SUCCEEDED(hr)) {
+ com_ptr<ID3D11DeviceContext> pD3D11DeviceContext;
+ pD3D11Device->GetImmediateContext(&pD3D11DeviceContext);
+ dumpDevice(writer, pD3D11DeviceContext);
+ return;
+ }
+ }
+
+ // Fallback -- this should really never happen.
+ assert(0);
+ writer.beginMember("framebuffer");
+ writer.beginObject();
+ if (pSwapChain) {
+ image::Image *image;
+ image = getRenderTargetImage(pSwapChain);
+ if (image) {
+ writer.beginMember("SWAP_CHAIN");
+ writer.writeImage(image);
+ writer.endMember();
+ delete image;
+ }
+ }
+ writer.endObject();
+ writer.endMember(); // framebuffer
+}
+
+
+std::string
+getDXGIFormatName(DXGI_FORMAT format)
+{
+ switch (format) {
+ case DXGI_FORMAT_UNKNOWN:
+ return "DXGI_FORMAT_UNKNOWN";
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ return "DXGI_FORMAT_R32G32B32A32_TYPELESS";
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ return "DXGI_FORMAT_R32G32B32A32_FLOAT";
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ return "DXGI_FORMAT_R32G32B32A32_UINT";
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return "DXGI_FORMAT_R32G32B32A32_SINT";
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ return "DXGI_FORMAT_R32G32B32_TYPELESS";
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ return "DXGI_FORMAT_R32G32B32_FLOAT";
+ case DXGI_FORMAT_R32G32B32_UINT:
+ return "DXGI_FORMAT_R32G32B32_UINT";
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return "DXGI_FORMAT_R32G32B32_SINT";
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ return "DXGI_FORMAT_R16G16B16A16_TYPELESS";
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return "DXGI_FORMAT_R16G16B16A16_FLOAT";
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ return "DXGI_FORMAT_R16G16B16A16_UNORM";
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ return "DXGI_FORMAT_R16G16B16A16_UINT";
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ return "DXGI_FORMAT_R16G16B16A16_SNORM";
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ return "DXGI_FORMAT_R16G16B16A16_SINT";
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ return "DXGI_FORMAT_R32G32_TYPELESS";
+ case DXGI_FORMAT_R32G32_FLOAT:
+ return "DXGI_FORMAT_R32G32_FLOAT";
+ case DXGI_FORMAT_R32G32_UINT:
+ return "DXGI_FORMAT_R32G32_UINT";
+ case DXGI_FORMAT_R32G32_SINT:
+ return "DXGI_FORMAT_R32G32_SINT";
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ return "DXGI_FORMAT_R32G8X24_TYPELESS";
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ return "DXGI_FORMAT_D32_FLOAT_S8X24_UINT";
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ return "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS";
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT";
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ return "DXGI_FORMAT_R10G10B10A2_TYPELESS";
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ return "DXGI_FORMAT_R10G10B10A2_UNORM";
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ return "DXGI_FORMAT_R10G10B10A2_UINT";
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ return "DXGI_FORMAT_R11G11B10_FLOAT";
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ return "DXGI_FORMAT_R8G8B8A8_TYPELESS";
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return "DXGI_FORMAT_R8G8B8A8_UNORM";
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ return "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB";
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ return "DXGI_FORMAT_R8G8B8A8_UINT";
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ return "DXGI_FORMAT_R8G8B8A8_SNORM";
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ return "DXGI_FORMAT_R8G8B8A8_SINT";
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ return "DXGI_FORMAT_R16G16_TYPELESS";
+ case DXGI_FORMAT_R16G16_FLOAT:
+ return "DXGI_FORMAT_R16G16_FLOAT";
+ case DXGI_FORMAT_R16G16_UNORM:
+ return "DXGI_FORMAT_R16G16_UNORM";
+ case DXGI_FORMAT_R16G16_UINT:
+ return "DXGI_FORMAT_R16G16_UINT";
+ case DXGI_FORMAT_R16G16_SNORM:
+ return "DXGI_FORMAT_R16G16_SNORM";
+ case DXGI_FORMAT_R16G16_SINT:
+ return "DXGI_FORMAT_R16G16_SINT";
+ case DXGI_FORMAT_R32_TYPELESS:
+ return "DXGI_FORMAT_R32_TYPELESS";
+ case DXGI_FORMAT_D32_FLOAT:
+ return "DXGI_FORMAT_D32_FLOAT";
+ case DXGI_FORMAT_R32_FLOAT:
+ return "DXGI_FORMAT_R32_FLOAT";
+ case DXGI_FORMAT_R32_UINT:
+ return "DXGI_FORMAT_R32_UINT";
+ case DXGI_FORMAT_R32_SINT:
+ return "DXGI_FORMAT_R32_SINT";
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ return "DXGI_FORMAT_R24G8_TYPELESS";
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ return "DXGI_FORMAT_D24_UNORM_S8_UINT";
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ return "DXGI_FORMAT_R24_UNORM_X8_TYPELESS";
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ return "DXGI_FORMAT_X24_TYPELESS_G8_UINT";
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ return "DXGI_FORMAT_R8G8_TYPELESS";
+ case DXGI_FORMAT_R8G8_UNORM:
+ return "DXGI_FORMAT_R8G8_UNORM";
+ case DXGI_FORMAT_R8G8_UINT:
+ return "DXGI_FORMAT_R8G8_UINT";
+ case DXGI_FORMAT_R8G8_SNORM:
+ return "DXGI_FORMAT_R8G8_SNORM";
+ case DXGI_FORMAT_R8G8_SINT:
+ return "DXGI_FORMAT_R8G8_SINT";
+ case DXGI_FORMAT_R16_TYPELESS:
+ return "DXGI_FORMAT_R16_TYPELESS";
+ case DXGI_FORMAT_R16_FLOAT:
+ return "DXGI_FORMAT_R16_FLOAT";
+ case DXGI_FORMAT_D16_UNORM:
+ return "DXGI_FORMAT_D16_UNORM";
+ case DXGI_FORMAT_R16_UNORM:
+ return "DXGI_FORMAT_R16_UNORM";
+ case DXGI_FORMAT_R16_UINT:
+ return "DXGI_FORMAT_R16_UINT";
+ case DXGI_FORMAT_R16_SNORM:
+ return "DXGI_FORMAT_R16_SNORM";
+ case DXGI_FORMAT_R16_SINT:
+ return "DXGI_FORMAT_R16_SINT";
+ case DXGI_FORMAT_R8_TYPELESS:
+ return "DXGI_FORMAT_R8_TYPELESS";
+ case DXGI_FORMAT_R8_UNORM:
+ return "DXGI_FORMAT_R8_UNORM";
+ case DXGI_FORMAT_R8_UINT:
+ return "DXGI_FORMAT_R8_UINT";
+ case DXGI_FORMAT_R8_SNORM:
+ return "DXGI_FORMAT_R8_SNORM";
+ case DXGI_FORMAT_R8_SINT:
+ return "DXGI_FORMAT_R8_SINT";
+ case DXGI_FORMAT_A8_UNORM:
+ return "DXGI_FORMAT_A8_UNORM";
+ case DXGI_FORMAT_R1_UNORM:
+ return "DXGI_FORMAT_R1_UNORM";
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ return "DXGI_FORMAT_R9G9B9E5_SHAREDEXP";
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ return "DXGI_FORMAT_R8G8_B8G8_UNORM";
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ return "DXGI_FORMAT_G8R8_G8B8_UNORM";
+ case DXGI_FORMAT_BC1_TYPELESS:
+ return "DXGI_FORMAT_BC1_TYPELESS";
+ case DXGI_FORMAT_BC1_UNORM:
+ return "DXGI_FORMAT_BC1_UNORM";
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ return "DXGI_FORMAT_BC1_UNORM_SRGB";
+ case DXGI_FORMAT_BC2_TYPELESS:
+ return "DXGI_FORMAT_BC2_TYPELESS";
+ case DXGI_FORMAT_BC2_UNORM:
+ return "DXGI_FORMAT_BC2_UNORM";
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ return "DXGI_FORMAT_BC2_UNORM_SRGB";
+ case DXGI_FORMAT_BC3_TYPELESS:
+ return "DXGI_FORMAT_BC3_TYPELESS";
+ case DXGI_FORMAT_BC3_UNORM:
+ return "DXGI_FORMAT_BC3_UNORM";
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ return "DXGI_FORMAT_BC3_UNORM_SRGB";
+ case DXGI_FORMAT_BC4_TYPELESS:
+ return "DXGI_FORMAT_BC4_TYPELESS";
+ case DXGI_FORMAT_BC4_UNORM:
+ return "DXGI_FORMAT_BC4_UNORM";
+ case DXGI_FORMAT_BC4_SNORM:
+ return "DXGI_FORMAT_BC4_SNORM";
+ case DXGI_FORMAT_BC5_TYPELESS:
+ return "DXGI_FORMAT_BC5_TYPELESS";
+ case DXGI_FORMAT_BC5_UNORM:
+ return "DXGI_FORMAT_BC5_UNORM";
+ case DXGI_FORMAT_BC5_SNORM:
+ return "DXGI_FORMAT_BC5_SNORM";
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ return "DXGI_FORMAT_B5G6R5_UNORM";
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return "DXGI_FORMAT_B5G5R5A1_UNORM";
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return "DXGI_FORMAT_B8G8R8A8_UNORM";
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ return "DXGI_FORMAT_B8G8R8X8_UNORM";
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ return "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM";
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ return "DXGI_FORMAT_B8G8R8A8_TYPELESS";
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ return "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB";
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ return "DXGI_FORMAT_B8G8R8X8_TYPELESS";
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ return "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB";
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ return "DXGI_FORMAT_BC6H_TYPELESS";
+ case DXGI_FORMAT_BC6H_UF16:
+ return "DXGI_FORMAT_BC6H_UF16";
+ case DXGI_FORMAT_BC6H_SF16:
+ return "DXGI_FORMAT_BC6H_SF16";
+ case DXGI_FORMAT_BC7_TYPELESS:
+ return "DXGI_FORMAT_BC7_TYPELESS";
+ case DXGI_FORMAT_BC7_UNORM:
+ return "DXGI_FORMAT_BC7_UNORM";
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return "DXGI_FORMAT_BC7_UNORM_SRGB";
+ case DXGI_FORMAT_AYUV:
+ return "DXGI_FORMAT_AYUV";
+ case DXGI_FORMAT_Y410:
+ return "DXGI_FORMAT_Y410";
+ case DXGI_FORMAT_Y416:
+ return "DXGI_FORMAT_Y416";
+ case DXGI_FORMAT_NV12:
+ return "DXGI_FORMAT_NV12";
+ case DXGI_FORMAT_P010:
+ return "DXGI_FORMAT_P010";
+ case DXGI_FORMAT_P016:
+ return "DXGI_FORMAT_P016";
+ case DXGI_FORMAT_420_OPAQUE:
+ return "DXGI_FORMAT_420_OPAQUE";
+ case DXGI_FORMAT_YUY2:
+ return "DXGI_FORMAT_YUY2";
+ case DXGI_FORMAT_Y210:
+ return "DXGI_FORMAT_Y210";
+ case DXGI_FORMAT_Y216:
+ return "DXGI_FORMAT_Y216";
+ case DXGI_FORMAT_NV11:
+ return "DXGI_FORMAT_NV11";
+ case DXGI_FORMAT_AI44:
+ return "DXGI_FORMAT_AI44";
+ case DXGI_FORMAT_IA44:
+ return "DXGI_FORMAT_IA44";
+ case DXGI_FORMAT_P8:
+ return "DXGI_FORMAT_P8";
+ case DXGI_FORMAT_A8P8:
+ return "DXGI_FORMAT_A8P8";
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return "DXGI_FORMAT_B4G4R4A4_UNORM";
+ case DXGI_FORMAT_FORCE_UINT:
+ return "DXGI_FORMAT_FORCE_UINT";
+ default:
+ return "DXGI_ERROR_FORMAT";
+ }
+}
+
} /* namespace d3dstate */
diff --git a/retrace/dxgistate.hpp b/retrace/dxgistate.hpp
index eb3a6fec..78cf4334 100644
--- a/retrace/dxgistate.hpp
+++ b/retrace/dxgistate.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _DXGISTATE_HPP_
-#define _DXGISTATE_HPP_
+#pragma once
#include <windows.h>
@@ -63,7 +62,13 @@ ConvertImage(DXGI_FORMAT SrcFormat,
UINT Width, UINT Height);
+image::Image *
+getRenderTargetImage(IDXGISwapChain *pSwapChain);
+
+std::string
+getDXGIFormatName(DXGI_FORMAT format);
+
+
} /* namespace d3dstate */
-#endif // _DXGISTATE_HPP_
diff --git a/retrace/dxgistate_so.hpp b/retrace/dxgistate_so.hpp
new file mode 100644
index 00000000..2472e7f2
--- /dev/null
+++ b/retrace/dxgistate_so.hpp
@@ -0,0 +1,116 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+
+#include "d3d10imports.hpp"
+#include "d3d11imports.hpp"
+#include "state_writer.hpp"
+#include "com_ptr.hpp"
+
+
+// Template to extract the type of ID3D*::GetDesc methods
+template< typename T >
+struct ExtractDescType
+{
+};
+
+template <typename InterfaceType, typename DescType>
+struct ExtractDescType< void (__stdcall InterfaceType::*)(DescType *) >
+{
+ typedef DescType type;
+};
+
+
+template< typename Interface >
+static inline void
+dumpStateObjectDesc(StateWriter &writer, Interface *pObj)
+{
+ if (pObj) {
+ typename ExtractDescType< decltype( &Interface::GetDesc ) >::type Desc;
+ pObj->GetDesc(&Desc);
+ dumpStateObject(writer, Desc);
+ } else {
+ writer.writeNull();
+ }
+}
+
+template< typename Interface >
+static inline void
+dumpStateObjectDesc(StateWriter &writer, com_ptr<Interface> & pObj)
+{
+ dumpStateObjectDesc(writer, static_cast<Interface *>(pObj));
+}
+
+
+void dumpStateObject(StateWriter &, const RECT &); // D3D10_RECT, D3D11_RECT
+
+void dumpStateObject(StateWriter &, const DXGI_FORMAT &);
+
+void dumpStateObject(StateWriter &, const D3D10_BLEND_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_BLEND_DESC1 &);
+void dumpStateObject(StateWriter &, const D3D10_BUFFER_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_COUNTER_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_DEPTH_STENCIL_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_DEPTH_STENCILOP_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_DEPTH_STENCIL_VIEW_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_INPUT_ELEMENT_DESC &);
+// FIXME: aliases with D3D_PRIMITIVE_TOPOLOGY clashing with D3D11_PRIMITIVE_TOPOLOGY
+//void dumpStateObject(StateWriter &, const D3D10_PRIMITIVE_TOPOLOGY &);
+void dumpStateObject(StateWriter &, const D3D10_QUERY_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_RASTERIZER_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_RENDER_TARGET_VIEW_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_SAMPLER_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_SHADER_RESOURCE_VIEW_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_SHADER_RESOURCE_VIEW_DESC1 &);
+void dumpStateObject(StateWriter &, const D3D10_TEXTURE1D_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_TEXTURE2D_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_TEXTURE3D_DESC &);
+void dumpStateObject(StateWriter &, const D3D10_VIEWPORT &);
+
+void dumpStateObject(StateWriter &, const D3D11_BLEND_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_BLEND_DESC1 &);
+void dumpStateObject(StateWriter &, const D3D11_BUFFER_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_CLASS_INSTANCE_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_COUNTER_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_DEPTH_STENCIL_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_DEPTH_STENCILOP_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_DEPTH_STENCIL_VIEW_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_INPUT_ELEMENT_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_PACKED_MIP_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_PRIMITIVE_TOPOLOGY &);
+void dumpStateObject(StateWriter &, const D3D11_QUERY_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_RASTERIZER_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_RASTERIZER_DESC1 &);
+void dumpStateObject(StateWriter &, const D3D11_RENDER_TARGET_BLEND_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_RENDER_TARGET_VIEW_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_SAMPLER_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_SHADER_RESOURCE_VIEW_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_TEXTURE1D_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_TEXTURE2D_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_TEXTURE3D_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_UNORDERED_ACCESS_VIEW_DESC &);
+void dumpStateObject(StateWriter &, const D3D11_VIEWPORT &);
diff --git a/retrace/dxgistate_so.py b/retrace/dxgistate_so.py
new file mode 100644
index 00000000..86f6db57
--- /dev/null
+++ b/retrace/dxgistate_so.py
@@ -0,0 +1,275 @@
+##########################################################################
+#
+# Copyright 2008-2015 VMware, Inc.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+##########################################################################/
+
+"""Common code generation."""
+
+
+# Adjust path
+import os.path
+import sys
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
+
+from specs import stdapi
+from specs import winapi
+from specs import dxgi
+from specs import d3d10
+from specs import d3d11
+from specs import d3d11
+
+
+class ValueDumper(stdapi.Visitor, stdapi.ExpanderMixin):
+ '''Visitor which generates code to dump any type.
+ '''
+
+ # TODO: Don't dump all types inline -- do like trace.py's ComplexValueDumper
+
+
+ def visitLiteral(self, literal, instance):
+ if literal.kind in ('SInt', 'UInt'):
+ print ' writer.writeInt(%s);' % (instance)
+ elif literal.kind in ('Float',):
+ print ' writer.writeFloat(%s);' % (instance)
+ else:
+ raise NotImplementedError
+
+ def visitString(self, string, instance):
+ if not string.wide:
+ cast = 'const char *'
+ suffix = 'String'
+ else:
+ assert False
+ cast = 'const wchar_t *'
+ suffix = 'WString'
+ if cast != string.expr:
+ # reinterpret_cast is necessary for GLubyte * <=> char *
+ instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
+ assert string.length is None
+ print ' writer.write%s(%s);' % (suffix, instance)
+
+ def visitConst(self, const, instance):
+ self.visit(const.type, instance)
+
+ def visitStruct(self, struct, instance):
+ print ' writer.beginObject();'
+ for member in struct.members:
+ memberType, memberName = member
+ if memberName is not None:
+ print ' writer.beginMember("%s");' % memberName
+ self.visitMember(member, instance)
+ if memberName is not None:
+ print ' writer.endMember(); // %s' % memberName
+ print ' writer.endObject();'
+
+ def visitArray(self, array, instance):
+ length = '_c' + array.type.tag
+ index = '_i' + array.type.tag
+ array_length = self.expand(array.length)
+ print ' if (%s) {' % instance
+ print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
+ print ' writer.beginArray();'
+ print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
+ self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
+ print ' }'
+ print ' writer.endArray();'
+ print ' } else {'
+ print ' writer.writeNull();'
+ print ' }'
+
+ def visitAttribArray(self, array, instance):
+ raise NotImplementedError
+
+ def visitBlob(self, blob, instance):
+ raise NotImplementedError
+
+ def visitEnum(self, enum, instance):
+ print ' switch (%s) {' % instance
+ for value in enum.values:
+ print ' case %s:' % value
+ print ' writer.writeString("%s");' % value
+ print ' break;'
+ print ' default:'
+ print ' writer.writeInt(%s);' % instance
+ print ' break;'
+ print ' }'
+
+ def visitBitmask(self, bitmask, instance):
+ # TODO
+ self.visit(bitmask.type, instance)
+
+ def visitPointer(self, pointer, instance):
+ print ' if (%s) {' % instance
+ print ' writer.beginArray();'
+ self.visit(pointer.type, "*" + instance)
+ print ' writer.endArray();'
+ print ' } else {'
+ print ' writer.writeNull();'
+ print ' }'
+
+ def visitIntPointer(self, pointer, instance):
+ print ' writer.writeInt((uintptr_t)%s);' % instance
+
+ def visitObjPointer(self, pointer, instance):
+ print ' writer.writeInt((uintptr_t)%s);' % instance
+
+ def visitLinearPointer(self, pointer, instance):
+ print ' writer.writeInt((uintptr_t)%s);' % instance
+
+ def visitReference(self, reference, instance):
+ self.visit(reference.type, instance)
+
+ def visitHandle(self, handle, instance):
+ self.visit(handle.type, instance)
+
+ def visitAlias(self, alias, instance):
+ self.visit(alias.type, instance)
+
+ def visitOpaque(self, opaque, instance):
+ print ' writer.writeInt((uintptr_t)%s);' % instance
+
+ def visitInterface(self, interface, instance):
+ assert False
+
+ def visitPolymorphic(self, polymorphic, instance):
+ switchExpr = self.expand(polymorphic.switchExpr)
+ print ' switch (static_cast<int>(%s)) {' % switchExpr
+ for cases, type in polymorphic.iterSwitch():
+ for case in cases:
+ print ' %s:' % case
+ caseInstance = instance
+ if type.expr is not None:
+ caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
+ self.visit(type, caseInstance)
+ print ' break;'
+ print ' }'
+
+
+class Dumper:
+ '''Base class to orchestrate the code generation of state object dumpers.'''
+
+ def __init__(self, api, types):
+ self.api = api
+ self.types = types
+
+ def dumperFactory(self):
+ '''Create a dumper.
+
+ Can be overriden by derived classes to inject their own dumper visitor.
+ '''
+
+ return ValueDumper()
+
+ def dump(self):
+
+ self.header()
+
+ # Includes
+ for module in api.modules:
+ for header in module.headers:
+ print header
+ print
+
+ # Generate the dumper functions
+ types = api.getAllTypes()
+ for type in self.types:
+ self.dumpType(type)
+
+ def dumpType(self, type):
+ print r'void'
+ print r'dumpStateObject(StateWriter &writer, const %s & so)' % type
+ print r'{'
+ visitor = self.dumperFactory()
+ visitor.visit(type, 'so')
+ print r'}'
+ print
+
+ def header(self):
+ pass
+
+ def footer(self):
+ pass
+
+
+if __name__ == '__main__':
+ print r'#include "dxgistate_so.hpp"'
+ print
+ print r'#include "state_writer.hpp"'
+ print
+
+ api = stdapi.API()
+ api.addModule(dxgi.dxgi)
+ api.addModule(d3d10.d3d10)
+ api.addModule(d3d10.d3d10_1)
+ api.addModule(d3d11.d3d11)
+
+ types = [
+ winapi.RECT,
+ dxgi.DXGI_FORMAT,
+ d3d10.D3D10_BLEND_DESC,
+ d3d10.D3D10_BUFFER_DESC,
+ d3d10.D3D10_COUNTER_DESC,
+ d3d10.D3D10_DEPTH_STENCIL_DESC,
+ d3d10.D3D10_DEPTH_STENCILOP_DESC,
+ d3d10.D3D10_DEPTH_STENCIL_VIEW_DESC,
+ d3d10.D3D10_INPUT_ELEMENT_DESC,
+ # FIXME: aliases to D3D_PRIMITIVE_TOPOLOGY clashing with D3D11_PRIMITIVE_TOPOLOGY
+ #d3d10.D3D10_PRIMITIVE_TOPOLOGY,
+ d3d10.D3D10_QUERY_DESC,
+ d3d10.D3D10_RASTERIZER_DESC,
+ d3d10.D3D10_RENDER_TARGET_VIEW_DESC,
+ d3d10.D3D10_SAMPLER_DESC,
+ d3d10.D3D10_SHADER_RESOURCE_VIEW_DESC,
+ d3d10.D3D10_TEXTURE1D_DESC,
+ d3d10.D3D10_TEXTURE2D_DESC,
+ d3d10.D3D10_TEXTURE3D_DESC,
+ d3d10.D3D10_VIEWPORT,
+ d3d10.D3D10_BLEND_DESC1,
+ d3d10.D3D10_SHADER_RESOURCE_VIEW_DESC1,
+ d3d11.D3D11_BLEND_DESC,
+ d3d11.D3D11_BLEND_DESC1,
+ d3d11.D3D11_BUFFER_DESC,
+ d3d11.D3D11_CLASS_INSTANCE_DESC,
+ d3d11.D3D11_COUNTER_DESC,
+ d3d11.D3D11_DEPTH_STENCIL_DESC,
+ d3d11.D3D11_DEPTH_STENCILOP_DESC,
+ d3d11.D3D11_DEPTH_STENCIL_VIEW_DESC,
+ d3d11.D3D11_INPUT_ELEMENT_DESC,
+ d3d11.D3D11_PACKED_MIP_DESC,
+ d3d11.D3D11_PRIMITIVE_TOPOLOGY,
+ d3d11.D3D11_QUERY_DESC,
+ d3d11.D3D11_RASTERIZER_DESC,
+ d3d11.D3D11_RASTERIZER_DESC1,
+ d3d11.D3D11_RENDER_TARGET_BLEND_DESC,
+ d3d11.D3D11_RENDER_TARGET_VIEW_DESC,
+ d3d11.D3D11_SAMPLER_DESC,
+ d3d11.D3D11_SHADER_RESOURCE_VIEW_DESC,
+ d3d11.D3D11_TEXTURE1D_DESC,
+ d3d11.D3D11_TEXTURE2D_DESC,
+ d3d11.D3D11_TEXTURE3D_DESC,
+ d3d11.D3D11_UNORDERED_ACCESS_VIEW_DESC,
+ d3d11.D3D11_VIEWPORT,
+ ]
+
+ dumper = Dumper(api, types)
+ dumper.dump()
diff --git a/retrace/glretrace.hpp b/retrace/glretrace.hpp
index 6c5a430a..6da4c480 100644
--- a/retrace/glretrace.hpp
+++ b/retrace/glretrace.hpp
@@ -23,11 +23,14 @@
*
**************************************************************************/
-#ifndef _GLRETRACE_HPP_
-#define _GLRETRACE_HPP_
+#pragma once
#include "glws.hpp"
#include "retrace.hpp"
+#include "metric_backend.hpp"
+#include "metric_writer.hpp"
+
+#include "os_thread.hpp"
namespace glretrace {
@@ -49,43 +52,70 @@ struct Context {
glws::Drawable *drawable;
GLuint activeProgram;
+ bool insideBeginEnd = false;
+ bool insideList = false;
+
bool used;
-
- // Context must be current
+
+ bool KHR_debug;
+ GLsizei maxDebugMessageLength = 0;
+
+ inline glprofile::Profile
+ profile(void) const {
+ return wsContext->profile;
+ }
+
+ inline glprofile::Profile
+ actualProfile(void) const {
+ return wsContext->actualProfile;
+ }
+
inline bool
hasExtension(const char *extension) const {
return wsContext->hasExtension(extension);
}
};
-extern glws::Profile defaultProfile;
+extern bool metricBackendsSetup;
+extern bool profilingContextAcquired;
+extern bool profilingBoundaries[QUERY_BOUNDARY_LIST_END];
+extern unsigned profilingBoundariesIndex[QUERY_BOUNDARY_LIST_END];
+extern std::vector<MetricBackend*> metricBackends;
+extern MetricBackend* curMetricBackend;
+extern MetricWriter profiler;
+
+extern glprofile::Profile defaultProfile;
-extern bool insideList;
-extern bool insideGlBeginEnd;
extern bool supportsARBShaderObjects;
-Context *
-getCurrentContext(void);
+extern OS_THREAD_SPECIFIC_PTR(Context)
+currentContextPtr;
+
+
+static inline Context *
+getCurrentContext(void) {
+ return currentContextPtr;
+}
int
-parseAttrib(const trace::Value *attribs, int param, int default_);
+parseAttrib(const trace::Value *attribs, int param, int default_ = 0, int terminator = 0);
-glws::Profile
+glprofile::Profile
parseContextAttribList(const trace::Value *attribs);
glws::Drawable *
-createDrawable(glws::Profile profile);
+createDrawable(glprofile::Profile profile);
glws::Drawable *
createDrawable(void);
glws::Drawable *
-createPbuffer(int width, int height);
+createPbuffer(int width, int height, const glws::pbuffer_info *info);
Context *
-createContext(Context *shareContext, glws::Profile profile);
+createContext(Context *shareContext, glprofile::Profile profile);
Context *
createContext(Context *shareContext = 0);
@@ -97,6 +127,10 @@ makeCurrent(trace::Call &call, glws::Drawable *drawable, Context *context);
void
checkGlError(trace::Call &call);
+void
+insertCallMarker(trace::Call &call, Context *currentContext);
+
+
extern const retrace::Entry gl_callbacks[];
extern const retrace::Entry cgl_callbacks[];
extern const retrace::Entry glx_callbacks[];
@@ -105,6 +139,8 @@ extern const retrace::Entry egl_callbacks[];
void frame_complete(trace::Call &call);
void initContext();
+void beforeContextSwitch();
+void afterContextSwitch();
void updateDrawable(int width, int height);
@@ -113,7 +149,33 @@ void flushQueries();
void beginProfile(trace::Call &call, bool isDraw);
void endProfile(trace::Call &call, bool isDraw);
+MetricBackend* getBackend(std::string backendName);
+
+bool isLastPass();
+
+void listMetricsCLI();
+
+void enableMetricsFromCLI(const char* metrics, QueryBoundary pollingRule);
+
+GLenum
+blockOnFence(trace::Call &call, GLsync sync, GLbitfield flags);
+
+GLenum
+clientWaitSync(trace::Call &call, GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+
+// WGL_ARB_render_texture
+bool
+bindTexImage(glws::Drawable *pBuffer, int iBuffer);
+
+// WGL_ARB_render_texture
+bool
+releaseTexImage(glws::Drawable *pBuffer, int iBuffer);
+
+// WGL_ARB_render_texture
+bool
+setPbufferAttrib(glws::Drawable *pBuffer, const int *attribList);
+
} /* namespace glretrace */
-#endif /* _GLRETRACE_HPP_ */
diff --git a/retrace/glretrace.py b/retrace/glretrace.py
index c0d60c6a..db16f11a 100644
--- a/retrace/glretrace.py
+++ b/retrace/glretrace.py
@@ -27,18 +27,29 @@
"""GL retracer generator."""
+import re
+import sys
+
from retrace import Retracer
import specs.stdapi as stdapi
import specs.glapi as glapi
-import specs.glesapi as glesapi
class GlRetracer(Retracer):
table_name = 'glretrace::gl_callbacks'
- def retraceFunction(self, function):
- Retracer.retraceFunction(self, function)
+ def retraceApi(self, api):
+ # Ensure pack function have side effects
+ abort = False
+ for function in api.getAllFunctions():
+ if not function.sideeffects and self.pack_function_regex.match(function.name):
+ sys.stderr.write('error: function %s must have sideeffects\n' % function.name)
+ abort = True
+ if abort:
+ sys.exit(1)
+
+ Retracer.retraceApi(self, api)
array_pointer_function_names = set((
"glVertexPointer",
@@ -72,128 +83,53 @@ class GlRetracer(Retracer):
#"glMatrixIndexPointerARB",
))
- draw_array_function_names = set([
- "glDrawArrays",
- "glDrawArraysEXT",
- "glDrawArraysIndirect",
- "glDrawArraysInstanced",
- "glDrawArraysInstancedARB",
- "glDrawArraysInstancedEXT",
- "glDrawArraysInstancedBaseInstance",
- "glDrawMeshArraysSUN",
- "glMultiDrawArrays",
- "glMultiDrawArraysEXT",
- "glMultiModeDrawArraysIBM",
- 'glMultiDrawArraysIndirect',
- 'glMultiDrawArraysIndirectAMD',
- ])
-
- draw_elements_function_names = set([
- "glDrawElements",
- "glDrawElementsBaseVertex",
- "glDrawElementsIndirect",
- "glDrawElementsInstanced",
- "glDrawElementsInstancedARB",
- "glDrawElementsInstancedEXT",
- "glDrawElementsInstancedBaseVertex",
- "glDrawElementsInstancedBaseInstance",
- "glDrawElementsInstancedBaseVertexBaseInstance",
- "glDrawRangeElements",
- "glDrawRangeElementsEXT",
- "glDrawRangeElementsBaseVertex",
- "glMultiDrawElements",
- "glMultiDrawElementsBaseVertex",
- "glMultiDrawElementsEXT",
- "glMultiModeDrawElementsIBM",
- 'glMultiDrawElementsIndirect',
- 'glMultiDrawElementsIndirectAMD',
- ])
-
- draw_indirect_function_names = set([
- "glDrawArraysIndirect",
- "glDrawElementsIndirect",
- 'glMultiDrawArraysIndirect',
- 'glMultiDrawArraysIndirectAMD',
- 'glMultiDrawElementsIndirect',
- 'glMultiDrawElementsIndirectAMD',
- ])
-
- misc_draw_function_names = set([
- "glCallList",
- "glCallLists",
- "glClear",
- "glEnd",
- "glDrawPixels",
- "glBlitFramebuffer",
- "glBlitFramebufferEXT",
- ])
-
- bind_framebuffer_function_names = set([
- "glBindFramebuffer",
- "glBindFramebufferEXT",
- "glBindFramebufferOES",
- ])
+ draw_arrays_function_regex = re.compile(r'^gl([A-Z][a-z]+)*Draw(Range)?Arrays([A-Z][a-zA-Z]*)?$' )
+ draw_elements_function_regex = re.compile(r'^gl([A-Z][a-z]+)*Draw(Range)?Elements([A-Z][a-zA-Z]*)?$' )
+ draw_indirect_function_regex = re.compile(r'^gl([A-Z][a-z]+)*Draw(Range)?(Arrays|Elements)Indirect([A-Z][a-zA-Z]*)?$' )
+
+ misc_draw_function_regex = re.compile(r'^gl(' + r'|'.join([
+ r'CallList',
+ r'CallLists',
+ r'Clear',
+ r'End',
+ r'DrawPixels',
+ r'DrawTransformFeedback([A-Z][a-zA-Z]*)?',
+ r'BlitFramebuffer',
+ r'Rect[dfis]v?',
+ r'EvalMesh[0-9]+',
+ ]) + r')[0-9A-Z]*$')
+
+
+ bind_framebuffer_function_regex = re.compile(r'^glBindFramebuffer[0-9A-Z]*$')
# Names of the functions that can pack into the current pixel buffer
# object. See also the ARB_pixel_buffer_object specification.
- pack_function_names = set([
- 'glGetCompressedTexImage',
- 'glGetCompressedTexImageARB',
- 'glGetCompressedTextureImageEXT',
- 'glGetCompressedMultiTexImageEXT',
- 'glGetConvolutionFilter',
- 'glGetHistogram',
- 'glGetMinmax',
- 'glGetPixelMapfv',
- 'glGetPixelMapuiv',
- 'glGetPixelMapusv',
- 'glGetPolygonStipple',
- 'glGetSeparableFilter',
- 'glGetTexImage',
- 'glGetTextureImageEXT',
- 'glGetMultiTexImageEXT',
- 'glReadPixels',
- 'glGetnCompressedTexImageARB',
- 'glGetnConvolutionFilterARB',
- 'glGetnHistogramARB',
- 'glGetnMinmaxARB',
- 'glGetnPixelMapfvARB',
- 'glGetnPixelMapuivARB',
- 'glGetnPixelMapusvARB',
- 'glGetnPolygonStippleARB',
- 'glGetnSeparableFilterARB',
- 'glGetnTexImageARB',
- 'glReadnPixelsARB',
- ])
-
- map_function_names = set([
- 'glMapBuffer',
- 'glMapBufferARB',
- 'glMapBufferOES',
- 'glMapBufferRange',
- 'glMapNamedBufferEXT',
- 'glMapNamedBufferRangeEXT',
- 'glMapObjectBufferATI',
- ])
-
- unmap_function_names = set([
- 'glUnmapBuffer',
- 'glUnmapBufferARB',
- 'glUnmapBufferOES',
- 'glUnmapNamedBufferEXT',
- 'glUnmapObjectBufferATI',
- ])
+ pack_function_regex = re.compile(r'^gl(' + r'|'.join([
+ r'Getn?Histogram',
+ r'Getn?PolygonStipple',
+ r'Getn?PixelMap[a-z]+v',
+ r'Getn?Minmax',
+ r'Getn?(Convolution|Separable)Filter',
+ r'Getn?(Compressed)?(Multi)?Tex(ture)?(Sub)?Image',
+ r'Readn?Pixels',
+ ]) + r')[0-9A-Z]*$')
+
+ map_function_regex = re.compile(r'^glMap(|Named|Object)Buffer(Range)?[0-9A-Z]*$')
+
+ unmap_function_regex = re.compile(r'^glUnmap(|Named|Object)Buffer[0-9A-Z]*$')
def retraceFunctionBody(self, function):
is_array_pointer = function.name in self.array_pointer_function_names
- is_draw_array = function.name in self.draw_array_function_names
- is_draw_elements = function.name in self.draw_elements_function_names
- is_misc_draw = function.name in self.misc_draw_function_names
+ is_draw_arrays = self.draw_arrays_function_regex.match(function.name) is not None
+ is_draw_elements = self.draw_elements_function_regex.match(function.name) is not None
+ is_draw_indirect = self.draw_indirect_function_regex.match(function.name) is not None
+ is_misc_draw = self.misc_draw_function_regex.match(function.name)
- if is_array_pointer or is_draw_array or is_draw_elements:
- print ' if (retrace::parser.version < 1) {'
+ # For backwards compatibility with old traces where non VBO drawing was supported
+ if (is_array_pointer or is_draw_arrays or is_draw_elements) and not is_draw_indirect:
+ print ' if (retrace::parser->getVersion() < 1) {'
- if is_array_pointer or is_draw_array:
+ if is_array_pointer or is_draw_arrays:
print ' GLint _array_buffer = 0;'
print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);'
print ' if (!_array_buffer) {'
@@ -210,7 +146,7 @@ class GlRetracer(Retracer):
print ' }'
# When no pack buffer object is bound, the pack functions are no-ops.
- if function.name in self.pack_function_names:
+ if self.pack_function_regex.match(function.name):
print ' GLint _pack_buffer = 0;'
print ' glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &_pack_buffer);'
print ' if (!_pack_buffer) {'
@@ -218,7 +154,7 @@ class GlRetracer(Retracer):
print ' }'
# Pre-snapshots
- if function.name in self.bind_framebuffer_function_names:
+ if self.bind_framebuffer_function_regex.match(function.name):
print ' assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);'
if function.name == 'glStringMarkerGREMEDY':
return
@@ -233,7 +169,7 @@ class GlRetracer(Retracer):
print ' if (!retrace::doubleBuffer) {'
print ' glretrace::frame_complete(call);'
print ' }'
- if is_draw_array or is_draw_elements or is_misc_draw:
+ if is_draw_arrays or is_draw_elements or is_misc_draw:
print ' assert(call.flags & trace::CALL_FLAG_RENDER);'
@@ -261,12 +197,27 @@ class GlRetracer(Retracer):
# then just blit to the drawable without ever calling glViewport.
print ' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));'
- if function.name == "glEnd":
- print ' glretrace::insideGlBeginEnd = false;'
-
if function.name.startswith('gl') and not function.name.startswith('glX'):
- print r' if (retrace::debug && !glretrace::getCurrentContext()) {'
- print r' retrace::warning(call) << "no current context\n";'
+ # The Windows OpenGL runtime will skip calls when there's no
+ # context bound to the current context, but this might cause
+ # crashes on other systems, particularly with NVIDIA Linux drivers.
+ print r' glretrace::Context *currentContext = glretrace::getCurrentContext();'
+ print r' if (!currentContext) {'
+ print r' if (retrace::debug) {'
+ print r' retrace::warning(call) << "no current context\n";'
+ print r' }'
+ print r'#ifndef _WIN32'
+ print r' return;'
+ print r'#endif'
+ print r' }'
+
+ print r' if (retrace::markers) {'
+ print r' glretrace::insertCallMarker(call, currentContext);'
+ print r' }'
+
+ if function.name == "glEnd":
+ print r' if (currentContext) {'
+ print r' currentContext->insideBeginEnd = false;'
print r' }'
if function.name == 'memcpy':
@@ -278,7 +229,7 @@ class GlRetracer(Retracer):
print ' if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) return;'
# Destroy the buffer mapping
- if function.name in self.unmap_function_names:
+ if self.unmap_function_regex.match(function.name):
print r' GLvoid *ptr = NULL;'
if function.name == 'glUnmapBuffer':
print r' glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);'
@@ -286,6 +237,8 @@ class GlRetracer(Retracer):
print r' glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);'
elif function.name == 'glUnmapBufferOES':
print r' glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);'
+ elif function.name == 'glUnmapNamedBuffer':
+ print r' glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &ptr);'
elif function.name == 'glUnmapNamedBufferEXT':
print r' glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);'
elif function.name == 'glUnmapObjectBufferATI':
@@ -296,7 +249,7 @@ class GlRetracer(Retracer):
print r' if (ptr) {'
print r' retrace::delRegionByPointer(ptr);'
print r' } else {'
- print r' retrace::warning(call) << "no current context\n";'
+ print r' retrace::warning(call) << "failed to get mapped pointer\n";'
print r' }'
if function.name in ('glBindProgramPipeline', 'glBindProgramPipelineEXT'):
@@ -305,56 +258,82 @@ class GlRetracer(Retracer):
print r' _pipelineHasBeenBound = true;'
print r' }'
+ if function.name.startswith('glCopyImageSubData'):
+ print r' if (srcTarget == GL_RENDERBUFFER || dstTarget == GL_RENDERBUFFER) {'
+ print r' retrace::warning(call) << " renderbuffer targets unsupported (https://github.com/apitrace/apitrace/issues/404)\n";'
+ print r' }'
+
+ is_draw_arrays = self.draw_arrays_function_regex.match(function.name) is not None
+ is_draw_elements = self.draw_elements_function_regex.match(function.name) is not None
+ is_misc_draw = self.misc_draw_function_regex.match(function.name) is not None
+
profileDraw = (
- function.name in self.draw_array_function_names or
- function.name in self.draw_elements_function_names or
- function.name in self.draw_indirect_function_names or
- function.name in self.misc_draw_function_names or
+ is_draw_arrays or
+ is_draw_elements or
+ is_misc_draw or
function.name == 'glBegin'
)
+ # Keep track of active program for call lists
if function.name in ('glUseProgram', 'glUseProgramObjectARB'):
- print r' glretrace::Context *currentContext = glretrace::getCurrentContext();'
print r' if (currentContext) {'
print r' currentContext->activeProgram = call.arg(0).toUInt();'
print r' }'
# Only profile if not inside a list as the queries get inserted into list
if function.name == 'glNewList':
- print r' glretrace::insideList = true;'
+ print r' if (currentContext) {'
+ print r' currentContext->insideList = true;'
+ print r' }'
if function.name == 'glEndList':
- print r' glretrace::insideList = false;'
+ print r' if (currentContext) {'
+ print r' currentContext->insideList = false;'
+ print r' }'
+
+ if function.name == 'glBegin' or \
+ is_draw_arrays or \
+ is_draw_elements or \
+ function.name.startswith('glBeginTransformFeedback'):
+ print r' if (retrace::debug) {'
+ print r' _validateActiveProgram(call);'
+ print r' }'
if function.name != 'glEnd':
- print r' if (!glretrace::insideList && !glretrace::insideGlBeginEnd && retrace::profiling) {'
+ print r' if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {'
if profileDraw:
print r' glretrace::beginProfile(call, true);'
else:
print r' glretrace::beginProfile(call, false);'
print r' }'
- if function.name == 'glCreateShaderProgramv':
- # When dumping state, break down glCreateShaderProgramv so that the
+ if function.name in ('glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT'):
+ # When dumping state, break down glCreateShaderProgram* so that the
# shader source can be recovered.
print r' if (retrace::dumpingState) {'
print r' GLuint _shader = glCreateShader(type);'
print r' if (_shader) {'
+ if not function.name.startswith('glCreateShaderProgramv'):
+ print r' GLsizei count = 1;'
+ print r' const GLchar **strings = &string;'
print r' glShaderSource(_shader, count, strings, NULL);'
print r' glCompileShader(_shader);'
print r' const GLuint _program = glCreateProgram();'
print r' if (_program) {'
print r' GLint compiled = GL_FALSE;'
print r' glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled);'
- print r' glProgramParameteri(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);'
+ if function.name == 'glCreateShaderProgramvEXT':
+ print r' glProgramParameteriEXT(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);'
+ else:
+ print r' glProgramParameteri(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);'
print r' if (compiled) {'
print r' glAttachShader(_program, _shader);'
print r' glLinkProgram(_program);'
- print r' //glDetachShader(_program, _shader);'
+ print r' if (false) glDetachShader(_program, _shader);'
print r' }'
- print r' //append-shader-info-log-to-program-info-log'
+ print r' // TODO: append shader info log to program info log'
print r' }'
- print r' //glDeleteShader(_shader);'
+ print r' glDeleteShader(_shader);'
print r' _result = _program;'
print r' } else {'
print r' _result = 0;'
@@ -362,13 +341,31 @@ class GlRetracer(Retracer):
print r' } else {'
Retracer.invokeFunction(self, function)
print r' }'
+ elif function.name in ('glDetachShader', 'glDetachObjectARB'):
+ print r' if (!retrace::dumpingState) {'
+ Retracer.invokeFunction(self, function)
+ print r' }'
+ elif function.name == 'glClientWaitSync':
+ print r' _result = glretrace::clientWaitSync(call, sync, flags, timeout);'
+ print r' (void)_result;'
+ elif function.name == 'glGetSynciv':
+ print r' if (pname == GL_SYNC_STATUS &&'
+ print r' bufSize >= 1 &&'
+ print r' values != NULL &&'
+ print r' call.arg(4)[0].toSInt() == GL_SIGNALED) {'
+ print r' // Fence was signalled, so ensure it happened here'
+ print r' glretrace::blockOnFence(call, sync, GL_SYNC_FLUSH_COMMANDS_BIT);'
+ print r' (void)length;'
+ print r' }'
else:
Retracer.invokeFunction(self, function)
if function.name == "glBegin":
- print ' glretrace::insideGlBeginEnd = true;'
+ print ' if (currentContext) {'
+ print ' currentContext->insideBeginEnd = true;'
+ print ' }'
- print r' if (!glretrace::insideList && !glretrace::insideGlBeginEnd && retrace::profiling) {'
+ print r' if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {'
if profileDraw:
print r' glretrace::endProfile(call, true);'
else:
@@ -378,34 +375,40 @@ class GlRetracer(Retracer):
# Error checking
if function.name.startswith('gl'):
# glGetError is not allowed inside glBegin/glEnd
- print ' if (retrace::debug && !glretrace::insideGlBeginEnd && glretrace::getCurrentContext()) {'
+ print ' if (retrace::debug && currentContext && !currentContext->insideBeginEnd) {'
print ' glretrace::checkGlError(call);'
- if function.name in ('glProgramStringARB', 'glProgramStringNV'):
+ if function.name in ('glProgramStringARB', 'glLoadProgramNV'):
print r' GLint error_position = -1;'
print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);'
print r' if (error_position != -1) {'
print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);'
- print r' retrace::warning(call) << error_string << "\n";'
+ print r' retrace::warning(call) << "error in position " << error_position << ": " << error_string << "\n";'
print r' }'
if function.name == 'glCompileShader':
print r' GLint compile_status = 0;'
print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);'
print r' if (!compile_status) {'
- print r' GLint info_log_length = 0;'
- print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
+ print r' retrace::warning(call) << "compilation failed\n";'
+ print r' }'
+ print r' GLint info_log_length = 0;'
+ print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
+ print r' if (info_log_length > 1) {'
print r' GLchar *infoLog = new GLchar[info_log_length];'
print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);'
print r' retrace::warning(call) << infoLog << "\n";'
print r' delete [] infoLog;'
print r' }'
- if function.name in ('glLinkProgram', 'glCreateShaderProgramv', 'glCreateShaderProgramEXT'):
- if function.name != 'glLinkProgram':
+ if function.name in ('glLinkProgram', 'glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT', 'glProgramBinary', 'glProgramBinaryOES'):
+ if function.name.startswith('glCreateShaderProgram'):
print r' GLuint program = _result;'
print r' GLint link_status = 0;'
print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);'
print r' if (!link_status) {'
- print r' GLint info_log_length = 0;'
- print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
+ print r' retrace::warning(call) << "link failed\n";'
+ print r' }'
+ print r' GLint info_log_length = 0;'
+ print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
+ print r' if (info_log_length > 1) {'
print r' GLchar *infoLog = new GLchar[info_log_length];'
print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);'
print r' retrace::warning(call) << infoLog << "\n";'
@@ -415,8 +418,11 @@ class GlRetracer(Retracer):
print r' GLint compile_status = 0;'
print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);'
print r' if (!compile_status) {'
- print r' GLint info_log_length = 0;'
- print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
+ print r' retrace::warning(call) << "compilation failed\n";'
+ print r' }'
+ print r' GLint info_log_length = 0;'
+ print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
+ print r' if (info_log_length > 1) {'
print r' GLchar *infoLog = new GLchar[info_log_length];'
print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);'
print r' retrace::warning(call) << infoLog << "\n";'
@@ -426,18 +432,21 @@ class GlRetracer(Retracer):
print r' GLint link_status = 0;'
print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);'
print r' if (!link_status) {'
- print r' GLint info_log_length = 0;'
- print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
+ print r' retrace::warning(call) << "link failed\n";'
+ print r' }'
+ print r' GLint info_log_length = 0;'
+ print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
+ print r' if (info_log_length > 1) {'
print r' GLchar *infoLog = new GLchar[info_log_length];'
print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);'
print r' retrace::warning(call) << infoLog << "\n";'
print r' delete [] infoLog;'
print r' }'
- if function.name in self.map_function_names:
+ if self.map_function_regex.match(function.name):
print r' if (!_result) {'
print r' retrace::warning(call) << "failed to map buffer\n";'
print r' }'
- if function.name in self.unmap_function_names and function.type is not stdapi.Void:
+ if self.unmap_function_regex.match(function.name) and function.type is not stdapi.Void:
print r' if (!_result) {'
print r' retrace::warning(call) << "failed to unmap buffer\n";'
print r' }'
@@ -446,7 +455,7 @@ class GlRetracer(Retracer):
print r' if (_result != _origResult) {'
print r' retrace::warning(call) << "vertex attrib location mismatch " << _origResult << " -> " << _result << "\n";'
print r' }'
- if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'):
+ if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatus', 'glCheckNamedFramebufferStatusEXT'):
print r' GLint _origResult = call.ret->toSInt();'
print r' if (_origResult == GL_FRAMEBUFFER_COMPLETE &&'
print r' _result != GL_FRAMEBUFFER_COMPLETE) {'
@@ -455,7 +464,7 @@ class GlRetracer(Retracer):
print ' }'
# Query the buffer length for whole buffer mappings
- if function.name in self.map_function_names:
+ if self.map_function_regex.match(function.name):
if 'length' in function.argNames():
assert 'BufferRange' in function.name
else:
@@ -465,6 +474,8 @@ class GlRetracer(Retracer):
print r' glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);'
elif function.name == 'glMapBufferARB':
print r' glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);'
+ elif function.name == 'glMapNamedBuffer':
+ print r' glGetNamedBufferParameteriv(buffer, GL_BUFFER_SIZE, &length);'
elif function.name == 'glMapNamedBufferEXT':
print r' glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);'
elif function.name == 'glMapObjectBufferATI':
@@ -477,38 +488,23 @@ class GlRetracer(Retracer):
print ' %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue)
return
- if function.name in self.draw_elements_function_names and arg.name == 'indices' or\
- function.name in self.draw_indirect_function_names and arg.name == 'indirect':
+ if self.draw_elements_function_regex.match(function.name) and arg.name == 'indices' or\
+ self.draw_indirect_function_regex.match(function.name) and arg.name == 'indirect':
self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue)
return
# Handle pointer with offsets into the current pack pixel buffer
# object.
- if function.name in self.pack_function_names and arg.output:
+ if self.pack_function_regex.match(function.name) and arg.output:
assert isinstance(arg_type, (stdapi.Pointer, stdapi.Array, stdapi.Blob, stdapi.Opaque))
print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue)
return
- if arg.type is glapi.GLlocation \
+ if (arg.type.depends(glapi.GLlocation) or \
+ arg.type.depends(glapi.GLsubroutine)) \
and 'program' not in function.argNames():
# Determine the active program for uniforms swizzling
- print ' GLint program = -1;'
- print ' if (glretrace::insideList) {'
- print ' // glUseProgram & glUseProgramObjectARB are display-list-able'
- print r' glretrace::Context *currentContext = glretrace::getCurrentContext();'
- print ' program = _program_map[currentContext->activeProgram];'
- print ' } else {'
- print ' GLint pipeline = 0;'
- print ' if (_pipelineHasBeenBound) {'
- print ' glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING, &pipeline);'
- print ' }'
- print ' if (pipeline) {'
- print ' glGetProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, &program);'
- print ' } else {'
- print ' glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
- print ' }'
- print ' }'
- print
+ print ' GLint program = _getActiveProgram();'
if arg.type is glapi.GLlocationARB \
and 'programObj' not in function.argNames():
@@ -518,12 +514,20 @@ class GlRetracer(Retracer):
# Don't try to use more samples than the implementation supports
if arg.name == 'samples':
- assert arg.type is glapi.GLsizei
- print ' GLint max_samples = 0;'
- print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
- print ' if (samples > max_samples) {'
- print ' samples = max_samples;'
- print ' }'
+ if function.name == 'glRasterSamplesEXT':
+ assert arg.type is glapi.GLuint
+ print ' GLint max_samples = 0;'
+ print ' glGetIntegerv(GL_MAX_RASTER_SAMPLES_EXT, &max_samples);'
+ print ' if (samples > static_cast<GLuint>(max_samples)) {'
+ print ' samples = static_cast<GLuint>(max_samples);'
+ print ' }'
+ else:
+ assert arg.type is glapi.GLsizei
+ print ' GLint max_samples = 0;'
+ print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
+ print ' if (samples > max_samples) {'
+ print ' samples = max_samples;'
+ print ' }'
# These parameters are referred beyond the call life-time
# TODO: Replace ad-hoc solution for bindable parameters with general one
@@ -542,9 +546,91 @@ if __name__ == '__main__':
static bool _pipelineHasBeenBound = false;
+
+
+static GLint
+_getActiveProgram(void);
+
+static void
+_validateActiveProgram(trace::Call &call);
+
'''
api = stdapi.API()
api.addModule(glapi.glapi)
- api.addModule(glesapi.glesapi)
retracer = GlRetracer()
retracer.retraceApi(api)
+
+ print r'''
+static GLint
+_getActiveProgram(void)
+{
+ GLint program = -1;
+ glretrace::Context *currentContext = glretrace::getCurrentContext();
+ if (currentContext && currentContext->insideList) {
+ // glUseProgram & glUseProgramObjectARB are display-list-able
+ program = _program_map[currentContext->activeProgram];
+ } else {
+ GLint pipeline = 0;
+ if (_pipelineHasBeenBound) {
+ glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING, &pipeline);
+ }
+ if (pipeline) {
+ glGetProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, &program);
+ } else {
+ glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+ }
+ }
+ return program;
+}
+
+static void
+_validateActiveProgram(trace::Call &call)
+{
+ assert(retrace::debug);
+
+ glretrace::Context *currentContext = glretrace::getCurrentContext();
+ if (!currentContext ||
+ currentContext->insideList ||
+ currentContext->insideBeginEnd ||
+ currentContext->wsContext->profile.major < 2) {
+ return;
+ }
+
+ GLint pipeline = 0;
+ if (_pipelineHasBeenBound) {
+ glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING, &pipeline);
+ }
+ if (pipeline) {
+ // TODO
+ } else {
+ GLint program = 0;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+ if (!program) {
+ return;
+ }
+
+ GLint validate_status = GL_FALSE;
+ glGetProgramiv(program, GL_VALIDATE_STATUS, &validate_status);
+ if (validate_status) {
+ // Validate only once
+ return;
+ }
+
+ glValidateProgram(program);
+ glGetProgramiv(program, GL_VALIDATE_STATUS, &validate_status);
+ if (!validate_status) {
+ retrace::warning(call) << "program validation failed\n";
+ }
+
+ GLint info_log_length = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);
+ if (info_log_length > 1) {
+ GLchar *infoLog = new GLchar[info_log_length];
+ glGetProgramInfoLog(program, info_log_length, NULL, infoLog);
+ retrace::warning(call) << infoLog << "\n";
+ delete [] infoLog;
+ }
+ }
+}
+
+'''
diff --git a/retrace/glretrace_cgl.cpp b/retrace/glretrace_cgl.cpp
index 22ef7681..21c42ca9 100644
--- a/retrace/glretrace_cgl.cpp
+++ b/retrace/glretrace_cgl.cpp
@@ -94,24 +94,21 @@ static DrawableMap drawable_map;
// ctx -> Context* map
static ContextMap context_map;
-// ctx -> Drawable* map
-static DrawableMap context_drawable_map;
-
static Context *sharedContext = NULL;
struct PixelFormat
{
- glws::Profile profile;
+ glprofile::Profile profile;
PixelFormat() :
- profile(glws::PROFILE_COMPAT)
+ profile(glprofile::API_GL, 1, 0)
{}
};
static glws::Drawable *
-getDrawable(unsigned long drawable_id) {
+getDrawable(unsigned long drawable_id, glprofile::Profile profile) {
if (drawable_id == 0) {
return NULL;
}
@@ -119,23 +116,7 @@ getDrawable(unsigned long drawable_id) {
DrawableMap::const_iterator it;
it = drawable_map.find(drawable_id);
if (it == drawable_map.end()) {
- return (drawable_map[drawable_id] = glretrace::createDrawable());
- }
-
- return it->second;
-}
-
-
-static glws::Drawable *
-getDrawableFromContext(unsigned long long ctx) {
- if (ctx == 0) {
- return NULL;
- }
-
- DrawableMap::const_iterator it;
- it = context_drawable_map.find(ctx);
- if (it == context_drawable_map.end()) {
- return (context_drawable_map[ctx] = glretrace::createDrawable());
+ return (drawable_map[drawable_id] = glretrace::createDrawable(profile));
}
return it->second;
@@ -168,6 +149,7 @@ static void retrace_CGLChoosePixelFormat(trace::Call &call) {
return;
}
+ bool singleBuffer = true;
int profile = 0;
const trace::Array * attribs = call.arg(0).toArray();
@@ -180,11 +162,11 @@ static void retrace_CGLChoosePixelFormat(trace::Call &call) {
}
switch (param) {
+
+ // Boolean attributes
+
case kCGLPFAAllRenderers:
- case kCGLPFATripleBuffer:
- case kCGLPFADoubleBuffer:
case kCGLPFAStereo:
- case kCGLPFAAuxBuffers:
case kCGLPFAMinimumPolicy:
case kCGLPFAMaximumPolicy:
case kCGLPFAOffScreen:
@@ -212,10 +194,18 @@ static void retrace_CGLChoosePixelFormat(trace::Call &call) {
case kCGLPFASupportsAutomaticGraphicsSwitching:
break;
+ case kCGLPFADoubleBuffer:
+ case kCGLPFATripleBuffer:
+ singleBuffer = false;
+ break;
+
+ // Valued attributes
+
case kCGLPFAColorSize:
case kCGLPFAAlphaSize:
case kCGLPFADepthSize:
case kCGLPFAStencilSize:
+ case kCGLPFAAuxBuffers:
case kCGLPFAAccumSize:
case kCGLPFASampleBuffers:
case kCGLPFASamples:
@@ -245,19 +235,22 @@ static void retrace_CGLChoosePixelFormat(trace::Call &call) {
case 0:
break;
case kCGLOGLPVersion_Legacy:
- pixelFormat->profile = glws::PROFILE_COMPAT;
+ pixelFormat->profile = glprofile::Profile(glprofile::API_GL, 1, 0);
break;
case kCGLOGLPVersion_GL3_Core:
- pixelFormat->profile = glws::PROFILE_3_2_CORE;
+ pixelFormat->profile = glprofile::Profile(glprofile::API_GL, 3, 2, true, true);
break;
case kCGLOGLPVersion_GL4_Core:
- pixelFormat->profile = glws::PROFILE_4_1_CORE;
+ pixelFormat->profile = glprofile::Profile(glprofile::API_GL, 4, 1, true, true);
break;
default:
retrace::warning(call) << "unexpected opengl profile " << std::hex << profile << std::dec << "\n";
break;
}
+ // XXX: Generalize this, don't override command line options.
+ retrace::doubleBuffer = !singleBuffer;
+
retrace::addObj(call, pix, pixelFormat);
}
@@ -283,7 +276,7 @@ static void retrace_CGLCreateContext(trace::Call &call) {
trace::Value & pix = call.argByName("pix");
const PixelFormat *pixelFormat = retrace::asObjPointer<PixelFormat>(call, pix);
- glws::Profile profile = pixelFormat ? pixelFormat->profile : glretrace::defaultProfile;
+ glprofile::Profile profile = pixelFormat ? pixelFormat->profile : glretrace::defaultProfile;
unsigned long long share = call.arg(1).toUIntPtr();
Context *sharedContext = getContext(share);
@@ -329,9 +322,11 @@ static void retrace_CGLSetSurface(trace::Call &call) {
(void)cid;
(void)wid;
- glws::Drawable *drawable = getDrawable(sid);
-
- context_drawable_map[ctx] = drawable;
+ Context *context = getContext(ctx);
+ if (context) {
+ glws::Drawable *drawable = getDrawable(sid, context->profile());
+ context->drawable = drawable;
+ }
}
@@ -341,8 +336,10 @@ static void retrace_CGLClearDrawable(trace::Call &call) {
}
unsigned long long ctx = call.arg(0).toUIntPtr();
-
- context_drawable_map[ctx] = NULL;
+ Context *context = getContext(ctx);
+ if (context) {
+ context->drawable = NULL;
+ }
}
@@ -353,8 +350,15 @@ static void retrace_CGLSetCurrentContext(trace::Call &call) {
unsigned long long ctx = call.arg(0).toUIntPtr();
- glws::Drawable *new_drawable = getDrawableFromContext(ctx);
Context *new_context = getContext(ctx);
+ glws::Drawable *new_drawable = NULL;
+ if (new_context) {
+ if (!new_context->drawable) {
+ glprofile::Profile profile = new_context->profile();
+ new_context->drawable = glretrace::createDrawable(profile);
+ }
+ new_drawable = new_context->drawable;
+ }
glretrace::makeCurrent(call, new_drawable, new_context);
}
@@ -369,7 +373,7 @@ static void retrace_CGLFlushDrawable(trace::Call &call) {
Context *context = getContext(ctx);
if (context) {
- glws::Drawable *drawable = getDrawableFromContext(ctx);
+ glws::Drawable *drawable = context->drawable;
if (drawable) {
if (retrace::doubleBuffer) {
drawable->swapBuffers();
@@ -386,6 +390,18 @@ static void retrace_CGLFlushDrawable(trace::Call &call) {
}
+static void retrace_CGLSetVirtualScreen(trace::Call &call) {
+ if (call.ret->toUInt() != kCGLNoError) {
+ return;
+ }
+
+ GLint screen = call.arg(1).toSInt();
+ if (screen != 0) {
+ retrace::warning(call) << "multiple virtual screens unsupported\n";
+ }
+}
+
+
/**
* We can't fully reimplement CGLTexImageIOSurface2D, as external IOSurface are
* no longer present. Simply emit a glTexImage2D to ensure the texture storage
@@ -430,15 +446,14 @@ static void retrace_CGLTexImageIOSurface2D(trace::Call &call) {
GLvoid * pixels = NULL;
- if (glretrace::getCurrentContext() != context) {
- if (retrace::debug) {
- retrace::warning(call) << "current context mismatch\n";
- }
+ glretrace::Context *currentContext = glretrace::getCurrentContext();
+ if (retrace::debug && currentContext != context) {
+ retrace::warning(call) << "current context mismatch\n";
}
glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
- if (retrace::debug && !glretrace::insideGlBeginEnd) {
+ if (retrace::debug && currentContext && !currentContext->insideBeginEnd) {
glretrace::checkGlError(call);
}
}
@@ -457,15 +472,23 @@ const retrace::Entry glretrace::cgl_callbacks[] = {
{"CGLErrorString", &retrace::ignore},
{"CGLFlushDrawable", &retrace_CGLFlushDrawable},
{"CGLGetCurrentContext", &retrace::ignore},
+ {"CGLGetGlobalOption", &retrace::ignore},
{"CGLGetOption", &retrace::ignore},
{"CGLGetParameter", &retrace::ignore},
+ {"CGLGetPixelFormat", &retrace::ignore},
+ {"CGLGetSurface", &retrace::ignore},
{"CGLGetVersion", &retrace::ignore},
{"CGLGetVirtualScreen", &retrace::ignore},
{"CGLIsEnabled", &retrace::ignore},
+ {"CGLLockContext", &retrace::ignore},
{"CGLSetCurrentContext", &retrace_CGLSetCurrentContext},
+ {"CGLSetGlobalOption", &retrace::ignore},
+ {"CGLSetOption", &retrace::ignore},
{"CGLSetSurface", &retrace_CGLSetSurface},
{"CGLSetParameter", &retrace::ignore},
+ {"CGLSetVirtualScreen", &retrace_CGLSetVirtualScreen},
{"CGLTexImageIOSurface2D", &retrace_CGLTexImageIOSurface2D},
+ {"CGLUnlockContext", &retrace::ignore},
{"CGLUpdateContext", &retrace::ignore},
{NULL, NULL},
};
diff --git a/retrace/glretrace_egl.cpp b/retrace/glretrace_egl.cpp
index fda9399f..c6fabddc 100644
--- a/retrace/glretrace_egl.cpp
+++ b/retrace/glretrace_egl.cpp
@@ -47,11 +47,12 @@ using namespace glretrace;
typedef std::map<unsigned long long, glws::Drawable *> DrawableMap;
typedef std::map<unsigned long long, Context *> ContextMap;
-typedef std::map<unsigned long long, glws::Profile> ProfileMap;
+typedef std::map<unsigned long long, glprofile::Profile> ProfileMap;
static DrawableMap drawable_map;
static ContextMap context_map;
static ProfileMap profile_map;
+/* FIXME: This should be tracked per thread. */
static unsigned int current_api = EGL_OPENGL_ES_API;
/*
@@ -60,7 +61,7 @@ static unsigned int current_api = EGL_OPENGL_ES_API;
* instead of guessing. For now, start with a guess of ES2 profile, which
* should be the most common case for EGL.
*/
-static glws::Profile last_profile = glws::PROFILE_ES2;
+static glprofile::Profile last_profile(glprofile::API_GLES, 2, 0);
static glws::Drawable *null_drawable = NULL;
@@ -102,7 +103,7 @@ getContext(unsigned long long context_ptr) {
static void createDrawable(unsigned long long orig_config, unsigned long long orig_surface)
{
ProfileMap::iterator it = profile_map.find(orig_config);
- glws::Profile profile;
+ glprofile::Profile profile;
// If the requested config is associated with a profile, use that
// profile. Otherwise, assume that the last used profile is what
@@ -117,6 +118,41 @@ static void createDrawable(unsigned long long orig_config, unsigned long long or
drawable_map[orig_surface] = drawable;
}
+static void retrace_eglChooseConfig(trace::Call &call) {
+ if (!call.ret->toSInt()) {
+ return;
+ }
+
+ trace::Array *attrib_array = call.arg(1).toArray();
+ trace::Array *config_array = call.arg(2).toArray();
+ trace::Array *num_config_ptr = call.arg(4).toArray();
+ if (!attrib_array || !config_array || !num_config_ptr) {
+ return;
+ }
+
+ glprofile::Profile profile;
+ unsigned renderableType = parseAttrib(attrib_array, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
+ std::cerr << "renderableType = " << renderableType << "\n";
+ if (renderableType & EGL_OPENGL_BIT) {
+ profile = glprofile::Profile(glprofile::API_GL, 1, 0);
+ } else {
+ profile.api = glprofile::API_GLES;
+ if (renderableType & EGL_OPENGL_ES3_BIT) {
+ profile.major = 3;
+ } else if (renderableType & EGL_OPENGL_ES2_BIT) {
+ profile.major = 2;
+ } else {
+ profile.major = 1;
+ }
+ }
+
+ unsigned num_config = num_config_ptr->values[0]->toUInt();
+ for (unsigned i = 0; i < num_config; ++i) {
+ unsigned long long orig_config = config_array->values[i]->toUIntPtr();
+ profile_map[orig_config] = profile;
+ }
+}
+
static void retrace_eglCreateWindowSurface(trace::Call &call) {
unsigned long long orig_config = call.arg(1).toUIntPtr();
unsigned long long orig_surface = call.ret->toUIntPtr();
@@ -147,8 +183,11 @@ static void retrace_eglDestroySurface(trace::Call &call) {
}
static void retrace_eglBindAPI(trace::Call &call) {
+ if (!call.ret->toBool()) {
+ return;
+ }
+
current_api = call.arg(0).toUInt();
- eglBindAPI(current_api);
}
static void retrace_eglCreateContext(trace::Call &call) {
@@ -156,51 +195,35 @@ static void retrace_eglCreateContext(trace::Call &call) {
unsigned long long orig_config = call.arg(1).toUIntPtr();
Context *share_context = getContext(call.arg(2).toUIntPtr());
trace::Array *attrib_array = call.arg(3).toArray();
- glws::Profile profile;
+ glprofile::Profile profile;
switch (current_api) {
case EGL_OPENGL_API:
- profile = glws::PROFILE_COMPAT;
+ profile.api = glprofile::API_GL;
+ profile.major = parseAttrib(attrib_array, EGL_CONTEXT_MAJOR_VERSION, 1);
+ profile.minor = parseAttrib(attrib_array, EGL_CONTEXT_MINOR_VERSION, 0);
+ if (profile.versionGreaterOrEqual(3,2)) {
+ int profileMask = parseAttrib(attrib_array, EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR);
+ if (profileMask & EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) {
+ profile.core = true;
+ }
+ int contextFlags = parseAttrib(attrib_array, EGL_CONTEXT_FLAGS_KHR, 0);
+ if (contextFlags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) {
+ profile.forwardCompatible = true;
+ }
+ }
break;
case EGL_OPENGL_ES_API:
default:
- profile = glws::PROFILE_ES1;
- if (attrib_array) {
- for (int i = 0; i < attrib_array->values.size(); i += 2) {
- int v = attrib_array->values[i]->toSInt();
- if (v == EGL_CONTEXT_CLIENT_VERSION) {
- v = attrib_array->values[i + 1]->toSInt();
- if (v == 2)
- profile = glws::PROFILE_ES2;
- break;
- }
- }
- }
+ profile.api = glprofile::API_GLES;
+ profile.major = parseAttrib(attrib_array, EGL_CONTEXT_MAJOR_VERSION, 1);
+ profile.minor = parseAttrib(attrib_array, EGL_CONTEXT_MINOR_VERSION, 0);
break;
}
Context *context = glretrace::createContext(share_context, profile);
- if (!context) {
- const char *name;
- switch (profile) {
- case glws::PROFILE_COMPAT:
- name = "OpenGL";
- break;
- case glws::PROFILE_ES1:
- name = "OpenGL ES 1.1";
- break;
- case glws::PROFILE_ES2:
- name = "OpenGL ES 2.0";
- break;
- default:
- name = "unknown";
- break;
- }
-
- retrace::warning(call) << "Failed to create " << name << " context.\n";
- exit(1);
- }
+ assert(context);
context_map[orig_context] = context;
profile_map[orig_config] = profile;
@@ -266,7 +289,7 @@ const retrace::Entry glretrace::egl_callbacks[] = {
{"eglTerminate", &retrace::ignore},
{"eglQueryString", &retrace::ignore},
{"eglGetConfigs", &retrace::ignore},
- {"eglChooseConfig", &retrace::ignore},
+ {"eglChooseConfig", &retrace_eglChooseConfig},
{"eglGetConfigAttrib", &retrace::ignore},
{"eglCreateWindowSurface", &retrace_eglCreateWindowSurface},
{"eglCreatePbufferSurface", &retrace_eglCreatePbufferSurface},
@@ -291,6 +314,7 @@ const retrace::Entry glretrace::egl_callbacks[] = {
{"eglQueryContext", &retrace::ignore},
{"eglWaitGL", &retrace::ignore},
{"eglWaitNative", &retrace::ignore},
+ {"eglReleaseThread", &retrace::ignore},
{"eglSwapBuffers", &retrace_eglSwapBuffers},
//{"eglCopyBuffers", &retrace::ignore},
{"eglGetProcAddress", &retrace::ignore},
diff --git a/retrace/glretrace_glx.cpp b/retrace/glretrace_glx.cpp
index d5a70775..4cb631f7 100644
--- a/retrace/glretrace_glx.cpp
+++ b/retrace/glretrace_glx.cpp
@@ -96,7 +96,7 @@ static void retrace_glXCreateContextAttribsARB(trace::Call &call) {
Context *share_context = getContext(call.arg(2).toUIntPtr());
const trace::Value * attrib_list = &call.arg(4);
- glws::Profile profile = parseContextAttribList(attrib_list);
+ glprofile::Profile profile = parseContextAttribList(attrib_list);
Context *context = glretrace::createContext(share_context, profile);
context_map[orig_context] = context;
@@ -173,8 +173,9 @@ static void retrace_glXCreatePbuffer(trace::Call &call) {
const trace::Value *attrib_list = &call.arg(2);
int width = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_WIDTH, 0);
int height = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_HEIGHT, 0);
+ glws::pbuffer_info pbInfo = {0, 0, false};
- glws::Drawable *drawable = glretrace::createPbuffer(width, height);
+ glws::Drawable *drawable = glretrace::createPbuffer(width, height, &pbInfo);
drawable_map[orig_drawable] = drawable;
}
@@ -288,6 +289,7 @@ const retrace::Entry glretrace::glx_callbacks[] = {
//{"glXSwapBuffersMscOML", &retrace_glXSwapBuffersMscOML},
{"glXSwapBuffers", &retrace_glXSwapBuffers},
{"glXSwapIntervalEXT", &retrace::ignore},
+ {"glXSwapIntervalMESA", &retrace::ignore},
{"glXSwapIntervalSGI", &retrace::ignore},
//{"glXUseXFont", &retrace_glXUseXFont},
{"glXWaitForMscOML", &retrace::ignore},
diff --git a/retrace/glretrace_main.cpp b/retrace/glretrace_main.cpp
index cd186100..a20c42e3 100755
--- a/retrace/glretrace_main.cpp
+++ b/retrace/glretrace_main.cpp
@@ -29,6 +29,7 @@
#include <string.h>
#include <map>
+#include <sstream>
#include "retrace.hpp"
#include "glproc.hpp"
@@ -38,19 +39,18 @@
#include "os_memory.hpp"
#include "highlight.hpp"
-
/* Synchronous debug output may reduce performance however,
* without it the callNo in the callback may be inaccurate
* as the callback may be called at any time.
*/
#define DEBUG_OUTPUT_SYNCHRONOUS 0
+#define APITRACE_MARKER_ID 0xA3ACE001U
+
namespace glretrace {
-glws::Profile defaultProfile = glws::PROFILE_COMPAT;
+glprofile::Profile defaultProfile(glprofile::API_GL, 1, 0);
-bool insideList = false;
-bool insideGlBeginEnd = false;
bool supportsARBShaderObjects = false;
enum {
@@ -78,58 +78,109 @@ struct CallQuery
static bool supportsElapsed = true;
static bool supportsTimestamp = true;
static bool supportsOcclusion = true;
-static bool supportsDebugOutput = true;
static std::list<CallQuery> callQueries;
static void APIENTRY
debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam);
+// Limit certain warnings
+// TODO: expose this via a command line option.
+static const unsigned
+maxWarningCount = 100;
+
+static std::map< uint64_t, unsigned > errorCounts;
+
void
checkGlError(trace::Call &call) {
GLenum error = glGetError();
while (error != GL_NO_ERROR) {
- std::ostream & os = retrace::warning(call);
-
- os << "glGetError(";
- os << call.name();
- os << ") = ";
-
- switch (error) {
- case GL_INVALID_ENUM:
- os << "GL_INVALID_ENUM";
- break;
- case GL_INVALID_VALUE:
- os << "GL_INVALID_VALUE";
- break;
- case GL_INVALID_OPERATION:
- os << "GL_INVALID_OPERATION";
- break;
- case GL_STACK_OVERFLOW:
- os << "GL_STACK_OVERFLOW";
- break;
- case GL_STACK_UNDERFLOW:
- os << "GL_STACK_UNDERFLOW";
- break;
- case GL_OUT_OF_MEMORY:
- os << "GL_OUT_OF_MEMORY";
- break;
- case GL_INVALID_FRAMEBUFFER_OPERATION:
- os << "GL_INVALID_FRAMEBUFFER_OPERATION";
- break;
- case GL_TABLE_TOO_LARGE:
- os << "GL_TABLE_TOO_LARGE";
- break;
- default:
- os << error;
- break;
+ uint64_t errorHash = call.sig->id ^ uint64_t(error) << 32;
+ size_t errorCount = errorCounts[errorHash]++;
+ if (errorCount <= maxWarningCount) {
+ std::ostream & os = retrace::warning(call);
+
+ os << "glGetError(";
+ os << call.name();
+ os << ") = ";
+
+ switch (error) {
+ case GL_INVALID_ENUM:
+ os << "GL_INVALID_ENUM";
+ break;
+ case GL_INVALID_VALUE:
+ os << "GL_INVALID_VALUE";
+ break;
+ case GL_INVALID_OPERATION:
+ os << "GL_INVALID_OPERATION";
+ break;
+ case GL_STACK_OVERFLOW:
+ os << "GL_STACK_OVERFLOW";
+ break;
+ case GL_STACK_UNDERFLOW:
+ os << "GL_STACK_UNDERFLOW";
+ break;
+ case GL_OUT_OF_MEMORY:
+ os << "GL_OUT_OF_MEMORY";
+ break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ os << "GL_INVALID_FRAMEBUFFER_OPERATION";
+ break;
+ case GL_TABLE_TOO_LARGE:
+ os << "GL_TABLE_TOO_LARGE";
+ break;
+ default:
+ os << error;
+ break;
+ }
+
+ if (errorCount == maxWarningCount) {
+ os << ": too many identical messages; ignoring";
+ }
+
+ os << std::endl;
}
- os << "\n";
-
+
error = glGetError();
}
}
+
+void
+insertCallMarker(trace::Call &call, Context *currentContext)
+{
+ if (!currentContext ||
+ currentContext->insideBeginEnd ||
+ !currentContext->KHR_debug) {
+ return;
+ }
+
+ glprofile::Profile currentProfile = currentContext->actualProfile();
+
+ std::stringstream ss;
+ trace::dump(call, ss,
+ trace::DUMP_FLAG_NO_COLOR |
+ trace::DUMP_FLAG_NO_ARG_NAMES |
+ trace::DUMP_FLAG_NO_MULTILINE);
+
+ std::string msg = ss.str();
+ GLsizei length = msg.length() > currentContext->maxDebugMessageLength
+ ? currentContext->maxDebugMessageLength
+ : msg.length();
+
+ auto pfnGlDebugMessageInsert = currentProfile.desktop()
+ ? glDebugMessageInsert
+ : glDebugMessageInsertKHR;
+
+ pfnGlDebugMessageInsert(GL_DEBUG_SOURCE_THIRD_PARTY,
+ GL_DEBUG_TYPE_MARKER,
+ APITRACE_MARKER_ID,
+ GL_DEBUG_SEVERITY_NOTIFICATION,
+ length,
+ msg.c_str());
+}
+
+
static inline int64_t
getCurrentTime(void) {
if (retrace::profilingGpuTimes && supportsTimestamp) {
@@ -221,6 +272,32 @@ flushQueries() {
void
beginProfile(trace::Call &call, bool isDraw) {
+ if (retrace::profilingWithBackends) {
+ if (profilingBoundaries[QUERY_BOUNDARY_CALL] ||
+ profilingBoundaries[QUERY_BOUNDARY_DRAWCALL]) {
+ if (curMetricBackend) {
+ curMetricBackend->beginQuery(isDraw ? QUERY_BOUNDARY_DRAWCALL : QUERY_BOUNDARY_CALL);
+ }
+ if (isLastPass() && curMetricBackend) {
+ Context *currentContext = getCurrentContext();
+ GLuint program = currentContext ? currentContext->activeProgram : 0;
+ unsigned eventId = profilingBoundariesIndex[QUERY_BOUNDARY_CALL]++;
+ ProfilerCall::data callData = {false,
+ call.no,
+ program,
+ call.sig->name};
+ if (profilingBoundaries[QUERY_BOUNDARY_CALL]) {
+ profiler.addQuery(QUERY_BOUNDARY_CALL, eventId, &callData);
+ }
+ if (isDraw && profilingBoundaries[QUERY_BOUNDARY_DRAWCALL]) {
+ eventId = profilingBoundariesIndex[QUERY_BOUNDARY_DRAWCALL]++;
+ profiler.addQuery(QUERY_BOUNDARY_DRAWCALL, eventId, &callData);
+ }
+ }
+ }
+ return;
+ }
+
glretrace::Context *currentContext = glretrace::getCurrentContext();
/* Create call query */
@@ -264,6 +341,15 @@ beginProfile(trace::Call &call, bool isDraw) {
void
endProfile(trace::Call &call, bool isDraw) {
+ if (retrace::profilingWithBackends) {
+ if (profilingBoundaries[QUERY_BOUNDARY_CALL] ||
+ profilingBoundaries[QUERY_BOUNDARY_DRAWCALL]) {
+ if (curMetricBackend) {
+ curMetricBackend->endQuery(isDraw ? QUERY_BOUNDARY_DRAWCALL : QUERY_BOUNDARY_CALL);
+ }
+ }
+ return;
+ }
/* CPU profiling for all calls */
if (retrace::profilingCpuTimes) {
@@ -289,22 +375,85 @@ endProfile(trace::Call &call, bool isDraw) {
}
}
+
+GLenum
+blockOnFence(trace::Call &call, GLsync sync, GLbitfield flags) {
+ GLenum result;
+
+ do {
+ result = glClientWaitSync(sync, flags, 1000);
+ } while (result == GL_TIMEOUT_EXPIRED);
+
+ switch (result) {
+ case GL_ALREADY_SIGNALED:
+ case GL_CONDITION_SATISFIED:
+ break;
+ default:
+ retrace::warning(call) << "got " << glstate::enumToString(result) << "\n";
+ }
+
+ return result;
+}
+
+
+/**
+ * Helper for properly retrace glClientWaitSync().
+ */
+GLenum
+clientWaitSync(trace::Call &call, GLsync sync, GLbitfield flags, GLuint64 timeout) {
+ GLenum result = call.ret->toSInt();
+ switch (result) {
+ case GL_ALREADY_SIGNALED:
+ case GL_CONDITION_SATISFIED:
+ // We must block, as following calls might rely on the fence being
+ // signaled
+ result = blockOnFence(call, sync, flags);
+ break;
+ case GL_TIMEOUT_EXPIRED:
+ result = glClientWaitSync(sync, flags, timeout);
+ break;
+ case GL_WAIT_FAILED:
+ break;
+ default:
+ retrace::warning(call) << "unexpected return value\n";
+ break;
+ }
+ return result;
+}
+
+
+/*
+ * Called the first time a context is made current.
+ */
void
initContext() {
glretrace::Context *currentContext = glretrace::getCurrentContext();
+ assert(currentContext);
/* Ensure we have adequate extension support */
- assert(currentContext);
- supportsTimestamp = currentContext->hasExtension("GL_ARB_timer_query");
+ glprofile::Profile currentProfile = currentContext->actualProfile();
+ supportsTimestamp = currentProfile.versionGreaterOrEqual(glprofile::API_GL, 3, 3) ||
+ currentContext->hasExtension("GL_ARB_timer_query");
supportsElapsed = currentContext->hasExtension("GL_EXT_timer_query") || supportsTimestamp;
- supportsOcclusion = currentContext->hasExtension("GL_ARB_occlusion_query");
- supportsDebugOutput = currentContext->hasExtension("GL_ARB_debug_output");
+ supportsOcclusion = currentProfile.versionGreaterOrEqual(glprofile::API_GL, 1, 5);
supportsARBShaderObjects = currentContext->hasExtension("GL_ARB_shader_objects");
+ currentContext->KHR_debug = currentContext->hasExtension("GL_KHR_debug");
+ if (currentContext->KHR_debug) {
+ glGetIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH, &currentContext->maxDebugMessageLength);
+ assert(currentContext->maxDebugMessageLength > 0);
+ }
+
+#ifdef __APPLE__
+ // GL_TIMESTAMP doesn't work on Apple. GL_TIME_ELAPSED still does however.
+ // http://lists.apple.com/archives/mac-opengl/2014/Nov/threads.html#00001
+ supportsTimestamp = false;
+#endif
+
/* Check for timer query support */
if (retrace::profilingGpuTimes) {
if (!supportsTimestamp && !supportsElapsed) {
- std::cout << "Error: Cannot run profile, GL_ARB_timer_query or GL_EXT_timer_query extensions are not supported." << std::endl;
+ std::cout << "error: cannot profile, GL_ARB_timer_query or GL_EXT_timer_query extensions are not supported." << std::endl;
exit(-1);
}
@@ -312,25 +461,38 @@ initContext() {
glGetQueryiv(GL_TIME_ELAPSED, GL_QUERY_COUNTER_BITS, &bits);
if (!bits) {
- std::cout << "Error: Cannot run profile, GL_QUERY_COUNTER_BITS == 0." << std::endl;
+ std::cout << "error: cannot profile, GL_QUERY_COUNTER_BITS == 0." << std::endl;
exit(-1);
}
}
/* Check for occlusion query support */
if (retrace::profilingPixelsDrawn && !supportsOcclusion) {
- std::cout << "Error: Cannot run profile, GL_ARB_occlusion_query extension is not supported." << std::endl;
+ std::cout << "error: cannot profile, GL_ARB_occlusion_query extension is not supported (" << currentProfile << ")" << std::endl;
exit(-1);
}
/* Setup debug message call back */
- if (retrace::debug && supportsDebugOutput) {
- glretrace::Context *currentContext = glretrace::getCurrentContext();
- glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
- glDebugMessageCallbackARB(&debugOutputCallback, currentContext);
+ if (retrace::debug) {
+ if (currentContext->KHR_debug) {
+ if (currentProfile.desktop()) {
+ glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
+ glDebugMessageCallback(&debugOutputCallback, currentContext);
+ } else {
+ glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
+ glDebugMessageCallbackKHR(&debugOutputCallback, currentContext);
+ }
+
+ if (DEBUG_OUTPUT_SYNCHRONOUS) {
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ }
+ } else if (currentContext->hasExtension("GL_ARB_debug_output")) {
+ glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
+ glDebugMessageCallbackARB(&debugOutputCallback, currentContext);
- if (DEBUG_OUTPUT_SYNCHRONOUS) {
- glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+ if (DEBUG_OUTPUT_SYNCHRONOUS) {
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+ }
}
}
@@ -355,7 +517,32 @@ initContext() {
void
frame_complete(trace::Call &call) {
- if (retrace::profiling) {
+ if (retrace::profilingWithBackends) {
+ if (profilingBoundaries[QUERY_BOUNDARY_CALL] ||
+ profilingBoundaries[QUERY_BOUNDARY_DRAWCALL])
+ {
+ if (isLastPass() && curMetricBackend) {
+ // frame end indicator
+ ProfilerCall::data callData = {true, 0, 0, ""};
+ if (profilingBoundaries[QUERY_BOUNDARY_CALL]) {
+ profiler.addQuery(QUERY_BOUNDARY_CALL, 0, &callData);
+ }
+ if (profilingBoundaries[QUERY_BOUNDARY_DRAWCALL]) {
+ profiler.addQuery(QUERY_BOUNDARY_DRAWCALL, 0, &callData);
+ }
+ }
+ }
+ if (curMetricBackend) {
+ curMetricBackend->endQuery(QUERY_BOUNDARY_FRAME);
+ }
+ if (profilingBoundaries[QUERY_BOUNDARY_FRAME]) {
+ if (isLastPass() && curMetricBackend) {
+ profiler.addQuery(QUERY_BOUNDARY_FRAME,
+ profilingBoundariesIndex[QUERY_BOUNDARY_FRAME]++);
+ }
+ }
+ }
+ else if (retrace::profiling) {
/* Complete any remaining queries */
flushQueries();
@@ -370,17 +557,90 @@ frame_complete(trace::Call &call) {
return;
}
- assert(currentContext->drawable);
- if (retrace::debug && !currentContext->drawable->visible) {
+ glws::Drawable *currentDrawable = currentContext->drawable;
+ assert(currentDrawable);
+ if (retrace::debug &&
+ !currentDrawable->pbuffer &&
+ !currentDrawable->visible) {
retrace::warning(call) << "could not infer drawable size (glViewport never called)\n";
}
+
+ if (curMetricBackend) {
+ curMetricBackend->beginQuery(QUERY_BOUNDARY_FRAME);
+ }
}
+void
+beforeContextSwitch()
+{
+ if (profilingContextAcquired && retrace::profilingWithBackends &&
+ curMetricBackend)
+ {
+ curMetricBackend->pausePass();
+ }
+}
+
+void
+afterContextSwitch()
+{
+
+ if (retrace::profilingListMetrics) {
+ listMetricsCLI();
+ exit(0);
+ }
+
+ if (retrace::profilingWithBackends) {
+ if (!metricBackendsSetup) {
+ if (retrace::profilingCallsMetricsString) {
+ enableMetricsFromCLI(retrace::profilingCallsMetricsString,
+ QUERY_BOUNDARY_CALL);
+ }
+ if (retrace::profilingFramesMetricsString) {
+ enableMetricsFromCLI(retrace::profilingFramesMetricsString,
+ QUERY_BOUNDARY_FRAME);
+ }
+ if (retrace::profilingDrawCallsMetricsString) {
+ enableMetricsFromCLI(retrace::profilingDrawCallsMetricsString,
+ QUERY_BOUNDARY_DRAWCALL);
+ }
+ unsigned numPasses = 0;
+ for (auto &b : metricBackends) {
+ b->generatePasses();
+ numPasses += b->getNumPasses();
+ }
+ retrace::numPasses = numPasses > 0 ? numPasses : 1;
+ if (retrace::profilingNumPasses) {
+ std::cout << retrace::numPasses << std::endl;
+ exit(0);
+ }
+ metricBackendsSetup = true;
+ }
+
+ if (!profilingContextAcquired) {
+ unsigned numPasses = 0;
+ for (auto &b : metricBackends) {
+ numPasses += b->getNumPasses();
+ if (retrace::curPass < numPasses) {
+ curMetricBackend = b;
+ b->beginPass(); // begin pass
+ break;
+ }
+ }
+
+ if (curMetricBackend) {
+ curMetricBackend->beginQuery(QUERY_BOUNDARY_FRAME);
+ }
+
+ profilingContextAcquired = true;
+ return;
+ }
+
+ if (curMetricBackend) {
+ curMetricBackend->continuePass();
+ }
+ }
+}
-// Limit messages
-// TODO: expose this via a command line option.
-static const unsigned
-maxMessageCount = 100;
static std::map< uint64_t, unsigned > messageCounts;
@@ -394,6 +654,11 @@ debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
source == GL_DEBUG_SOURCE_APPLICATION) {
return;
}
+ if (retrace::markers &&
+ source == GL_DEBUG_SOURCE_THIRD_PARTY &&
+ id == APITRACE_MARKER_ID) {
+ return;
+ }
/* Ignore NVIDIA's "Buffer detailed info:" messages, as they seem to be
* purely informative, and high frequency. */
@@ -410,7 +675,7 @@ debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
+ ((uint64_t)type << 32)
+ ((uint64_t)source << 48);
size_t messageCount = messageCounts[messageHash]++;
- if (messageCount > maxMessageCount) {
+ if (messageCount > maxWarningCount) {
return;
}
@@ -437,23 +702,22 @@ debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
assert(0);
}
- std::cerr << *color << retrace::callNo << ": message:" << severityStr;
-
+ const char *sourceStr = "";
switch (source) {
case GL_DEBUG_SOURCE_API:
- std::cerr << " api";
+ sourceStr = " api";
break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
- std::cerr << " window system";
+ sourceStr = " window system";
break;
case GL_DEBUG_SOURCE_SHADER_COMPILER:
- std::cerr << " shader compiler";
+ sourceStr = " shader compiler";
break;
case GL_DEBUG_SOURCE_THIRD_PARTY:
- std::cerr << " third party";
+ sourceStr = " third party";
break;
case GL_DEBUG_SOURCE_APPLICATION:
- std::cerr << " application";
+ sourceStr = " application";
break;
case GL_DEBUG_SOURCE_OTHER:
break;
@@ -461,44 +725,56 @@ debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
assert(0);
}
+ const char *typeStr = "";
switch (type) {
case GL_DEBUG_TYPE_ERROR:
- std::cerr << " error";
+ typeStr = " error";
break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
- std::cerr << " deprecated behaviour";
+ typeStr = " deprecated behaviour";
break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
- std::cerr << " undefined behaviour";
+ typeStr = " undefined behaviour";
break;
case GL_DEBUG_TYPE_PORTABILITY:
- std::cerr << " portability issue";
+ typeStr = " portability issue";
break;
case GL_DEBUG_TYPE_PERFORMANCE:
- std::cerr << " performance issue";
+ typeStr = " performance issue";
break;
default:
assert(0);
/* fall-through */
case GL_DEBUG_TYPE_OTHER:
- std::cerr << " issue";
+ typeStr = " issue";
break;
case GL_DEBUG_TYPE_MARKER:
- std::cerr << " marker";
+ typeStr = " marker";
break;
case GL_DEBUG_TYPE_PUSH_GROUP:
- std::cerr << " push group";
+ typeStr = " push group";
break;
case GL_DEBUG_TYPE_POP_GROUP:
- std::cerr << " pop group";
+ typeStr = " pop group";
break;
}
+ std::cerr << *color << retrace::callNo << ": message:" << severityStr << sourceStr << typeStr;
+
if (id) {
std::cerr << " " << id;
}
- std::cerr << ": " << message;
+ std::cerr << ": ";
+
+ if (messageCount == maxWarningCount) {
+ std::cerr << "too many identical messages; ignoring"
+ << highlighter.normal()
+ << std::endl;
+ return;
+ }
+
+ std::cerr << message;
std::cerr << highlighter.normal();
@@ -509,12 +785,6 @@ debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
message[messageLen - 1] != '\r')) {
std::cerr << std::endl;
}
-
- if (messageCount == maxMessageCount) {
- std::cerr << retrace::callNo
- << ": warning: too many identical messages; ignoring"
- << std::endl;
- }
}
} /* namespace glretrace */
@@ -531,27 +801,20 @@ public:
}
bool
- dumpState(std::ostream &os) {
+ canDump(void) {
glretrace::Context *currentContext = glretrace::getCurrentContext();
- if (glretrace::insideGlBeginEnd ||
- !currentContext) {
+ if (!currentContext ||
+ currentContext->insideBeginEnd) {
return false;
}
- if (glretrace::supportsDebugOutput) {
- // Our state dump generates lots of errors as it often tries to get
- // state that's not supported, so silence debug messages temporarily.
- glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_FALSE);
- }
-
- glstate::dumpCurrentContext(os);
-
- if (glretrace::supportsDebugOutput) {
- glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
- }
-
return true;
}
+
+ void
+ dumpState(StateWriter &writer) {
+ glstate::dumpCurrentContext(writer);
+ }
};
static GLDumper glDumper;
@@ -560,7 +823,7 @@ static GLDumper glDumper;
void
retrace::setFeatureLevel(const char *featureLevel)
{
- glretrace::defaultProfile = glws::PROFILE_3_2_CORE;
+ glretrace::defaultProfile = glprofile::Profile(glprofile::API_GL, 3, 2, true);
}
@@ -592,10 +855,39 @@ retrace::flushRendering(void) {
void
retrace::finishRendering(void) {
+ if (profilingWithBackends && glretrace::curMetricBackend) {
+ (glretrace::curMetricBackend)->endQuery(QUERY_BOUNDARY_FRAME);
+ }
+ if (glretrace::profilingBoundaries[QUERY_BOUNDARY_FRAME]) {
+ if (glretrace::isLastPass() && glretrace::curMetricBackend) {
+ glretrace::profiler.addQuery(QUERY_BOUNDARY_FRAME,
+ glretrace::profilingBoundariesIndex[QUERY_BOUNDARY_FRAME]++);
+ }
+ }
+
glretrace::Context *currentContext = glretrace::getCurrentContext();
if (currentContext) {
glFinish();
}
+
+ if (retrace::profilingWithBackends) {
+ if (glretrace::curMetricBackend) {
+ (glretrace::curMetricBackend)->endPass();
+ glretrace::profilingContextAcquired = false;
+ }
+
+ if (glretrace::isLastPass()) {
+ if (glretrace::profilingBoundaries[QUERY_BOUNDARY_FRAME]) {
+ glretrace::profiler.writeAll(QUERY_BOUNDARY_FRAME);
+ }
+ if (glretrace::profilingBoundaries[QUERY_BOUNDARY_CALL]) {
+ glretrace::profiler.writeAll(QUERY_BOUNDARY_CALL);
+ }
+ if (glretrace::profilingBoundaries[QUERY_BOUNDARY_DRAWCALL]) {
+ glretrace::profiler.writeAll(QUERY_BOUNDARY_DRAWCALL);
+ }
+ }
+ }
}
void
diff --git a/retrace/glretrace_wgl.cpp b/retrace/glretrace_wgl.cpp
index 44726d23..6c139791 100644
--- a/retrace/glretrace_wgl.cpp
+++ b/retrace/glretrace_wgl.cpp
@@ -24,6 +24,8 @@
**************************************************************************/
+#include "glretrace_wgl.hpp"
+
#include "glproc.hpp"
#include "retrace.hpp"
#include "glretrace.hpp"
@@ -145,7 +147,7 @@ static void retrace_wglShareLists(trace::Call &call) {
Context *share_context = getContext(hglrc1);
Context *old_context = getContext(hglrc2);
- glws::Profile profile = old_context->wsContext->profile;
+ glprofile::Profile profile = old_context->profile();
Context *new_context = glretrace::createContext(share_context, profile);
if (new_context) {
glretrace::Context *currentContext = glretrace::getCurrentContext();
@@ -167,6 +169,36 @@ static void retrace_wglSwapLayerBuffers(trace::Call &call) {
retrace_wglSwapBuffers(call);
}
+#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
+#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
+#define WGL_TEXTURE_FORMAT_ARB 0x2072
+#define WGL_TEXTURE_TARGET_ARB 0x2073
+#define WGL_MIPMAP_TEXTURE_ARB 0x2074
+#define WGL_TEXTURE_RGB_ARB 0x2075
+#define WGL_TEXTURE_RGBA_ARB 0x2076
+#define WGL_NO_TEXTURE_ARB 0x2077
+#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078
+#define WGL_TEXTURE_1D_ARB 0x2079
+#define WGL_TEXTURE_2D_ARB 0x207A
+#define WGL_NO_TEXTURE_ARB 0x2077
+#define WGL_MIPMAP_LEVEL_ARB 0x207B
+#define WGL_CUBE_MAP_FACE_ARB 0x207C
+#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
+#define WGL_FRONT_LEFT_ARB 0x2083
+#define WGL_FRONT_RIGHT_ARB 0x2084
+#define WGL_BACK_LEFT_ARB 0x2085
+#define WGL_BACK_RIGHT_ARB 0x2086
+#define WGL_AUX0_ARB 0x2087
+#define WGL_AUX1_ARB 0x2088
+#define WGL_AUX2_ARB 0x2089
+#define WGL_AUX3_ARB 0x208A
+#define WGL_AUX4_ARB 0x208B
+#define WGL_AUX5_ARB 0x208C
+#define WGL_AUX6_ARB 0x208D
+#define WGL_AUX7_ARB 0x208E
+#define WGL_AUX8_ARB 0x208F
+#define WGL_AUX9_ARB 0x2090
+
static void retrace_wglCreatePbufferARB(trace::Call &call) {
unsigned long long orig_pbuffer = call.ret->toUIntPtr();
if (!orig_pbuffer) {
@@ -175,8 +207,54 @@ static void retrace_wglCreatePbufferARB(trace::Call &call) {
int iWidth = call.arg(2).toUInt();
int iHeight = call.arg(3).toUInt();
+ const trace::Value *attribs = &call.arg(4);
+ glws::pbuffer_info pbInfo = {0, 0, false};
+
+ // XXX parse attrib list to populate pbInfo
+ int k;
+
+ k = parseAttrib(attribs, WGL_TEXTURE_FORMAT_ARB, WGL_NO_TEXTURE_ARB);
+ switch (k) {
+ case WGL_TEXTURE_RGB_ARB:
+ pbInfo.texFormat = GL_RGB;
+ break;
+ case WGL_TEXTURE_RGBA_ARB:
+ pbInfo.texFormat = GL_RGBA;
+ break;
+ case WGL_NO_TEXTURE_ARB:
+ pbInfo.texFormat = GL_NONE;
+ break;
+ default:
+ std::cerr << "error: invalid value for WGL_TEXTURE_FORMAT_ARB\n";
+ pbInfo.texFormat = GL_NONE;
+ }
+
+ k = parseAttrib(attribs, WGL_TEXTURE_TARGET_ARB, WGL_NO_TEXTURE_ARB);
+ switch (k) {
+ case WGL_TEXTURE_CUBE_MAP_ARB:
+ pbInfo.texTarget = GL_TEXTURE_CUBE_MAP;
+ break;
+ case WGL_TEXTURE_1D_ARB:
+ pbInfo.texTarget = GL_TEXTURE_1D;
+ break;
+ case WGL_TEXTURE_2D_ARB:
+ pbInfo.texTarget = GL_TEXTURE_2D;
+ break;
+ case WGL_NO_TEXTURE_ARB:
+ pbInfo.texTarget = GL_NONE;
+ break;
+ default:
+ std::cerr << "error: invalid value for WGL_TEXTURE_TARGET_ARB\n";
+ pbInfo.texTarget = GL_NONE;
+ }
+
+ pbInfo.texMipmap = !!parseAttrib(attribs, WGL_MIPMAP_TEXTURE_ARB, 0);
+
+ // WGL interface needs the HDC
+ pbInfo.hdc_drawable = getDrawable(call.arg(0).toUInt());
- glws::Drawable *drawable = glretrace::createPbuffer(iWidth, iHeight);
+ glws::Drawable *drawable = glretrace::createPbuffer(iWidth, iHeight,
+ &pbInfo);
pbuffer_map[orig_pbuffer] = drawable;
}
@@ -201,14 +279,136 @@ static void retrace_wglCreateContextAttribsARB(trace::Call &call) {
Context *share_context = getContext(call.arg(1).toUIntPtr());
const trace::Value * attribList = &call.arg(2);
- glws::Profile profile = parseContextAttribList(attribList);
+ glprofile::Profile profile = parseContextAttribList(attribList);
Context *context = glretrace::createContext(share_context, profile);
context_map[orig_context] = context;
}
+
+static GLenum
+wgl_buffer_to_enum(int iBuffer)
+{
+ switch (iBuffer) {
+ case WGL_FRONT_LEFT_ARB:
+ return GL_FRONT_LEFT;
+ case WGL_BACK_LEFT_ARB:
+ return GL_BACK_LEFT;
+ case WGL_FRONT_RIGHT_ARB:
+ return GL_FRONT_RIGHT;
+ case WGL_BACK_RIGHT_ARB:
+ return GL_BACK_RIGHT;
+ case WGL_AUX0_ARB:
+ return GL_AUX0;
+ default:
+ std::cerr << "error: invalid iBuffer in wgl_buffer_to_enum()\n";
+ return GL_FRONT_LEFT;
+ }
+}
+
+static void retrace_wglBindTexImageARB(trace::Call &call) {
+ glws::Drawable *pbuffer = pbuffer_map[call.arg(0).toUIntPtr()];
+ signed long long iBuffer = call.arg(1).toSInt();
+
+ glretrace::bindTexImage(pbuffer, wgl_buffer_to_enum(iBuffer));
+}
+
+static void retrace_wglReleaseTexImageARB(trace::Call &call) {
+ glws::Drawable *pbuffer = pbuffer_map[call.arg(0).toUIntPtr()];
+ signed long long iBuffer = call.arg(1).toSInt();
+
+ glretrace::releaseTexImage(pbuffer, wgl_buffer_to_enum(iBuffer));
+}
+
+static void retrace_wglSetPbufferAttribARB(trace::Call &call) {
+ glws::Drawable *pbuffer = pbuffer_map[call.arg(0).toUIntPtr()];
+ const trace::Value * attribList = &call.arg(1);
+
+ // call the window system's setPbufferAttrib function.
+ {
+ int attribs[100], j = 0;
+ const trace::Array *attribs_ = attribList ? attribList->toArray() : NULL;
+
+ for (size_t i = 0; i + 1 < attribs_->values.size(); i += 2) {
+ int param_i = attribs_->values[i]->toSInt();
+ if (param_i == 0) {
+ attribs[j] = 0;
+ }
+
+ attribs[j] = param_i;
+ attribs[j+1] = attribs_->values[i+1]->toSInt();
+ }
+
+ glretrace::setPbufferAttrib(pbuffer, attribs);
+ }
+
+ if (!pbuffer || !attribList)
+ return;
+
+ // Update the glws::Drawable's fields
+ const int undefined = -99999;
+ int val;
+
+ val = parseAttrib(attribList, WGL_MIPMAP_LEVEL_ARB, undefined);
+ if (val != undefined) {
+ pbuffer->mipmapLevel = val;
+ }
+
+ val = parseAttrib(attribList, WGL_CUBE_MAP_FACE_ARB, undefined);
+ if (val != undefined) {
+ // Drawable::cubeFace is integer in [0..5]
+ val -= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
+ if (val < 0 || val > 5) {
+ fprintf(stderr, "Invalid WGL_CUBE_MAP_FACE_ARB value!\n");
+ }
+ else {
+ pbuffer->cubeFace = val;
+ }
+ }
+}
+
+
+static void retrace_wglUseFontBitmapsAW(trace::Call &call)
+{
+ bool ret = call.ret->toBool();
+ if (!ret) {
+ return;
+ }
+
+ uint32_t first = call.arg(1).toUInt();
+ uint32_t count = call.arg(2).toUInt();
+ uint32_t listBase = call.arg(3).toUInt();
+
+ GLint row_length = 0;
+ GLint alignment = 4;
+ _glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
+ _glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
+
+ for (uint32_t i = 0; i < count; ++i) {
+ uint32_t dwChar = (first + i) % 256;
+ const Bitmap *bm = &wglSystemFontBitmaps[dwChar];
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, bm->width);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ glNewList(listBase + i, GL_COMPILE);
+
+ glBitmap(bm->width, bm->height,
+ bm->xorig, bm->yorig, bm->xmove, bm->ymove,
+ (const GLubyte *)bm->pixels);
+
+ glEndList();
+ }
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+}
+
+
+
const retrace::Entry glretrace::wgl_callbacks[] = {
{"glAddSwapHintRectWIN", &retrace::ignore},
+ {"wglBindTexImageARB", &retrace_wglBindTexImageARB},
{"wglChoosePixelFormat", &retrace::ignore},
{"wglChoosePixelFormatARB", &retrace::ignore},
{"wglChoosePixelFormatEXT", &retrace::ignore},
@@ -239,13 +439,15 @@ const retrace::Entry glretrace::wgl_callbacks[] = {
{"wglMakeCurrent", &retrace_wglMakeCurrent},
{"wglQueryPbufferARB", &retrace::ignore},
{"wglReleasePbufferDCARB", &retrace::ignore},
- {"wglReleaseTexImageARB", &retrace::ignore},
- {"wglSetPbufferAttribARB", &retrace::ignore},
+ {"wglReleaseTexImageARB", &retrace_wglReleaseTexImageARB},
+ {"wglSetPbufferAttribARB", &retrace_wglSetPbufferAttribARB},
{"wglSetPixelFormat", &retrace::ignore},
{"wglShareLists", &retrace_wglShareLists},
{"wglSwapBuffers", &retrace_wglSwapBuffers},
{"wglSwapIntervalEXT", &retrace::ignore},
{"wglSwapLayerBuffers", &retrace_wglSwapLayerBuffers},
+ {"wglUseFontBitmapsA", &retrace_wglUseFontBitmapsAW},
+ {"wglUseFontBitmapsW", &retrace_wglUseFontBitmapsAW},
{NULL, NULL}
};
diff --git a/retrace/glretrace_wgl.hpp b/retrace/glretrace_wgl.hpp
new file mode 100644
index 00000000..ba5219d0
--- /dev/null
+++ b/retrace/glretrace_wgl.hpp
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * Copyright 2016 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+#include "glimports.hpp"
+
+
+struct Bitmap {
+ GLsizei width;
+ GLsizei height;
+ GLfloat xorig;
+ GLfloat yorig;
+ GLfloat xmove;
+ GLfloat ymove;
+ const char * pixels;
+};
+
+extern const Bitmap wglSystemFontBitmaps[256];
diff --git a/retrace/glretrace_wgl_font.cpp b/retrace/glretrace_wgl_font.cpp
new file mode 100755
index 00000000..4fd0310d
--- /dev/null
+++ b/retrace/glretrace_wgl_font.cpp
@@ -0,0 +1,4896 @@
+/**************************************************************************
+ *
+ * Copyright 2016 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "glretrace_wgl.hpp"
+
+
+const Bitmap
+wglSystemFontBitmaps[256] = {
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\xFC\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0F\xC0\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xFC\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x7F\x80\x00\x00"
+ "\x7F\x80\x00\x00"
+ "\x7F\x80\x00\x00"
+ "\x7F\x80\x00\x00"
+ "\x3F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\xE3\x80\x00\x00"
+ "\xC1\x80\x00\x00"
+ "\xC1\x80\x00\x00"
+ "\xC1\x80\x00\x00"
+ "\xC1\x80\x00\x00"
+ "\xE1\x80\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x07\x80\x00\x00"
+ "\x0F\x80\x00\x00"
+ "\x01\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\xE0\x00\x00\x00"
+ "\x73\x80\x00\x00"
+ "\x33\xC0\x00\x00"
+ "\x30\xC0\x00\x00"
+ "\x30\xC0\x00\x00"
+ "\x30\xC0\x00\x00"
+ "\x3C\xC0\x00\x00"
+ "\x3F\xC0\x00\x00"
+ "\x37\xC0\x00\x00"
+ "\x3E\xC0\x00\x00"
+ "\x1F\xC0\x00\x00"
+ "\x01\xC0\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\xCD\x80\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x37\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\xE3\x80\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x37\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\xCD\x80\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\xFF\xC0\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x01\x80\x00\x00"
+ "\x07\x80\x00\x00"
+ "\x0F\x80\x00\x00"
+ "\x1F\x80\x00\x00"
+ "\x7F\x80\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\x7F\x80\x00\x00"
+ "\x1F\x80\x00\x00"
+ "\x0F\x80\x00\x00"
+ "\x03\x80\x00\x00"
+ "\x01\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0D\x80\x00\x00"
+ "\x0D\x80\x00\x00"
+ "\x0D\x80\x00\x00"
+ "\x0D\x80\x00\x00"
+ "\x0D\x80\x00\x00"
+ "\x0D\x80\x00\x00"
+ "\x0D\x80\x00\x00"
+ "\x3D\x80\x00\x00"
+ "\xED\x80\x00\x00"
+ "\xCD\x80\x00\x00"
+ "\xCD\x80\x00\x00"
+ "\xED\x80\x00\x00"
+ "\x3F\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xFF\xC0\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\xFF\xC0\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\xFC\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x3F\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0F\xC0\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x03\x00\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\x07\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 6.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\xFE\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 11.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC1\xC0\x00\x00"
+ "\x63\x60\x00\x00"
+ "\x33\x60\x00\x00"
+ "\x1B\x60\x00\x00"
+ "\x0D\xC0\x00\x00"
+ "\x76\x00\x00\x00"
+ "\xDB\x00\x00\x00"
+ "\xD9\x80\x00\x00"
+ "\xD8\xC0\x00\x00"
+ "\x70\x60\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3F\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x67\x00\x00\x00"
+ "\x6D\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\xC0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 6.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x48\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\xFC\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xF0\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x0E\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 14.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x07\xC0\x00\x00"
+ "\x1C\x70\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x36\xF0\x00\x00"
+ "\x6D\x98\x00\x00"
+ "\x6D\x98\x00\x00"
+ "\x6C\xD8\x00\x00"
+ "\x66\xD8\x00\x00"
+ "\x66\xD8\x00\x00"
+ "\x33\xB0\x00\x00"
+ "\x30\x30\x00\x00"
+ "\x1C\xE0\x00\x00"
+ "\x07\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x61\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x80\x00\x00"
+ "\x31\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x67\x80\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x80\x00\x00"
+ "\x31\x80\x00\x00"
+ "\x1F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x7F\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 7.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\xCC\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 12.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x6F\x60\x00\x00"
+ "\x6F\x60\x00\x00"
+ "\x79\xE0\x00\x00"
+ "\x79\xE0\x00\x00"
+ "\x70\xE0\x00\x00"
+ "\x70\xE0\x00\x00"
+ "\x60\x60\x00\x00"
+ "\x60\x60\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x63\x80\x00\x00"
+ "\x67\x80\x00\x00"
+ "\x67\x80\x00\x00"
+ "\x6D\x80\x00\x00"
+ "\x6D\x80\x00\x00"
+ "\x79\x80\x00\x00"
+ "\x79\x80\x00\x00"
+ "\x71\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1F\x80\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x67\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\xC0\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x03\x00\x00\x00"
+ "\x0E\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\xFF\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 14.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x60\x00\x00"
+ "\x18\x60\x00\x00"
+ "\x18\x60\x00\x00"
+ "\x3C\xF0\x00\x00"
+ "\x34\xB0\x00\x00"
+ "\x67\x98\x00\x00"
+ "\x67\x98\x00\x00"
+ "\xC3\x0C\x00\x00"
+ "\xC3\x0C\x00\x00"
+ "\xC3\x0C\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC1\x80\x00\x00"
+ "\xC1\x80\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\xC1\x80\x00\x00"
+ "\xC1\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\xC0\xC0\x00\x00"
+ "\xC0\xC0\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x03\x00\x00\x00"
+ "\x01\x80\x00\x00"
+ "\xFF\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x70\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\xE0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xE0\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xD8\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x20\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\xFF\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 7.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xF0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\xC0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 7.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 12.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x7F\xC0\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xF0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x7F\x80\x00\x00"
+ "\x6D\x80\x00\x00"
+ "\x6D\x80\x00\x00"
+ "\xCC\xC0\x00\x00"
+ "\xC0\xC0\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x18\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\xC0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xB8\x00\x00\x00"
+ "\xE8\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x76\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x68\x00\x00\x00"
+ "\x68\x00\x00\x00"
+ "\x6E\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\xFF\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\xFF\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xD8\x00\x00\x00"
+ "\xD8\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3F\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\xCC\xC0\x00\x00"
+ "\xD2\xC0\x00\x00"
+ "\xD0\xC0\x00\x00"
+ "\xD0\xC0\x00\x00"
+ "\xD2\xC0\x00\x00"
+ "\xCC\xC0\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x3F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x50\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x10\x00\x00\x00"
+ "\x20\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 7.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\xD8\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xF0\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3F\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\xD2\xC0\x00\x00"
+ "\xD4\xC0\x00\x00"
+ "\xDC\xC0\x00\x00"
+ "\xD2\xC0\x00\x00"
+ "\xD2\xC0\x00\x00"
+ "\xDC\xC0\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x3F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xFF\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x50\x00\x00\x00"
+ "\x50\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xF0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\xB0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xB0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xB0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 7.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x70\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xE0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 5.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x50\x00\x00\x00"
+ "\x50\x00\x00\x00"
+ "\x50\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 7.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xD8\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\xD8\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 11.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC0\xC0\x00\x00"
+ "\x63\xC0\x00\x00"
+ "\x33\x40\x00\x00"
+ "\x19\xC0\x00\x00"
+ "\x0C\xC0\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x31\x80\x00\x00"
+ "\x70\xC0\x00\x00"
+ "\x30\x60\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 11.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC3\xC0\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x30\xC0\x00\x00"
+ "\x1A\xC0\x00\x00"
+ "\x0D\x80\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x31\x80\x00\x00"
+ "\x70\xC0\x00\x00"
+ "\x30\x60\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 11.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC0\xC0\x00\x00"
+ "\x63\xC0\x00\x00"
+ "\x33\x40\x00\x00"
+ "\x19\xC0\x00\x00"
+ "\x0C\xC0\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x5B\x00\x00\x00"
+ "\x31\x80\x00\x00"
+ "\x58\xC0\x00\x00"
+ "\x30\x60\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x5E\x00\x00\x00"
+ "\x7A\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x24\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 13.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC7\xF0\x00\x00"
+ "\xC6\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x37\xE0\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x1F\xF0\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x1C\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x61\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0E\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7F\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x90\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x90\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\xF9\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x63\x80\x00\x00"
+ "\x67\x80\x00\x00"
+ "\x67\x80\x00\x00"
+ "\x6D\x80\x00\x00"
+ "\x6D\x80\x00\x00"
+ "\x79\x80\x00\x00"
+ "\x79\x80\x00\x00"
+ "\x71\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x2F\x00\x00\x00"
+ "\x3D\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0E\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x2F\x00\x00\x00"
+ "\x3D\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x71\x80\x00\x00"
+ "\x79\x80\x00\x00"
+ "\x6D\x80\x00\x00"
+ "\x6D\x80\x00\x00"
+ "\x67\x80\x00\x00"
+ "\x63\x80\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1F\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x06\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0E\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x61\x80\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 10.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x33\x00\x00\x00"
+ "\x61\x80\x00\x00"
+ "\xC0\xC0\x00\x00"
+ "\xC0\xC0\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x0E\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 9.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x63\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x5E\x00\x00\x00"
+ "\x7A\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 12.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3F\xC0\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x36\x00\x00\x00"
+ "\x1F\xE0\x00\x00"
+ "\x66\x60\x00\x00"
+ "\x3F\xC0\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 7.0f, 0.0f,
+ "\x38\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\xE0\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xC0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x70\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\xF0\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 4.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x90\x00\x00\x00"
+ "\x90\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x6C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x76\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x5E\x00\x00\x00"
+ "\x7A\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x5E\x00\x00\x00"
+ "\x7A\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 6.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x78\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x76\x00\x00\x00"
+ "\x76\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x6E\x00\x00\x00"
+ "\x6E\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x0C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x38\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x3E\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x1C\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x7C\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x60\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ },
+ {
+ 32, 16, 0.0f, 3.0f, 8.0f, 0.0f,
+ "\x60\x00\x00\x00"
+ "\x30\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x18\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x3C\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\xC3\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x66\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ }
+};
diff --git a/retrace/glretrace_ws.cpp b/retrace/glretrace_ws.cpp
index bcf298c8..6ab2f18b 100644
--- a/retrace/glretrace_ws.cpp
+++ b/retrace/glretrace_ws.cpp
@@ -44,13 +44,13 @@
namespace glretrace {
-static std::map<glws::Profile, glws::Visual *>
+static std::map<glprofile::Profile, glws::Visual *>
visuals;
inline glws::Visual *
-getVisual(glws::Profile profile) {
- std::map<glws::Profile, glws::Visual *>::iterator it = visuals.find(profile);
+getVisual(glprofile::Profile profile) {
+ std::map<glprofile::Profile, glws::Visual *>::iterator it = visuals.find(profile);
if (it == visuals.end()) {
glws::Visual *visual = NULL;
unsigned samples = retrace::samples;
@@ -76,20 +76,24 @@ getVisual(glws::Profile profile) {
static glws::Drawable *
-createDrawableHelper(glws::Profile profile, int width = 32, int height = 32, bool pbuffer = false) {
+createDrawableHelper(glprofile::Profile profile, int width = 32, int height = 32,
+ const glws::pbuffer_info *pbInfo = NULL) {
glws::Visual *visual = getVisual(profile);
- glws::Drawable *draw = glws::createDrawable(visual, width, height, pbuffer);
+ glws::Drawable *draw = glws::createDrawable(visual, width, height, pbInfo);
if (!draw) {
std::cerr << "error: failed to create OpenGL drawable\n";
exit(1);
}
+ if (pbInfo)
+ draw->pbInfo = *pbInfo;
+
return draw;
}
glws::Drawable *
-createDrawable(glws::Profile profile) {
+createDrawable(glprofile::Profile profile) {
return createDrawableHelper(profile);
}
@@ -101,20 +105,24 @@ createDrawable(void) {
glws::Drawable *
-createPbuffer(int width, int height) {
- return createDrawableHelper(defaultProfile, width, height, true);
+createPbuffer(int width, int height, const glws::pbuffer_info *pbInfo) {
+ // Zero area pbuffers are often accepted, but given we create window
+ // drawables instead, they should have non-zero area.
+ width = std::max(width, 1);
+ height = std::max(height, 1);
+
+ return createDrawableHelper(defaultProfile, width, height, pbInfo);
}
Context *
-createContext(Context *shareContext, glws::Profile profile) {
+createContext(Context *shareContext, glprofile::Profile profile) {
glws::Visual *visual = getVisual(profile);
glws::Context *shareWsContext = shareContext ? shareContext->wsContext : NULL;
glws::Context *ctx = glws::createContext(visual, shareWsContext, retrace::debug);
if (!ctx) {
- std::cerr << "error: failed to create OpenGL context\n";
+ std::cerr << "error: failed to create " << profile << " context.\n";
exit(1);
- return NULL;
}
return new Context(ctx);
@@ -136,7 +144,7 @@ Context::~Context()
}
-static OS_THREAD_SPECIFIC_PTR(Context)
+OS_THREAD_SPECIFIC_PTR(Context)
currentContextPtr;
@@ -159,12 +167,13 @@ makeCurrent(trace::Call &call, glws::Drawable *drawable, Context *context)
flushQueries();
+ beforeContextSwitch();
+
bool success = glws::makeCurrent(drawable, context ? context->wsContext : NULL);
if (!success) {
std::cerr << "error: failed to make current OpenGL context and drawable\n";
exit(1);
- return false;
}
currentContextPtr = context;
@@ -178,13 +187,9 @@ makeCurrent(trace::Call &call, glws::Drawable *drawable, Context *context)
}
}
- return true;
-}
-
+ afterContextSwitch();
-Context *
-getCurrentContext(void) {
- return currentContextPtr;
+ return true;
}
@@ -202,7 +207,9 @@ updateDrawable(int width, int height) {
}
glws::Drawable *currentDrawable = currentContext->drawable;
- assert(currentDrawable);
+ if (!currentDrawable) {
+ return;
+ }
if (currentDrawable->pbuffer) {
return;
@@ -232,18 +239,31 @@ updateDrawable(int width, int height) {
currentDrawable->resize(width, height);
currentDrawable->show();
+ // Ensure the drawable dimensions, as perceived by glstate match.
+ if (retrace::debug) {
+ GLint newWidth = 0;
+ GLint newHeight = 0;
+ if (glstate::getDrawableBounds(&newWidth, &newHeight) &&
+ (newWidth != width || newHeight != height)) {
+ std::cerr
+ << "error: drawable failed to resize: "
+ << "expected " << width << "x" << height << ", "
+ << "got " << newWidth << "x" << newHeight << "\n";
+ }
+ }
+
glScissor(0, 0, width, height);
}
int
-parseAttrib(const trace::Value *attribs, int param, int default_ = 0) {
+parseAttrib(const trace::Value *attribs, int param, int default_, int terminator) {
const trace::Array *attribs_ = attribs ? attribs->toArray() : NULL;
if (attribs_) {
for (size_t i = 0; i + 1 < attribs_->values.size(); i += 2) {
int param_i = attribs_->values[i]->toSInt();
- if (param_i == 0) {
+ if (param_i == terminator) {
break;
}
@@ -261,23 +281,65 @@ parseAttrib(const trace::Value *attribs, int param, int default_ = 0) {
/**
* Parse GLX/WGL_ARB_create_context attribute list.
*/
-glws::Profile
+glprofile::Profile
parseContextAttribList(const trace::Value *attribs)
{
+ // {GLX,WGL}_CONTEXT_MAJOR_VERSION_ARB
int major_version = parseAttrib(attribs, 0x2091, 1);
+
+ // {GLX,WGL}_CONTEXT_MINOR_VERSION_ARB
int minor_version = parseAttrib(attribs, 0x2092, 0);
- int profile_mask = parseAttrib(attribs, GL_CONTEXT_PROFILE_MASK, 0);
+
+ int profile_mask = parseAttrib(attribs, GL_CONTEXT_PROFILE_MASK, GL_CONTEXT_CORE_PROFILE_BIT);
+
bool core_profile = profile_mask & GL_CONTEXT_CORE_PROFILE_BIT;
+ if (major_version < 3 ||
+ (major_version == 3 && minor_version < 2)) {
+ core_profile = false;
+ }
+
+ int context_flags = parseAttrib(attribs, GL_CONTEXT_FLAGS, 0);
+
+ bool forward_compatible = context_flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
+ if (major_version < 3) {
+ forward_compatible = false;
+ }
- glws::Profile profile = glws::PROFILE_COMPAT;
- if (major_version >= 3) {
- profile = (glws::Profile)((core_profile ? 0x100 : 0) |
- (major_version << 4) |
- minor_version);
+ // {GLX,WGL}_CONTEXT_ES_PROFILE_BIT_EXT
+ bool es_profile = profile_mask & 0x0004;
+
+ glprofile::Profile profile;
+ if (es_profile) {
+ profile.api = glprofile::API_GLES;
+ } else {
+ profile.api = glprofile::API_GL;
+ profile.core = core_profile;
+ profile.forwardCompatible = forward_compatible;
}
+ profile.major = major_version;
+ profile.minor = minor_version;
+
return profile;
}
+// WGL_ARB_render_texture / wglBindTexImageARB()
+bool
+bindTexImage(glws::Drawable *pBuffer, int iBuffer) {
+ return glws::bindTexImage(pBuffer, iBuffer);
+}
+
+// WGL_ARB_render_texture / wglReleaseTexImageARB()
+bool
+releaseTexImage(glws::Drawable *pBuffer, int iBuffer) {
+ return glws::releaseTexImage(pBuffer, iBuffer);
+}
+
+// WGL_ARB_render_texture / wglSetPbufferAttribARB()
+bool
+setPbufferAttrib(glws::Drawable *pBuffer, const int *attribs) {
+ return glws::setPbufferAttrib(pBuffer, attribs);
+}
+
} /* namespace glretrace */
diff --git a/retrace/glstate.cpp b/retrace/glstate.cpp
index 2094483d..b7e5e0f6 100644
--- a/retrace/glstate.cpp
+++ b/retrace/glstate.cpp
@@ -30,7 +30,7 @@
#include <iostream>
#include "image.hpp"
-#include "json.hpp"
+#include "state_writer.hpp"
#include "glproc.hpp"
#include "glws.hpp"
#include "glsize.hpp"
@@ -44,64 +44,30 @@ namespace glstate {
Context::Context(void) {
memset(this, 0, sizeof *this);
- const char *version = (const char *)glGetString(GL_VERSION);
- unsigned version_major = 0;
- unsigned version_minor = 0;
- unsigned version_release = 0;
- if (version) {
- if (version[0] == 'O' &&
- version[1] == 'p' &&
- version[2] == 'e' &&
- version[3] == 'n' &&
- version[4] == 'G' &&
- version[5] == 'L' &&
- version[6] == ' ' &&
- version[7] == 'E' &&
- version[8] == 'S' &&
- (version[9] == ' ' || version[9] == '-')) {
- ES = true;
- }
- if (version[0] >= '0' && version[0] <= '9') {
- sscanf(version, "%u.%u.%u", &version_major, &version_minor, &version_release);
- }
- }
+ glprofile::Profile profile = glprofile::getCurrentContextProfile();
+ glprofile::Extensions ext;
+
+ ext.getCurrentContextExtensions(profile);
+
+ ES = profile.es();
+ core = profile.core;
ARB_draw_buffers = !ES;
// Check extensions we use.
-
- if (!ES) {
- if (version_major > 3 ||
- (version_major == 3 && version_minor >= 2)) {
- GLint num_extensions = 0;
- glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
- for (GLint i = 0; i < num_extensions; ++i) {
- const char *extension = (const char *)glGetStringi(GL_EXTENSIONS, i);
- if (extension) {
- if (strcmp(extension, "GL_ARB_sampler_objects") == 0) {
- ARB_sampler_objects = true;
- } else if (strcmp(extension, "GL_KHR_debug") == 0) {
- KHR_debug = true;
- } else if (strcmp(extension, "GL_EXT_debug_label") == 0) {
- EXT_debug_label = true;
- }
- }
- }
- } else {
- const char *extensions = (const char *)glGetString(GL_EXTENSIONS);
- ARB_sampler_objects = glws::checkExtension("GL_ARB_sampler_objects", extensions);
- KHR_debug = glws::checkExtension("GL_KHR_debug", extensions);
- EXT_debug_label = glws::checkExtension("GL_EXT_debug_label", extensions);
- }
- } else {
- const char *extensions = (const char *)glGetString(GL_EXTENSIONS);
- KHR_debug = glws::checkExtension("GL_KHR_debug", extensions);
- EXT_debug_label = glws::checkExtension("GL_EXT_debug_label", extensions);
- }
+ ARB_sampler_objects = ext.has("GL_ARB_sampler_objects");
+ ARB_get_program_binary = ext.has("GL_ARB_get_program_binary");
+ KHR_debug = !ES && ext.has("GL_KHR_debug");
+ EXT_debug_label = ext.has("GL_EXT_debug_label");
+ ARB_direct_state_access = ext.has("GL_ARB_direct_state_access");
+ ARB_shader_image_load_store = ext.has("GL_ARB_shader_image_load_store");
+
+ NV_read_depth_stencil = ES && ext.has("GL_NV_read_depth_stencil");
}
-void
-Context::resetPixelPackState(void) {
+PixelPackState::PixelPackState(const Context &context) {
+ ES = context.ES;
+
// Start with default state
pack_alignment = 4;
pack_image_height = 0;
@@ -140,8 +106,7 @@ Context::resetPixelPackState(void) {
}
}
-void
-Context::restorePixelPackState(void) {
+PixelPackState::~PixelPackState() {
glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment);
if (!ES) {
glPixelStorei(GL_PACK_IMAGE_HEIGHT, pack_image_height);
@@ -156,6 +121,155 @@ Context::restorePixelPackState(void) {
}
+static GLenum
+getBufferBinding(GLenum target) {
+ switch (target) {
+ case GL_ARRAY_BUFFER:
+ return GL_ARRAY_BUFFER_BINDING;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return GL_ATOMIC_COUNTER_BUFFER_BINDING;
+ case GL_COPY_READ_BUFFER:
+ return GL_COPY_READ_BUFFER_BINDING;
+ case GL_COPY_WRITE_BUFFER:
+ return GL_COPY_WRITE_BUFFER_BINDING;
+ case GL_DRAW_INDIRECT_BUFFER:
+ return GL_DRAW_INDIRECT_BUFFER_BINDING;
+ case GL_DISPATCH_INDIRECT_BUFFER:
+ return GL_DISPATCH_INDIRECT_BUFFER_BINDING;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ return GL_ELEMENT_ARRAY_BUFFER_BINDING;
+ case GL_PIXEL_PACK_BUFFER:
+ return GL_PIXEL_PACK_BUFFER_BINDING;
+ case GL_PIXEL_UNPACK_BUFFER:
+ return GL_PIXEL_UNPACK_BUFFER_BINDING;
+ case GL_QUERY_BUFFER:
+ return GL_QUERY_BUFFER_BINDING;
+ case GL_SHADER_STORAGE_BUFFER:
+ return GL_SHADER_STORAGE_BUFFER_BINDING;
+ case GL_TEXTURE_BUFFER:
+ return GL_TEXTURE_BUFFER;
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ return GL_TRANSFORM_FEEDBACK_BUFFER_BINDING;
+ case GL_UNIFORM_BUFFER:
+ return GL_UNIFORM_BUFFER_BINDING;
+ default:
+ assert(false);
+ return GL_NONE;
+ }
+}
+
+
+BufferBinding::BufferBinding(GLenum _target, GLuint _buffer) :
+ target(_target),
+ buffer(_buffer),
+ prevBuffer(0)
+{
+ GLenum binding = getBufferBinding(target);
+ glGetIntegerv(binding, (GLint *) &prevBuffer);
+
+ if (prevBuffer != buffer) {
+ glBindBuffer(target, buffer);
+ }
+}
+
+BufferBinding::~BufferBinding() {
+ if (prevBuffer != buffer) {
+ glBindBuffer(target, prevBuffer);
+ }
+}
+
+
+BufferMapping::BufferMapping() :
+ target(GL_NONE),
+ buffer(0),
+ map_pointer(NULL),
+ unmap(false)
+{
+}
+
+GLvoid *
+BufferMapping::map(GLenum _target, GLuint _buffer)
+{
+ if (target == _target && buffer == _buffer) {
+ return map_pointer;
+ }
+
+ target = _target;
+ buffer = _buffer;
+ map_pointer = NULL;
+ unmap = false;
+
+ BufferBinding bb(target, buffer);
+
+ // Recursive mappings of the same buffer are not allowed. And with the
+ // pursuit of persistent mappings for performance this will become more
+ // and more common.
+ GLint mapped = GL_FALSE;
+ glGetBufferParameteriv(target, GL_BUFFER_MAPPED, &mapped);
+ if (mapped) {
+ glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map_pointer);
+ assert(map_pointer != NULL);
+
+ GLint map_offset = 0;
+ glGetBufferParameteriv(target, GL_BUFFER_MAP_OFFSET, &map_offset);
+ if (map_offset != 0) {
+ std::cerr << "warning: " << enumToString(target) << " buffer " << buffer << " is already mapped with offset " << map_offset << "\n";
+ // FIXME: This most likely won't work. We should remap the
+ // buffer with the full range, then re-map when done. This
+ // should never happen in practice with persistent mappings
+ // though.
+ map_pointer = (GLubyte *)map_pointer - map_offset;
+ }
+ } else {
+ map_pointer = glMapBuffer(target, GL_READ_ONLY);
+ if (map_pointer) {
+ unmap = true;
+ }
+ }
+
+ return map_pointer;
+}
+
+BufferMapping::~BufferMapping() {
+ if (unmap) {
+ BufferBinding bb(target, buffer);
+
+ GLenum ret = glUnmapBuffer(target);
+ assert(ret == GL_TRUE);
+ (void)ret;
+ }
+}
+
+
+void
+dumpBoolean(StateWriter &writer, GLboolean value)
+{
+ switch (value) {
+ case GL_FALSE:
+ writer.writeString("GL_FALSE");
+ break;
+ case GL_TRUE:
+ writer.writeString("GL_TRUE");
+ break;
+ default:
+ writer.writeInt(static_cast<GLint>(value));
+ break;
+ }
+}
+
+
+void
+dumpEnum(StateWriter &writer, GLenum pname)
+{
+ const char *s = enumToString(pname);
+ if (s) {
+ writer.writeString(s);
+ } else {
+ writer.writeInt(pname);
+ }
+}
+
+
/**
* Get a GL_KHR_debug/GL_EXT_debug_label object label.
*
@@ -223,13 +337,13 @@ getObjectLabel(Context &context, GLenum identifier, GLuint name)
* Dump a GL_KHR_debug/GL_EXT_debug_label object label.
*/
void
-dumpObjectLabel(JSONWriter &json, Context &context, GLenum identifier, GLuint name, const char *member) {
+dumpObjectLabel(StateWriter &writer, Context &context, GLenum identifier, GLuint name, const char *member) {
char *label = getObjectLabel(context, identifier, name);
if (!label) {
return;
}
- json.writeStringMember(member, label);
+ writer.writeStringMember(member, label);
free(label);
}
@@ -260,15 +374,112 @@ static const GLenum bindings[] = {
GL_DRAW_BUFFER5,
GL_DRAW_BUFFER6,
GL_DRAW_BUFFER7,
+ GL_TRANSFORM_FEEDBACK_BUFFER_BINDING,
+ GL_UNIFORM_BUFFER_BINDING,
};
#define NUM_BINDINGS sizeof(bindings)/sizeof(bindings[0])
-void dumpCurrentContext(std::ostream &os)
+static void APIENTRY
+debugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
+ GLsizei length, const GLchar* message, const void *userParam)
+{
+ const char *severityStr = "";
+ switch (severity) {
+ case GL_DEBUG_SEVERITY_HIGH:
+ severityStr = " high";
+ break;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ break;
+ case GL_DEBUG_SEVERITY_LOW:
+ severityStr = " low";
+ break;
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ /* ignore */
+ return;
+ default:
+ assert(0);
+ }
+
+ const char *sourceStr = "";
+ switch (source) {
+ case GL_DEBUG_SOURCE_API:
+ break;
+ case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ sourceStr = " window system";
+ break;
+ case GL_DEBUG_SOURCE_SHADER_COMPILER:
+ sourceStr = " shader compiler";
+ break;
+ case GL_DEBUG_SOURCE_THIRD_PARTY:
+ sourceStr = " third party";
+ break;
+ case GL_DEBUG_SOURCE_APPLICATION:
+ sourceStr = " application";
+ break;
+ case GL_DEBUG_SOURCE_OTHER:
+ break;
+ default:
+ assert(0);
+ }
+
+ const char *typeStr = "";
+ switch (type) {
+ case GL_DEBUG_TYPE_ERROR:
+ typeStr = " error";
+ break;
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ typeStr = " deprecated behaviour";
+ break;
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ typeStr = " undefined behaviour";
+ break;
+ case GL_DEBUG_TYPE_PORTABILITY:
+ typeStr = " portability issue";
+ break;
+ case GL_DEBUG_TYPE_PERFORMANCE:
+ return;
+ default:
+ assert(0);
+ /* fall-through */
+ case GL_DEBUG_TYPE_OTHER:
+ typeStr = " issue";
+ break;
+ case GL_DEBUG_TYPE_MARKER:
+ case GL_DEBUG_TYPE_PUSH_GROUP:
+ case GL_DEBUG_TYPE_POP_GROUP:
+ return;
+ }
+
+ std::cerr << "warning: message:" << severityStr << sourceStr << typeStr;
+
+ if (id) {
+ std::cerr << " " << id;
+ }
+
+ std::cerr << ": ";
+
+ std::cerr << message;
+
+ // Write new line if not included in the message already.
+ size_t messageLen = strlen(message);
+ if (!messageLen ||
+ (message[messageLen - 1] != '\n' &&
+ message[messageLen - 1] != '\r')) {
+ std::cerr << std::endl;
+ }
+
+ /* To help debug bugs in glstate. */
+ if (0) {
+ os::breakpoint();
+ }
+}
+
+
+void dumpCurrentContext(StateWriter &writer)
{
- JSONWriter json(os);
#ifndef NDEBUG
GLint old_bindings[NUM_BINDINGS];
@@ -280,10 +491,27 @@ void dumpCurrentContext(std::ostream &os)
Context context;
- dumpParameters(json, context);
- dumpShadersUniforms(json, context);
- dumpTextures(json, context);
- dumpFramebuffer(json, context);
+ /* Temporarily disable messages, as dumpParameters blindlessly tries to
+ * get state, regardless the respective extension is supported or not.
+ */
+ GLDEBUGPROC prevDebugCallbackFunction = 0;
+ void *prevDebugCallbackUserParam = 0;
+ if (context.KHR_debug) {
+ glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION, (GLvoid **) &prevDebugCallbackFunction);
+ glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM, &prevDebugCallbackUserParam);
+ glDebugMessageCallback(NULL, NULL);
+ }
+
+ dumpParameters(writer, context);
+
+ // Use our own debug-message callback.
+ if (context.KHR_debug) {
+ glDebugMessageCallback(debugMessageCallback, NULL);
+ }
+
+ dumpShadersUniforms(writer, context);
+ dumpTextures(writer, context);
+ dumpFramebuffer(writer, context);
#ifndef NDEBUG
for (unsigned i = 0; i < NUM_BINDINGS; ++i) {
@@ -295,6 +523,10 @@ void dumpCurrentContext(std::ostream &os)
}
#endif
+ // Restore debug message callback
+ if (context.KHR_debug) {
+ glDebugMessageCallback(prevDebugCallbackFunction, prevDebugCallbackUserParam);
+ }
}
diff --git a/retrace/glstate.hpp b/retrace/glstate.hpp
index 2e0df1a5..417a0328 100644
--- a/retrace/glstate.hpp
+++ b/retrace/glstate.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _GLSTATE_HPP_
-#define _GLSTATE_HPP_
+#pragma once
#include <ostream>
@@ -41,6 +40,8 @@ namespace image {
class Image;
}
+class StateWriter;
+
namespace glstate {
@@ -57,7 +58,11 @@ getTextureBinding(GLenum target);
const char *enumToString(GLenum pname);
-void dumpCurrentContext(std::ostream &os);
+void
+dumpCurrentContext(StateWriter &writer);
+
+bool
+getDrawableBounds(GLint *width, GLint *height);
image::Image *
getDrawBufferImage(void);
@@ -66,4 +71,3 @@ getDrawBufferImage(void);
} /* namespace glstate */
-#endif /* _GLSTATE_HPP_ */
diff --git a/retrace/glstate_formats.cpp b/retrace/glstate_formats.cpp
new file mode 100644
index 00000000..c7eb0716
--- /dev/null
+++ b/retrace/glstate_formats.cpp
@@ -0,0 +1,679 @@
+/**************************************************************************
+ *
+ * Copyright 2014 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "glstate_internal.hpp"
+
+#include <assert.h>
+
+#include <iostream>
+#include <limits>
+#include <type_traits>
+
+#include "glsize.hpp"
+#include "glstate.hpp"
+
+
+namespace glstate {
+
+
+/**
+ * Sames as enumToString, but with special provision to handle luminance/alpha
+ * formats.
+ *
+ * OpenGL 2.1 specification states that "internalFormat may (for backwards
+ * compatibility with the 1.0 version of the GL) also take on the integer
+ * values 1, 2, 3, and 4, which are equivalent to symbolic constants LUMINANCE,
+ * LUMINANCE ALPHA, RGB, and RGBA respectively".
+ */
+const char *
+formatToString(GLenum internalFormat) {
+ switch (internalFormat) {
+ case 1:
+ return "GL_LUMINANCE";
+ case 2:
+ return "GL_LUMINANCE_ALPHA";
+ case 3:
+ return "GL_RGB";
+ case 4:
+ return "GL_RGBA";
+ default:
+ return enumToString(internalFormat);
+ }
+}
+
+
+static const InternalFormatDesc
+internalFormatDescs[] = {
+ // GLenum internalFormat, GLenum format, GLenum type, GLenum readType
+
+ // Unsized UNORM
+ { 1, GL_RED, GL_NONE, GL_UNSIGNED_BYTE },
+ { 2, GL_RG, GL_NONE, GL_UNSIGNED_BYTE },
+ { 3, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE },
+ { 4, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RED, GL_RED, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_GREEN, GL_GREEN, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_BLUE, GL_BLUE, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RG, GL_RG, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RGB, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_BGR, GL_BGR, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RGBA, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_BGRA, GL_BGRA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_ALPHA, GL_ALPHA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_INTENSITY, GL_INTENSITY, GL_NONE, GL_UNSIGNED_BYTE },
+
+ // Unsized SNORM
+ { GL_RED_SNORM, GL_RED, GL_NONE, GL_FLOAT },
+ { GL_RG_SNORM, GL_RG, GL_NONE, GL_FLOAT },
+ { GL_RGB_SNORM, GL_RGB, GL_NONE, GL_FLOAT },
+ { GL_RGBA_SNORM, GL_RGBA, GL_NONE, GL_FLOAT },
+ { GL_LUMINANCE_SNORM, GL_LUMINANCE, GL_NONE, GL_FLOAT },
+ { GL_ALPHA_SNORM, GL_ALPHA, GL_NONE, GL_FLOAT },
+ { GL_LUMINANCE_ALPHA_SNORM, GL_LUMINANCE_ALPHA, GL_NONE, GL_FLOAT },
+ { GL_INTENSITY_SNORM, GL_INTENSITY, GL_NONE, GL_FLOAT },
+
+ // 4-bit UNORM
+ { GL_RGB4, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RGBA4, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE4, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_ALPHA4, GL_ALPHA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_INTENSITY4, GL_INTENSITY, GL_NONE, GL_UNSIGNED_BYTE },
+
+ // 8-bit UNORM
+ { GL_R8, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_RG8, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_BGRA8_EXT, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_INTENSITY8, GL_INTENSITY, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+
+ // 8-bit SNORM
+ { GL_R8_SNORM, GL_RED, GL_BYTE, GL_FLOAT },
+ { GL_RG8_SNORM, GL_RG, GL_BYTE, GL_FLOAT },
+ { GL_RGB8_SNORM, GL_RGB, GL_BYTE, GL_FLOAT },
+ { GL_RGBA8_SNORM, GL_RGBA, GL_BYTE, GL_FLOAT },
+ { GL_LUMINANCE8_SNORM, GL_LUMINANCE, GL_BYTE, GL_FLOAT },
+ { GL_ALPHA8_SNORM, GL_ALPHA, GL_BYTE, GL_FLOAT },
+ { GL_LUMINANCE8_ALPHA8_SNORM, GL_LUMINANCE_ALPHA, GL_BYTE, GL_FLOAT },
+ { GL_INTENSITY8_SNORM, GL_INTENSITY, GL_BYTE, GL_FLOAT },
+
+ // Other UNORM
+ { GL_R3_G3_B2, GL_RGB, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_BYTE },
+ { GL_RGB4, GL_RGB, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_BYTE },
+ { GL_RGB5, GL_RGB, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_BYTE },
+ { GL_RGB10, GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_BYTE },
+ { GL_RGB12, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RGBA2, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_BYTE },
+ { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_BYTE },
+ { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_BYTE },
+ { GL_RGBA12, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+
+ // 16-bit UNORM
+ { GL_R16, GL_RED, GL_UNSIGNED_SHORT, GL_FLOAT },
+ { GL_RG16, GL_RG, GL_UNSIGNED_SHORT, GL_FLOAT },
+ { GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT, GL_FLOAT },
+ { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, GL_FLOAT },
+ { GL_LUMINANCE16, GL_LUMINANCE, GL_UNSIGNED_SHORT, GL_FLOAT },
+ { GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT, GL_FLOAT },
+ { GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT, GL_FLOAT },
+ { GL_INTENSITY16, GL_INTENSITY, GL_UNSIGNED_SHORT, GL_FLOAT },
+
+ // 16-bit SNORM
+ { GL_R16_SNORM, GL_RED, GL_SHORT, GL_FLOAT },
+ { GL_RG16_SNORM, GL_RG, GL_SHORT, GL_FLOAT },
+ { GL_RGB16_SNORM, GL_RGB, GL_SHORT, GL_FLOAT },
+ { GL_RGBA16_SNORM, GL_RGBA, GL_SHORT, GL_FLOAT },
+ { GL_LUMINANCE16_SNORM, GL_LUMINANCE, GL_SHORT, GL_FLOAT },
+ { GL_ALPHA16_SNORM, GL_ALPHA, GL_SHORT, GL_FLOAT },
+ { GL_LUMINANCE16_ALPHA16_SNORM, GL_LUMINANCE_ALPHA, GL_SHORT, GL_FLOAT },
+ { GL_INTENSITY16_SNORM, GL_INTENSITY, GL_SHORT, GL_FLOAT },
+
+ // 16-bit float
+ { GL_R16F, GL_RED, GL_HALF_FLOAT, GL_FLOAT },
+ { GL_RG16F, GL_RG, GL_HALF_FLOAT, GL_FLOAT },
+ { GL_RGB16F, GL_RGB, GL_HALF_FLOAT, GL_FLOAT },
+ { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT },
+ { GL_LUMINANCE16F_ARB, GL_LUMINANCE, GL_HALF_FLOAT, GL_FLOAT },
+ { GL_ALPHA16F_ARB, GL_ALPHA, GL_HALF_FLOAT, GL_FLOAT },
+ { GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_FLOAT },
+ { GL_INTENSITY16F_ARB, GL_INTENSITY, GL_HALF_FLOAT, GL_FLOAT },
+
+ // 32-bit float
+ { GL_R32F, GL_RED, GL_FLOAT, GL_FLOAT },
+ { GL_RG32F, GL_RG, GL_FLOAT, GL_FLOAT },
+ { GL_RGB32F, GL_RGB, GL_FLOAT, GL_FLOAT },
+ { GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_FLOAT },
+ { GL_LUMINANCE32F_ARB, GL_LUMINANCE, GL_FLOAT, GL_FLOAT },
+ { GL_ALPHA32F_ARB, GL_ALPHA, GL_FLOAT, GL_FLOAT },
+ { GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT },
+ { GL_INTENSITY32F_ARB, GL_INTENSITY, GL_FLOAT, GL_FLOAT },
+
+ // Other float
+ { GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT },
+ { GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT },
+
+ // Unsized integer
+ // FIXME: currently we can only dump integers as GL_UNSIGNED_BYTE
+ { GL_RED_INTEGER, GL_RED_INTEGER, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_GREEN_INTEGER, GL_GREEN_INTEGER, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_BLUE_INTEGER, GL_BLUE_INTEGER, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_ALPHA_INTEGER, GL_ALPHA_INTEGER, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RG_INTEGER, GL_RG_INTEGER, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RGB_INTEGER, GL_RGB_INTEGER, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_BGR_INTEGER, GL_BGR_INTEGER, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_RGBA_INTEGER, GL_RGBA_INTEGER, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_BGRA_INTEGER, GL_BGRA_INTEGER, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE_INTEGER_EXT, GL_LUMINANCE_INTEGER_EXT, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_NONE, GL_UNSIGNED_BYTE },
+
+ // 8-bit unsigned integer
+ { GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE8UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_ALPHA8UI_EXT, GL_ALPHA_INTEGER_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE_ALPHA8UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_INTENSITY8UI_EXT, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+
+ // 8-bit signed integer
+ { GL_R8I, GL_RED_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE },
+ { GL_RG8I, GL_RG_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE },
+ { GL_RGB8I, GL_RGB_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE },
+ { GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE8I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_BYTE, GL_UNSIGNED_BYTE },
+ { GL_ALPHA8I_EXT, GL_ALPHA_INTEGER_EXT, GL_BYTE, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE_ALPHA8I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_BYTE, GL_UNSIGNED_BYTE },
+ { GL_INTENSITY8I_EXT, GL_RED_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE },
+
+ // 10-bit unsigned integer
+ { GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_BYTE },
+
+ // 16-bit unsigned integer
+ { GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE },
+ { GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE },
+ { GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE },
+ { GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE16UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE },
+ { GL_ALPHA16UI_EXT, GL_ALPHA_INTEGER_EXT, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE_ALPHA16UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE },
+ { GL_INTENSITY16UI_EXT, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE },
+
+ // 16-bit signed integer
+ { GL_R16I, GL_RED_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE },
+ { GL_RG16I, GL_RG_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE },
+ { GL_RGB16I, GL_RGB_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE },
+ { GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE16I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_SHORT, GL_UNSIGNED_BYTE },
+ { GL_ALPHA16I_EXT, GL_ALPHA_INTEGER_EXT, GL_SHORT, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE_ALPHA16I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_SHORT, GL_UNSIGNED_BYTE },
+ { GL_INTENSITY16I_EXT, GL_RED_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE },
+
+ // 32-bit unsigned integer
+ { GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE },
+ { GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE },
+ { GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE },
+ { GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE32UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE },
+ { GL_ALPHA32UI_EXT, GL_ALPHA_INTEGER_EXT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE_ALPHA32UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE },
+ { GL_INTENSITY32UI_EXT, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE },
+
+ // 32-bit signed integer
+ { GL_R32I, GL_RED_INTEGER, GL_INT, GL_UNSIGNED_BYTE },
+ { GL_RG32I, GL_RG_INTEGER, GL_INT, GL_UNSIGNED_BYTE },
+ { GL_RGB32I, GL_RGB_INTEGER, GL_INT, GL_UNSIGNED_BYTE },
+ { GL_RGBA32I, GL_RGBA_INTEGER, GL_INT, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE32I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_INT, GL_UNSIGNED_BYTE },
+ { GL_ALPHA32I_EXT, GL_ALPHA_INTEGER_EXT, GL_INT, GL_UNSIGNED_BYTE },
+ { GL_LUMINANCE_ALPHA32I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_INT, GL_UNSIGNED_BYTE },
+ { GL_INTENSITY32I_EXT, GL_RED_INTEGER, GL_INT, GL_UNSIGNED_BYTE },
+
+ // Compressed
+ { GL_COMPRESSED_RED, GL_RED, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RED_RGTC1, GL_RED, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_R11_EAC, GL_RED, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RG, GL_RG, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RG_RGTC2, GL_RG, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RG11_EAC, GL_RG, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RGB, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RGB8_ETC2, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RGBA, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RGBA8_ETC2_EAC, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_LUMINANCE, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE },
+
+ // Compressed signed
+ { GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED, GL_NONE, GL_FLOAT },
+ { GL_COMPRESSED_SIGNED_R11_EAC, GL_RED, GL_NONE, GL_FLOAT },
+ { GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_NONE, GL_FLOAT },
+ { GL_COMPRESSED_SIGNED_RG11_EAC, GL_RG, GL_NONE, GL_FLOAT },
+ { GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT, GL_LUMINANCE, GL_NONE, GL_FLOAT },
+ { GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT, GL_LUMINANCE_ALPHA, GL_NONE, GL_FLOAT },
+
+ // SRGB
+ { GL_SRGB, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_SRGB_ALPHA, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_SLUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_SLUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_SLUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_SRGB, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_SRGB_ALPHA, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_SLUMINANCE, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_SLUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE },
+
+ // depth-stencil
+ { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_NONE, GL_FLOAT },
+ { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_FLOAT },
+ { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_NONE, GL_FLOAT },
+ { GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_FLOAT },
+ { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT },
+ { GL_DEPTH_COMPONENT32F_NV, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT },
+ { GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_NONE, GL_FLOAT },
+ { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8_EXT, GL_FLOAT },
+ { GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT },
+ { GL_DEPTH32F_STENCIL8_NV, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT },
+ { GL_STENCIL_INDEX, GL_STENCIL_INDEX, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_STENCIL_INDEX1, GL_STENCIL_INDEX, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_STENCIL_INDEX4, GL_STENCIL_INDEX, GL_NONE, GL_UNSIGNED_BYTE },
+ { GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE },
+ { GL_STENCIL_INDEX16, GL_STENCIL_INDEX, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE },
+};
+
+
+static const InternalFormatDesc
+defaultInternalFormatDesc = {
+ GL_RGBA, GL_RGBA, GL_NONE, GL_FLOAT
+};
+
+
+const InternalFormatDesc &
+getInternalFormatDesc(GLenum internalFormat)
+{
+ for (unsigned i = 0; i < sizeof internalFormatDescs / sizeof internalFormatDescs[0]; ++i) {
+ if (internalFormatDescs[i].internalFormat == internalFormat) {
+ return internalFormatDescs[i];
+ }
+ }
+
+ std::cerr << "warning: unexpected internalFormat " << enumToString(internalFormat) << "\n";
+
+ return defaultInternalFormatDesc;
+}
+
+
+/**
+ * Choose appropriate format/type for glReadPixels()/glGetTexImage()
+ */
+void
+chooseReadBackFormat(const InternalFormatDesc &formatDesc, GLenum &format, GLenum &type)
+{
+ /* TODO: leverage glGetInternalformat where available */
+
+ type = formatDesc.readType;
+ assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT);
+
+ switch (formatDesc.format) {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_RG:
+ case GL_RGB:
+ case GL_BGR:
+ format = GL_RGB;
+ break;
+ case GL_ALPHA:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_INTENSITY:
+ format = GL_RGBA;
+ break;
+ case GL_LUMINANCE:
+ format = GL_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ format = GL_LUMINANCE_ALPHA;
+ break;
+
+ case GL_RED_INTEGER:
+ case GL_GREEN_INTEGER:
+ case GL_BLUE_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_BGR_INTEGER:
+ case GL_ALPHA_INTEGER:
+ case GL_RGBA_INTEGER:
+ case GL_BGRA_INTEGER:
+ format = GL_RGBA_INTEGER;
+ break;
+ case GL_LUMINANCE_INTEGER_EXT:
+ format = GL_LUMINANCE_INTEGER_EXT;
+ break;
+ case GL_LUMINANCE_ALPHA_INTEGER_EXT:
+ format = GL_LUMINANCE_ALPHA_INTEGER_EXT;
+ break;
+
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL:
+ /* TODO: allow pick stencil component too*/
+ format = GL_DEPTH_COMPONENT;
+ type = GL_FLOAT;
+ break;
+ case GL_STENCIL_INDEX:
+ format = GL_STENCIL_INDEX;
+ type = GL_UNSIGNED_BYTE;
+ break;
+
+ default:
+ assert(0);
+ format = GL_RGBA;
+ type = GL_FLOAT;
+ break;
+ }
+}
+
+
+void
+getImageFormat(GLenum format, GLenum type,
+ GLuint & channels, image::ChannelType & channelType)
+{
+ channels = _gl_format_channels(format);
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ channelType = image::TYPE_UNORM8;
+ break;
+ case GL_FLOAT:
+ channelType = image::TYPE_FLOAT;
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+// Macros for describing arbitrary swizzles
+
+#define SWIZZLE_X 0
+#define SWIZZLE_Y 1
+#define SWIZZLE_Z 2
+#define SWIZZLE_W 3
+#define SWIZZLE_0 4
+#define SWIZZLE_1 5
+#define SWIZZLE_COUNT 6
+
+#define SWIZZLE_BITS 4
+#define SWIZZLE_MASK ((1 << SWIZZLE_BITS) - 1)
+
+#define SWIZZLE(x, y, z, w) \
+ (((SWIZZLE_##x) << (SWIZZLE_BITS*0)) | \
+ ((SWIZZLE_##y) << (SWIZZLE_BITS*1)) | \
+ ((SWIZZLE_##z) << (SWIZZLE_BITS*2)) | \
+ ((SWIZZLE_##w) << (SWIZZLE_BITS*3)))
+
+#define SWIZZLE_RGBA SWIZZLE(X,Y,Z,W)
+#define SWIZZLE_RGB SWIZZLE(X,Y,Z,1)
+#define SWIZZLE_RG SWIZZLE(X,Y,0,1)
+#define SWIZZLE_R SWIZZLE(X,0,0,1)
+#define SWIZZLE_LA SWIZZLE(X,X,X,Y)
+#define SWIZZLE_L SWIZZLE(X,X,X,1)
+#define SWIZZLE_A SWIZZLE(0,0,0,X)
+#define SWIZZLE_I SWIZZLE(X,X,X,X)
+
+#define SWIZZLE_EXTRACT(swizzle, channel) \
+ ((swizzle) >> (SWIZZLE_BITS * (channel)) & SWIZZLE_MASK)
+
+
+// Template that can describe all regular array-based pixel formats
+template< typename Type, unsigned components, bool normalized, uint16_t swizzle >
+class PixelTemplate : public PixelFormat
+{
+protected:
+
+ static_assert( 1 <= components && components <= 4, "invalid number of components" );
+
+ static const unsigned swizzle_r = SWIZZLE_EXTRACT(swizzle, 0);
+ static const unsigned swizzle_g = SWIZZLE_EXTRACT(swizzle, 1);
+ static const unsigned swizzle_b = SWIZZLE_EXTRACT(swizzle, 2);
+ static const unsigned swizzle_a = SWIZZLE_EXTRACT(swizzle, 3);
+
+ static_assert( swizzle_r < components || swizzle_r == SWIZZLE_0 || swizzle_r == SWIZZLE_1, "invalid R swizzle" );
+ static_assert( swizzle_g < components || swizzle_g == SWIZZLE_0 || swizzle_g == SWIZZLE_1, "invalid G swizzle" );
+ static_assert( swizzle_b < components || swizzle_b == SWIZZLE_0 || swizzle_b == SWIZZLE_1, "invalid B swizzle" );
+ static_assert( swizzle_a < components || swizzle_a == SWIZZLE_0 || swizzle_a == SWIZZLE_1, "invalid A swizzle" );
+
+ // We must use double precision intermediate values when normalizing 32bits integers.
+ typedef typename std::conditional< normalized && sizeof(Type) >= 4 , double , float >::type Scale;
+
+ // Scale normalized types
+ template<typename T = void>
+ static inline Scale
+ scale(Scale value, typename std::enable_if<normalized, T>::type* = 0)
+ {
+ static_assert( normalized, "should only be instantiated for normalized types" );
+#ifndef _MSC_VER
+ static constexpr Type typeMax = std::numeric_limits<Type>::max();
+ static_assert( static_cast<Type>(static_cast<Scale>(typeMax)) == typeMax,
+ "intermediate type cannot represent maximum value without loss of precission" );
+ static constexpr Scale scaleFactor = Scale(1) / Scale(typeMax);
+ static_assert( Scale(typeMax) * scaleFactor == Scale(1), "cannot represent unity" );
+ static_assert( Scale(0) * scaleFactor == Scale(0), "cannot represent zero" );
+#else
+ // XXX: MSCV doesn't support constexpr yet
+ static const Type typeMax = std::numeric_limits<Type>::max();
+ assert( static_cast<Type>(static_cast<Scale>(typeMax)) == typeMax );
+ static const Scale scaleFactor = Scale(1) / Scale(typeMax);
+ assert( Scale(typeMax) * scaleFactor == Scale(1) );
+ assert( Scale(0) * scaleFactor == Scale(0) );
+#endif
+ return value * scaleFactor;
+ }
+
+ // No-op for unormalized types
+ template<typename T = void>
+ static inline Scale
+ scale(Scale value, typename std::enable_if<!normalized, T>::type* = 0)
+ {
+ static_assert( !normalized, "should only be instantiated for non-normalized types" );
+ return value;
+ }
+
+ // Unpack a single pixel
+ static inline void
+ unpackPixel(const Type *inPixel, float outPixel[4])
+ {
+ float scaledComponents[SWIZZLE_COUNT];
+ for (unsigned component = 0; component < components; ++component) {
+ Scale scaledComponent = scale(static_cast<Scale>(inPixel[component]));
+ scaledComponents[component] = static_cast<float>(scaledComponent);
+ }
+ scaledComponents[SWIZZLE_0] = 0.0f;
+ scaledComponents[SWIZZLE_1] = 1.0f;
+
+ outPixel[0] = scaledComponents[swizzle_r];
+ outPixel[1] = scaledComponents[swizzle_g];
+ outPixel[2] = scaledComponents[swizzle_b];
+ outPixel[3] = scaledComponents[swizzle_a];
+ }
+
+public:
+
+ inline
+ PixelTemplate(void) {
+ }
+
+ size_t
+ size(void) const {
+ return sizeof(Type) * components;
+ }
+
+ void
+ unpackSpan(const uint8_t *inSpan, float *outSpan, unsigned width) const
+ {
+ const Type *inPixel = reinterpret_cast<const Type *>(inSpan);
+
+ for (unsigned x = 0; x < width; ++x) {
+ unpackPixel(inPixel, outSpan);
+ inPixel += components;
+ outSpan += 4;
+ }
+ }
+};
+
+
+const PixelFormat *
+getPixelFormat(GLenum internalFormat)
+{
+ static const bool Y = true;
+ static const bool N = false;
+
+#define CASE(internalFormat, type, components, norm, swizzle) \
+ case GL_##internalFormat: \
+ { \
+ static const PixelTemplate< GL##type, components, norm, SWIZZLE_##swizzle > pixel; \
+ return &pixel; \
+ }
+
+ switch (internalFormat) {
+
+ CASE(ALPHA8, ubyte, 1, Y, A);
+ CASE(ALPHA16, ushort, 1, Y, A);
+ CASE(ALPHA16F_ARB, half, 1, N, A);
+ CASE(ALPHA32F_ARB, float, 1, N, A);
+ CASE(ALPHA8I_EXT, byte, 1, N, A);
+ CASE(ALPHA16I_EXT, short, 1, N, A);
+ CASE(ALPHA32I_EXT, int, 1, N, A);
+ CASE(ALPHA8UI_EXT, ubyte, 1, N, A);
+ CASE(ALPHA16UI_EXT, ushort, 1, N, A);
+ CASE(ALPHA32UI_EXT, uint, 1, N, A);
+
+ CASE(LUMINANCE8, ubyte, 1, Y, L);
+ CASE(LUMINANCE16, ushort, 1, Y, L);
+ CASE(LUMINANCE16F_ARB, half, 1, N, L);
+ CASE(LUMINANCE32F_ARB, float, 1, N, L);
+ CASE(LUMINANCE8I_EXT, byte, 1, N, L);
+ CASE(LUMINANCE16I_EXT, short, 1, N, L);
+ CASE(LUMINANCE32I_EXT, int, 1, N, L);
+ CASE(LUMINANCE8UI_EXT, ubyte, 1, N, L);
+ CASE(LUMINANCE16UI_EXT, ushort, 1, N, L);
+ CASE(LUMINANCE32UI_EXT, uint, 1, N, L);
+
+ CASE(LUMINANCE8_ALPHA8, ubyte, 2, Y, LA);
+ CASE(LUMINANCE16_ALPHA16, ushort, 2, Y, LA);
+ CASE(LUMINANCE_ALPHA16F_ARB, half, 2, N, LA);
+ CASE(LUMINANCE_ALPHA32F_ARB, float, 2, N, LA);
+ CASE(LUMINANCE_ALPHA8I_EXT, byte, 2, N, LA);
+ CASE(LUMINANCE_ALPHA16I_EXT, short, 2, N, LA);
+ CASE(LUMINANCE_ALPHA32I_EXT, int, 2, N, LA);
+ CASE(LUMINANCE_ALPHA8UI_EXT, ubyte, 2, N, LA);
+ CASE(LUMINANCE_ALPHA16UI_EXT, ushort, 2, N, LA);
+ CASE(LUMINANCE_ALPHA32UI_EXT, uint, 2, N, LA);
+
+ CASE(INTENSITY8, ubyte, 1, Y, I);
+ CASE(INTENSITY16, ushort, 1, Y, I);
+ CASE(INTENSITY16F_ARB, half, 1, N, I);
+ CASE(INTENSITY32F_ARB, float, 1, N, I);
+ CASE(INTENSITY8I_EXT, byte, 1, N, I);
+ CASE(INTENSITY16I_EXT, short, 1, N, I);
+ CASE(INTENSITY32I_EXT, int, 1, N, I);
+ CASE(INTENSITY8UI_EXT, ubyte, 1, N, I);
+ CASE(INTENSITY16UI_EXT, ushort, 1, N, I);
+ CASE(INTENSITY32UI_EXT, uint, 1, N, I);
+
+ CASE(RGBA8, ubyte, 4, Y, RGBA);
+ CASE(RGBA16, ushort, 4, Y, RGBA);
+ CASE(RGBA16F, half, 4, N, RGBA);
+ CASE(RGBA32F, float, 4, N, RGBA);
+ CASE(RGBA8I, byte, 4, N, RGBA);
+ CASE(RGBA16I, short, 4, N, RGBA);
+ CASE(RGBA32I, int, 4, N, RGBA);
+ CASE(RGBA8UI, ubyte, 4, N, RGBA);
+ CASE(RGBA16UI, ushort, 4, N, RGBA);
+ CASE(RGBA32UI, uint, 4, N, RGBA);
+
+ CASE(RGB8, ubyte, 3, Y, RGB);
+ CASE(RGB16, ushort, 3, Y, RGB);
+ CASE(RGB16F, half, 3, N, RGB);
+ CASE(RGB32F, float, 3, N, RGB);
+ CASE(RGB8I, byte, 3, N, RGB);
+ CASE(RGB16I, short, 3, N, RGB);
+ CASE(RGB32I, int, 3, N, RGB);
+ CASE(RGB8UI, ubyte, 3, N, RGB);
+ CASE(RGB16UI, ushort, 3, N, RGB);
+ CASE(RGB32UI, uint, 3, N, RGB);
+
+ CASE(RG8, ubyte, 2, Y, RG);
+ CASE(RG16, ushort, 2, Y, RG);
+ CASE(RG16F, half, 2, N, RG);
+ CASE(RG32F, float, 2, N, RG);
+ CASE(RG8I, byte, 2, N, RG);
+ CASE(RG16I, short, 2, N, RG);
+ CASE(RG32I, int, 2, N, RG);
+ CASE(RG8UI, ubyte, 2, N, RG);
+ CASE(RG16UI, ushort, 2, N, RG);
+ CASE(RG32UI, uint, 2, N, RG);
+
+ CASE(R8, ubyte, 1, Y, R);
+ CASE(R16, ushort, 1, Y, R);
+ CASE(R16F, half, 1, N, R);
+ CASE(R32F, float, 1, N, R);
+ CASE(R8I, byte, 1, N, R);
+ CASE(R16I, short, 1, N, R);
+ CASE(R32I, int, 1, N, R);
+ CASE(R8UI, ubyte, 1, N, R);
+ CASE(R16UI, ushort, 1, N, R);
+ CASE(R32UI, uint, 1, N, R);
+
+ default:
+ return nullptr;
+ }
+
+#undef CASE
+}
+
+
+} /* namespace glstate */
diff --git a/retrace/glstate_images.cpp b/retrace/glstate_images.cpp
index 5cf5e9f1..9aadc586 100644
--- a/retrace/glstate_images.cpp
+++ b/retrace/glstate_images.cpp
@@ -32,7 +32,7 @@
#include <sstream>
#include "image.hpp"
-#include "json.hpp"
+#include "state_writer.hpp"
#include "glproc.hpp"
#include "glsize.hpp"
#include "glstate.hpp"
@@ -96,33 +96,8 @@ struct ImageDesc
};
-static bool
-getInternalFormatType(GLenum internalFormat, GLenum &format, GLenum &type);
-
-
-/**
- * Sames as enumToString, but with special provision to handle formatsLUMINANCE_ALPHA.
- *
- * OpenGL 2.1 specification states that "internalFormat may (for backwards
- * compatibility with the 1.0 version of the GL) also take on the integer
- * values 1, 2, 3, and 4, which are equivalent to symbolic constants LUMINANCE,
- * LUMINANCE ALPHA, RGB, and RGBA respectively".
- */
-const char *
-formatToString(GLenum internalFormat) {
- switch (internalFormat) {
- case 1:
- return "GL_LUMINANCE";
- case 2:
- return "GL_LUMINANCE_ALPHA";
- case 3:
- return "GL_RGB";
- case 4:
- return "GL_RGBA";
- default:
- return enumToString(internalFormat);
- }
-}
+static GLenum
+getTextureTarget(Context &context, GLuint texture);
/**
@@ -131,12 +106,11 @@ formatToString(GLenum internalFormat) {
* call.
*/
static bool
-probeTextureLevelSizeOES(GLenum target, GLint level, const GLint size[3]) {
- while (glGetError() != GL_NO_ERROR)
- ;
+probeTextureLevelSizeOES(GLenum target, GLint level, const GLint size[3],
+ GLenum internalFormat, GLenum type)
+{
+ flushErrors();
- GLenum internalFormat = GL_RGBA;
- GLenum type = GL_UNSIGNED_BYTE;
GLint dummy = 0;
switch (target) {
@@ -152,6 +126,7 @@ probeTextureLevelSizeOES(GLenum target, GLint level, const GLint size[3]) {
break;
case GL_TEXTURE_3D_OES:
glTexSubImage3DOES(target, level, size[0], size[1], size[2], 0, 0, 0, internalFormat, type, &dummy);
+ break;
default:
assert(0);
return false;
@@ -167,8 +142,41 @@ probeTextureLevelSizeOES(GLenum target, GLint level, const GLint size[3]) {
return true;
}
- while (glGetError() != GL_NO_ERROR)
- ;
+ flushErrors();
+
+ return false;
+}
+
+
+static bool
+probeTextureFormatOES(GLenum target, GLint level,
+ GLenum *internalFormat, GLenum *type)
+{
+ static const struct {
+ GLenum internalFormat;
+ GLenum type;
+ } info[] = {
+ /* internalFormat */ /* type */
+ { GL_RGBA, GL_UNSIGNED_BYTE },
+ { GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV },
+ { GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 },
+ { GL_DEPTH_COMPONENT, GL_FLOAT },
+ { GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT },
+ { GL_STENCIL_INDEX, GL_UNSIGNED_BYTE },
+ /* others? */
+ { 0, 0 },
+ };
+ static const GLint size[3] = {1, 1, 1};
+
+ for (int i = 0; info[i].internalFormat; i++) {
+ if (probeTextureLevelSizeOES(target, level, size,
+ info[i].internalFormat,
+ info[i].type)) {
+ *internalFormat = info[i].internalFormat;
+ *type = info[i].type;
+ return true;
+ }
+ }
return false;
}
@@ -180,7 +188,9 @@ probeTextureLevelSizeOES(GLenum target, GLint level, const GLint size[3]) {
* It is assumed that the texture exists.
*/
static GLint
-bisectTextureLevelSizeOES(GLenum target, GLint level, GLint axis, GLint max) {
+bisectTextureLevelSizeOES(GLenum target, GLint level, GLint axis, GLint max,
+ GLenum internalFormat, GLenum type)
+{
GLint size[3] = {0, 0, 0};
assert(axis < 3);
@@ -195,7 +205,7 @@ bisectTextureLevelSizeOES(GLenum target, GLint level, GLint axis, GLint max) {
size[axis] = test;
- if (probeTextureLevelSizeOES(target, level, size)) {
+ if (probeTextureLevelSizeOES(target, level, size, internalFormat, type)) {
min = test;
} else {
max = test;
@@ -215,21 +225,20 @@ getActiveTextureLevelDescOES(Context &context, GLenum target, GLint level, Image
// OpenGL ES does not support 1D textures
return false;
}
+ GLenum internalFormat, type;
- const GLint size[3] = {1, 1, 1};
- if (!probeTextureLevelSizeOES(target, level, size)) {
+ if (!probeTextureFormatOES(target, level, &internalFormat, &type)) {
return false;
}
- // XXX: mere guess
- desc.internalFormat = GL_RGBA;
+ desc.internalFormat = internalFormat;
GLint maxSize = 0;
switch (target) {
case GL_TEXTURE_2D:
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
- desc.width = bisectTextureLevelSizeOES(target, level, 0, maxSize);
- desc.height = bisectTextureLevelSizeOES(target, level, 1, maxSize);
+ desc.width = bisectTextureLevelSizeOES(target, level, 0, maxSize, internalFormat, type);
+ desc.height = bisectTextureLevelSizeOES(target, level, 1, maxSize, internalFormat, type);
desc.depth = 1;
break;
case GL_TEXTURE_CUBE_MAP:
@@ -240,15 +249,15 @@ getActiveTextureLevelDescOES(Context &context, GLenum target, GLint level, Image
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxSize);
- desc.width = bisectTextureLevelSizeOES(target, level, 0, maxSize);
+ desc.width = bisectTextureLevelSizeOES(target, level, 0, maxSize, internalFormat, type);
desc.height = desc.width;
desc.depth = 1;
break;
case GL_TEXTURE_3D_OES:
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_OES, &maxSize);
- desc.width = bisectTextureLevelSizeOES(target, level, 0, maxSize);
- desc.width = bisectTextureLevelSizeOES(target, level, 1, maxSize);
- desc.depth = bisectTextureLevelSizeOES(target, level, 2, maxSize);
+ desc.width = bisectTextureLevelSizeOES(target, level, 0, maxSize, internalFormat, type);
+ desc.width = bisectTextureLevelSizeOES(target, level, 1, maxSize, internalFormat, type);
+ desc.depth = bisectTextureLevelSizeOES(target, level, 2, maxSize, internalFormat, type);
break;
default:
return false;
@@ -296,17 +305,14 @@ getActiveTextureLevelDesc(Context &context, GLenum target, GLint level, ImageDes
glGetIntegerv(GL_TEXTURE_BUFFER_FORMAT_ARB, &desc.internalFormat);
- GLenum format;
- GLenum type;
- if (!getInternalFormatType(desc.internalFormat, format, type)) {
+ const InternalFormatDesc &formatDesc = getInternalFormatDesc(desc.internalFormat);
+ if (formatDesc.type == GL_NONE) {
assert(0);
return false;
+
}
- assert(type != GL_NONE);
- unsigned bits_per_element;
- unsigned bits_per_pixel;
- _gl_format_size(format, type, bits_per_element, bits_per_pixel);
+ unsigned bits_per_pixel = _gl_format_size(formatDesc.format, formatDesc.type);
desc.width = buffer_size * 8 / bits_per_pixel;
desc.height = 1;
@@ -320,13 +326,17 @@ getActiveTextureLevelDesc(Context &context, GLenum target, GLint level, ImageDes
desc.width = 0;
glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &desc.width);
- if (target == GL_TEXTURE_1D) {
+ if (target == GL_TEXTURE_BUFFER ||
+ target == GL_TEXTURE_1D) {
desc.height = 1;
desc.depth = 1;
} else {
desc.height = 0;
glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &desc.height);
- if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY) {
+ if (target != GL_TEXTURE_3D &&
+ target != GL_TEXTURE_2D_ARRAY &&
+ target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY &&
+ target != GL_TEXTURE_CUBE_MAP_ARRAY) {
desc.depth = 1;
} else {
desc.depth = 0;
@@ -403,7 +413,8 @@ getTextureBinding(GLenum target)
* texture to a framebuffer.
*/
static inline void
-getTexImageOES(GLenum target, GLint level, ImageDesc &desc, GLubyte *pixels)
+getTexImageOES(GLenum target, GLint level, GLenum format, GLenum type,
+ ImageDesc &desc, GLubyte *pixels)
{
memset(pixels, 0x80, desc.height * desc.width * 4);
@@ -439,12 +450,12 @@ getTexImageOES(GLenum target, GLint level, ImageDesc &desc, GLubyte *pixels)
if (status != GL_FRAMEBUFFER_COMPLETE) {
std::cerr << __FUNCTION__ << ": " << enumToString(status) << "\n";
}
- glReadPixels(0, 0, desc.width, desc.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ glReadPixels(0, 0, desc.width, desc.height, format, type, pixels);
break;
case GL_TEXTURE_3D_OES:
for (int i = 0; i < desc.depth; i++) {
glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, texture, level, i);
- glReadPixels(0, 0, desc.width, desc.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels + 4 * i * desc.width * desc.height);
+ glReadPixels(0, 0, desc.width, desc.height, format, type, pixels + 4 * i * desc.width * desc.height);
}
break;
}
@@ -455,285 +466,139 @@ getTexImageOES(GLenum target, GLint level, ImageDesc &desc, GLubyte *pixels)
}
-struct InternalFormatDesc
-{
- GLenum internalFormat;
- GLenum format;
- GLenum type;
-};
-
-
-static const InternalFormatDesc
-internalFormatDescs[] = {
-
- {1, GL_RED, GL_NONE},
- {2, GL_RG, GL_NONE},
- {3, GL_RGB, GL_NONE},
- {4, GL_RGBA, GL_NONE},
-
- {GL_RED, GL_RED, GL_NONE},
- {GL_GREEN, GL_GREEN, GL_NONE},
- {GL_BLUE, GL_BLUE, GL_NONE},
- {GL_ALPHA, GL_ALPHA, GL_NONE},
- {GL_RG, GL_RG, GL_NONE},
- {GL_RGB, GL_RGB, GL_NONE},
- {GL_BGR, GL_RGB, GL_NONE},
- {GL_RGBA, GL_RGBA, GL_NONE},
- {GL_BGRA, GL_RGBA, GL_NONE},
- {GL_LUMINANCE, GL_LUMINANCE, GL_NONE},
- {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE},
- {GL_INTENSITY, GL_INTENSITY, GL_NONE},
-
- {GL_RG8, GL_RG, GL_UNSIGNED_BYTE},
- {GL_RG16, GL_RG, GL_UNSIGNED_SHORT},
- {GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},
- {GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT},
- {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
- {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT},
- {GL_RGB10_A2, GL_RGBA, GL_NONE},
- {GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE},
- {GL_LUMINANCE16, GL_LUMINANCE, GL_UNSIGNED_SHORT},
- {GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE},
- {GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT},
- {GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
- {GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT},
- {GL_INTENSITY8, GL_INTENSITY, GL_UNSIGNED_BYTE},
- {GL_INTENSITY16, GL_INTENSITY, GL_UNSIGNED_SHORT},
-
- {GL_RG16F, GL_RG, GL_HALF_FLOAT},
- {GL_RG32F, GL_RG, GL_FLOAT},
- {GL_RGB16F, GL_RGB, GL_HALF_FLOAT},
- {GL_RGB32F, GL_RGB, GL_FLOAT},
- {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT},
- {GL_RGBA32F, GL_RGBA, GL_FLOAT},
- {GL_RGB10_A2, GL_RGBA, GL_NONE},
- {GL_LUMINANCE16F_ARB, GL_LUMINANCE, GL_HALF_FLOAT},
- {GL_LUMINANCE32F_ARB, GL_LUMINANCE, GL_FLOAT},
- {GL_ALPHA16F_ARB, GL_ALPHA, GL_HALF_FLOAT},
- {GL_ALPHA32F_ARB, GL_ALPHA, GL_FLOAT},
- {GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT},
- {GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, GL_FLOAT},
- {GL_INTENSITY16F_ARB, GL_INTENSITY, GL_HALF_FLOAT},
- {GL_INTENSITY32F_ARB, GL_INTENSITY, GL_FLOAT},
-
- {GL_RED_INTEGER, GL_RED_INTEGER, GL_NONE},
- {GL_GREEN_INTEGER, GL_GREEN_INTEGER, GL_NONE},
- {GL_BLUE_INTEGER, GL_BLUE_INTEGER, GL_NONE},
- {GL_ALPHA_INTEGER, GL_ALPHA_INTEGER, GL_NONE},
- {GL_RG_INTEGER, GL_RG_INTEGER, GL_NONE},
- {GL_RGB_INTEGER, GL_RGB_INTEGER, GL_NONE},
- {GL_BGR_INTEGER, GL_RGB_INTEGER, GL_NONE},
- {GL_RGBA_INTEGER, GL_RGBA_INTEGER, GL_NONE},
- {GL_BGRA_INTEGER, GL_RGBA_INTEGER, GL_NONE},
- {GL_LUMINANCE_INTEGER_EXT, GL_LUMINANCE_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_NONE},
-
- {GL_R8I, GL_RED_INTEGER, GL_NONE},
- {GL_R8UI, GL_RED_INTEGER, GL_NONE},
- {GL_R16I, GL_RED_INTEGER, GL_NONE},
- {GL_R16UI, GL_RED_INTEGER, GL_NONE},
- {GL_R32I, GL_RED_INTEGER, GL_NONE},
- {GL_R32UI, GL_RED_INTEGER, GL_NONE},
- {GL_RG8I, GL_RG_INTEGER, GL_NONE},
- {GL_RG8UI, GL_RG_INTEGER, GL_NONE},
- {GL_RG16I, GL_RG_INTEGER, GL_NONE},
- {GL_RG16UI, GL_RG_INTEGER, GL_NONE},
- {GL_RG32I, GL_RG_INTEGER, GL_NONE},
- {GL_RG32UI, GL_RG_INTEGER, GL_NONE},
- {GL_RGB8I, GL_RGB_INTEGER, GL_NONE},
- {GL_RGB8UI, GL_RGB_INTEGER, GL_NONE},
- {GL_RGB16I, GL_RGB_INTEGER, GL_NONE},
- {GL_RGB16UI, GL_RGB_INTEGER, GL_NONE},
- {GL_RGB32I, GL_RGB_INTEGER, GL_NONE},
- {GL_RGB32UI, GL_RGB_INTEGER, GL_NONE},
- {GL_RGBA8I, GL_RGBA_INTEGER, GL_NONE},
- {GL_RGBA8UI, GL_RGBA_INTEGER, GL_NONE},
- {GL_RGBA16I, GL_RGBA_INTEGER, GL_NONE},
- {GL_RGBA16UI, GL_RGBA_INTEGER, GL_NONE},
- {GL_RGBA32I, GL_RGBA_INTEGER, GL_NONE},
- {GL_RGBA32UI, GL_RGBA_INTEGER, GL_NONE},
- {GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_NONE},
- {GL_LUMINANCE8I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE8UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE16I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE16UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE32I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE32UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_NONE},
- {GL_ALPHA8I_EXT, GL_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_ALPHA8UI_EXT, GL_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_ALPHA16I_EXT, GL_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_ALPHA16UI_EXT, GL_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_ALPHA32I_EXT, GL_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_ALPHA32UI_EXT, GL_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE_ALPHA8I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE_ALPHA8UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE_ALPHA16I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE_ALPHA16UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE_ALPHA32I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_LUMINANCE_ALPHA32UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_NONE},
- {GL_INTENSITY8I_EXT, GL_RED_INTEGER, GL_NONE},
- {GL_INTENSITY8UI_EXT, GL_RED_INTEGER, GL_NONE},
- {GL_INTENSITY16I_EXT, GL_RED_INTEGER, GL_NONE},
- {GL_INTENSITY16UI_EXT, GL_RED_INTEGER, GL_NONE},
- {GL_INTENSITY32I_EXT, GL_RED_INTEGER, GL_NONE},
- {GL_INTENSITY32UI_EXT, GL_RED_INTEGER, GL_NONE},
-
- {GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_NONE},
- {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_NONE},
- {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_NONE},
- {GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_NONE},
- {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_NONE},
- {GL_DEPTH_COMPONENT32F_NV, GL_DEPTH_COMPONENT, GL_NONE},
- {GL_DEPTH_STENCIL, GL_DEPTH_COMPONENT, GL_NONE},
- {GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT, GL_NONE},
- {GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT, GL_NONE},
- {GL_DEPTH32F_STENCIL8_NV, GL_DEPTH_COMPONENT, GL_NONE},
-};
-
-
-static bool
-getInternalFormatType(GLenum internalFormat, GLenum &format, GLenum &type)
-{
- for (unsigned i = 0; i < sizeof internalFormatDescs / sizeof internalFormatDescs[0]; ++i) {
- if (internalFormatDescs[i].internalFormat == internalFormat) {
- format = internalFormatDescs[i].format;
- type = internalFormatDescs[i].type;
- return true;
- }
- }
-
- return false;
-}
-
-
-/**
- * Choose the glReadPixels/glGetTexImage format appropriate for the given
- * internalFormat.
- */
-static GLenum
-getFormat(GLenum internalFormat)
-{
- GLenum format;
- GLenum type;
- if (getInternalFormatType(internalFormat, format, type)) {
- return format;
- }
- return GL_RGBA;
-}
-
-
static inline void
-dumpActiveTextureLevel(JSONWriter &json, Context &context,
- GLenum target, GLint level, const char *object_label)
+dumpActiveTextureLevel(StateWriter &writer, Context &context,
+ GLenum target, GLint level,
+ const std::string & label,
+ const char *userLabel)
{
ImageDesc desc;
if (!getActiveTextureLevelDesc(context, target, level, desc)) {
return;
}
+ const InternalFormatDesc &formatDesc = getInternalFormatDesc(desc.internalFormat);
+
GLenum format;
GLenum type;
+ const PixelFormat *pixelFormat = nullptr;
- if (!getInternalFormatType(desc.internalFormat, format, type)) {
+ if (target == GL_TEXTURE_BUFFER) {
+ pixelFormat = getPixelFormat(desc.internalFormat);
+ if (!pixelFormat) {
+ std::cerr << "warning: unsupported texture buffer internal format " << formatToString(desc.internalFormat) << "\n";
+ return;
+ }
format = GL_RGBA;
- type = GL_NONE;
- }
-
- if (target == GL_TEXTURE_BUFFER && type != GL_UNSIGNED_BYTE) {
- // FIXME: We rely on glGetTexImage to convert the pixels, but we can't use it with texture buffers.
- return;
+ type = GL_FLOAT;
+ } else {
+ chooseReadBackFormat(formatDesc, format, type);
}
- GLint active_texture = GL_TEXTURE0;
- glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
+ writer.beginMember(label);
- std::stringstream label;
- label << enumToString(active_texture) << ", "
- << enumToString(target);
- if (object_label)
- label << ", \"" << object_label << "\"";
- if (target != GL_TEXTURE_BUFFER) {
- label << ", level = " << level;
+ if (context.ES && format == GL_DEPTH_COMPONENT) {
+ format = GL_RED;
}
- json.beginMember(label.str());
+ GLuint channels;
+ image::ChannelType channelType;
+ getImageFormat(format, type, channels, channelType);
- if (context.ES && format == GL_DEPTH_COMPONENT) {
- format = GL_RED;
+ if (0) {
+ std::cerr << enumToString(desc.internalFormat) << " "
+ << enumToString(format) << " "
+ << enumToString(type) << "\n";
}
- GLuint channels = _gl_format_channels(format);
- image::Image *image = new image::Image(desc.width, desc.height*desc.depth, channels, true);
+ image::Image *image = new image::Image(desc.width, desc.height*desc.depth, channels, true, channelType);
- context.resetPixelPackState();
+ PixelPackState pps(context);
if (target == GL_TEXTURE_BUFFER) {
assert(desc.height == 1);
- assert(type == GL_UNSIGNED_BYTE);
+ assert(desc.depth == 1);
+ assert(pixelFormat);
+ assert(format == GL_RGBA);
+ assert(type == GL_FLOAT);
+ assert(image->bytesPerPixel == sizeof(float[4]));
GLint buffer = 0;
glGetIntegerv(GL_TEXTURE_BUFFER_DATA_STORE_BINDING, &buffer);
assert(buffer);
- GLint active_buffer = 0;
- glGetIntegerv(GL_TEXTURE_BUFFER, &active_buffer);
- glBindBuffer(GL_TEXTURE_BUFFER, buffer);
+ BufferMapping bm;
- glGetBufferSubData(GL_TEXTURE_BUFFER,
- 0, image->width * image->bytesPerPixel,
- image->pixels);
-
- glBindBuffer(GL_TEXTURE_BUFFER, active_buffer);
+ const GLvoid *map = bm.map(GL_TEXTURE_BUFFER, buffer);
+ if (map) {
+ pixelFormat->unpackSpan(static_cast<const uint8_t *>(map),
+ reinterpret_cast<float *>(image->pixels), image->width);
+ }
} else {
if (context.ES) {
- getTexImageOES(target, level, desc, image->pixels);
+ getTexImageOES(target, level, format, type, desc, image->pixels);
} else {
- glGetTexImage(target, level, format, GL_UNSIGNED_BYTE, image->pixels);
+ glGetTexImage(target, level, format, type, image->pixels);
}
}
- context.restorePixelPackState();
+ if (userLabel) {
+ image->label = userLabel;
+ }
- json.writeImage(image, formatToString(desc.internalFormat), desc.depth);
+ StateWriter::ImageDesc imageDesc;
+ imageDesc.depth = desc.depth;
+ imageDesc.format = formatToString(desc.internalFormat);
+ writer.writeImage(image, imageDesc);
delete image;
- json.endMember(); // label
+ writer.endMember(); // label
}
static inline void
-dumpTexture(JSONWriter &json, Context &context, GLenum target)
+dumpActiveTexture(StateWriter &writer, Context &context, GLenum target, GLuint texture)
{
- GLenum binding = getTextureBinding(target);
+ char *object_label = getObjectLabel(context, GL_TEXTURE, texture);
- GLint texture_binding = 0;
- glGetIntegerv(binding, &texture_binding);
- if (!glIsEnabled(target) && !texture_binding) {
- return;
+ GLint active_texture = GL_TEXTURE0;
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
+ assert(active_texture >= GL_TEXTURE0);
+
+ GLenum start_subtarget;
+ GLenum stop_subtarget;
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ start_subtarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ stop_subtarget = start_subtarget + 6;
+ } else {
+ start_subtarget = target;
+ stop_subtarget = start_subtarget + 1;
}
- char *object_label = getObjectLabel(context, GL_TEXTURE, texture_binding);
+ GLboolean allowMipmaps = target != GL_TEXTURE_RECTANGLE &&
+ target != GL_TEXTURE_BUFFER;
GLint level = 0;
do {
ImageDesc desc;
- if (target == GL_TEXTURE_CUBE_MAP) {
- for (GLint face = 0; face < 6; ++face) {
- if (!getActiveTextureLevelDesc(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, desc)) {
- goto finished;
- }
- dumpActiveTextureLevel(json, context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, object_label);
+ for (GLenum subtarget = start_subtarget; subtarget < stop_subtarget; ++subtarget) {
+ std::stringstream label;
+ label << "GL_TEXTURE" << (active_texture - GL_TEXTURE0) << ", "
+ << enumToString(subtarget);
+ if (allowMipmaps) {
+ label << ", level = " << level;
}
- } else {
- if (!getActiveTextureLevelDesc(context, target, level, desc)) {
+
+ if (!getActiveTextureLevelDesc(context, subtarget, level, desc)) {
goto finished;
}
- dumpActiveTextureLevel(json, context, target, level, object_label);
+ dumpActiveTextureLevel(writer, context, subtarget, level, label.str(), object_label);
}
- if (target == GL_TEXTURE_BUFFER) {
+ if (!allowMipmaps) {
+ // no mipmaps
break;
}
@@ -744,27 +609,75 @@ finished:
free(object_label);
}
+static void
+dumpTextureImages(StateWriter &writer, Context &context)
+{
+ if (!context.ARB_shader_image_load_store) {
+ return;
+ }
+
+ GLint maxImageUnits = 0;
+ glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImageUnits);
+ glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
+
+ for (GLint imageUnit = 0; imageUnit < maxImageUnits; ++imageUnit) {
+ GLint texture = 0;
+ glGetIntegeri_v(GL_IMAGE_BINDING_NAME, imageUnit, &texture);
+ if (texture) {
+ GLint level = 0;
+ glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, imageUnit, &level);
+ GLint isLayered = 0;
+ glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, imageUnit, &isLayered);
+ GLint layer = 0;
+ glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, imageUnit, &layer);
+ std::stringstream label;
+ label << "Image Unit " << imageUnit;
+ if (level) {
+ label << ", level = " << level;
+ }
+ if (isLayered) {
+ label << ", layer = " << layer;
+ }
+ GLenum target = getTextureTarget(context, texture);
+ GLint previousTexture = 0;
+ glGetIntegerv(getTextureBinding(target), &previousTexture);
+
+ glBindTexture(target, texture);
+ char *object_label = getObjectLabel(context, GL_TEXTURE, texture);
+ dumpActiveTextureLevel(writer, context, target, level, label.str(),
+ object_label);
+ free(object_label);
+ glBindTexture(target, previousTexture);
+ }
+ }
+}
+
void
-dumpTextures(JSONWriter &json, Context &context)
+dumpTextures(StateWriter &writer, Context &context)
{
- json.beginMember("textures");
- json.beginObject();
- GLint active_texture = GL_TEXTURE0;
- glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
+ writer.beginMember("textures");
+ writer.beginObject();
GLint max_texture_coords = 0;
- glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);
+ if (!context.core) {
+ glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);
+ }
+
GLint max_combined_texture_image_units = 0;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);
- GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);
/*
* At least the Android software GL implementation doesn't return the
* proper value for this, but rather returns 0. The GL(ES) specification
* mandates a minimum value of 2, so use this as a fall-back value.
*/
- max_units = std::max(max_units, 2);
+ max_combined_texture_image_units = std::max(max_combined_texture_image_units, 2);
+
+ GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);
+
+ GLint active_texture = GL_TEXTURE0;
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
for (GLint unit = 0; unit < max_units; ++unit) {
GLenum texture = GL_TEXTURE0 + unit;
@@ -772,19 +685,44 @@ dumpTextures(JSONWriter &json, Context &context)
for (unsigned i = 0; i < numTextureTargets; ++i) {
GLenum target = textureTargets[i];
- dumpTexture(json, context, target);
+
+ // Whether this fixed-function stage is enabled
+ GLboolean enabled = GL_FALSE;
+ if (unit < max_texture_coords &&
+ (target == GL_TEXTURE_1D ||
+ target == GL_TEXTURE_2D ||
+ target == GL_TEXTURE_3D ||
+ target == GL_TEXTURE_CUBE_MAP ||
+ target == GL_TEXTURE_RECTANGLE)) {
+ glGetBooleanv(target, &enabled);
+ }
+
+ // Whether a texture object is bound
+ GLint texture = 0;
+ if (unit < max_combined_texture_image_units) {
+ GLenum binding = getTextureBinding(target);
+ glGetIntegerv(binding, &texture);
+ }
+
+ if (enabled || texture) {
+ dumpActiveTexture(writer, context, target, texture);
+ }
}
}
+
glActiveTexture(active_texture);
- json.endObject();
- json.endMember(); // textures
+
+ dumpTextureImages(writer, context);
+
+ writer.endObject();
+ writer.endMember(); // textures
}
-static bool
+bool
getDrawableBounds(GLint *width, GLint *height) {
#if defined(__linux__)
- if (dlsym(RTLD_DEFAULT, "eglGetCurrentContext")) {
+ if (_getPublicProcAddress("eglGetCurrentContext")) {
EGLContext currentContext = eglGetCurrentContext();
if (currentContext != EGL_NO_CONTEXT) {
EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW);
@@ -853,10 +791,7 @@ getDrawableBounds(GLint *width, GLint *height) {
#elif defined(HAVE_X11)
Display *display;
- Drawable drawable;
- Window root;
- int x, y;
- unsigned int w, h, bw, depth;
+ GLXDrawable drawable;
display = glXGetCurrentDisplay();
if (!display) {
@@ -868,9 +803,11 @@ getDrawableBounds(GLint *width, GLint *height) {
return false;
}
- if (!XGetGeometry(display, drawable, &root, &x, &y, &w, &h, &bw, &depth)) {
- return false;
- }
+ // XGetGeometry will fail for PBuffers, whereas glXQueryDrawable should not.
+ unsigned int w = 0;
+ unsigned int h = 0;
+ glXQueryDrawable(display, drawable, GLX_WIDTH, &w);
+ glXQueryDrawable(display, drawable, GLX_HEIGHT, &h);
*width = w;
*height = h;
@@ -885,33 +822,56 @@ getDrawableBounds(GLint *width, GLint *height) {
static GLenum
-getTextureTarget(GLint texture)
+getTextureTarget(Context &context, GLuint texture)
{
if (!glIsTexture(texture)) {
return GL_NONE;
}
- for (unsigned i = 0; i < numTextureTargets; ++i) {
- GLenum target = textureTargets[i];
- GLenum binding = getTextureBinding(target);
+ GLint result = GL_NONE;
+ if (context.ARB_direct_state_access) {
- while (glGetError() != GL_NO_ERROR)
- ;
+ glGetTextureParameteriv(texture, GL_TEXTURE_TARGET, &result);
+ assert(result != GL_NONE);
- GLint bound_texture = 0;
- glGetIntegerv(binding, &bound_texture);
- glBindTexture(target, texture);
+ } else {
+ flushErrors();
+
+ // Temporarily disable debug messages
+ GLDEBUGPROC prevDebugCallbackFunction = 0;
+ void *prevDebugCallbackUserParam = 0;
+ if (context.KHR_debug) {
+ glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION, (GLvoid **) &prevDebugCallbackFunction);
+ glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM, &prevDebugCallbackUserParam);
+ glDebugMessageCallback(NULL, NULL);
+ }
- bool succeeded = glGetError() == GL_NO_ERROR;
+ for (unsigned i = 0; i < numTextureTargets; ++i) {
+ GLenum target = textureTargets[i];
+ GLenum binding = getTextureBinding(target);
+
+ GLint bound_texture = 0;
+ glGetIntegerv(binding, &bound_texture);
+ glBindTexture(target, texture);
+
+ bool succeeded = glGetError() == GL_NO_ERROR;
- glBindTexture(target, bound_texture);
+ glBindTexture(target, bound_texture);
- if (succeeded) {
- return target;
+ if (succeeded) {
+ result = target;
+ break;
+ }
+
+ flushErrors();
+ }
+
+ if (context.KHR_debug) {
+ glDebugMessageCallback(prevDebugCallbackFunction, prevDebugCallbackUserParam);
}
}
- return GL_NONE;
+ return result;
}
@@ -984,7 +944,7 @@ getFramebufferAttachmentDesc(Context &context, GLenum target, GLenum attachment,
getActiveTextureLevelDesc(context, texture_face, texture_level, desc);
glBindTexture(GL_TEXTURE_CUBE_MAP, bound_texture);
} else {
- GLenum texture_target = getTextureTarget(object_name);
+ GLenum texture_target = getTextureTarget(context, object_name);
GLenum texture_binding = getTextureBinding(texture_target);
glGetIntegerv(texture_binding, &bound_texture);
glBindTexture(texture_target, object_name);
@@ -994,7 +954,7 @@ getFramebufferAttachmentDesc(Context &context, GLenum target, GLenum attachment,
return desc.valid();
} else {
- std::cerr << "warning: unexpected GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = " << object_type << "\n";
+ std::cerr << "warning: unexpected GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = " << enumToString(object_type) << "\n";
return false;
}
}
@@ -1003,12 +963,6 @@ getFramebufferAttachmentDesc(Context &context, GLenum target, GLenum attachment,
image::Image *
getDrawBufferImage() {
- GLenum format = GL_RGB;
- GLint channels = _gl_format_channels(format);
- if (channels > 4) {
- return NULL;
- }
-
Context context;
GLenum framebuffer_binding;
@@ -1061,7 +1015,17 @@ getDrawBufferImage() {
desc.depth = 1;
}
+ GLenum format = GL_RGB;
GLenum type = GL_UNSIGNED_BYTE;
+ if (context.ES) {
+ format = GL_RGBA;
+ }
+
+ GLint channels = _gl_format_channels(format);
+ if (channels > 4) {
+ return NULL;
+ }
+
image::ChannelType channelType = image::TYPE_UNORM8;
if (format == GL_DEPTH_COMPONENT) {
@@ -1075,7 +1039,7 @@ getDrawBufferImage() {
return NULL;
}
- while (glGetError() != GL_NO_ERROR) {}
+ flushErrors();
GLint read_framebuffer = 0;
GLint read_buffer = GL_NONE;
@@ -1087,12 +1051,12 @@ getDrawBufferImage() {
glReadBuffer(draw_buffer);
}
- // TODO: reset imaging state too
- context.resetPixelPackState();
-
- glReadPixels(0, 0, desc.width, desc.height, format, type, image->pixels);
+ {
+ // TODO: reset imaging state too
+ PixelPackState pps(context);
+ glReadPixels(0, 0, desc.width, desc.height, format, type, image->pixels);
+ }
- context.restorePixelPackState();
if (!context.ES) {
glReadBuffer(read_buffer);
@@ -1117,36 +1081,67 @@ getDrawBufferImage() {
* Dump the image of the currently bound read buffer.
*/
static inline void
-dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format,
- GLint internalFormat = GL_NONE)
+dumpReadBufferImage(StateWriter &writer,
+ Context & context,
+ const char *label,
+ const char *userLabel,
+ GLint width, GLint height,
+ GLenum format, GLenum type,
+ GLenum internalFormat = GL_NONE)
{
- GLint channels = _gl_format_channels(format);
-
if (internalFormat == GL_NONE) {
internalFormat = format;
}
- Context context;
+ if (context.ES) {
+ switch (format) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL:
+ if (!context.NV_read_depth_stencil) {
+ return;
+ }
+ /* FIXME: NV_read_depth_stencil states that type must match the
+ * internal format, whereas we always request GL_FLOAT, as that's
+ * what we want. To fix this we should probe the adequate type
+ * here, and then manually convert the pixels to float after
+ * glReadPixels */
+ break;
+ case GL_STENCIL_INDEX:
+ if (!context.NV_read_depth_stencil) {
+ return;
+ }
+ type = GL_UNSIGNED_BYTE;
+ break;
+ default:
+ // Color formats -- GLES glReadPixels only supports the following combinations:
+ // - GL_RGBA and GL_UNSIGNED_BYTE
+ // - values of IMPLEMENTATION_COLOR_READ_FORMAT and IMPLEMENTATION_COLOR_READ_TYPE
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ }
+ }
- GLenum type = GL_UNSIGNED_BYTE;
- image::ChannelType channelType = image::TYPE_UNORM8;
+ GLuint channels;
+ image::ChannelType channelType;
+ getImageFormat(format, type, channels, channelType);
- if (format == GL_DEPTH_COMPONENT) {
- type = GL_FLOAT;
- channels = 1;
- channelType = image::TYPE_FLOAT;
+ if (0) {
+ std::cerr << enumToString(internalFormat) << " "
+ << enumToString(format) << " "
+ << enumToString(type) << "\n";
}
image::Image *image = new image::Image(width, height, channels, true, channelType);
- while (glGetError() != GL_NO_ERROR) {}
-
- // TODO: reset imaging state too
- context.resetPixelPackState();
+ flushErrors();
- glReadPixels(0, 0, width, height, format, type, image->pixels);
+ {
+ // TODO: reset imaging state too
+ PixelPackState pps(context);
- context.restorePixelPackState();
+ glReadPixels(0, 0, width, height, format, type, image->pixels);
+ }
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
@@ -1154,9 +1149,16 @@ dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format,
std::cerr << "warning: " << enumToString(error) << " while reading framebuffer\n";
error = glGetError();
} while(error != GL_NO_ERROR);
- json.writeNull();
} else {
- json.writeImage(image, formatToString(internalFormat));
+ if (userLabel) {
+ image->label = userLabel;
+ }
+
+ StateWriter::ImageDesc imageDesc;
+ imageDesc.format = formatToString(internalFormat);
+ writer.beginMember(label);
+ writer.writeImage(image, imageDesc);
+ writer.endMember();
}
delete image;
@@ -1173,12 +1175,16 @@ downsampledFramebuffer(Context &context,
{
GLuint fbo;
-
*numRbs = 0;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ GLboolean scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ if (scissor_test) {
+ glDisable(GL_SCISSOR_TEST);
+ }
+
{
// color buffer
glGenRenderbuffers(1, &rbs[*numRbs]);
@@ -1248,6 +1254,10 @@ downsampledFramebuffer(Context &context,
}
}
+ if (scissor_test) {
+ glEnable(GL_SCISSOR_TEST);
+ }
+
return fbo;
}
@@ -1256,7 +1266,7 @@ downsampledFramebuffer(Context &context,
* Dump images of current draw drawable/window.
*/
static void
-dumpDrawableImages(JSONWriter &json, Context &context)
+dumpDrawableImages(StateWriter &writer, Context &context)
{
GLint width, height;
@@ -1299,9 +1309,9 @@ dumpDrawableImages(JSONWriter &json, Context &context)
glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
#endif
GLenum format = alpha_bits ? GL_RGBA : GL_RGB;
- json.beginMember(enumToString(draw_buffer));
- dumpReadBufferImage(json, width, height, format);
- json.endMember();
+ GLenum type = GL_UNSIGNED_BYTE;
+
+ dumpReadBufferImage(writer, context, enumToString(draw_buffer), NULL, width, height, format, type);
// Restore original read buffer
if (!context.ES) {
@@ -1309,21 +1319,26 @@ dumpDrawableImages(JSONWriter &json, Context &context)
}
}
- if (!context.ES) {
+ if (!context.ES || context.NV_read_depth_stencil) {
GLint depth_bits = 0;
- glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
+ if (context.core) {
+ glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_DEPTH, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
+ } else {
+ glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
+ }
if (depth_bits) {
- json.beginMember("GL_DEPTH_COMPONENT");
- dumpReadBufferImage(json, width, height, GL_DEPTH_COMPONENT);
- json.endMember();
+ dumpReadBufferImage(writer, context, "GL_DEPTH_COMPONENT", NULL, width, height, GL_DEPTH_COMPONENT, GL_FLOAT);
}
GLint stencil_bits = 0;
- glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
+ if (context.core) {
+ glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
+ } else {
+ glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
+ }
if (stencil_bits) {
- json.beginMember("GL_STENCIL_INDEX");
- dumpReadBufferImage(json, width, height, GL_STENCIL_INDEX);
- json.endMember();
+ assert(stencil_bits <= 8);
+ dumpReadBufferImage(writer, context, "GL_STENCIL_INDEX", NULL, width, height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE);
}
}
@@ -1342,7 +1357,7 @@ dumpDrawableImages(JSONWriter &json, Context &context)
* In the case of a color attachment, it assumes it is already bound for read.
*/
static void
-dumpFramebufferAttachment(JSONWriter &json, Context &context, GLenum target, GLenum attachment, GLenum format = GL_NONE)
+dumpFramebufferAttachment(StateWriter &writer, Context &context, GLenum target, GLenum attachment)
{
ImageDesc desc;
if (!getFramebufferAttachmentDesc(context, target, attachment, desc)) {
@@ -1351,9 +1366,21 @@ dumpFramebufferAttachment(JSONWriter &json, Context &context, GLenum target, GLe
assert(desc.samples == 0);
- if (format == GL_NONE) {
+ GLenum format;
+ GLenum type;
+ switch (attachment) {
+ case GL_DEPTH_ATTACHMENT:
+ format = GL_DEPTH_COMPONENT;
+ type = GL_FLOAT;
+ break;
+ case GL_STENCIL_ATTACHMENT:
+ format = GL_STENCIL_INDEX;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ default:
assert(desc.internalFormat != GL_NONE);
- format = getFormat(desc.internalFormat);
+ const InternalFormatDesc &formatDesc = getInternalFormatDesc(desc.internalFormat);
+ chooseReadBackFormat(formatDesc, format, type);
}
GLint object_type = GL_NONE;
@@ -1366,22 +1393,62 @@ dumpFramebufferAttachment(JSONWriter &json, Context &context, GLenum target, GLe
&object_name);
char *object_label = getObjectLabel(context, object_type, object_name);
- std::stringstream label;
- label << enumToString(attachment);
- if (object_label) {
- label << ", \"" << object_label << "\"";
- free(object_label);
+ const char *label = enumToString(attachment);
+
+ if (object_type == GL_TEXTURE) {
+ GLint layered = GL_FALSE;
+ glGetFramebufferAttachmentParameteriv(target, attachment,
+ GL_FRAMEBUFFER_ATTACHMENT_LAYERED,
+ &layered);
+ if (layered &&
+ isGeometryShaderBound(context)) {
+ /*
+ * Dump the whole texture array.
+ *
+ * Unfortunately we can't tell whether the bound GS writes or not gl_Layer.
+ */
+
+ GLint level = 0;
+ glGetFramebufferAttachmentParameteriv(target, attachment,
+ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
+ &level);
+
+ GLenum texture_target = getTextureTarget(context, object_name);
+ GLenum texture_binding = getTextureBinding(texture_target);
+
+ GLint bound_texture = 0;
+ glGetIntegerv(texture_binding, &bound_texture);
+ glBindTexture(texture_target, object_name);
+
+ dumpActiveTextureLevel(writer, context, texture_target, level, label, object_label);
+
+ glBindTexture(texture_target, bound_texture);
+
+ free(object_label);
+ return;
+ }
}
- json.beginMember(label.str());
- dumpReadBufferImage(json, desc.width, desc.height, format, desc.internalFormat);
- json.endMember();
+
+ dumpReadBufferImage(writer, context,
+ label, object_label,
+ desc.width, desc.height,
+ format, type, desc.internalFormat);
+ free(object_label);
}
static void
-dumpFramebufferAttachments(JSONWriter &json, Context &context, GLenum target)
+dumpFramebufferAttachments(StateWriter &writer, Context &context, GLenum target)
{
+ GLenum status = glCheckFramebufferStatus(target);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ std::cerr
+ << "warning: incomplete " << enumToString(target)
+ << " (" << enumToString(status) << ")\n";
+ return;
+ }
+
GLint read_framebuffer = 0;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
@@ -1405,15 +1472,15 @@ dumpFramebufferAttachments(JSONWriter &json, Context &context, GLenum target)
std::cerr << "warning: unexpected GL_DRAW_BUFFER" << i << " = " << draw_buffer << "\n";
attachment = GL_COLOR_ATTACHMENT0;
}
- dumpFramebufferAttachment(json, context, target, attachment);
+ dumpFramebufferAttachment(writer, context, target, attachment);
}
}
glReadBuffer(read_buffer);
- if (!context.ES) {
- dumpFramebufferAttachment(json, context, target, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT);
- dumpFramebufferAttachment(json, context, target, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX);
+ if (!context.ES || context.NV_read_depth_stencil) {
+ dumpFramebufferAttachment(writer, context, target, GL_DEPTH_ATTACHMENT);
+ dumpFramebufferAttachment(writer, context, target, GL_STENCIL_ATTACHMENT);
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer);
@@ -1421,18 +1488,18 @@ dumpFramebufferAttachments(JSONWriter &json, Context &context, GLenum target)
void
-dumpFramebuffer(JSONWriter &json, Context &context)
+dumpFramebuffer(StateWriter &writer, Context &context)
{
- json.beginMember("framebuffer");
- json.beginObject();
+ writer.beginMember("framebuffer");
+ writer.beginObject();
GLint boundDrawFbo = 0, boundReadFbo = 0;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo);
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo);
if (!boundDrawFbo) {
- dumpDrawableImages(json, context);
+ dumpDrawableImages(writer, context);
} else if (context.ES) {
- dumpFramebufferAttachments(json, context, GL_FRAMEBUFFER);
+ dumpFramebufferAttachments(writer, context, GL_FRAMEBUFFER);
} else {
GLint draw_buffer0 = GL_NONE;
glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer0);
@@ -1477,7 +1544,7 @@ dumpFramebuffer(JSONWriter &json, Context &context)
glBindFramebuffer(GL_READ_FRAMEBUFFER, boundDrawFbo);
}
- dumpFramebufferAttachments(json, context, GL_READ_FRAMEBUFFER);
+ dumpFramebufferAttachments(writer, context, GL_READ_FRAMEBUFFER);
if (multisample) {
glBindRenderbuffer(GL_RENDERBUFFER, boundRb);
@@ -1489,8 +1556,8 @@ dumpFramebuffer(JSONWriter &json, Context &context)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo);
}
- json.endObject();
- json.endMember(); // framebuffer
+ writer.endObject();
+ writer.endMember(); // framebuffer
}
diff --git a/retrace/glstate_internal.hpp b/retrace/glstate_internal.hpp
index e31ee23f..789975a8 100644
--- a/retrace/glstate_internal.hpp
+++ b/retrace/glstate_internal.hpp
@@ -23,14 +23,17 @@
*
**************************************************************************/
-#ifndef _GLSTATE_INTERNAL_HPP_
-#define _GLSTATE_INTERNAL_HPP_
+#pragma once
+#include <stdint.h>
+
#include "glimports.hpp"
+#include "glproc.hpp"
+#include "image.hpp"
-class JSONWriter;
+class StateWriter;
namespace glstate {
@@ -38,22 +41,32 @@ namespace glstate {
struct Context
{
- bool ES;
-
- bool ARB_draw_buffers;
- bool ARB_sampler_objects;
- bool KHR_debug;
- bool EXT_debug_label;
+ unsigned ES:1;
+ unsigned core:1;
+
+ unsigned ARB_draw_buffers:1;
+ unsigned ARB_sampler_objects:1;
+ unsigned ARB_get_program_binary:1;
+ unsigned KHR_debug:1;
+ unsigned EXT_debug_label:1;
+ unsigned NV_read_depth_stencil:1; /* ES only */
+ unsigned ARB_shader_image_load_store:1;
+ unsigned ARB_direct_state_access:1;
Context(void);
+};
+
- void
- resetPixelPackState(void);
+class PixelPackState
+{
+public:
+ PixelPackState(const Context & context);
- void
- restorePixelPackState(void);
+ ~PixelPackState();
private:
+ bool ES;
+
// Pack state
GLint pack_alignment;
GLint pack_image_height;
@@ -67,25 +80,123 @@ private:
};
-void dumpBoolean(JSONWriter &json, GLboolean value);
+static inline void
+flushErrors(void) {
+ while (glGetError() != GL_NO_ERROR) {
+ }
+}
+
+
+
+const char *
+formatToString(GLenum internalFormat);
+
+
+struct InternalFormatDesc
+{
+ GLenum internalFormat;
+
+ /* The external format/type that matches the internalFormat exactly, or GL_NONE. */
+ GLenum format;
+ GLenum type;
+
+ /* The appropriate read type for dumping. */
+ GLenum readType;
+};
+
+
+const InternalFormatDesc &
+getInternalFormatDesc(GLenum internalFormat);
+
+void
+chooseReadBackFormat(const InternalFormatDesc &formatDesc, GLenum &format, GLenum &type);
+
+void
+getImageFormat(GLenum format, GLenum type,
+ GLuint &channels, image::ChannelType &channelType);
+
+
+// Abstract base class for pixel format conversion
+class PixelFormat
+{
+public:
+ virtual ~PixelFormat() {}
+
+ // Size in bytes
+ virtual size_t
+ size(void) const = 0;
+
+ // Unpack a span of pixels
+ virtual void
+ unpackSpan(const uint8_t *inSpan, float *outSpan, unsigned width) const = 0;
+};
+
+
+const PixelFormat *
+getPixelFormat(GLenum internalFormat);
+
+
+/**
+ * Helper class to temporarily bind a buffer to the specified target until
+ * control leaves the declaration scope.
+ */
+class BufferBinding
+{
+private:
+ GLenum target;
+ GLuint buffer;
+ GLuint prevBuffer;
+
+public:
+ BufferBinding(GLenum _target, GLuint _buffer);
+
+ ~BufferBinding();
+};
+
+
+/**
+ * Helper class to temporarily map a buffer (if necessary), and unmap when
+ * destroyed.
+ */
+class BufferMapping
+{
+ GLuint target;
+ GLuint buffer;
+ GLvoid *map_pointer;
+ bool unmap;
+
+public:
+ BufferMapping();
+
+ GLvoid *
+ map(GLenum _target, GLuint _buffer);
+
+ ~BufferMapping();
+};
+
+
+bool
+isGeometryShaderBound(Context &context);
+
+
+void dumpBoolean(StateWriter &writer, GLboolean value);
-void dumpEnum(JSONWriter &json, GLenum pname);
+void dumpEnum(StateWriter &writer, GLenum pname);
char *
getObjectLabel(Context &context, GLenum identifier, GLuint name);
-void dumpObjectLabel(JSONWriter &json, Context &context, GLenum identifier, GLuint name, const char *member);
+void dumpObjectLabel(StateWriter &writer, Context &context, GLenum identifier, GLuint name, const char *member);
-void dumpParameters(JSONWriter &json, Context &context);
+void dumpParameters(StateWriter &writer, Context &context);
-void dumpShadersUniforms(JSONWriter &json, Context &context);
+void dumpShadersUniforms(StateWriter &writer, Context &context);
-void dumpTextures(JSONWriter &json, Context &context);
+void dumpTextures(StateWriter &writer, Context &context);
-void dumpFramebuffer(JSONWriter &json, Context &context);
+void dumpFramebuffer(StateWriter &writer, Context &context);
} /* namespace glstate */
-#endif /* _GLSTATE_INTERNAL_HPP_ */
diff --git a/retrace/glstate_params.py b/retrace/glstate_params.py
index 46c1978f..fb49ff9a 100755
--- a/retrace/glstate_params.py
+++ b/retrace/glstate_params.py
@@ -84,7 +84,7 @@ class StateGetter(Visitor):
It will declare any temporary variable
'''
- def __init__(self, radical=None, inflections=None, suffix='', inflector=None, key=None):
+ def __init__(self, radical=None, inflections=None, suffix='', inflector=None, key=None, pnameIdx=-1):
if inflector is None:
assert radical is not None
assert inflections is not None
@@ -98,6 +98,7 @@ class StateGetter(Visitor):
self.key = self.inflector.key()
else:
self.key = key
+ self.pnameIdx = pnameIdx
def iter(self):
for function, type, count, name in parameters:
@@ -108,12 +109,12 @@ class StateGetter(Visitor):
yield type, count, name
def __call__(self, *args):
- pname = args[-1]
+ pname = args[self.pnameIdx]
for type, count, name in self.iter():
if name == pname:
if count != 1:
- type = Array(type, str(count))
+ type = Array(type, count)
return type, self.visit(type, args)
@@ -121,7 +122,7 @@ class StateGetter(Visitor):
def temp_name(self, args):
'''Return the name of a temporary variable to hold the state.'''
- pname = args[-1]
+ pname = args[self.pnameIdx]
return pname[3:].lower()
@@ -163,7 +164,7 @@ class StateGetter(Visitor):
inflection = self.inflector.inflect(array.type)
assert inflection.endswith('v' + self.inflector.suffix)
array_length = array.length
- if array_length.isdigit():
+ if isinstance(array_length, int):
# Static integer length
print ' %s %s[%s + 1];' % (elem_type, temp_name, array_length)
else:
@@ -205,6 +206,14 @@ glGet = StateGetter(inflector = glGet_inflector)
glGet_texture = StateGetter(inflector = glGet_inflector, key = 'glGet_texture')
+glGet_i = StateGetter('glGet', {
+ B: 'Booleani_v',
+ I: 'Integeri_v',
+ F: 'Floati_v',
+ D: 'Doublei_v',
+}, key = 'glGet_i', pnameIdx=0)
+
+
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'})
@@ -223,30 +232,30 @@ class JsonWriter(Visitor):
'''Type visitor that will dump a value of the specified type through the
JSON writer.
- It expects a previously declared JSONWriter instance named "json".'''
+ It expects a previously declared StateWriter instance named "writer".'''
def visitLiteral(self, literal, instance):
if literal.kind == 'Bool':
- print ' json.writeBool(%s);' % instance
+ print ' writer.writeBool(%s);' % instance
elif literal.kind in ('SInt', 'Uint'):
- print ' json.writeInt(%s);' % instance
+ print ' writer.writeInt(%s);' % instance
elif literal.kind in ('Float', 'Double'):
- print ' json.writeFloat(%s);' % instance
+ print ' writer.writeFloat(%s);' % instance
else:
raise NotImplementedError
def visitString(self, string, instance):
assert string.length is None
- print ' json.writeString((const char *)%s);' % instance
+ print ' writer.writeString((const char *)%s);' % instance
def visitEnum(self, enum, instance):
if enum is GLboolean:
- print ' dumpBoolean(json, %s);' % instance
+ print ' dumpBoolean(writer, %s);' % instance
elif enum is GLenum:
- print ' dumpEnum(json, %s);' % instance
+ print ' dumpEnum(writer, %s);' % instance
else:
assert False
- print ' json.writeInt(%s);' % instance
+ print ' writer.writeInt(%s);' % instance
def visitBitmask(self, bitmask, instance):
raise NotImplementedError
@@ -255,18 +264,18 @@ class JsonWriter(Visitor):
self.visit(alias.type, instance)
def visitOpaque(self, opaque, instance):
- print ' json.writeInt((size_t)%s);' % instance
+ print ' writer.writeInt((size_t)%s);' % instance
__index = 0
def visitArray(self, array, instance):
index = '_i%u' % JsonWriter.__index
JsonWriter.__index += 1
- print ' json.beginArray();'
+ print ' writer.beginArray();'
print ' for (unsigned %s = 0; %s < %s; ++%s) {' % (index, index, array.length, index)
self.visit(array.type, '%s[%s]' % (instance, index))
print ' }'
- print ' json.endArray();'
+ print ' writer.endArray();'
@@ -281,7 +290,7 @@ class StateDumper:
print '#include <assert.h>'
print '#include <string.h>'
print
- print '#include "json.hpp"'
+ print '#include "state_writer.hpp"'
print '#include "scoped_allocator.hpp"'
print '#include "glproc.hpp"'
print '#include "glsize.hpp"'
@@ -291,29 +300,6 @@ class StateDumper:
print 'namespace glstate {'
print
- print 'static void'
- print 'flushErrors(void) {'
- print ' while (glGetError() != GL_NO_ERROR) {}'
- print '}'
- print
-
- print 'void'
- print 'dumpBoolean(JSONWriter &json, GLboolean value)'
- print '{'
- print ' switch (value) {'
- print ' case GL_FALSE:'
- print ' json.writeString("GL_FALSE");'
- print ' break;'
- print ' case GL_TRUE:'
- print ' json.writeString("GL_TRUE");'
- print ' break;'
- print ' default:'
- print ' json.writeInt(static_cast<GLint>(value));'
- print ' break;'
- print ' }'
- print '}'
- print
-
print 'const char *'
print 'enumToString(GLenum pname)'
print '{'
@@ -327,71 +313,49 @@ class StateDumper:
print '}'
print
- print 'void'
- print 'dumpEnum(JSONWriter &json, GLenum pname)'
- print '{'
- print ' const char *s = enumToString(pname);'
- print ' if (s) {'
- print ' json.writeString(s);'
- print ' } else {'
- print ' json.writeInt(pname);'
- print ' }'
- print '}'
- print
-
print 'static void'
- print 'dumpTextureTargetParameters(JSONWriter &json, Context &context, GLenum target)'
+ print 'dumpTextureTargetParameters(StateWriter &writer, Context &context, GLenum target, GLuint texture)'
print '{'
- print ' GLenum binding_param = getTextureBinding(target);'
- print ' GLboolean enabled = GL_FALSE;'
- print ' GLint binding = 0;'
- print ' if (target != GL_TEXTURE_BUFFER) {'
- print ' // GL_TEXTURE_BUFFER is not a boolean, but a buffer binding parameter...'
- print ' glGetBooleanv(target, &enabled);'
- print ' }'
- print ' glGetIntegerv(binding_param, &binding);'
- print ' if (enabled || binding) {'
- print ' json.beginMember(enumToString(target));'
- print ' json.beginObject();'
- print ' dumpObjectLabel(json, context, GL_TEXTURE, binding, "GL_TEXTURE_LABEL");'
+ print ' writer.beginMember(enumToString(target));'
+ print ' writer.beginObject();'
+ print ' dumpObjectLabel(writer, context, GL_TEXTURE, texture, "GL_TEXTURE_LABEL");'
# ARB_texture_buffer forbids glGetTexParameter and
# glGetTexLevelParameter for TEXTURE_BUFFER, but
# ARB_texture_buffer_range introduced parameters which can be queries
# with glGetTexLevelParameter...
- print ' if (target != GL_TEXTURE_BUFFER) {'
+ print ' if (target != GL_TEXTURE_BUFFER) {'
self.dump_atoms(glGetTexParameter, 'target')
+ print ' }'
+ print ' if (!context.ES) {'
+ print ' GLenum levelTarget;'
+ print ' if (target == GL_TEXTURE_CUBE_MAP ||'
+ print ' target == GL_TEXTURE_CUBE_MAP_ARRAY) {'
+ print ' // Must pick a face'
+ print ' levelTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;'
+ print ' } else {'
+ print ' levelTarget = target;'
print ' }'
- print ' if (!context.ES) {'
- print ' GLenum levelTarget;'
- print ' if (target == GL_TEXTURE_CUBE_MAP ||'
- print ' target == GL_TEXTURE_CUBE_MAP_ARRAY) {'
- print ' // Must pick a face'
- print ' levelTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;'
- print ' } else {'
- print ' levelTarget = target;'
- print ' }'
self.dump_atoms(glGetTexLevelParameter, 'levelTarget', '0')
- print ' }'
- print ' json.endObject();'
- print ' json.endMember(); // target'
print ' }'
+ print ' writer.endObject();'
+ print ' writer.endMember(); // target'
print '}'
print
print 'static void'
- print 'dumpFramebufferAttachementParameters(JSONWriter &json, Context &context, GLenum target, GLenum attachment)'
+ print 'dumpFramebufferAttachementParameters(StateWriter &writer, Context &context, GLenum target, GLenum attachment)'
print '{'
self.dump_attachment_parameters('target', 'attachment')
print '}'
print
- print 'void dumpParameters(JSONWriter &json, Context &context)'
+ print 'void dumpParameters(StateWriter &writer, Context &context)'
print '{'
print ' ScopedAllocator _allocator;'
print ' (void)_allocator;'
print
- print ' json.beginMember("parameters");'
- print ' json.beginObject();'
+ print ' writer.beginMember("parameters");'
+ print ' writer.beginObject();'
self.dump_atoms(glGet)
@@ -404,8 +368,8 @@ class StateDumper:
self.dump_framebuffer_parameters()
self.dump_labels()
- print ' json.endObject();'
- print ' json.endMember(); // parameters'
+ print ' writer.endObject();'
+ print ' writer.endMember(); // parameters'
print '}'
print
@@ -414,10 +378,10 @@ class StateDumper:
def dump_material_params(self):
print ' if (!context.ES) {'
for face in ['GL_FRONT', 'GL_BACK']:
- print ' json.beginMember("%s");' % face
- print ' json.beginObject();'
+ print ' writer.beginMember("%s");' % face
+ print ' writer.beginObject();'
self.dump_atoms(glGetMaterial, face)
- print ' json.endObject();'
+ print ' writer.endObject();'
print ' }'
print
@@ -429,11 +393,11 @@ class StateDumper:
print ' if (glIsEnabled(light)) {'
print ' char name[32];'
print ' snprintf(name, sizeof name, "GL_LIGHT%i", index);'
- print ' json.beginMember(name);'
- print ' json.beginObject();'
+ print ' writer.beginMember(name);'
+ print ' writer.beginObject();'
self.dump_atoms(glGetLight, ' GL_LIGHT0 + index')
- print ' json.endObject();'
- print ' json.endMember(); // GL_LIGHTi'
+ print ' writer.endObject();'
+ print ' writer.endMember(); // GL_LIGHTi'
print ' }'
print ' }'
print
@@ -443,17 +407,17 @@ class StateDumper:
print ' if (context.ARB_sampler_objects) {'
print ' GLint sampler_binding = 0;'
print ' glGetIntegerv(GL_SAMPLER_BINDING, &sampler_binding);'
- print ' json.beginMember("GL_SAMPLER_BINDING");'
- print ' json.writeInt(sampler_binding);'
- print ' json.endMember();'
+ print ' writer.beginMember("GL_SAMPLER_BINDING");'
+ print ' writer.writeInt(sampler_binding);'
+ print ' writer.endMember();'
print ' if (sampler_binding) {'
- print ' json.beginMember("GL_SAMPLER");'
- print ' json.beginObject();'
- print ' dumpObjectLabel(json, context, GL_SAMPLER, sampler_binding, "GL_SAMPLER_LABEL");'
+ print ' writer.beginMember("GL_SAMPLER");'
+ print ' writer.beginObject();'
+ print ' dumpObjectLabel(writer, context, GL_SAMPLER, sampler_binding, "GL_SAMPLER_LABEL");'
for _, _, name in glGetSamplerParameter.iter():
self.dump_atom(glGetSamplerParameter, 'sampler_binding', name)
- print ' json.endObject();'
- print ' json.endMember(); // GL_SAMPLER'
+ print ' writer.endObject();'
+ print ' writer.endMember(); // GL_SAMPLER'
print ' }'
print ' }'
@@ -468,12 +432,12 @@ class StateDumper:
def dump_texenv_params(self):
for target in ['GL_TEXTURE_ENV', 'GL_TEXTURE_FILTER_CONTROL', 'GL_POINT_SPRITE']:
print ' if (!context.ES) {'
- print ' json.beginMember("%s");' % target
- print ' json.beginObject();'
+ print ' writer.beginMember("%s");' % target
+ print ' writer.beginObject();'
for _, _, name in glGetTexEnv.iter():
if self.texenv_param_target(name) == target:
self.dump_atom(glGetTexEnv, target, name)
- print ' json.endObject();'
+ print ' writer.endObject();'
print ' }'
def dump_vertex_attribs(self):
@@ -482,17 +446,17 @@ class StateDumper:
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();'
+ print ' writer.beginMember(name);'
+ print ' writer.beginObject();'
self.dump_atoms(glGetVertexAttrib, 'index')
# Dump vertex attrib buffer label
print ' GLint buffer_binding = 0;'
print ' glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_binding);'
- print ' dumpObjectLabel(json, context, GL_BUFFER, buffer_binding, "GL_VERTEX_ATTRIB_ARRAY_BUFFER_LABEL");'
+ print ' dumpObjectLabel(writer, context, GL_BUFFER, buffer_binding, "GL_VERTEX_ATTRIB_ARRAY_BUFFER_LABEL");'
- print ' json.endObject();'
- print ' json.endMember(); // GL_VERTEX_ATTRIB_ARRAYi'
+ print ' writer.endObject();'
+ print ' writer.endMember(); // GL_VERTEX_ATTRIB_ARRAYi'
print ' }'
print
@@ -527,7 +491,7 @@ class StateDumper:
print ' {'
print ' GLint binding = 0;'
print ' glGetIntegerv(%s, &binding);' % object_binding
- print ' dumpObjectLabel(json, context, %s, binding, "%s");' % (object_type, member_name)
+ print ' dumpObjectLabel(writer, context, %s, binding, "%s");' % (object_type, member_name)
print ' }'
program_targets = [
@@ -538,41 +502,63 @@ class StateDumper:
def dump_program_params(self):
for target in self.program_targets:
print ' if (glIsEnabled(%s)) {' % target
- print ' json.beginMember("%s");' % target
- print ' json.beginObject();'
+ print ' writer.beginMember("%s");' % target
+ print ' writer.beginObject();'
self.dump_atoms(glGetProgramARB, target)
- print ' json.endObject();'
+ print ' writer.endObject();'
print ' }'
buffer_targets = [
- ('GL_ARRAY_BUFFER', 'GL_ARRAY_BUFFER_BINDING'),
- # FIXME: Causes Mesa to segfault. Disable for now.
- #('GL_ATOMIC_COUNTER_BUFFER', 'GL_ATOMIC_COUNTER_BUFFER_BINDING'),
- ('GL_COPY_READ_BUFFER', 'GL_COPY_READ_BUFFER_BINDING'),
- ('GL_COPY_WRITE_BUFFER', 'GL_COPY_WRITE_BUFFER_BINDING'),
- ('GL_DRAW_INDIRECT_BUFFER', 'GL_DRAW_INDIRECT_BUFFER_BINDING'),
- ('GL_DISPATCH_INDIRECT_BUFFER', 'GL_DISPATCH_INDIRECT_BUFFER_BINDING'),
- ('GL_ELEMENT_ARRAY_BUFFER', 'GL_ELEMENT_ARRAY_BUFFER_BINDING'),
- ('GL_PIXEL_PACK_BUFFER', 'GL_PIXEL_PACK_BUFFER_BINDING'),
- ('GL_PIXEL_UNPACK_BUFFER', 'GL_PIXEL_UNPACK_BUFFER_BINDING'),
- ('GL_QUERY_BUFFER', 'GL_QUERY_BUFFER_BINDING'),
- ('GL_SHADER_STORAGE_BUFFER', 'GL_SHADER_STORAGE_BUFFER_BINDING'),
- ('GL_TEXTURE_BUFFER', 'GL_TEXTURE_BUFFER'),
- ('GL_TRANSFORM_FEEDBACK_BUFFER', 'GL_TRANSFORM_FEEDBACK_BUFFER_BINDING'),
- ('GL_UNIFORM_BUFFER', 'GL_UNIFORM_BUFFER_BINDING'),
+ ('GL_ARRAY_BUFFER', 'GL_ARRAY_BUFFER_BINDING', None),
+ # FIXME: Causes Mesa to segfault (issue #332). Disable for now.
+ #('GL_ATOMIC_COUNTER_BUFFER', 'GL_ATOMIC_COUNTER_BUFFER_BINDING', 'GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS'),
+ ('GL_COPY_READ_BUFFER', 'GL_COPY_READ_BUFFER_BINDING', None),
+ ('GL_COPY_WRITE_BUFFER', 'GL_COPY_WRITE_BUFFER_BINDING', None),
+ ('GL_DRAW_INDIRECT_BUFFER', 'GL_DRAW_INDIRECT_BUFFER_BINDING', None),
+ ('GL_DISPATCH_INDIRECT_BUFFER', 'GL_DISPATCH_INDIRECT_BUFFER_BINDING', None),
+ ('GL_ELEMENT_ARRAY_BUFFER', 'GL_ELEMENT_ARRAY_BUFFER_BINDING', None),
+ ('GL_PIXEL_PACK_BUFFER', 'GL_PIXEL_PACK_BUFFER_BINDING', None),
+ ('GL_PIXEL_UNPACK_BUFFER', 'GL_PIXEL_UNPACK_BUFFER_BINDING', None),
+ ('GL_QUERY_BUFFER', 'GL_QUERY_BUFFER_BINDING', None),
+ ('GL_SHADER_STORAGE_BUFFER', 'GL_SHADER_STORAGE_BUFFER_BINDING', 'GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS'),
+ ('GL_TEXTURE_BUFFER', 'GL_TEXTURE_BUFFER', None),
+ ('GL_TRANSFORM_FEEDBACK_BUFFER', 'GL_TRANSFORM_FEEDBACK_BUFFER_BINDING', 'GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS'),
+ ('GL_UNIFORM_BUFFER', 'GL_UNIFORM_BUFFER_BINDING', 'GL_MAX_UNIFORM_BUFFER_BINDINGS'),
]
def dump_buffer_parameters(self):
- for target, binding in self.buffer_targets:
+ # general binding points
+ for target, binding, max_bindings in self.buffer_targets:
+ print ' // %s' % target
print ' {'
+ print ' writer.beginMember("%s");' % target
+ print ' writer.beginObject();'
print ' GLint buffer = 0;'
print ' glGetIntegerv(%s, &buffer);' % binding
print ' if (buffer) {'
- print ' json.beginMember("%s");' % target
- print ' json.beginObject();'
self.dump_atoms(glGetBufferParameter, target)
- print ' json.endObject();'
print ' }'
+ if max_bindings is not None:
+ # indexed binding points
+ start = target + '_START'
+ size = target + '_SIZE'
+ print ' GLint max_bindings = 0;'
+ print ' glGetIntegerv(%s, &max_bindings);' % max_bindings
+ print ' if (max_bindings) {'
+ print ' writer.beginMember("i");'
+ print ' writer.beginArray();'
+ print ' for (GLint i = 0; i < max_bindings; ++i) {'
+ print ' writer.beginObject();'
+ for pname in [binding, start, size]:
+ self.dump_atom(glGet_i, pname, 'i')
+ print ' writer.endObject();'
+ print ' }'
+ print ' writer.endArray();'
+ print ' writer.endMember();'
+ print ' }'
+
+ print ' writer.endObject();'
+ print ' writer.endMember();'
print ' }'
print
@@ -581,22 +567,42 @@ class StateDumper:
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 ' if (!context.core) {'
+ print ' glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
+ print ' }'
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(std::max(max_combined_texture_image_units, max_texture_coords), 2);'
+ print ' max_combined_texture_image_units = std::max(max_combined_texture_image_units, 2);'
+ 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 ' writer.beginMember(name);'
print ' glActiveTexture(GL_TEXTURE0 + unit);'
- print ' json.beginObject();'
+ print ' writer.beginObject();'
print
self.dump_atoms(glGet_texture)
print
print ' for (unsigned i = 0; i < numTextureTargets; ++i) {'
print ' GLenum target = textureTargets[i];'
- print ' dumpTextureTargetParameters(json, context, target);'
+ print ' GLboolean enabled = GL_FALSE;'
+ print ' if (unit < max_texture_coords &&'
+ print ' (target == GL_TEXTURE_1D ||'
+ print ' target == GL_TEXTURE_2D ||'
+ print ' target == GL_TEXTURE_3D ||'
+ print ' target == GL_TEXTURE_CUBE_MAP ||'
+ print ' target == GL_TEXTURE_RECTANGLE)) {'
+ print ' glGetBooleanv(target, &enabled);'
+ print ' writer.beginMember(enumToString(target));'
+ print ' dumpBoolean(writer, enabled);'
+ print ' writer.endMember();'
+ print ' }'
+ print ' GLint texture = 0;'
+ print ' GLenum binding = getTextureBinding(target);'
+ print ' glGetIntegerv(binding, &texture);'
+ print ' if (enabled || texture) {'
+ print ' dumpTextureTargetParameters(writer, context, target, texture);'
+ print ' }'
print ' }'
print
self.dump_sampler_params()
@@ -604,8 +610,8 @@ class StateDumper:
print ' if (unit < max_texture_coords) {'
self.dump_texenv_params()
print ' }'
- print ' json.endObject();'
- print ' json.endMember(); // GL_TEXTUREi'
+ print ' writer.endObject();'
+ print ' writer.endMember(); // GL_TEXTUREi'
print ' }'
print ' glActiveTexture(active_texture);'
print ' }'
@@ -621,17 +627,17 @@ class StateDumper:
print ' framebuffer = 0;'
print ' glGetIntegerv(%s, &framebuffer);' % binding
print ' if (framebuffer) {'
- print ' json.beginMember("%s");' % target
- print ' json.beginObject();'
- print ' dumpObjectLabel(json, context, GL_FRAMEBUFFER, framebuffer, "GL_FRAMEBUFFER_LABEL");'
+ print ' writer.beginMember("%s");' % target
+ print ' writer.beginObject();'
+ print ' dumpObjectLabel(writer, context, GL_FRAMEBUFFER, framebuffer, "GL_FRAMEBUFFER_LABEL");'
print ' for (GLint i = 0; i < max_color_attachments; ++i) {'
print ' GLint color_attachment = GL_COLOR_ATTACHMENT0 + i;'
- print ' dumpFramebufferAttachementParameters(json, context, %s, color_attachment);' % target
+ print ' dumpFramebufferAttachementParameters(writer, context, %s, color_attachment);' % target
print ' }'
- print ' dumpFramebufferAttachementParameters(json, context, %s, GL_DEPTH_ATTACHMENT);' % target
- print ' dumpFramebufferAttachementParameters(json, context, %s, GL_STENCIL_ATTACHMENT);' % target
- print ' json.endObject();'
- print ' json.endMember(); // %s' % target
+ print ' dumpFramebufferAttachementParameters(writer, context, %s, GL_DEPTH_ATTACHMENT);' % target
+ print ' dumpFramebufferAttachementParameters(writer, context, %s, GL_STENCIL_ATTACHMENT);' % target
+ print ' writer.endObject();'
+ print ' writer.endMember(); // %s' % target
print ' }'
print
print ' }'
@@ -642,14 +648,14 @@ class StateDumper:
print ' GLint object_type = GL_NONE;'
print ' glGetFramebufferAttachmentParameteriv(%s, %s, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);' % (target, attachment)
print ' if (object_type != GL_NONE) {'
- print ' json.beginMember(enumToString(%s));' % attachment
- print ' json.beginObject();'
+ print ' writer.beginMember(enumToString(%s));' % attachment
+ print ' writer.beginObject();'
self.dump_atoms(glGetFramebufferAttachmentParameter, target, attachment)
print ' GLint object_name = 0;'
print ' glGetFramebufferAttachmentParameteriv(%s, %s, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &object_name);' % (target, attachment)
- print ' dumpObjectLabel(json, context, object_type, object_name, "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_LABEL");'
- print ' json.endObject();'
- print ' json.endMember(); // GL_x_ATTACHMENT'
+ print ' dumpObjectLabel(writer, context, object_type, object_name, "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_LABEL");'
+ print ' writer.endObject();'
+ print ' writer.endMember(); // GL_x_ATTACHMENT'
print ' }'
print ' }'
@@ -658,7 +664,7 @@ class StateDumper:
self.dump_atom(getter, *(args + (name,)))
def dump_atom(self, getter, *args):
- name = args[-1]
+ name = args[getter.pnameIdx]
print ' // %s' % name
print ' {'
@@ -668,9 +674,9 @@ class StateDumper:
#print ' std::cerr << "warning: %s(%s) failed\\n";' % (inflection, name)
print ' flushErrors();'
print ' } else {'
- print ' json.beginMember("%s");' % name
+ print ' writer.beginMember("%s");' % name
JsonWriter().visit(type, value)
- print ' json.endMember();'
+ print ' writer.endMember();'
print ' }'
print ' }'
print
diff --git a/retrace/glstate_shaders.cpp b/retrace/glstate_shaders.cpp
index 825e3aeb..2db1bfb9 100644
--- a/retrace/glstate_shaders.cpp
+++ b/retrace/glstate_shaders.cpp
@@ -26,13 +26,15 @@
#include <assert.h>
#include <string.h>
+#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <sstream>
+#include <vector>
-#include "json.hpp"
+#include "state_writer.hpp"
#include "glproc.hpp"
#include "glsize.hpp"
#include "glstate.hpp"
@@ -77,45 +79,13 @@ getShaderSource(ShaderMap &shaderMap, GLuint shader)
}
-static void
-getShaderObjSource(ShaderMap &shaderMap, GLhandleARB shaderObj)
+static inline void
+dumpProgram(StateWriter &writer, Context &context, GLint program)
{
- if (!shaderObj) {
- return;
- }
-
- GLint object_type = 0;
- glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &object_type);
- if (object_type != GL_SHADER_OBJECT_ARB) {
- return;
- }
-
- GLint shader_type = 0;
- glGetObjectParameterivARB(shaderObj, GL_OBJECT_SUBTYPE_ARB, &shader_type);
- if (!shader_type) {
+ if (program <= 0) {
return;
}
- GLint source_length = 0;
- glGetObjectParameterivARB(shaderObj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &source_length);
- if (!source_length) {
- return;
- }
-
- GLcharARB *source = new GLcharARB[source_length];
- GLsizei length = 0;
- source[0] = 0;
- glGetShaderSource(shaderObj, source_length, &length, source);
-
- shaderMap[enumToString(shader_type)] += source;
-
- delete [] source;
-}
-
-
-static inline void
-dumpProgram(JSONWriter &json, GLint program)
-{
GLint attached_shaders = 0;
glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
if (!attached_shaders) {
@@ -134,45 +104,72 @@ dumpProgram(JSONWriter &json, GLint program)
delete [] shaders;
for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
- json.beginMember(it->first);
- json.writeString(it->second);
- json.endMember();
- }
-}
-
-
-static inline void
-dumpProgramObj(JSONWriter &json, GLhandleARB programObj)
-{
- GLint attached_shaders = 0;
- glGetObjectParameterivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders);
- if (!attached_shaders) {
- return;
+ writer.beginMember(it->first);
+ writer.writeString(it->second);
+ writer.endMember();
}
- ShaderMap shaderMap;
-
- GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders];
- GLsizei count = 0;
- glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs);
- std::sort(shaderObjs, shaderObjs + count);
- for (GLsizei i = 0; i < count; ++ i) {
- getShaderObjSource(shaderMap, shaderObjs[i]);
- }
- delete [] shaderObjs;
-
- for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
- json.beginMember(it->first);
- json.writeString(it->second);
- json.endMember();
+ // Dump NVIDIA GPU programs via GL_ARB_get_program_binary
+ if (context.ARB_get_program_binary) {
+ GLint binaryLength = 0;
+ glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
+ if (binaryLength > 0) {
+ std::vector<char> binary(binaryLength);
+ GLenum format = GL_NONE;
+ glGetProgramBinary(program, binaryLength, NULL, &format, &binary[0]);
+ if (format == 0x8e21) {
+ if (0) {
+ FILE *fp = fopen("program.bin", "wb");
+ if (fp) {
+ fwrite(&binary[0], 1, binaryLength, fp);
+ fclose(fp);
+ }
+ }
+
+ // Extract NVIDIA GPU programs
+ std::string str(binary.begin(), binary.end());
+ size_t end = 0;
+ while (true) {
+ // Each program starts with a !!NV header token
+ size_t start = str.find("!!NV", end);
+ if (start == std::string::npos) {
+ break;
+ }
+
+ // And is preceeded by a length DWORD
+ assert(start >= end + 4);
+ if (start < end + 4) {
+ break;
+ }
+ uint32_t length;
+ str.copy(reinterpret_cast<char *>(&length), 4, start - 4);
+ assert(start + length <= binaryLength);
+ if (start + length > binaryLength) {
+ break;
+ }
+
+ std::string nvProg = str.substr(start, length);
+
+ size_t eol = nvProg.find('\n');
+ std::string nvHeader = nvProg.substr(2, eol - 2);
+
+ writer.beginMember(nvHeader);
+ writer.writeString(nvProg);
+ writer.endMember();
+
+ end = start + length;
+ }
+ }
+ }
}
}
+
/**
- * Built-in uniforms can't be queried through glGetUniform*.
+ * Built-in uniforms/attributes need special treatment.
*/
static inline bool
-isBuiltinUniform(const GLchar *name)
+isBuiltinName(const GLchar *name)
{
return name[0] == 'g' && name[1] == 'l' && name[2] == '_';
}
@@ -203,78 +200,157 @@ resolveUniformName(const GLchar *name, GLint size)
}
-static void
-dumpUniformValues(JSONWriter &json, GLenum type, const void *values, GLint matrix_stride = 0, GLboolean is_row_major = GL_FALSE) {
- GLenum elemType;
- GLint numCols, numRows;
- _gl_uniform_size(type, elemType, numCols, numRows);
- if (!numCols || !numRows) {
- json.writeNull();
- }
+struct AttribDesc
+{
+ GLenum type = GL_NONE;
+ GLenum size = 0;
- size_t elemSize = _gl_type_size(elemType);
+ GLenum elemType = GL_NONE;
+ GLint elemStride = 0;
- GLint row_stride = 0;
- GLint col_stride = 0;
- if (is_row_major) {
- row_stride = elemSize;
- col_stride = matrix_stride ? matrix_stride : numRows * elemSize;
- } else {
- col_stride = elemSize;
- row_stride = matrix_stride ? matrix_stride : numCols * elemSize;
+ GLint numCols = 0;
+ GLint numRows = 0;
+
+ GLsizei rowStride = 0;
+ GLsizei colStride = 0;
+
+ GLsizei arrayStride = 0;
+
+ AttribDesc(void)
+ {}
+
+ AttribDesc(GLenum _type,
+ GLint _size,
+ GLint array_stride = 0,
+ GLint matrix_stride = 0,
+ GLboolean is_row_major = GL_FALSE) :
+ type(_type),
+ size(_size)
+ {
+ _gl_uniform_size(type, elemType, numCols, numRows);
+
+ elemStride = _gl_type_size(elemType);
+
+ rowStride = 0;
+ colStride = 0;
+ if (is_row_major) {
+ rowStride = elemStride;
+ if (!matrix_stride) {
+ matrix_stride = numRows * elemStride;
+ }
+ colStride = matrix_stride;
+ if (!array_stride) {
+ arrayStride = numCols * colStride;
+ }
+ } else {
+ colStride = elemStride;
+ if (!matrix_stride) {
+ matrix_stride = numCols * elemStride;
+ }
+ rowStride = matrix_stride;
+ if (!array_stride) {
+ arrayStride = numRows * rowStride;
+ }
+ }
}
- if (numRows > 1) {
- json.beginArray();
+ inline
+ operator bool (void) const {
+ return elemType != GL_NONE;
+ }
+};
+
+
+static void
+dumpAttrib(StateWriter &writer,
+ const AttribDesc &desc,
+ const GLbyte *data)
+{
+ assert(desc);
+
+ if (desc.numRows > 1) {
+ writer.beginArray();
}
- for (GLint row = 0; row < numRows; ++row) {
- if (numCols > 1) {
- json.beginArray();
+ for (GLint row = 0; row < desc.numRows; ++row) {
+ if (desc.numCols > 1) {
+ writer.beginArray();
}
- for (GLint col = 0; col < numCols; ++col) {
+ for (GLint col = 0; col < desc.numCols; ++col) {
union {
const GLbyte *rawvalue;
const GLfloat *fvalue;
const GLdouble *dvalue;
const GLint *ivalue;
const GLuint *uivalue;
+ const GLint64 *i64value;
+ const GLuint64 *ui64value;
} u;
- u.rawvalue = (const GLbyte *)values + row*row_stride + col*col_stride;
+ u.rawvalue = data + row*desc.rowStride + col*desc.colStride;
- switch (elemType) {
+ switch (desc.elemType) {
case GL_FLOAT:
- json.writeFloat(*u.fvalue);
+ writer.writeFloat(*u.fvalue);
break;
case GL_DOUBLE:
- json.writeFloat(*u.dvalue);
+ writer.writeFloat(*u.dvalue);
break;
case GL_INT:
- json.writeInt(*u.ivalue);
+ writer.writeInt(*u.ivalue);
break;
case GL_UNSIGNED_INT:
- json.writeInt(*u.uivalue);
+ writer.writeInt(*u.uivalue);
+ break;
+ case GL_INT64_ARB:
+ writer.writeInt(*u.i64value);
+ break;
+ case GL_UNSIGNED_INT64_ARB:
+ writer.writeInt(*u.ui64value);
break;
case GL_BOOL:
- json.writeBool(*u.uivalue);
+ writer.writeBool(*u.uivalue);
break;
default:
assert(0);
- json.writeNull();
+ writer.writeNull();
break;
}
}
- if (numCols > 1) {
- json.endArray();
+ if (desc.numCols > 1) {
+ writer.endArray();
}
}
- if (numRows > 1) {
- json.endArray();
+ if (desc.numRows > 1) {
+ writer.endArray();
+ }
+}
+
+
+static void
+dumpAttribArray(StateWriter &writer,
+ const std::string & name,
+ const AttribDesc &desc,
+ const GLbyte *data)
+{
+ writer.beginMember(name);
+ if (desc.size > 1) {
+ writer.beginArray();
+ }
+
+ for (GLint i = 0; i < desc.size; ++i) {
+ const GLbyte *row = data + desc.arrayStride*i;
+
+ dumpAttrib(writer, desc, row);
+ }
+
+ if (desc.size > 1) {
+ writer.endArray();
}
+ writer.endMember();
}
@@ -282,7 +358,14 @@ dumpUniformValues(JSONWriter &json, GLenum type, const void *values, GLint matri
* Dump an uniform that belows to an uniform block.
*/
static void
-dumpUniformBlock(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name, GLuint index, GLuint block_index) {
+dumpUniformBlock(StateWriter &writer,
+ GLint program,
+ GLint size,
+ GLenum type,
+ const GLchar *name,
+ GLuint index,
+ GLuint block_index)
+{
GLint offset = 0;
GLint array_stride = 0;
@@ -299,6 +382,11 @@ dumpUniformBlock(JSONWriter &json, GLint program, GLint size, GLenum type, const
return;
}
+ AttribDesc desc(type, size, array_stride, matrix_stride, is_row_major);
+ if (!desc) {
+ return;
+ }
+
if (0) {
GLint active_uniform_block_max_name_length = 0;
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &active_uniform_block_max_name_length);
@@ -312,58 +400,36 @@ dumpUniformBlock(JSONWriter &json, GLint program, GLint size, GLenum type, const
glGetActiveUniformBlockName(program, index, active_uniform_block_max_name_length, &length, block_name);
std::cerr
- << "uniform `" << name << "`, size " << size << ", type " << enumToString(type) << "\n"
+ << "uniform `" << name << "`, size " << size << ", type " << enumToString(desc.type) << "\n"
<< " block " << block_index << ", name `" << block_name << "`, size " << block_data_size << "; binding " << slot << "; \n"
<< " offset " << offset << ", array stride " << array_stride << ", matrix stride " << matrix_stride << ", row_major " << is_row_major << "\n"
;
- delete block_name;
+ delete [] block_name;
}
GLint ubo = 0;
glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, slot, &ubo);
+ GLint start = 0;
+ glGetIntegeri_v(GL_UNIFORM_BUFFER_START, slot, &start);
- GLint previous_ubo = 0;
- glGetIntegerv(GL_UNIFORM_BUFFER_BINDING, &previous_ubo);
-
- glBindBuffer(GL_UNIFORM_BUFFER, ubo);
-
- const GLbyte *raw_data = (const GLbyte *)glMapBuffer(GL_UNIFORM_BUFFER, GL_READ_ONLY);
+ BufferMapping mapping;
+ const GLbyte *raw_data = (const GLbyte *)mapping.map(GL_UNIFORM_BUFFER, ubo);
if (raw_data) {
std::string qualifiedName = resolveUniformName(name, size);
- for (GLint i = 0; i < size; ++i) {
- std::stringstream ss;
- ss << qualifiedName;
-
- if (size > 1) {
- ss << '[' << i << ']';
- }
-
- std::string elemName = ss.str();
-
- json.beginMember(elemName);
-
- const GLbyte *row = raw_data + offset + array_stride*i;
-
- dumpUniformValues(json, type, row, matrix_stride, is_row_major);
-
- json.endMember();
- }
-
- glUnmapBuffer(GL_UNIFORM_BUFFER);
+ dumpAttribArray(writer, qualifiedName, desc, raw_data + start + offset);
}
-
- glBindBuffer(GL_UNIFORM_BUFFER, previous_ubo);
}
static void
-dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name) {
- GLenum elemType;
- GLint numCols, numRows;
- _gl_uniform_size(type, elemType, numCols, numRows);
- if (elemType == GL_NONE) {
+dumpUniform(StateWriter &writer,
+ GLint program,
+ const AttribDesc & desc,
+ const GLchar *name)
+{
+ if (desc.elemType == GL_NONE) {
return;
}
@@ -372,20 +438,26 @@ dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLch
GLdouble dvalues[4*4];
GLint ivalues[4*4];
GLuint uivalues[4*4];
+ GLint64 i64values[4*4];
+ GLuint64 ui64values[4*4];
+ GLbyte data[4*4*4];
} u;
GLint i;
- std::string qualifiedName = resolveUniformName(name, size);
+ std::string qualifiedName = resolveUniformName(name, desc.size);
- for (i = 0; i < size; ++i) {
+ writer.beginMember(qualifiedName);
+ if (desc.size > 1) {
+ writer.beginArray();
+ }
+
+ for (i = 0; i < desc.size; ++i) {
std::stringstream ss;
ss << qualifiedName;
-
- if (size > 1) {
+ if (desc.size > 1) {
ss << '[' << i << ']';
}
-
std::string elemName = ss.str();
GLint location = glGetUniformLocation(program, elemName.c_str());
@@ -394,9 +466,7 @@ dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLch
continue;
}
- json.beginMember(elemName);
-
- switch (elemType) {
+ switch (desc.elemType) {
case GL_FLOAT:
glGetUniformfv(program, location, u.fvalues);
break;
@@ -409,6 +479,12 @@ dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLch
case GL_UNSIGNED_INT:
glGetUniformuiv(program, location, u.uivalues);
break;
+ case GL_INT64_ARB:
+ glGetUniformi64vARB(program, location, u.i64values);
+ break;
+ case GL_UNSIGNED_INT64_ARB:
+ glGetUniformui64vARB(program, location, u.ui64values);
+ break;
case GL_BOOL:
glGetUniformiv(program, location, u.ivalues);
break;
@@ -417,84 +493,19 @@ dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLch
break;
}
- dumpUniformValues(json, type, &u);
-
- json.endMember();
+ dumpAttrib(writer, desc, u.data);
}
-}
-
-static void
-dumpUniformARB(JSONWriter &json, GLhandleARB programObj, GLint size, GLenum type, const GLchar *name) {
- GLenum elemType;
- GLint numCols, numRows;
- _gl_uniform_size(type, elemType, numCols, numRows);
- GLint numElems = numCols * numRows;
- if (elemType == GL_NONE) {
- return;
+ if (desc.size > 1) {
+ writer.endArray();
}
- GLfloat fvalues[4*4];
- union {
- GLdouble dvalues[4*4];
- GLfloat fvalues[4*4];
- GLint ivalues[4*4];
- } u;
-
- GLint i, j;
-
- std::string qualifiedName = resolveUniformName(name, size);
-
- for (i = 0; i < size; ++i) {
- std::stringstream ss;
- ss << qualifiedName;
-
- if (size > 1) {
- ss << '[' << i << ']';
- }
-
- std::string elemName = ss.str();
-
- json.beginMember(elemName);
-
- GLint location = glGetUniformLocationARB(programObj, elemName.c_str());
- if (location == -1) {
- continue;
- }
-
- switch (elemType) {
- case GL_DOUBLE:
- // glGetUniformdvARB does not exists
- glGetUniformfvARB(programObj, location, fvalues);
- for (j = 0; j < numElems; ++j) {
- u.dvalues[j] = fvalues[j];
- }
- break;
- case GL_FLOAT:
- glGetUniformfvARB(programObj, location, fvalues);
- break;
- case GL_UNSIGNED_INT:
- // glGetUniformuivARB does not exists
- case GL_INT:
- glGetUniformivARB(programObj, location, u.ivalues);
- break;
- case GL_BOOL:
- glGetUniformivARB(programObj, location, u.ivalues);
- break;
- default:
- assert(0);
- break;
- }
-
- dumpUniformValues(json, type, &u);
-
- json.endMember();
- }
+ writer.endMember();
}
static inline void
-dumpProgramUniforms(JSONWriter &json, GLint program)
+dumpProgramUniforms(StateWriter &writer, GLint program)
{
GLint active_uniforms = 0;
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniforms);
@@ -515,20 +526,21 @@ dumpProgramUniforms(JSONWriter &json, GLint program)
GLenum type = GL_NONE;
glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name);
- if (isBuiltinUniform(name)) {
+ if (isBuiltinName(name)) {
continue;
}
GLint location = glGetUniformLocation(program, name);
if (location != -1) {
- dumpUniform(json, program, size, type, name);
+ AttribDesc desc(type, size);
+ dumpUniform(writer, program, desc, name);
continue;
}
GLint block_index = -1;
glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_BLOCK_INDEX, &block_index);
if (block_index != -1) {
- dumpUniformBlock(json, program, size, type, name, index, block_index);
+ dumpUniformBlock(writer, program, size, type, name, index, block_index);
continue;
}
@@ -542,43 +554,178 @@ dumpProgramUniforms(JSONWriter &json, GLint program)
}
-static inline void
-dumpProgramObjUniforms(JSONWriter &json, GLhandleARB programObj)
+// Calculate how many elements (or vertices) can fit in the specified buffer.
+static unsigned
+calcNumElements(GLsizei bufferSize,
+ GLsizei elemOffset,
+ GLsizei elemSize,
+ GLsizei elemStride)
{
- GLint active_uniforms = 0;
- glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &active_uniforms);
- if (!active_uniforms) {
- return;
+ if (0 >= bufferSize ||
+ elemOffset >= bufferSize ||
+ elemOffset + elemSize >= bufferSize) {
+ return 0;
}
- GLint active_uniform_max_length = 0;
- glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &active_uniform_max_length);
- GLchar *name = new GLchar[active_uniform_max_length];
- if (!name) {
+ assert(elemStride >= 0);
+ if (elemStride < 0) {
+ return 1;
+ }
+
+ if (elemStride == 0) {
+ // XXX: It should be infinite, but lets return something more manageable here.
+ return 0x10000;
+ }
+
+ return (bufferSize - elemOffset - elemSize) / elemStride;
+}
+
+
+struct TransformFeedbackAttrib {
+ std::string name;
+ AttribDesc desc;
+ GLsizei offset;
+ GLsizei stride;
+ GLsizei size;
+ BufferMapping mapping;
+ const GLbyte *map;
+};
+
+
+static inline void
+dumpTransformFeedback(StateWriter &writer, GLint program)
+{
+ GLint transform_feedback_varyings = 0;
+ glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &transform_feedback_varyings);
+ if (!transform_feedback_varyings) {
return;
}
- for (GLint index = 0; index < active_uniforms; ++index) {
+ GLint max_name_length = 0;
+ glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_name_length);
+ std::vector<GLchar> name(max_name_length);
+
+ GLint buffer_mode = GL_INTERLEAVED_ATTRIBS;
+ glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &buffer_mode);
+
+ std::vector<TransformFeedbackAttrib> attribs(transform_feedback_varyings);
+
+ // Calculate the offsets and strides of each attribute according to
+ // the value of GL_TRANSFORM_FEEDBACK_BUFFER_MODE
+ GLsizei cum_attrib_offset = 0;
+ for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) {
+ TransformFeedbackAttrib & attrib = attribs[slot];
+
GLsizei length = 0;
- GLint size = 0;
+ GLsizei size = 0;
GLenum type = GL_NONE;
- glGetActiveUniformARB(programObj, index, active_uniform_max_length, &length, &size, &type, name);
+ glGetTransformFeedbackVarying(program, slot, max_name_length, &length, &size, &type, &name[0]);
+
+ attrib.name = &name[0];
+
+ const AttribDesc & desc = attrib.desc = AttribDesc(type, size);
+ if (!desc) {
+ return;
+ }
+
+ attrib.size = desc.arrayStride;
+
+ switch (buffer_mode) {
+ case GL_INTERLEAVED_ATTRIBS:
+ attrib.offset = cum_attrib_offset;
+ break;
+ case GL_SEPARATE_ATTRIBS:
+ attrib.offset = 0;
+ attrib.stride = desc.arrayStride;
+ break;
+ default:
+ assert(0);
+ attrib.offset = 0;
+ attrib.stride = 0;
+ }
- if (isBuiltinUniform(name)) {
- continue;
+ cum_attrib_offset += desc.arrayStride;
}
+ if (buffer_mode == GL_INTERLEAVED_ATTRIBS) {
+ for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) {
+ TransformFeedbackAttrib & attrib = attribs[slot];
+ attrib.stride = cum_attrib_offset;
+ }
+ }
+
+ GLint previous_tbo = 0;
+ glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &previous_tbo);
+
+ // Map the buffers and calculate how many vertices can they hold
+ // XXX: We currently limit to 1024, or things can get significantly slow.
+ unsigned numVertices = 16*1024;
+ for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) {
+ TransformFeedbackAttrib & attrib = attribs[slot];
+ attrib.map = NULL;
+ if (slot == 0 || buffer_mode != GL_INTERLEAVED_ATTRIBS) {
+ GLint tbo = 0;
+ glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, slot, &tbo);
+ if (!tbo) {
+ numVertices = 0;
+ continue;
+ }
- dumpUniformARB(json, programObj, size, type, name);
+ GLint start = 0;
+ glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_START, slot, &start);
+ GLint size = 0;
+ glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, slot, &size);
+
+ glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);
+
+ if (size == 0) {
+ glGetBufferParameteriv(GL_TRANSFORM_FEEDBACK_BUFFER, GL_BUFFER_SIZE, &size);
+ assert(size >= start);
+ size -= start;
+ }
+
+ unsigned numAttribVertices = calcNumElements(size,
+ attrib.offset,
+ attrib.size,
+ attrib.stride);
+ numVertices = std::min(numVertices, numAttribVertices);
+
+ attrib.map = (const GLbyte *)attrib.mapping.map(GL_TRANSFORM_FEEDBACK_BUFFER, tbo) + start;
+ } else {
+ attrib.map = attribs[0].map;
+ }
}
+ glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, previous_tbo);
+
+ // Actually dump the vertices
+ writer.beginMember("GL_TRANSFORM_FEEDBACK");
+ writer.beginArray();
+ for (unsigned vertex = 0; vertex < numVertices; ++vertex) {
+ writer.beginObject();
+ for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) {
+ TransformFeedbackAttrib & attrib = attribs[slot];
+ if (!attrib.map) {
+ continue;
+ }
- delete [] name;
+ const AttribDesc & desc = attrib.desc;
+ assert(desc);
+
+ const GLbyte *vertex_data = attrib.map + attrib.stride*vertex + attrib.offset;
+ dumpAttribArray(writer, attrib.name, desc, vertex_data);
+ }
+ writer.endObject();
+ }
+ writer.endArray();
+ writer.endMember();
}
static inline void
-dumpArbProgram(JSONWriter &json, GLenum target)
+dumpArbProgram(StateWriter &writer, Context &context, GLenum target)
{
- if (!glIsEnabled(target)) {
+ if (context.ES ||
+ context.core ||
+ !glIsEnabled(target)) {
return;
}
@@ -593,18 +740,20 @@ dumpArbProgram(JSONWriter &json, GLenum target)
glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
source[program_length] = 0;
- json.beginMember(enumToString(target));
- json.writeString(source);
- json.endMember();
+ writer.beginMember(enumToString(target));
+ writer.writeString(source);
+ writer.endMember();
delete [] source;
}
static inline void
-dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix)
+dumpArbProgramUniforms(StateWriter &writer, Context &context, GLenum target, const char *prefix)
{
- if (!glIsEnabled(target)) {
+ if (context.ES ||
+ context.core ||
+ !glIsEnabled(target)) {
return;
}
@@ -627,14 +776,14 @@ dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix)
char name[256];
snprintf(name, sizeof name, "%sprogram.local[%i]", prefix, index);
- json.beginMember(name);
- json.beginArray();
- json.writeFloat(params[0]);
- json.writeFloat(params[1]);
- json.writeFloat(params[2]);
- json.writeFloat(params[3]);
- json.endArray();
- json.endMember();
+ writer.beginMember(name);
+ writer.beginArray();
+ writer.writeFloat(params[0]);
+ writer.writeFloat(params[1]);
+ writer.writeFloat(params[2]);
+ writer.writeFloat(params[3]);
+ writer.endArray();
+ writer.endMember();
}
GLint max_program_env_parameters = 0;
@@ -650,31 +799,179 @@ dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix)
char name[256];
snprintf(name, sizeof name, "%sprogram.env[%i]", prefix, index);
- json.beginMember(name);
- json.beginArray();
- json.writeFloat(params[0]);
- json.writeFloat(params[1]);
- json.writeFloat(params[2]);
- json.writeFloat(params[3]);
- json.endArray();
- json.endMember();
+ writer.beginMember(name);
+ writer.beginArray();
+ writer.writeFloat(params[0]);
+ writer.writeFloat(params[1]);
+ writer.writeFloat(params[2]);
+ writer.writeFloat(params[3]);
+ writer.endArray();
+ writer.endMember();
}
}
static void
-dumpProgramUniformsStage(JSONWriter &json, GLint program, const char *stage)
+dumpProgramUniformsStage(StateWriter &writer, GLint program, const char *stage)
{
- if (program) {
- json.beginMember(stage);
- json.beginObject();
- dumpProgramUniforms(json, program);
- json.endObject();
- json.endMember();
+ if (program <= 0) {
+ return;
+ }
+
+ writer.beginMember(stage);
+ writer.beginObject();
+ dumpProgramUniforms(writer, program);
+ writer.endObject();
+ writer.endMember();
+}
+
+struct VertexAttrib {
+ std::string name;
+ AttribDesc desc;
+ GLsizei offset = 0;
+ GLsizei stride = 0;
+ GLsizei size = 0;
+ const GLbyte *map;
+};
+
+static void
+dumpVertexAttributes(StateWriter &writer, Context &context, GLint program)
+{
+ if (program <= 0) {
+ return;
+ }
+
+ GLint activeAttribs = 0;
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
+ if (!activeAttribs) {
+ return;
+ }
+
+ GLint max_name_length = 0;
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length);
+ std::vector<GLchar> name(max_name_length);
+
+ std::map<GLuint, BufferMapping> mappings;
+ std::vector<VertexAttrib> attribs;
+ unsigned count = ~0U;
+
+ for (GLint index = 0; index < activeAttribs; ++index) {
+ GLsizei length = 0;
+ GLint shaderSize = 0;
+ GLenum shaderType = GL_NONE;
+ glGetActiveAttrib(program, index, max_name_length, &length, &shaderSize, &shaderType, &name[0]);
+
+ if (isBuiltinName(&name[0])) {
+ // TODO: Handle built-ins too
+ std::cerr << "warning: dumping of built-in vertex attribute (" << &name[0] << ") not yet supported\n";
+ continue;
+ }
+
+ GLint location = glGetAttribLocation(program, &name[0]);
+ if (location < 0) {
+ continue;
+ }
+
+ GLint buffer = 0;
+ glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer);
+ if (!buffer) {
+ continue;
+ }
+
+
+
+ GLint size = 0;
+ glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size);
+ GLint type = 0;
+ glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type);
+ GLint normalized = 0;
+ glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized);
+ GLint stride = 0;
+ glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride);
+ GLvoid * pointer = 0;
+ glGetVertexAttribPointerv(location, GL_VERTEX_ATTRIB_ARRAY_POINTER, &pointer);
+
+ GLint offset = reinterpret_cast<intptr_t>(pointer);
+ assert(offset >= 0);
+
+ GLint divisor = 0;
+ glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor);
+ if (divisor) {
+ // TODO: not clear the best way of presenting instanced attibutes on the dump
+ std::cerr << "warning: dumping of instanced attributes (" << &name[0] << ") not yet supported\n";
+ return;
+ }
+
+ if (size == GL_BGRA) {
+ std::cerr << "warning: dumping of GL_BGRA attributes (" << &name[0] << ") not yet supported\n";
+ size = 4;
+ }
+
+ AttribDesc desc(type, size);
+ if (!desc) {
+ std::cerr << "warning: dumping of packed attribute (" << &name[0] << ") not yet supported\n";
+ // TODO: handle
+ continue;
+ }
+
+ attribs.emplace_back();
+ VertexAttrib &attrib = attribs.back();
+ attrib.name = &name[0];
+
+ // TODO handle normalized attributes
+ if (normalized) {
+ std::cerr << "warning: dumping of normalized attribute (" << &name[0] << ") not yet supported\n";
+ }
+
+ attrib.desc = desc;
+ GLsizei attribSize = attrib.desc.arrayStride;
+
+ if (stride == 0) {
+ // tightly packed
+ stride = attribSize;
+ }
+
+ attrib.offset = offset;
+ attrib.stride = stride;
+
+ BufferMapping &mapping = mappings[buffer];
+ attrib.map = (const GLbyte *)mapping.map(GL_ARRAY_BUFFER, buffer);
+
+ BufferBinding bb(GL_ARRAY_BUFFER, buffer);
+ GLint bufferSize = 0;
+ glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bufferSize);
+
+ if (bufferSize <= offset ||
+ bufferSize <= offset + attribSize) {
+ return;
+ } else {
+ unsigned attribCount = (bufferSize - offset - attribSize)/stride + 1;
+ count = std::min(count, attribCount);
+ }
+ }
+
+ if (count == 0 || count == ~0U || attribs.empty()) {
+ return;
+ }
+
+ writer.beginMember("vertices");
+ writer.beginArray();
+ for (unsigned vertex = 0; vertex < count; ++vertex) {
+ writer.beginObject();
+ for (auto attrib : attribs) {
+ const AttribDesc & desc = attrib.desc;
+ assert(desc);
+
+ const GLbyte *vertex_data = attrib.map + attrib.stride*vertex + attrib.offset;
+ dumpAttribArray(writer, attrib.name, desc, vertex_data);
+ }
+ writer.endObject();
}
+ writer.endArray();
+ writer.endMember();
}
void
-dumpShadersUniforms(JSONWriter &json, Context &context)
+dumpShadersUniforms(StateWriter &writer, Context &context)
{
GLint pipeline = 0;
GLint vertex_program = 0;
@@ -697,53 +994,109 @@ dumpShadersUniforms(JSONWriter &json, Context &context)
}
GLint program = 0;
- GLhandleARB programObj = 0;
if (!pipeline) {
glGetIntegerv(GL_CURRENT_PROGRAM, &program);
- if (!context.ES && !program) {
- programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
- }
}
- json.beginMember("shaders");
- json.beginObject();
+ writer.beginMember("shaders");
+ writer.beginObject();
if (pipeline) {
- dumpProgram(json, vertex_program);
- dumpProgram(json, fragment_program);
- dumpProgram(json, geometry_program);
- dumpProgram(json, tess_control_program);
- dumpProgram(json, tess_evaluation_program);
- dumpProgram(json, compute_program);
+ dumpProgram(writer, context, vertex_program);
+ dumpProgram(writer, context, fragment_program);
+ dumpProgram(writer, context, geometry_program);
+ dumpProgram(writer, context, tess_control_program);
+ dumpProgram(writer, context, tess_evaluation_program);
+ dumpProgram(writer, context, compute_program);
} else if (program) {
- dumpProgram(json, program);
- } else if (programObj) {
- dumpProgramObj(json, programObj);
+ dumpProgram(writer, context, program);
} else {
- dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB);
- dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB);
+ dumpArbProgram(writer, context, GL_FRAGMENT_PROGRAM_ARB);
+ dumpArbProgram(writer, context, GL_VERTEX_PROGRAM_ARB);
}
- json.endObject();
- json.endMember(); // shaders
+ writer.endObject();
+ writer.endMember(); // shaders
- json.beginMember("uniforms");
- json.beginObject();
+ writer.beginMember("uniforms");
+ writer.beginObject();
if (pipeline) {
- dumpProgramUniformsStage(json, vertex_program, "GL_VERTEX_SHADER");
- dumpProgramUniformsStage(json, fragment_program, "GL_FRAGMENT_SHADER");
- dumpProgramUniformsStage(json, geometry_program, "GL_GEOMETRY_SHADER");
- dumpProgramUniformsStage(json, tess_control_program, "GL_TESS_CONTROL_SHADER");
- dumpProgramUniformsStage(json, tess_evaluation_program, "GL_TESS_EVALUATION_SHADER");
- dumpProgramUniformsStage(json, compute_program, "GL_COMPUTE_SHADER");
+ dumpProgramUniformsStage(writer, vertex_program, "GL_VERTEX_SHADER");
+ dumpProgramUniformsStage(writer, fragment_program, "GL_FRAGMENT_SHADER");
+ dumpProgramUniformsStage(writer, geometry_program, "GL_GEOMETRY_SHADER");
+ dumpProgramUniformsStage(writer, tess_control_program, "GL_TESS_CONTROL_SHADER");
+ dumpProgramUniformsStage(writer, tess_evaluation_program, "GL_TESS_EVALUATION_SHADER");
+ dumpProgramUniformsStage(writer, compute_program, "GL_COMPUTE_SHADER");
} else if (program) {
- dumpProgramUniforms(json, program);
- } else if (programObj) {
- dumpProgramObjUniforms(json, programObj);
+ dumpProgramUniforms(writer, program);
} else {
- dumpArbProgramUniforms(json, GL_FRAGMENT_PROGRAM_ARB, "fp.");
- dumpArbProgramUniforms(json, GL_VERTEX_PROGRAM_ARB, "vp.");
+ dumpArbProgramUniforms(writer, context, GL_FRAGMENT_PROGRAM_ARB, "fp.");
+ dumpArbProgramUniforms(writer, context, GL_VERTEX_PROGRAM_ARB, "vp.");
+ }
+ writer.endObject();
+ writer.endMember(); // uniforms
+
+ writer.beginMember("buffers");
+ writer.beginObject();
+ if (pipeline) {
+ dumpVertexAttributes(writer, context, vertex_program);
+ } else {
+ dumpVertexAttributes(writer, context, program);
+ }
+ if (program) {
+ dumpTransformFeedback(writer, program);
}
- json.endObject();
- json.endMember(); // uniforms
+ writer.endObject();
+ writer.endMember(); // buffers
+}
+
+
+bool
+isGeometryShaderBound(Context &context)
+{
+ GLint pipeline = 0;
+ GLint program = 0;
+
+ if (!context.ES) {
+ glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING, &pipeline);
+ if (pipeline) {
+ glGetProgramPipelineiv(pipeline, GL_GEOMETRY_SHADER, &program);
+ }
+ }
+
+ if (!pipeline) {
+ glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+ }
+
+ if (!program) {
+ return false;
+ }
+
+ GLint attached_shaders = 0;
+ glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
+ if (!attached_shaders) {
+ return false;
+ }
+
+ GLuint *shaders = new GLuint[attached_shaders];
+ GLsizei count = 0;
+ glGetAttachedShaders(program, attached_shaders, &count, shaders);
+ for (GLsizei i = 0; i < count; ++i) {
+ GLuint shader = shaders[i];
+ if (!shader) {
+ continue;
+ }
+
+ GLint shader_type = 0;
+ glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type);
+
+ if (shader_type == GL_GEOMETRY_SHADER) {
+ delete [] shaders;
+ return true;
+ }
+ }
+
+ delete [] shaders;
+
+ return false;
}
diff --git a/retrace/glws.cpp b/retrace/glws.cpp
index 2c0fa51e..4d036ca3 100644
--- a/retrace/glws.cpp
+++ b/retrace/glws.cpp
@@ -25,6 +25,7 @@
#include <assert.h>
+#include <stdlib.h>
#include <iostream>
@@ -35,15 +36,6 @@
namespace glws {
-void
-getProfileVersion(Profile profile, unsigned &major, unsigned &minor, bool &core)
-{
- major = (profile >> 4) & 0xf;
- minor = profile & 0xf;
- core = isCoreProfile(profile);
-}
-
-
bool
checkExtension(const char *extName, const char *extString)
{
@@ -82,48 +74,36 @@ Drawable::copySubBuffer(int x, int y, int width, int height) {
}
-bool
-Context::hasExtension(const char *string) {
- if (extensions.empty()) {
- unsigned major, minor;
- bool core;
- getProfileVersion(profile, major, minor, core);
- if (major >= 3) {
- // Use glGetStringi
- GLint num_extensions = 0;
- glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
- assert(num_extensions);
- for (int i = 0; i < num_extensions; ++i) {
- const char *extension = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
- assert(extension);
- if (extension) {
- extensions.insert(extension);
- }
- }
+void
+Context::initialize(void)
+{
+ assert(!initialized);
+
+ actualProfile = glprofile::getCurrentContextProfile();
+ actualExtensions.getCurrentContextExtensions(actualProfile);
+
+ /* Ensure we got a matching profile.
+ *
+ * In particular on MacOSX, there is no way to specify specific versions, so this is all we can do.
+ *
+ * Also, see if OpenGL ES can be handled through ARB_ES*_compatibility.
+ */
+ glprofile::Profile expectedProfile = profile;
+ if (!actualProfile.matches(expectedProfile)) {
+ if (expectedProfile.api == glprofile::API_GLES &&
+ actualProfile.api == glprofile::API_GL &&
+ ((expectedProfile.major == 2 && actualExtensions.has("GL_ARB_ES2_compatibility")) ||
+ (expectedProfile.major == 3 && actualExtensions.has("GL_ARB_ES3_compatibility")))) {
+ std::cerr << "warning: context mismatch:"
+ << " expected " << expectedProfile << ","
+ << " but got " << actualProfile << " with GL_ARB_ES" << expectedProfile.major << "_compatibility\n";
} else {
- // Use glGetString
- const char *begin = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
- assert(begin);
- do {
- const char *end = begin;
- char c = *end;
- while (c != '\0' && c != ' ') {
- ++end;
- c = *end;
- }
- if (end != begin) {
- extensions.insert(std::string(begin, end));
- }
-
- if (c == '\0') {
- break;
- }
- begin = end + 1;
- } while(1);
+ std::cerr << "error: context mismatch: expected " << expectedProfile << ", but got " << actualProfile << "\n";
+ exit(1);
}
}
- return extensions.find(string) != extensions.end();
+ initialized = true;
}
diff --git a/retrace/glws.hpp b/retrace/glws.hpp
index 9ecbc12f..fd234c5a 100644
--- a/retrace/glws.hpp
+++ b/retrace/glws.hpp
@@ -27,50 +27,38 @@
* Abstraction for GL window system specific APIs (GLX, WGL).
*/
-#ifndef _GLWS_HPP_
-#define _GLWS_HPP_
+#pragma once
#include <assert.h>
#include <vector>
-#include <set>
#include <string>
+#include "glprofile.hpp"
-namespace glws {
-
-
-enum Profile {
- PROFILE_COMPAT = 0x000,
- PROFILE_3_0 = 0x030,
- PROFILE_3_1 = 0x031,
- PROFILE_3_2_CORE = 0x132,
- PROFILE_3_3_CORE = 0x133,
- PROFILE_4_0_CORE = 0x140,
- PROFILE_4_1_CORE = 0x141,
- PROFILE_4_2_CORE = 0x142,
- PROFILE_4_3_CORE = 0x143,
- PROFILE_4_4_CORE = 0x144,
- PROFILE_ES1 = 0x210,
- PROFILE_ES2 = 0x220,
- PROFILE_MAX
-};
+namespace glws {
-static inline bool
-isCoreProfile(Profile profile) {
- return (profile & 0x100) == 0x100;
-}
+using glprofile::Profile;
-void
-getProfileVersion(Profile profile, unsigned &major, unsigned &minor, bool &core);
+class Drawable;
bool
checkExtension(const char *extName, const char *extString);
+// Extra info for creating PBuffers
+struct pbuffer_info
+{
+ int texFormat; // GL_RGB, GL_RGBA, or GL_NONE
+ int texTarget; // GL_TEXTURE_1D/2D/CUBE_MAP or GL_NONE
+ bool texMipmap; // 0 or 1 (false/true)
+
+ Drawable *hdc_drawable; // Needed for WGL Pbuffers
+};
+
template< class T >
class Attributes {
@@ -132,12 +120,18 @@ public:
bool pbuffer;
bool visible;
+ // For WGL_ARB_render_texture
+ glws::pbuffer_info pbInfo;
+ int mipmapLevel, cubeFace;
+
Drawable(const Visual *vis, int w, int h, bool pb) :
visual(vis),
width(w),
height(h),
pbuffer(pb),
- visible(false)
+ visible(false),
+ mipmapLevel(0),
+ cubeFace(0)
{}
virtual ~Drawable() {}
@@ -164,20 +158,35 @@ class Context
{
public:
const Visual *visual;
+
+ // Requested profile
Profile profile;
-
- std::set<std::string> extensions;
+
+ // Created profile
+ Profile actualProfile;
+ glprofile::Extensions actualExtensions;
Context(const Visual *vis) :
visual(vis),
- profile(vis->profile)
+ profile(vis->profile),
+ actualProfile(profile),
+ initialized(false)
{}
virtual ~Context() {}
- // Context must be current
- bool
- hasExtension(const char *extension);
+ // Context must have been made current once
+ inline bool
+ hasExtension(const char *extension) const {
+ assert(initialized);
+ return actualExtensions.has(extension);
+ }
+
+private:
+ bool initialized;
+ void initialize(void);
+
+ friend bool makeCurrent(Drawable *, Context *);
};
@@ -188,22 +197,41 @@ void
cleanup(void);
Visual *
-createVisual(bool doubleBuffer = false, unsigned samples = 1, Profile profile = PROFILE_COMPAT);
+createVisual(bool doubleBuffer, unsigned samples, Profile profile);
Drawable *
-createDrawable(const Visual *visual, int width, int height, bool pbuffer = false);
+createDrawable(const Visual *visual, int width, int height,
+ const glws::pbuffer_info *pbInfo = NULL);
Context *
createContext(const Visual *visual, Context *shareContext = 0, bool debug = false);
bool
-makeCurrent(Drawable *drawable, Context *context);
+makeCurrentInternal(Drawable *drawable, Context *context);
+
+inline bool
+makeCurrent(Drawable *drawable, Context *context)
+{
+ bool success = makeCurrentInternal(drawable, context);
+ if (success && context && !context->initialized) {
+ context->initialize();
+ }
+ return success;
+}
bool
processEvents(void);
+// iBuffer is one of GL_FRONT/BACK_LEFT/RIGHT, GL_AUX0...
+bool
+bindTexImage(Drawable *pBuffer, int iBuffer);
-} /* namespace glws */
+// iBuffer is one of GL_FRONT/BACK_LEFT/RIGHT, GL_AUX0...
+bool
+releaseTexImage(Drawable *pBuffer, int iBuffer);
+
+bool
+setPbufferAttrib(Drawable *pBuffer, const int *attribList);
-#endif /* _GLWS_HPP_ */
+} /* namespace glws */
diff --git a/retrace/glws_cocoa.mm b/retrace/glws_cocoa.mm
index 7c8935f4..f8b32926 100644
--- a/retrace/glws_cocoa.mm
+++ b/retrace/glws_cocoa.mm
@@ -53,6 +53,9 @@
/**
* Dummy thread to force Cocoa to enter multithreading mode.
+ *
+ * See also:
+ * - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
*/
@interface DummyThread : NSObject
+ (void)enterMultiThreaded;
@@ -102,8 +105,8 @@ public:
NSOpenGLView *view;
NSOpenGLContext *currentContext;
- CocoaDrawable(const Visual *vis, int w, int h, bool pbuffer) :
- Drawable(vis, w, h, pbuffer),
+ CocoaDrawable(const Visual *vis, int w, int h, const pbuffer_info *info) :
+ Drawable(vis, w, h, info),
currentContext(nil)
{
NSOpenGLPixelFormat *pixelFormat = static_cast<const CocoaVisual *>(visual)->pixelFormat;
@@ -126,11 +129,11 @@ public:
[window setContentView:view];
[window setTitle:@"glretrace"];
-
}
~CocoaDrawable() {
- [window release];
+ [view release];
+ [window close];
}
void
@@ -141,6 +144,8 @@ public:
[window setContentSize:NSMakeSize(w, h)];
+ processEvents();
+
if (currentContext != nil) {
[currentContext update];
[window makeKeyAndOrderFront:nil];
@@ -195,7 +200,8 @@ initThread(void) {
void
init(void) {
// Prevent glproc to load system's OpenGL, so that we can trace glretrace.
- _libGlHandle = dlopen("OpenGL", RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
+ _libGlHandle = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
+ assert(_libGlHandle);
initThread();
@@ -209,7 +215,11 @@ init(void) {
[NSApplication sharedApplication];
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
[NSApp finishLaunching];
+
+ [NSApp activateIgnoringOtherApps:YES];
}
@@ -233,40 +243,41 @@ createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
}
attribs.add(NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)1);
attribs.add(NSOpenGLPFAStencilSize, (NSOpenGLPixelFormatAttribute)1);
- switch (profile) {
- case PROFILE_COMPAT:
- break;
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
- case PROFILE_3_3_CORE:
- case PROFILE_4_0_CORE:
- case PROFILE_4_1_CORE:
+
+ if (profile.api != glprofile::API_GL) {
+ return NULL;
+ }
+
+ // We snap 3.1 to 3.2 core, as allowed by GLX/WGL_ARB_create_context
+ if (profile.versionGreaterOrEqual(3, 1) || profile.core) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
/*
- * Fall-through.
- *
* kCGLOGLPVersion_GL4_Core doesn't seem to work as expected. The
* recommended approach is to use NSOpenGLProfileVersion3_2Core and
* then check the OpenGL version.
- *
- * TODO: Actually check the OpenGL version (the first time the OpenGL
- * context is bound).
*/
-#endif
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
- case PROFILE_3_0:
- case PROFILE_3_1:
- case PROFILE_3_2_CORE:
attribs.add(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
- break;
+#else
+ return NULL;
#endif
- default:
+ } else if (profile.versionGreaterOrEqual(3, 0)) {
+ // Compatibility profile is not supported
return NULL;
}
// Use Apple software rendering for debugging purposes.
+ // TODO: Allow to control this via command line options.
if (0) {
attribs.add(NSOpenGLPFARendererID, 0x00020200); // kCGLRendererGenericID
}
+ // Force hardware acceleration
+ // https://developer.apple.com/library/mac/qa/qa1502/_index.html
+ if (0) {
+ attribs.add(NSOpenGLPFAAccelerated);
+ attribs.add(NSOpenGLPFANoRecovery);
+ }
+
attribs.end();
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc]
@@ -276,11 +287,12 @@ createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
}
Drawable *
-createDrawable(const Visual *visual, int width, int height, bool pbuffer)
+createDrawable(const Visual *visual, int width, int height,
+ const pbuffer_info *info)
{
initThread();
- return new CocoaDrawable(visual, width, height, pbuffer);
+ return new CocoaDrawable(visual, width, height, info);
}
Context *
@@ -305,7 +317,7 @@ createContext(const Visual *visual, Context *shareContext, bool debug)
}
bool
-makeCurrent(Drawable *drawable, Context *context)
+makeCurrentInternal(Drawable *drawable, Context *context)
{
initThread();
@@ -342,5 +354,26 @@ processEvents(void) {
return true;
}
+bool
+bindTexImage(Drawable *pBuffer, int iBuffer) {
+ std::cerr << "error: Cocoa::wglBindTexImageARB not implemented.\n";
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
+bool
+releaseTexImage(Drawable *pBuffer, int iBuffer) {
+ std::cerr << "error: Cocoa::wglReleaseTexImageARB not implemented.\n";
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
+bool
+setPbufferAttrib(Drawable *pBuffer, const int *attribList) {
+ // nothing to do here.
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
} /* namespace glws */
diff --git a/retrace/glws_egl_android.cpp b/retrace/glws_egl_android.cpp
new file mode 100644
index 00000000..377d91bf
--- /dev/null
+++ b/retrace/glws_egl_android.cpp
@@ -0,0 +1,745 @@
+/**************************************************************************
+ *
+ * Copyright 2011 LunarG, Inc.
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2015 BogDan Vatra
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <atomic>
+#include <cassert>
+#include <condition_variable>
+#include <cstdlib>
+#include <future>
+#include <iostream>
+#include <memory>
+#include <mutex>
+#include <vector>
+#include <regex>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <android/native_window_jni.h>
+#include <android/log.h>
+
+#include "glproc.hpp"
+#include "glws.hpp"
+
+
+extern "C" int main(int, char **);
+
+namespace glws {
+static char TAG[]="apitrace";
+
+static JavaVM *s_javaVM = nullptr;
+static jobject s_activityObject = nullptr;
+static std::mutex s_activityObjectMutex;
+
+static jmethodID s_setSurfaceSizeMethodID = nullptr;
+
+static jfieldID s_descriptor = nullptr;
+
+typedef std::shared_ptr<ANativeWindow> AndroidWindow;
+static AndroidWindow s_currentNativeWindow;
+static std::atomic_int s_currentNativeWindowId(0);
+static std::mutex s_currentNativeWindowMutex;
+
+static int s_stdout_fd = -1;
+static int s_stderr_fd = -1;
+static std::mutex s_stateMutex;
+static std::condition_variable s_stateWait;
+
+static EGLDisplay eglDisplay = EGL_NO_DISPLAY;
+static char const *eglExtensions = NULL;
+static bool has_EGL_KHR_create_context = false;
+struct ResourceTracker;
+
+static std::mutex s_resourcesMutex;
+static std::vector<ResourceTracker*> s_resources;
+
+class FdWriter : public std::streambuf
+{
+public:
+ FdWriter(int fd)
+ {
+ m_fd = fd;
+ int opts = fcntl(m_fd, F_GETFL);
+ opts = opts & (~O_NONBLOCK);
+ fcntl(m_fd, F_SETFL, opts);
+ }
+
+ // basic_streambuf interface
+protected:
+ std::streamsize xsputn(const char_type *__s, std::streamsize __n)
+ {
+ std::streamsize ret = 0;
+ while( __n ) {
+ ssize_t written = write(m_fd, __s, __n);
+ if (written > 0) {
+ __n -= written;
+ __s += written;
+ ret += written;
+ } else {
+ switch (errno) {
+ case EBADF:
+ case EINVAL:
+ case EPIPE:
+ std::exit(1);
+ break;
+ }
+ }
+ }
+ return ret;
+ }
+
+ int_type overflow(int_type __c)
+ {
+ return xsputn(reinterpret_cast<const char_type *>(&__c), 1) == 1 ? __c : traits_type::eof();
+ }
+
+private:
+ int m_fd = -1;
+};
+
+static EGLenum
+translateAPI(glprofile::Profile profile)
+{
+ switch (profile.api) {
+ case glprofile::API_GL:
+ return EGL_OPENGL_API;
+ case glprofile::API_GLES:
+ return EGL_OPENGL_ES_API;
+ default:
+ assert(0);
+ return EGL_NONE;
+ }
+}
+
+
+/* Must be called before
+ *
+ * - eglCreateContext
+ * - eglGetCurrentContext
+ * - eglGetCurrentDisplay
+ * - eglGetCurrentSurface
+ * - eglMakeCurrent (when its ctx parameter is EGL_NO_CONTEXT ),
+ * - eglWaitClient
+ * - eglWaitNative
+ */
+static void
+bindAPI(EGLenum api)
+{
+ if (eglBindAPI(api) != EGL_TRUE) {
+ std::cerr << "error: eglBindAPI failed\n";
+ exit(1);
+ }
+}
+
+struct EglVisual : public Visual
+{
+ EglVisual(Profile prof) : Visual(prof) {}
+ EGLConfig config = 0;
+ EGLint format = -1;
+};
+
+struct ResourceTracker
+{
+ ResourceTracker()
+ {
+ s_resourcesMutex.lock();
+ s_resources.push_back(this);
+ s_resourcesMutex.unlock();
+ }
+
+ virtual ~ResourceTracker()
+ {
+ s_resourcesMutex.lock();
+ s_resources.erase(std::find(s_resources.begin(), s_resources.end(), this));
+ s_resourcesMutex.unlock();
+ }
+};
+
+class EglDrawable : public Drawable, private ResourceTracker
+{
+public:
+ EglDrawable(const Visual *vis, int w, int h, const pbuffer_info *info) :
+ Drawable(vis, w, h, info),
+ api(EGL_OPENGL_ES_API),
+ windowId(0)
+ {
+ eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+ const EglVisual * eglVisual = static_cast<const EglVisual *>(visual);
+ update();
+ ANativeWindow_setBuffersGeometry(window.get(), 0, 0, eglVisual->format);
+ surface = eglCreateWindowSurface(eglDisplay, eglVisual->config, window.get(), NULL);
+ }
+
+ ~EglDrawable()
+ {
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(eglDisplay, surface);
+ eglWaitClient();
+ eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+ }
+
+ void recreate(void)
+ {
+ EGLContext currentContext = eglGetCurrentContext();
+ EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+ EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
+ bool rebindDrawSurface = currentDrawSurface == surface;
+ bool rebindReadSurface = currentReadSurface == surface;
+
+ if (rebindDrawSurface || rebindReadSurface) {
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(eglDisplay, surface);
+ }
+
+ const EglVisual * eglVisual = static_cast<const EglVisual *>(visual);
+ ANativeWindow_setBuffersGeometry(window.get(), 0, 0, eglVisual->format);
+ surface = eglCreateWindowSurface(eglDisplay, eglVisual->config, (EGLNativeWindowType)window.get(), NULL);
+
+ if (rebindDrawSurface || rebindReadSurface)
+ eglMakeCurrent(eglDisplay, surface, surface, currentContext);
+ }
+
+ void
+ resize(int w, int h) {
+ if (w == width && h == height) {
+ return;
+ }
+ eglWaitClient();
+ Drawable::resize(w, h);
+ resizeSurface(w, h);
+ }
+
+ void show(void) {
+ if (visible) {
+ return;
+ }
+ eglWaitClient();
+ eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+ Drawable::show();
+ }
+
+ void swapBuffers(void) {
+ if (update())
+ recreate();
+ bindAPI(api);
+ eglSwapBuffers(eglDisplay, surface);
+ }
+
+private:
+ inline bool update()
+ {
+ if (windowId.load() == s_currentNativeWindowId.load())
+ return false;
+
+ s_currentNativeWindowMutex.lock();
+ window = s_currentNativeWindow;
+ windowId.store(s_currentNativeWindowId.load());
+ s_currentNativeWindowMutex.unlock();
+ return true;
+ }
+
+ void resizeSurface(int w, int h)
+ {
+ JNIEnv *env = nullptr;
+ if (JNI_OK != s_javaVM->AttachCurrentThread(&env, nullptr)) {
+ __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed");
+ std::exit(1);
+ }
+ s_activityObjectMutex.lock();
+ env->CallVoidMethod(s_activityObject, s_setSurfaceSizeMethodID, w, h);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ s_activityObjectMutex.unlock();
+ s_javaVM->DetachCurrentThread();
+ }
+
+public:
+ EGLSurface surface;
+ EGLenum api;
+
+private:
+ AndroidWindow window;
+ std::atomic_int windowId;
+};
+
+
+class EglContext : public Context, private ResourceTracker
+{
+public:
+ EGLContext context;
+
+ EglContext(const Visual *vis, EGLContext ctx) :
+ Context(vis),
+ context(ctx)
+ {}
+
+ ~EglContext() {
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(eglDisplay, context);
+ }
+};
+
+void
+init(void) {
+ eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (eglDisplay == EGL_NO_DISPLAY) {
+ std::cerr << "error: unable to get EGL display\n";
+ exit(1);
+ }
+
+ EGLint major, minor;
+ if (!eglInitialize(eglDisplay, &major, &minor)) {
+ std::cerr << "error: unable to initialize EGL display\n";
+ exit(1);
+ }
+
+ eglExtensions = eglQueryString(eglDisplay, EGL_EXTENSIONS);
+ has_EGL_KHR_create_context = checkExtension("EGL_KHR_create_context", eglExtensions);
+}
+
+void
+cleanup(void) {
+ while (!s_resources.empty()) {
+ delete *s_resources.rbegin();
+ }
+
+ if (eglDisplay != EGL_NO_DISPLAY) {
+ eglTerminate(eglDisplay);
+ }
+ eglDisplay = EGL_NO_DISPLAY;
+ eglExtensions = nullptr;
+ has_EGL_KHR_create_context = false;
+ s_stateMutex.lock();
+ close(s_stdout_fd);
+ close(s_stderr_fd);
+ s_stdout_fd = -1;
+ s_stderr_fd = -1;
+ s_stateMutex.unlock();
+}
+
+Visual *
+createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
+ EGLint api_bits;
+ if (profile.api == glprofile::API_GL) {
+ api_bits = EGL_OPENGL_BIT;
+ if (profile.core && !has_EGL_KHR_create_context) {
+ return NULL;
+ }
+ } else if (profile.api == glprofile::API_GLES) {
+ switch (profile.major) {
+ case 1:
+ api_bits = EGL_OPENGL_ES_BIT;
+ break;
+ case 3:
+ if (has_EGL_KHR_create_context) {
+ api_bits = EGL_OPENGL_ES3_BIT;
+ break;
+ }
+ /* fall-through */
+ case 2:
+ api_bits = EGL_OPENGL_ES2_BIT;
+ break;
+ default:
+ return NULL;
+ }
+ } else {
+ assert(0);
+ return NULL;
+ }
+
+ Attributes<EGLint> attribs;
+ attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+ attribs.add(EGL_RED_SIZE, 1);
+ attribs.add(EGL_GREEN_SIZE, 1);
+ attribs.add(EGL_BLUE_SIZE, 1);
+ attribs.add(EGL_ALPHA_SIZE, 1);
+ attribs.add(EGL_DEPTH_SIZE, 1);
+ attribs.add(EGL_STENCIL_SIZE, 1);
+ attribs.add(EGL_RENDERABLE_TYPE, api_bits);
+ attribs.end(EGL_NONE);
+
+ EGLint num_configs = 0;
+ if (!eglGetConfigs(eglDisplay, NULL, 0, &num_configs) ||
+ num_configs <= 0) {
+ return NULL;
+ }
+
+ std::vector<EGLConfig> configs(num_configs);
+ if (!eglChooseConfig(eglDisplay, attribs, &configs[0], num_configs, &num_configs) ||
+ num_configs <= 0) {
+ return NULL;
+ }
+
+ // We can't tell what other APIs the trace will use afterwards, therefore
+ // try to pick a config which supports the widest set of APIs.
+ int bestScore = -1;
+ EGLConfig config = configs[0];
+ for (EGLint i = 0; i < num_configs; ++i) {
+ EGLint renderable_type = EGL_NONE;
+ eglGetConfigAttrib(eglDisplay, configs[i], EGL_RENDERABLE_TYPE, &renderable_type);
+ int score = 0;
+ assert(renderable_type & api_bits);
+ renderable_type &= ~api_bits;
+ if (renderable_type & EGL_OPENGL_ES2_BIT) {
+ score += 1 << 4;
+ }
+ if (renderable_type & EGL_OPENGL_ES3_BIT) {
+ score += 1 << 3;
+ }
+ if (renderable_type & EGL_OPENGL_ES_BIT) {
+ score += 1 << 2;
+ }
+ if (renderable_type & EGL_OPENGL_BIT) {
+ score += 1 << 1;
+ }
+ if (score > bestScore) {
+ config = configs[i];
+ bestScore = score;
+ }
+ }
+ assert(bestScore >= 0);
+
+ EGLint visual_id = -1;
+ if (!eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &visual_id)) {
+ assert(0);
+ return NULL;
+ }
+ assert(visual_id != -1);
+
+ EglVisual *visual = new EglVisual(profile);
+ visual->config = config;
+ visual->format = visual_id;
+
+ return visual;
+}
+
+Drawable *
+createDrawable(const Visual *visual, int width, int height,
+ const pbuffer_info *info)
+{
+ return new EglDrawable(visual, width, height, info);
+}
+
+
+Context *
+createContext(const Visual *_visual, Context *shareContext, bool debug)
+{
+ Profile profile = _visual->profile;
+ const EglVisual *visual = static_cast<const EglVisual *>(_visual);
+ EGLContext share_context = EGL_NO_CONTEXT;
+ EGLContext context;
+ Attributes<EGLint> attribs;
+
+ if (shareContext) {
+ share_context = static_cast<EglContext*>(shareContext)->context;
+ }
+
+ int contextFlags = 0;
+ if (profile.api == glprofile::API_GL) {
+ if (has_EGL_KHR_create_context) {
+ attribs.add(EGL_CONTEXT_MAJOR_VERSION_KHR, profile.major);
+ attribs.add(EGL_CONTEXT_MINOR_VERSION_KHR, profile.minor);
+ int profileMask = profile.core ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
+ attribs.add(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, profileMask);
+ if (profile.forwardCompatible) {
+ contextFlags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
+ }
+ } else if (profile.versionGreaterOrEqual(3, 2)) {
+ std::cerr << "error: EGL_KHR_create_context not supported\n";
+ return NULL;
+ }
+ } else if (profile.api == glprofile::API_GLES) {
+ if (has_EGL_KHR_create_context) {
+ attribs.add(EGL_CONTEXT_MAJOR_VERSION_KHR, profile.major);
+ attribs.add(EGL_CONTEXT_MINOR_VERSION_KHR, profile.minor);
+ } else {
+ attribs.add(EGL_CONTEXT_CLIENT_VERSION, profile.major);
+ }
+ } else {
+ assert(0);
+ return NULL;
+ }
+
+ if (debug) {
+ contextFlags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+ }
+ if (contextFlags && has_EGL_KHR_create_context) {
+ attribs.add(EGL_CONTEXT_FLAGS_KHR, contextFlags);
+ }
+ attribs.end(EGL_NONE);
+
+ EGLenum api = translateAPI(profile);
+ bindAPI(api);
+
+ context = eglCreateContext(eglDisplay, visual->config, share_context, attribs);
+ if (!context) {
+ if (debug) {
+ // XXX: Mesa has problems with EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
+ // with OpenGL ES contexts, so retry without it
+ return createContext(_visual, shareContext, false);
+ }
+ return NULL;
+ }
+
+ return new EglContext(visual, context);
+}
+
+bool
+makeCurrentInternal(Drawable *drawable, Context *context)
+{
+ if (!drawable || !context) {
+ return eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ } else {
+ EglDrawable *eglDrawable = static_cast<EglDrawable *>(drawable);
+ EglContext *eglContext = static_cast<EglContext *>(context);
+ EGLBoolean ok;
+
+ EGLenum api = translateAPI(eglContext->profile);
+ bindAPI(api);
+
+ ok = eglMakeCurrent(eglDisplay, eglDrawable->surface,
+ eglDrawable->surface, eglContext->context);
+
+ if (ok) {
+ eglDrawable->api = api;
+ }
+
+ return ok;
+ }
+}
+
+bool processEvents(void)
+{
+ return false;
+}
+
+bool
+bindTexImage(Drawable *pBuffer, int iBuffer) {
+ std::cerr << "error: EGL/Android::wglBindTexImageARB not implemented.\n";
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
+bool
+releaseTexImage(Drawable *pBuffer, int iBuffer) {
+ std::cerr << "error: EGL/Android::wglReleaseTexImageARB not implemented.\n";
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
+bool
+setPbufferAttrib(Drawable *pBuffer, const int *attribList) {
+ // nothing to do here.
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
+static void readParamsAndStartTrace()
+{
+ std::string paramsLine;
+ char buff[4096];
+ while (true) {
+ ssize_t sz = read(s_stdout_fd, buff, 4095);
+ if (sz < 0) {
+ cleanup();
+ return ;
+ }
+ buff[sz] = '\0';
+ paramsLine += buff;
+ if (paramsLine.find('\n') > 0)
+ break;
+ }
+ std::regex word_regex("(\"[^\"]*\")|([^\\s]+)");
+ auto words_begin =
+ std::sregex_iterator(paramsLine.begin(), paramsLine.end(), word_regex);
+ auto words_end = std::sregex_iterator();
+ std::vector<std::string> paramsVector;
+ std::vector<char *> params;
+ params.push_back(TAG);
+ for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
+ paramsVector.push_back(i->str());
+ params.push_back(const_cast<char*>(paramsVector.back().c_str()));
+ }
+
+ {
+ std::unique_lock<std::mutex> lock(s_stateMutex);
+ __android_log_print(ANDROID_LOG_DEBUG, TAG, "Wait for stderr socket");
+ s_stateWait.wait(lock, []{return s_stderr_fd != -1; });
+ }
+ __android_log_print(ANDROID_LOG_DEBUG, TAG, "Start retrace");
+ optind = 1;
+ optreset = 1;
+ main(params.size(), &params[0]);
+ cleanup();
+
+ // Remove "std::exit" after apitrace will cleanup its static variables.
+ std::exit(0); // goodbye cruel world !
+}
+
+static inline int getFd(JNIEnv* env, jobject obj)
+{
+ return env->GetIntField(obj, s_descriptor);
+}
+
+static bool setFd(std::ostream &stream, int *state_fd, int fd)
+{
+ std::lock_guard<std::mutex> lock(s_stateMutex);
+ if (*state_fd != -1)
+ return false;
+ *state_fd = fd;
+ delete dynamic_cast<FdWriter*>(stream.rdbuf(new FdWriter(fd)));
+ return true;
+}
+
+static jboolean setStdoutFileDescriptor(JNIEnv *env, jobject /*object*/, jobject fd)
+{
+ bool res = setFd(std::cout, &s_stdout_fd, getFd(env, fd));
+ if (res)
+ std::async(std::launch::async, glws::readParamsAndStartTrace);
+ return res;
+}
+
+static jboolean setStderrFileDescriptor(JNIEnv *env, jobject /*object*/, jobject fd)
+{
+ bool res = setFd(std::cerr, &s_stderr_fd, getFd(env, fd));
+ if (res)
+ s_stateWait.notify_one();
+ return res;
+}
+
+static void onActivityCreated(JNIEnv *env, jobject /*object*/, jobject activity)
+{
+ s_activityObjectMutex.lock();
+ s_activityObject = env->NewGlobalRef(activity);
+ s_activityObjectMutex.unlock();
+}
+
+static void onSurfaceCreated(JNIEnv *env, jobject /*object*/, jobject surface)
+{
+ s_currentNativeWindowMutex.lock();
+ s_currentNativeWindow = AndroidWindow(ANativeWindow_fromSurface(env, surface), [](ANativeWindow *w) { ANativeWindow_release(w); });
+ ++s_currentNativeWindowId;
+ s_currentNativeWindowMutex.unlock();
+}
+
+static void onSurfaceChanged(JNIEnv *env, jobject /*object*/, jobject surface, int /*format*/, int /*width*/, int /*height*/)
+{
+ s_currentNativeWindowMutex.lock();
+ s_currentNativeWindow = AndroidWindow(ANativeWindow_fromSurface(env, surface), [](ANativeWindow *w) { ANativeWindow_release(w); });
+ ++s_currentNativeWindowId;
+ s_currentNativeWindowMutex.unlock();
+}
+
+static void onSurfaceRedrawNeeded(JNIEnv */*env*/, jobject /*object*/, jobject /*surface*/)
+{
+}
+
+static void onSurfaceDestroyed(JNIEnv */*env*/, jobject /*object*/)
+{
+ s_currentNativeWindowMutex.lock();
+ s_currentNativeWindow.reset();
+ s_currentNativeWindowId.store(0);
+ s_currentNativeWindowMutex.unlock();
+}
+
+static void onActivityDestroyed(JNIEnv *env, jobject /*object*/)
+{
+ s_activityObjectMutex.lock();
+ env->DeleteGlobalRef(s_activityObject);
+ s_activityObject = nullptr;
+ s_activityObjectMutex.unlock();
+}
+
+static JNINativeMethod methods[] = {
+ {"setStdoutFileDescriptor", "(Ljava/io/FileDescriptor;)Z", (void *)setStdoutFileDescriptor},
+ {"setStderrFileDescriptor", "(Ljava/io/FileDescriptor;)Z", (void *)setStderrFileDescriptor},
+ {"onActivityCreatedNative", "(Lapitrace/github/io/eglretrace/RetraceActivity;)V", (void *)onActivityCreated},
+ {"onSurfaceCreatedNative", "(Landroid/view/Surface;)V", (void *)onSurfaceCreated},
+ {"onSurfaceChangedNative", "(Landroid/view/Surface;III)V", (void *)onSurfaceChanged},
+ {"onSurfaceRedrawNeededNative", "(Landroid/view/Surface;)V", (void *)onSurfaceRedrawNeeded},
+ {"onSurfaceDestroyedNative", "()V", (void *)onSurfaceDestroyed},
+ {"onActivityDestroyedNative", "()V", (void *)onActivityDestroyed}
+};
+
+} /* namespace glws */
+
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
+{
+ typedef union {
+ JNIEnv *nativeEnvironment;
+ void *venv;
+ } UnionJNIEnvToVoid;
+
+ __android_log_print(ANDROID_LOG_INFO, glws::TAG, "apitrace start");
+ UnionJNIEnvToVoid uenv;
+ uenv.venv = nullptr;
+ glws::s_javaVM = nullptr;
+
+ if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
+ __android_log_print(ANDROID_LOG_FATAL, glws::TAG, "GetEnv failed");
+ return -1;
+ }
+
+ JNIEnv *env = uenv.nativeEnvironment;
+
+ jclass clazz;
+ clazz = env->FindClass("apitrace/github/io/eglretrace/RetraceActivity");
+ if (!clazz) {
+ __android_log_print(ANDROID_LOG_FATAL, glws::TAG, "Can't find RetraceActivity");
+ return JNI_FALSE;
+ }
+
+ glws::s_setSurfaceSizeMethodID = env->GetMethodID(clazz, "setSurfaceSize", "(II)V");
+ if (!glws::s_setSurfaceSizeMethodID) {
+ __android_log_print(ANDROID_LOG_FATAL, glws::TAG, "Can't find setSurfaceSize method");
+ return JNI_FALSE;
+ }
+
+ if (env->RegisterNatives(clazz, glws::methods, sizeof(glws::methods) / sizeof(glws::methods[0])) < 0) {
+ __android_log_print(ANDROID_LOG_FATAL, glws::TAG, "RegisterNatives failed");
+ return JNI_FALSE;
+ }
+
+ clazz = env->FindClass("java/io/FileDescriptor");
+ if (!clazz) {
+ __android_log_print(ANDROID_LOG_FATAL, glws::TAG, "Can't find FileDescriptor class");
+ return JNI_FALSE;
+ }
+ glws::s_descriptor = env->GetFieldID(clazz, "descriptor", "I");
+ if (!glws::s_descriptor) {
+ __android_log_print(ANDROID_LOG_FATAL, glws::TAG, "Can't find descriptor field");
+ return JNI_FALSE;
+ }
+
+ glws::s_javaVM = vm;
+ return JNI_VERSION_1_4;
+}
diff --git a/retrace/glws_egl_xlib.cpp b/retrace/glws_egl_xlib.cpp
index cb5cf1d2..f4c363c3 100644
--- a/retrace/glws_egl_xlib.cpp
+++ b/retrace/glws_egl_xlib.cpp
@@ -35,6 +35,8 @@
#include "glws.hpp"
#include "glws_xlib.hpp"
+#include <EGL/eglext.h>
+
namespace glws {
@@ -44,6 +46,41 @@ static char const *eglExtensions = NULL;
static bool has_EGL_KHR_create_context = false;
+static EGLenum
+translateAPI(glprofile::Profile profile)
+{
+ switch (profile.api) {
+ case glprofile::API_GL:
+ return EGL_OPENGL_API;
+ case glprofile::API_GLES:
+ return EGL_OPENGL_ES_API;
+ default:
+ assert(0);
+ return EGL_NONE;
+ }
+}
+
+
+/* Must be called before
+ *
+ * - eglCreateContext
+ * - eglGetCurrentContext
+ * - eglGetCurrentDisplay
+ * - eglGetCurrentSurface
+ * - eglMakeCurrent (when its ctx parameter is EGL_NO_CONTEXT ),
+ * - eglWaitClient
+ * - eglWaitNative
+ */
+static void
+bindAPI(EGLenum api)
+{
+ if (eglBindAPI(api) != EGL_TRUE) {
+ std::cerr << "error: eglBindAPI failed\n";
+ exit(1);
+ }
+}
+
+
class EglVisual : public Visual
{
public:
@@ -67,10 +104,11 @@ class EglDrawable : public Drawable
public:
Window window;
EGLSurface surface;
- EGLint api;
+ EGLenum api;
- EglDrawable(const Visual *vis, int w, int h, bool pbuffer) :
- Drawable(vis, w, h, pbuffer),
+ EglDrawable(const Visual *vis, int w, int h,
+ const glws::pbuffer_info *pbInfo) :
+ Drawable(vis, w, h, pbInfo),
api(EGL_OPENGL_ES_API)
{
XVisualInfo *visinfo = static_cast<const EglVisual *>(visual)->visinfo;
@@ -172,7 +210,7 @@ public:
}
void swapBuffers(void) {
- eglBindAPI(api);
+ bindAPI(api);
eglSwapBuffers(eglDisplay, surface);
processKeys(window);
}
@@ -213,7 +251,19 @@ init(void) {
initX();
- eglDisplay = eglGetDisplay((EGLNativeDisplayType)display);
+ eglExtensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (eglExtensions &&
+ checkExtension("EGL_EXT_platform_x11", eglExtensions)) {
+
+ Attributes<EGLint> attribs;
+ attribs.add(EGL_PLATFORM_X11_SCREEN_EXT, screen);
+ attribs.add(EGL_NONE);
+
+ eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, display, attribs);
+ } else {
+ eglDisplay = eglGetDisplay((EGLNativeDisplayType)display);
+ }
+
if (eglDisplay == EGL_NO_DISPLAY) {
std::cerr << "error: unable to get EGL display\n";
XCloseDisplay(display);
@@ -240,93 +290,115 @@ cleanup(void) {
cleanupX();
}
+
Visual *
createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
- EglVisual *visual = new EglVisual(profile);
- // possible combinations
- const EGLint api_bits_gl[7] = {
- EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT,
- EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_BIT,
- EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_ES_BIT,
- };
- const EGLint api_bits_gles1[7] = {
- EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT,
- EGL_OPENGL_ES_BIT,
- EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_BIT,
- EGL_OPENGL_ES2_BIT,
- };
- const EGLint api_bits_gles2[7] = {
- EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_ES2_BIT,
- EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT,
- EGL_OPENGL_BIT,
- EGL_OPENGL_ES_BIT,
- };
- const EGLint *api_bits;
-
- switch(profile) {
- default:
- if (!has_EGL_KHR_create_context) {
+ EGLint api_bits;
+ if (profile.api == glprofile::API_GL) {
+ api_bits = EGL_OPENGL_BIT;
+ if (profile.core && !has_EGL_KHR_create_context) {
return NULL;
}
- /* pass-through */
- case PROFILE_COMPAT:
- api_bits = api_bits_gl;
- break;
- case PROFILE_ES1:
- api_bits = api_bits_gles1;
- break;
- case PROFILE_ES2:
- api_bits = api_bits_gles2;
- break;
- };
-
- for (int i = 0; i < 7; i++) {
- Attributes<EGLint> attribs;
-
- attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
- attribs.add(EGL_RED_SIZE, 1);
- attribs.add(EGL_GREEN_SIZE, 1);
- attribs.add(EGL_BLUE_SIZE, 1);
- attribs.add(EGL_ALPHA_SIZE, 1);
- attribs.add(EGL_DEPTH_SIZE, 1);
- attribs.add(EGL_STENCIL_SIZE, 1);
- attribs.add(EGL_RENDERABLE_TYPE, api_bits[i]);
- attribs.end(EGL_NONE);
-
- EGLint num_configs, vid;
- if (eglChooseConfig(eglDisplay, attribs, &visual->config, 1, &num_configs) &&
- num_configs == 1 &&
- eglGetConfigAttrib(eglDisplay, visual->config, EGL_NATIVE_VISUAL_ID, &vid)) {
- XVisualInfo templ;
- int num_visuals;
-
- templ.visualid = vid;
- visual->visinfo = XGetVisualInfo(display, VisualIDMask, &templ, &num_visuals);
+ } else if (profile.api == glprofile::API_GLES) {
+ switch (profile.major) {
+ case 1:
+ api_bits = EGL_OPENGL_ES_BIT;
+ break;
+ case 3:
+ if (has_EGL_KHR_create_context) {
+ api_bits = EGL_OPENGL_ES3_BIT;
+ break;
+ }
+ /* fall-through */
+ case 2:
+ api_bits = EGL_OPENGL_ES2_BIT;
break;
+ default:
+ return NULL;
+ }
+ } else {
+ assert(0);
+ return NULL;
+ }
+
+ Attributes<EGLint> attribs;
+ attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+ attribs.add(EGL_RED_SIZE, 1);
+ attribs.add(EGL_GREEN_SIZE, 1);
+ attribs.add(EGL_BLUE_SIZE, 1);
+ attribs.add(EGL_ALPHA_SIZE, 1);
+ attribs.add(EGL_DEPTH_SIZE, 1);
+ attribs.add(EGL_STENCIL_SIZE, 1);
+ attribs.add(EGL_RENDERABLE_TYPE, api_bits);
+ attribs.end(EGL_NONE);
+
+ EGLint num_configs = 0;
+ if (!eglGetConfigs(eglDisplay, NULL, 0, &num_configs) ||
+ num_configs <= 0) {
+ return NULL;
+ }
+
+ std::vector<EGLConfig> configs(num_configs);
+ if (!eglChooseConfig(eglDisplay, attribs, &configs[0], num_configs, &num_configs) ||
+ num_configs <= 0) {
+ return NULL;
+ }
+
+ // We can't tell what other APIs the trace will use afterwards, therefore
+ // try to pick a config which supports the widest set of APIs.
+ int bestScore = -1;
+ EGLConfig config = configs[0];
+ for (EGLint i = 0; i < num_configs; ++i) {
+ EGLint renderable_type = EGL_NONE;
+ eglGetConfigAttrib(eglDisplay, configs[i], EGL_RENDERABLE_TYPE, &renderable_type);
+ int score = 0;
+ assert(renderable_type & api_bits);
+ renderable_type &= ~api_bits;
+ if (renderable_type & EGL_OPENGL_ES2_BIT) {
+ score += 1 << 4;
+ }
+ if (renderable_type & EGL_OPENGL_ES3_BIT) {
+ score += 1 << 3;
+ }
+ if (renderable_type & EGL_OPENGL_ES_BIT) {
+ score += 1 << 2;
+ }
+ if (renderable_type & EGL_OPENGL_BIT) {
+ score += 1 << 1;
+ }
+ if (score > bestScore) {
+ config = configs[i];
+ bestScore = score;
}
}
+ assert(bestScore >= 0);
+ EGLint visual_id;
+ if (!eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &visual_id)) {
+ assert(0);
+ return NULL;
+ }
+
+ EglVisual *visual = new EglVisual(profile);
+ visual->config = config;
+
+ XVisualInfo templ;
+ int num_visuals = 0;
+ templ.visualid = visual_id;
+ visual->visinfo = XGetVisualInfo(display, VisualIDMask, &templ, &num_visuals);
assert(visual->visinfo);
return visual;
}
Drawable *
-createDrawable(const Visual *visual, int width, int height, bool pbuffer)
+createDrawable(const Visual *visual, int width, int height,
+ const glws::pbuffer_info *pbInfo)
{
- return new EglDrawable(visual, width, height, pbuffer);
+ return new EglDrawable(visual, width, height, pbInfo);
}
+
Context *
createContext(const Visual *_visual, Context *shareContext, bool debug)
{
@@ -340,60 +412,66 @@ createContext(const Visual *_visual, Context *shareContext, bool debug)
share_context = static_cast<EglContext*>(shareContext)->context;
}
- EGLint api = eglQueryAPI();
-
- switch (profile) {
- case PROFILE_COMPAT:
+ int contextFlags = 0;
+ if (profile.api == glprofile::API_GL) {
load("libGL.so.1");
- eglBindAPI(EGL_OPENGL_API);
- break;
- case PROFILE_ES1:
- load("libGLESv1_CM.so.1");
- eglBindAPI(EGL_OPENGL_ES_API);
- break;
- case PROFILE_ES2:
- load("libGLESv2.so.2");
- eglBindAPI(EGL_OPENGL_ES_API);
- attribs.add(EGL_CONTEXT_CLIENT_VERSION, 2);
- break;
- default:
+
if (has_EGL_KHR_create_context) {
- unsigned major, minor;
- bool core;
- getProfileVersion(profile, major, minor, core);
- attribs.add(EGL_CONTEXT_MAJOR_VERSION_KHR, major);
- attribs.add(EGL_CONTEXT_MINOR_VERSION_KHR, minor);
- if (core) {
- attribs.add(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR);
+ attribs.add(EGL_CONTEXT_MAJOR_VERSION_KHR, profile.major);
+ attribs.add(EGL_CONTEXT_MINOR_VERSION_KHR, profile.minor);
+ int profileMask = profile.core ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
+ attribs.add(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, profileMask);
+ if (profile.forwardCompatible) {
+ contextFlags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
}
- } else {
+ } else if (profile.versionGreaterOrEqual(3, 2)) {
+ std::cerr << "error: EGL_KHR_create_context not supported\n";
return NULL;
}
- }
+ } else if (profile.api == glprofile::API_GLES) {
+ if (profile.major >= 2) {
+ load("libGLESv2.so.2");
+ } else {
+ load("libGLESv1_CM.so.1");
+ }
- if (debug && has_EGL_KHR_create_context) {
- attribs.add(EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR);
+ if (has_EGL_KHR_create_context) {
+ attribs.add(EGL_CONTEXT_MAJOR_VERSION_KHR, profile.major);
+ attribs.add(EGL_CONTEXT_MINOR_VERSION_KHR, profile.minor);
+ } else {
+ attribs.add(EGL_CONTEXT_CLIENT_VERSION, profile.major);
+ }
+ } else {
+ assert(0);
+ return NULL;
}
+ if (debug) {
+ contextFlags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+ }
+ if (contextFlags && has_EGL_KHR_create_context) {
+ attribs.add(EGL_CONTEXT_FLAGS_KHR, contextFlags);
+ }
attribs.end(EGL_NONE);
+ EGLenum api = translateAPI(profile);
+ bindAPI(api);
+
context = eglCreateContext(eglDisplay, visual->config, share_context, attribs);
if (!context) {
if (debug) {
- // XXX: Mesa seems to have problem with
- // EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, so retry without it
+ // XXX: Mesa has problems with EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
+ // with OpenGL ES contexts, so retry without it
return createContext(_visual, shareContext, false);
}
return NULL;
}
- eglBindAPI(api);
-
return new EglContext(visual, context);
}
bool
-makeCurrent(Drawable *drawable, Context *context)
+makeCurrentInternal(Drawable *drawable, Context *context)
{
if (!drawable || !context) {
return eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -402,15 +480,13 @@ makeCurrent(Drawable *drawable, Context *context)
EglContext *eglContext = static_cast<EglContext *>(context);
EGLBoolean ok;
+ EGLenum api = translateAPI(eglContext->profile);
+ bindAPI(api);
+
ok = eglMakeCurrent(eglDisplay, eglDrawable->surface,
eglDrawable->surface, eglContext->context);
if (ok) {
- EGLint api;
-
- eglQueryContext(eglDisplay, eglContext->context,
- EGL_CONTEXT_CLIENT_TYPE, &api);
-
eglDrawable->api = api;
}
@@ -419,5 +495,26 @@ makeCurrent(Drawable *drawable, Context *context)
}
+bool
+bindTexImage(Drawable *pBuffer, int iBuffer) {
+ std::cerr << "error: EGL/XLIB::wglBindTexImageARB not implemented.\n";
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
+bool
+releaseTexImage(Drawable *pBuffer, int iBuffer) {
+ std::cerr << "error: EGL/XLIB::wglReleaseTexImageARB not implemented.\n";
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
+bool
+setPbufferAttrib(Drawable *pBuffer, const int *attribList) {
+ // nothing to do here.
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
} /* namespace glws */
diff --git a/retrace/glws_glx.cpp b/retrace/glws_glx.cpp
index bb47f781..08a29d9a 100644
--- a/retrace/glws_glx.cpp
+++ b/retrace/glws_glx.cpp
@@ -25,6 +25,7 @@
#include <assert.h>
#include <stdlib.h>
+#include <limits.h>
#include <iostream>
@@ -36,9 +37,11 @@
namespace glws {
-static unsigned glxVersion = 0;
static const char *extensions = 0;
static bool has_GLX_ARB_create_context = false;
+static bool has_GLX_ARB_create_context_profile = false;
+static bool has_GLX_EXT_create_context_es_profile = false;
+static bool has_GLX_EXT_create_context_es2_profile = false;
class GlxVisual : public Visual
@@ -62,27 +65,43 @@ public:
class GlxDrawable : public Drawable
{
public:
- Window window;
- bool ever_current;
+ Window window = 0;
+ GLXDrawable drawable = 0;
- GlxDrawable(const Visual *vis, int w, int h, bool pbuffer) :
- Drawable(vis, w, h, pbuffer),
- ever_current(false)
+ GlxDrawable(const Visual *vis, int w, int h,
+ const glws::pbuffer_info *pbInfo) :
+ Drawable(vis, w, h, pbInfo ? true : false)
{
- XVisualInfo *visinfo = static_cast<const GlxVisual *>(visual)->visinfo;
+ const GlxVisual *glxvisual = static_cast<const GlxVisual *>(visual);
+ XVisualInfo *visinfo = glxvisual->visinfo;
const char *name = "glretrace";
- window = createWindow(visinfo, name, width, height);
+ if (pbInfo) {
+ drawable = createPbuffer(display, glxvisual, pbInfo, w, h);
+ }
+ else {
+ window = createWindow(visinfo, name, width, height);
+ drawable = glXCreateWindow(display, glxvisual->fbconfig, window, NULL);
+ }
glXWaitX();
}
~GlxDrawable() {
- XDestroyWindow(display, window);
+ if (pbuffer) {
+ glXDestroyPbuffer(display, drawable);
+ } else {
+ glXDestroyWindow(display, drawable);
+ XDestroyWindow(display, window);
+ }
}
void
resize(int w, int h) {
+ if (!window) {
+ return;
+ }
+
if (w == width && h == height) {
return;
}
@@ -102,7 +121,8 @@ public:
}
void show(void) {
- if (visible) {
+ if (!window ||
+ visible) {
return;
}
@@ -116,23 +136,24 @@ public:
}
void copySubBuffer(int x, int y, int width, int height) {
- glXCopySubBufferMESA(display, window, x, y, width, height);
+ glXCopySubBufferMESA(display, drawable, x, y, width, height);
- processKeys(window);
+ if (window) {
+ processKeys(window);
+ }
}
void swapBuffers(void) {
- if (ever_current) {
- // The window has been bound to a context at least once
- glXSwapBuffers(display, window);
- } else {
- // Don't call glXSwapBuffers on this window to avoid an
- // (untrappable) X protocol error with NVIDIA's driver.
- std::cerr << "warning: attempt to issue SwapBuffers on unbound window "
- " - skipping.\n";
+ assert(!pbuffer);
+ glXSwapBuffers(display, drawable);
+ if (window) {
+ processKeys(window);
}
- processKeys(window);
}
+
+private:
+ Window createPbuffer(Display *dpy, const GlxVisual *visinfo,
+ const glws::pbuffer_info *pbInfo, int w, int h);
};
@@ -151,20 +172,65 @@ public:
}
};
+
+#ifndef GLXBadFBConfig
+#define GLXBadFBConfig 9
+#endif
+
+static int errorBase = INT_MIN;
+static int eventBase = INT_MIN;
+
+static int (*oldErrorHandler)(Display *, XErrorEvent *) = NULL;
+
+static int
+errorHandler(Display *dpy, XErrorEvent *error)
+{
+ if (error->error_code == errorBase + GLXBadFBConfig) {
+ // Ignore, as we handle these.
+ return 0;
+ }
+
+ return oldErrorHandler(dpy, error);
+}
+
+
void
init(void) {
initX();
int major = 0, minor = 0;
- glXQueryVersion(display, &major, &minor);
- glxVersion = (major << 8) | minor;
+ if (!glXQueryVersion(display, &major, &minor)) {
+ std::cerr << "error: failed to obtain GLX version\n";
+ exit(1);
+ }
+ const int requiredMajor = 1, requiredMinor = 3;
+ if (major < requiredMajor ||
+ (major == requiredMajor && minor < requiredMinor)) {
+ std::cerr << "error: GLX version " << requiredMajor << "." << requiredMinor << " required, but got version " << major << "." << minor << "\n";
+ exit(1);
+ }
+
+ glXQueryExtension(display, &errorBase, &eventBase);
+ oldErrorHandler = XSetErrorHandler(errorHandler);
extensions = glXQueryExtensionsString(display, screen);
- has_GLX_ARB_create_context = checkExtension("GLX_ARB_create_context", extensions);
+
+#define CHECK_EXTENSION(name) \
+ has_##name = checkExtension(#name, extensions)
+
+ CHECK_EXTENSION(GLX_ARB_create_context);
+ CHECK_EXTENSION(GLX_ARB_create_context_profile);
+ CHECK_EXTENSION(GLX_EXT_create_context_es_profile);
+ CHECK_EXTENSION(GLX_EXT_create_context_es2_profile);
+
+#undef CHECK_EXTENSION
}
void
cleanup(void) {
+ XSetErrorHandler(oldErrorHandler);
+ oldErrorHandler = NULL;
+
cleanupX();
}
@@ -172,61 +238,41 @@ Visual *
createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
GlxVisual *visual = new GlxVisual(profile);
- if (glxVersion >= 0x0103) {
- Attributes<int> attribs;
- attribs.add(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT);
- attribs.add(GLX_RENDER_TYPE, GLX_RGBA_BIT);
- attribs.add(GLX_RED_SIZE, 1);
- attribs.add(GLX_GREEN_SIZE, 1);
- attribs.add(GLX_BLUE_SIZE, 1);
- attribs.add(GLX_ALPHA_SIZE, 1);
- attribs.add(GLX_DOUBLEBUFFER, doubleBuffer ? GL_TRUE : GL_FALSE);
- attribs.add(GLX_DEPTH_SIZE, 1);
- attribs.add(GLX_STENCIL_SIZE, 1);
- if (samples > 1) {
- attribs.add(GLX_SAMPLE_BUFFERS, 1);
- attribs.add(GLX_SAMPLES_ARB, samples);
- }
- attribs.end();
-
- int num_configs = 0;
- GLXFBConfig * fbconfigs;
- fbconfigs = glXChooseFBConfig(display, screen, attribs, &num_configs);
- if (!num_configs || !fbconfigs) {
- return NULL;
- }
- visual->fbconfig = fbconfigs[0];
- assert(visual->fbconfig);
- visual->visinfo = glXGetVisualFromFBConfig(display, visual->fbconfig);
- assert(visual->visinfo);
- } else {
- Attributes<int> attribs;
- attribs.add(GLX_RGBA);
- attribs.add(GLX_RED_SIZE, 1);
- attribs.add(GLX_GREEN_SIZE, 1);
- attribs.add(GLX_BLUE_SIZE, 1);
- attribs.add(GLX_ALPHA_SIZE, 1);
- if (doubleBuffer) {
- attribs.add(GLX_DOUBLEBUFFER);
- }
- attribs.add(GLX_DEPTH_SIZE, 1);
- attribs.add(GLX_STENCIL_SIZE, 1);
- if (samples > 1) {
- attribs.add(GLX_SAMPLE_BUFFERS, 1);
- attribs.add(GLX_SAMPLES_ARB, samples);
- }
- attribs.end();
+ Attributes<int> attribs;
+ attribs.add(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT);
+ attribs.add(GLX_RENDER_TYPE, GLX_RGBA_BIT);
+ attribs.add(GLX_RED_SIZE, 1);
+ attribs.add(GLX_GREEN_SIZE, 1);
+ attribs.add(GLX_BLUE_SIZE, 1);
+ attribs.add(GLX_ALPHA_SIZE, 1);
+ attribs.add(GLX_DOUBLEBUFFER, doubleBuffer ? GL_TRUE : GL_FALSE);
+ attribs.add(GLX_DEPTH_SIZE, 1);
+ attribs.add(GLX_STENCIL_SIZE, 1);
+ if (samples > 1) {
+ attribs.add(GLX_SAMPLE_BUFFERS, 1);
+ attribs.add(GLX_SAMPLES_ARB, samples);
+ }
+ attribs.end();
- visual->visinfo = glXChooseVisual(display, screen, attribs);
+ int num_configs = 0;
+ GLXFBConfig * fbconfigs;
+ fbconfigs = glXChooseFBConfig(display, screen, attribs, &num_configs);
+ if (!num_configs || !fbconfigs) {
+ return NULL;
}
+ visual->fbconfig = fbconfigs[0];
+ assert(visual->fbconfig);
+ visual->visinfo = glXGetVisualFromFBConfig(display, visual->fbconfig);
+ assert(visual->visinfo);
return visual;
}
Drawable *
-createDrawable(const Visual *visual, int width, int height, bool pbuffer)
+createDrawable(const Visual *visual, int width, int height,
+ const glws::pbuffer_info *pbInfo)
{
- return new GlxDrawable(visual, width, height, pbuffer);
+ return new GlxDrawable(visual, width, height, pbInfo);
}
Context *
@@ -241,49 +287,68 @@ createContext(const Visual *_visual, Context *shareContext, bool debug)
share_context = static_cast<GlxContext*>(shareContext)->context;
}
- if (glxVersion >= 0x0104 && has_GLX_ARB_create_context) {
+ if (has_GLX_ARB_create_context) {
Attributes<int> attribs;
-
attribs.add(GLX_RENDER_TYPE, GLX_RGBA_TYPE);
- if (debug) {
- attribs.add(GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB);
- }
-
- switch (profile) {
- case PROFILE_COMPAT:
- break;
- case PROFILE_ES1:
- return NULL;
- case PROFILE_ES2:
- attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT);
- break;
- default:
- {
- unsigned major, minor;
- bool core;
- getProfileVersion(profile, major, minor, core);
- attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, major);
- attribs.add(GLX_CONTEXT_MINOR_VERSION_ARB, minor);
- if (core) {
- attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB);
+ int contextFlags = 0;
+ if (profile.api == glprofile::API_GL) {
+ attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, profile.major);
+ attribs.add(GLX_CONTEXT_MINOR_VERSION_ARB, profile.minor);
+ if (profile.versionGreaterOrEqual(3, 2)) {
+ if (!has_GLX_ARB_create_context_profile) {
+ std::cerr << "error: GLX_ARB_create_context_profile not supported\n";
+ return NULL;
+ }
+ int profileMask = profile.core ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, profileMask);
+ if (profile.forwardCompatible) {
+ contextFlags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
}
- break;
}
+ } else if (profile.api == glprofile::API_GLES) {
+ if (has_GLX_EXT_create_context_es_profile) {
+ attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES_PROFILE_BIT_EXT);
+ attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, profile.major);
+ attribs.add(GLX_CONTEXT_MINOR_VERSION_ARB, profile.minor);
+ } else if (profile.major < 2) {
+ std::cerr << "error: " << profile << " requested but GLX_EXT_create_context_es_profile not supported\n";
+ return NULL;
+ } else if (has_GLX_EXT_create_context_es2_profile) {
+ assert(profile.major >= 2);
+ if (profile.major != 2 || profile.minor != 0) {
+ // We might still get a ES 3.0 context later (in particular Mesa does this)
+ std::cerr << "warning: " << profile << " requested but GLX_EXT_create_context_es_profile not supported\n";
+ }
+ attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT);
+ attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, 2);
+ attribs.add(GLX_CONTEXT_MINOR_VERSION_ARB, 0);
+ } else {
+ std::cerr << "warning: " << profile << " requested but GLX_EXT_create_context_es_profile or GLX_EXT_create_context_es2_profile not supported\n";
+ }
+ } else {
+ assert(0);
+ }
+ if (debug) {
+ contextFlags |= GLX_CONTEXT_DEBUG_BIT_ARB;
+ }
+ if (contextFlags) {
+ attribs.add(GLX_CONTEXT_FLAGS_ARB, contextFlags);
}
-
attribs.end();
context = glXCreateContextAttribsARB(display, visual->fbconfig, share_context, True, attribs);
+ if (!context && debug) {
+ // XXX: Mesa has problems with GLX_CONTEXT_DEBUG_BIT_ARB with
+ // OpenGL ES contexts, so retry without it
+ return createContext(_visual, shareContext, false);
+ }
} else {
- if (profile != PROFILE_COMPAT) {
+ if (profile.api != glprofile::API_GL ||
+ profile.core) {
return NULL;
}
- if (glxVersion >= 0x103) {
- context = glXCreateNewContext(display, visual->fbconfig, GLX_RGBA_TYPE, share_context, True);
- } else {
- context = glXCreateContext(display, visual->visinfo, share_context, True);
- }
+ context = glXCreateNewContext(display, visual->fbconfig, GLX_RGBA_TYPE, share_context, True);
}
if (!context) {
@@ -294,19 +359,199 @@ createContext(const Visual *_visual, Context *shareContext, bool debug)
}
bool
-makeCurrent(Drawable *drawable, Context *context)
+makeCurrentInternal(Drawable *drawable, Context *context)
{
- if (!drawable || !context) {
- return glXMakeCurrent(display, None, NULL);
- } else {
+ Window draw = None;
+ if (drawable) {
GlxDrawable *glxDrawable = static_cast<GlxDrawable *>(drawable);
+ draw = glxDrawable->drawable;
+ }
+
+ GLXContext ctx = nullptr;
+ if (context) {
GlxContext *glxContext = static_cast<GlxContext *>(context);
+ ctx = glxContext->context;
+ }
+
+ return glXMakeCurrent(display, draw, ctx);
+}
+
+Window
+GlxDrawable::createPbuffer(Display *dpy, const GlxVisual *visinfo,
+ const glws::pbuffer_info *pbInfo, int w, int h)
+{
+ int samples = 0;
+
+ // XXX ideally, we'd populate these attributes according to the Visual info
+ Attributes<int> attribs;
+ attribs.add(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
+ attribs.add(GLX_RENDER_TYPE, GLX_RGBA_BIT);
+ attribs.add(GLX_RED_SIZE, 1);
+ attribs.add(GLX_GREEN_SIZE, 1);
+ attribs.add(GLX_BLUE_SIZE, 1);
+ attribs.add(GLX_ALPHA_SIZE, 1);
+ //attribs.add(GLX_DOUBLEBUFFER, doubleBuffer ? GL_TRUE : GL_FALSE);
+ attribs.add(GLX_DEPTH_SIZE, 1);
+ attribs.add(GLX_STENCIL_SIZE, 1);
+ if (samples > 1) {
+ attribs.add(GLX_SAMPLE_BUFFERS, 1);
+ attribs.add(GLX_SAMPLES_ARB, samples);
+ }
+ attribs.end();
+
+ int num_configs = 0;
+ GLXFBConfig *fbconfigs;
+ fbconfigs = glXChooseFBConfig(dpy, screen, attribs, &num_configs);
+ if (!num_configs || !fbconfigs) {
+ std::cerr << "error: glXChooseFBConfig for pbuffer failed.\n";
+ exit(1);
+ }
- glxDrawable->ever_current = true;
+ Attributes<int> pbAttribs;
+ pbAttribs.add(GLX_PBUFFER_WIDTH, w);
+ pbAttribs.add(GLX_PBUFFER_HEIGHT, h);
+ pbAttribs.add(GLX_PRESERVED_CONTENTS, True);
+ pbAttribs.end();
- return glXMakeCurrent(display, glxDrawable->window, glxContext->context);
+ GLXDrawable pbuffer = glXCreatePbuffer(dpy, fbconfigs[0], pbAttribs);
+ if (!pbuffer) {
+ std::cerr << "error: glXCreatePbuffer() failed\n";
+ exit(1);
}
+
+ return pbuffer;
}
+// For GLX, we implement wglBindTexARB() as a copy operation.
+// We copy the pbuffer image to the currently bound texture.
+// If there's any rendering to the pbuffer before the wglReleaseTexImage()
+// call, the results are undefined (and permitted by the extension spec).
+//
+// The spec says that glTexImage and glCopyTexImage calls which effect
+// the pbuffer/texture should not be allowed, but we do not enforce that.
+//
+// The spec says that when a pbuffer is released from the texture that
+// the contents do not have to be preserved. But that's what will happen
+// since we're copying here.
+bool
+bindTexImage(Drawable *pBuffer, int iBuffer) {
+ GLint readBufSave;
+ GLint width, height;
+
+ assert(pBuffer->pbuffer);
+
+ // Save the current drawing surface and bind the pbuffer surface
+ GLXDrawable prevDrawable = glXGetCurrentDrawable();
+ GLXContext prevContext = glXGetCurrentContext();
+ GlxDrawable *glxPBuffer = static_cast<GlxDrawable *>(pBuffer);
+ glXMakeCurrent(display, glxPBuffer->drawable, prevContext);
+
+ glGetIntegerv(GL_READ_BUFFER, &readBufSave);
+
+ assert(iBuffer == GL_FRONT_LEFT ||
+ iBuffer == GL_BACK_LEFT ||
+ iBuffer == GL_FRONT_RIGHT ||
+ iBuffer == GL_BACK_RIGHT ||
+ iBuffer == GL_AUX0);
+
+ // set src buffer
+ glReadBuffer(iBuffer);
+
+ // Just copy image from pbuffer to texture
+ switch (pBuffer->pbInfo.texTarget) {
+ case GL_TEXTURE_1D:
+ glGetTexLevelParameteriv(GL_TEXTURE_1D, pBuffer->mipmapLevel,
+ GL_TEXTURE_WIDTH, &width);
+ if (width == pBuffer->width) {
+ // replace existing texture
+ glCopyTexSubImage1D(GL_TEXTURE_1D,
+ pBuffer->mipmapLevel,
+ 0, // xoffset
+ 0, 0, // x, y
+ pBuffer->width);
+ } else {
+ // define initial texture
+ glCopyTexImage1D(GL_TEXTURE_1D,
+ pBuffer->mipmapLevel,
+ pBuffer->pbInfo.texFormat,
+ 0, 0, // x, y
+ pBuffer->width, 0);
+ }
+ break;
+ case GL_TEXTURE_2D:
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, pBuffer->mipmapLevel,
+ GL_TEXTURE_WIDTH, &width);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, pBuffer->mipmapLevel,
+ GL_TEXTURE_HEIGHT, &height);
+ if (width == pBuffer->width && height == pBuffer->height) {
+ // replace existing texture
+ glCopyTexSubImage2D(GL_TEXTURE_2D,
+ pBuffer->mipmapLevel,
+ 0, 0, // xoffset, yoffset
+ 0, 0, // x, y
+ pBuffer->width, pBuffer->height);
+ } else {
+ // define initial texture
+ glCopyTexImage2D(GL_TEXTURE_2D,
+ pBuffer->mipmapLevel,
+ pBuffer->pbInfo.texFormat,
+ 0, 0, // x, y
+ pBuffer->width, pBuffer->height, 0);
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ {
+ const GLenum target =
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X + pBuffer->cubeFace;
+ glGetTexLevelParameteriv(target, pBuffer->mipmapLevel,
+ GL_TEXTURE_WIDTH, &width);
+ glGetTexLevelParameteriv(target, pBuffer->mipmapLevel,
+ GL_TEXTURE_HEIGHT, &height);
+ if (width == pBuffer->width && height == pBuffer->height) {
+ // replace existing texture
+ glCopyTexSubImage2D(target,
+ pBuffer->mipmapLevel,
+ 0, 0, // xoffset, yoffset
+ 0, 0, // x, y
+ pBuffer->width, pBuffer->height);
+ } else {
+ // define new texture
+ glCopyTexImage2D(target,
+ pBuffer->mipmapLevel,
+ pBuffer->pbInfo.texFormat,
+ 0, 0, // x, y
+ pBuffer->width, pBuffer->height, 0);
+ }
+ }
+ break;
+ default:
+ ; // no op
+ }
+
+ // restore
+ glReadBuffer(readBufSave);
+
+ // rebind previous drawing surface
+ glXMakeCurrent(display, prevDrawable, prevContext);
+
+ return true;
+}
+
+bool
+releaseTexImage(Drawable *pBuffer, int iBuffer) {
+ assert(pBuffer->pbuffer);
+ // nothing to do here.
+ return true;
+}
+
+bool
+setPbufferAttrib(Drawable *pBuffer, const int *attribList) {
+ assert(pBuffer->pbuffer);
+ // Nothing to do here. retrace_wglSetPbufferAttribARB() will have parsed
+ // and saved the mipmap/cubeface info in the Drawable.
+ std::cout << "Calling GLX setPbufferAttrib\n";
+ return true;
+}
+
} /* namespace glws */
diff --git a/retrace/glws_waffle.cpp b/retrace/glws_waffle.cpp
index f6464a56..6b34eb04 100644
--- a/retrace/glws_waffle.cpp
+++ b/retrace/glws_waffle.cpp
@@ -1,7 +1,37 @@
+/*********************************************************************
+ *
+ * Copyright 2013 Intel Corporation
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************************/
+
#define WAFFLE_API_EXPERIMENTAL
#define WAFFLE_API_VERSION 0x0103
-#include "os.hpp"
+#include <string.h>
+
+#include <iostream>
+
#include "waffle.h"
#include "glws.hpp"
@@ -32,9 +62,10 @@ class WaffleDrawable : public Drawable
public:
struct waffle_window *window;
- WaffleDrawable(const Visual *vis, int w, int h, bool pbuffer,
+ WaffleDrawable(const Visual *vis, int w, int h,
+ const pbuffer_info *info,
struct waffle_window *win) :
- Drawable (vis, w, h, pbuffer),
+ Drawable (vis, w, h, info),
window (win)
{}
@@ -89,36 +120,46 @@ processEvents(void) {
}
void
-init(void) {
- int i;
- int waffle_init_attrib_list[3];
+init(void)
+{
+ int32_t waffle_platform;;
- i = 0;
- waffle_init_attrib_list[i++] = WAFFLE_PLATFORM;
- waffle_init_attrib_list[i++] =
#if defined(__ANDROID__)
- WAFFLE_PLATFORM_ANDROID
+ waffle_platform = WAFFLE_PLATFORM_ANDROID;
#elif defined(__APPLE__)
- WAFFLE_PLATFORM_CGL
-#elif defined(HAVE_X11)
-# if 1
- WAFFLE_PLATFORM_GLX
-# else
- WAFFLE_PLATFORM_X11_EGL
-# endif
+ waffle_platform = WAFFLE_PLATFORM_CGL
+#elif defined(_WIN32)
+ waffle_platform = WAFFLE_PLATFORM_WGL
#else
-# warning Unsupported platform
- WAFFLE_NONE
+ waffle_platform = WAFFLE_PLATFORM_GLX;
+
+ const char *waffle_platform_name = getenv("WAFFLE_PLATFORM");
+ if (waffle_platform_name) {
+ if (strcmp(waffle_platform_name, "gbm") == 0) {
+ waffle_platform = WAFFLE_PLATFORM_GBM;
+ } else if (strcmp(waffle_platform_name, "glx") == 0) {
+ waffle_platform = WAFFLE_PLATFORM_GLX;
+ } else if (strcmp(waffle_platform_name, "wayland") == 0) {
+ waffle_platform = WAFFLE_PLATFORM_WAYLAND;
+ } else if (strcmp(waffle_platform_name, "x11_egl") == 0) {
+ waffle_platform = WAFFLE_PLATFORM_X11_EGL;
+ } else {
+ std::cerr << "error: unsupported WAFFLE_PLATFORM \"" << waffle_platform_name << "\"\n";
+ exit(1);
+ }
+ }
#endif
- ;
- waffle_init_attrib_list[i++] = WAFFLE_NONE;
+
+ Attributes<int32_t> waffle_init_attrib_list;
+ waffle_init_attrib_list.add(WAFFLE_PLATFORM, waffle_platform);
+ waffle_init_attrib_list.end(WAFFLE_NONE);
waffle_init(waffle_init_attrib_list);
dpy = waffle_display_connect(NULL);
if (!dpy) {
- os::log("%s: waffle_display_connect(NULL) == NULL\n", __FILE__);
- os::abort();
+ std::cerr << "error: waffle_display_connect failed\n";
+ exit(1);
}
}
@@ -130,67 +171,81 @@ cleanup(void) {
Visual *
createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
struct waffle_config *cfg;
- int config_attrib_list[64], i(0), waffle_profile;
-
- switch (profile) {
- case PROFILE_ES1:
- waffle_profile = WAFFLE_CONTEXT_OPENGL_ES1;
- break;
- case PROFILE_ES2:
- waffle_profile = WAFFLE_CONTEXT_OPENGL_ES2;
- break;
- default:
- os::log("%s: Unsupported context profile\n", __FILE__);
- os::abort();
+
+ int waffle_api;
+ if (profile.api == glprofile::API_GL) {
+ waffle_api = WAFFLE_CONTEXT_OPENGL;
+ } else if (profile.api == glprofile::API_GLES) {
+ switch (profile.major) {
+ case 1:
+ waffle_api = WAFFLE_CONTEXT_OPENGL_ES1;
+ break;
+ case 2:
+ waffle_api = WAFFLE_CONTEXT_OPENGL_ES2;
+ break;
+ case 3:
+ waffle_api = WAFFLE_CONTEXT_OPENGL_ES3;
+ break;
+ default:
+ std::cerr << "error: unsupported context profile " << profile << "\n";
+ exit(1);
+ return NULL;
+ }
+ } else {
+ assert(0);
return NULL;
}
- if(!waffle_display_supports_context_api(dpy, waffle_profile)) {
- os::log("%s: !waffle_display_supports_context_api\n",
- __FILE__);
-
- os::abort();
+ if (!waffle_display_supports_context_api(dpy, waffle_api)) {
+ std::cerr << "error: waffle_display_supports_context_api failed \n";
+ exit(1);
return NULL;
}
- config_attrib_list[i++] = WAFFLE_CONTEXT_API;
- config_attrib_list[i++] = waffle_profile;
- config_attrib_list[i++] = WAFFLE_RED_SIZE;
- config_attrib_list[i++] = 8;
- config_attrib_list[i++] = WAFFLE_GREEN_SIZE;
- config_attrib_list[i++] = 8;
- config_attrib_list[i++] = WAFFLE_BLUE_SIZE;
- config_attrib_list[i++] = 8;
- config_attrib_list[i++] = WAFFLE_DEPTH_SIZE;
- config_attrib_list[i++] = 8;
- config_attrib_list[i++] = WAFFLE_ALPHA_SIZE;
- config_attrib_list[i++] = 8;
- config_attrib_list[i++] = WAFFLE_STENCIL_SIZE;
- config_attrib_list[i++] = 8;
- config_attrib_list[i++] = WAFFLE_DOUBLE_BUFFERED;
- config_attrib_list[i++] = doubleBuffer;
- config_attrib_list[i++] = 0;
+ Attributes<int32_t> config_attrib_list;
+ config_attrib_list.add(WAFFLE_CONTEXT_API, waffle_api);
+ if (profile.api == glprofile::API_GL) {
+ config_attrib_list.add(WAFFLE_CONTEXT_MAJOR_VERSION, profile.major);
+ config_attrib_list.add(WAFFLE_CONTEXT_MINOR_VERSION, profile.minor);
+ if (profile.versionGreaterOrEqual(3, 2)) {
+ int profileMask = profile.core ? WAFFLE_CONTEXT_CORE_PROFILE : WAFFLE_CONTEXT_COMPATIBILITY_PROFILE;
+ config_attrib_list.add(WAFFLE_CONTEXT_PROFILE, profileMask);
+ }
+ if (profile.forwardCompatible) {
+ config_attrib_list.add(WAFFLE_CONTEXT_FORWARD_COMPATIBLE, true);
+ }
+ }
+ config_attrib_list.add(WAFFLE_RED_SIZE, 8);
+ config_attrib_list.add(WAFFLE_GREEN_SIZE, 8);
+ config_attrib_list.add(WAFFLE_BLUE_SIZE, 8);
+ config_attrib_list.add(WAFFLE_DEPTH_SIZE, 8);
+ config_attrib_list.add(WAFFLE_ALPHA_SIZE, 8);
+ config_attrib_list.add(WAFFLE_STENCIL_SIZE, 8);
+ config_attrib_list.add(WAFFLE_DOUBLE_BUFFERED, doubleBuffer);
+ if (0) {
+ config_attrib_list.add(WAFFLE_CONTEXT_DEBUG, true);
+ }
+ config_attrib_list.end();
cfg = waffle_config_choose(dpy, config_attrib_list);
- if (!cfg)
- {
- os::log("Error in %s waffle_config_choose(dpy, " \
- "config_attrib_list)\n", __FILE__);
- os::abort();
+ if (!cfg) {
+ std::cerr << "error: waffle_config_choose failed\n";
+ exit(1);
return NULL;
}
return new WaffleVisual(profile, cfg);
}
Drawable *
-createDrawable(const Visual *visual, int width, int height, bool pbuffer)
+createDrawable(const Visual *visual, int width, int height,
+ const pbuffer_info *info)
{
struct waffle_window *window;
const WaffleVisual *waffleVisual =
static_cast<const WaffleVisual *>(visual);
window = waffle_window_create(waffleVisual->config, width, height);
- return new WaffleDrawable(visual, width, height, pbuffer, window);
+ return new WaffleDrawable(visual, width, height, info, window);
}
Context *
@@ -208,17 +263,15 @@ createContext(const Visual *visual, Context *shareContext,
context = waffle_context_create(waffleVisual->config, share_context);
if (!context) {
- os::log("Error in %s waffle_context_create()\n",
- __FILE__);
-
- os::abort();
+ std::cerr << "error: waffle_context_create failed\n";
+ exit(1);
return NULL;
}
return new WaffleContext(visual, context);
}
bool
-makeCurrent(Drawable *drawable, Context *context)
+makeCurrentInternal(Drawable *drawable, Context *context)
{
if (!drawable || !context) {
return waffle_make_current(dpy, NULL, NULL);
@@ -234,4 +287,25 @@ makeCurrent(Drawable *drawable, Context *context)
}
}
+bool
+bindTexImage(Drawable *pBuffer, int iBuffer) {
+ std::cerr << "error: Waffle::wglBindTexImageARB not implemented.\n";
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
+bool
+releaseTexImage(Drawable *pBuffer, int iBuffer) {
+ std::cerr << "error: Waffle::wglReleaseTexImageARB not implemented.\n";
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
+bool
+setPbufferAttrib(Drawable *pBuffer, const int *attribList) {
+ // nothing to do here.
+ assert(pBuffer->pbuffer);
+ return true;
+}
+
} /* namespace glws */
diff --git a/retrace/glws_wgl.cpp b/retrace/glws_wgl.cpp
index d5f7ca20..2c5e2f7f 100644
--- a/retrace/glws_wgl.cpp
+++ b/retrace/glws_wgl.cpp
@@ -33,7 +33,9 @@
#include "glproc.hpp"
#include "glws.hpp"
+#include "ws_win32.hpp"
+#include <GL/wglext.h>
namespace glws {
@@ -55,200 +57,106 @@ namespace glws {
* - http://www.opengl.org/archives/resources/faq/technical/mswindows.htm
*/
static PFN_WGLCHOOSEPIXELFORMAT pfnChoosePixelFormat = &ChoosePixelFormat;
+static PFN_WGLDESCRIBEPIXELFORMAT pfnDescribePixelFormat = &DescribePixelFormat;
static PFN_WGLSETPIXELFORMAT pfnSetPixelFormat = &SetPixelFormat;
static PFN_WGLSWAPBUFFERS pfnSwapBuffers = &SwapBuffers;
-static LRESULT CALLBACK
-WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- MINMAXINFO *pMMI;
- switch (uMsg) {
- case WM_KEYDOWN:
- switch (wParam) {
- case VK_ESCAPE:
- PostMessage(hWnd, WM_CLOSE, 0, 0);
- break;
- }
- break;
- case WM_GETMINMAXINFO:
- // Allow to create a window bigger than the desktop
- pMMI = (MINMAXINFO *)lParam;
- pMMI->ptMaxSize.x = 60000;
- pMMI->ptMaxSize.y = 60000;
- pMMI->ptMaxTrackSize.x = 60000;
- pMMI->ptMaxTrackSize.y = 60000;
- break;
- case WM_CLOSE:
- exit(0);
- break;
- default:
- break;
- }
-
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
-}
-
-
-static const DWORD dwExStyle = 0;
-static const DWORD dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
-
-
-struct WindowThreadParam
-{
- int nWidth;
- int nHeight;
-
- HANDLE hEvent;
-
- HWND hWnd;
-};
-
-
-static DWORD WINAPI
-windowThreadFunction( LPVOID _lpParam )
-{
- WindowThreadParam *lpParam = (WindowThreadParam *)_lpParam;
-
- // Actually create the window
- lpParam->hWnd = CreateWindowEx(dwExStyle,
- "glretrace", /* wc.lpszClassName */
- NULL,
- dwStyle,
- 0, /* x */
- 0, /* y */
- lpParam->nWidth,
- lpParam->nHeight,
- NULL,
- NULL,
- NULL,
- NULL);
-
- // Notify parent thread that window has been created
- SetEvent(lpParam->hEvent);
-
- BOOL bRet;
- MSG msg;
- while ((bRet = GetMessage(&msg, NULL, 0, 0 )) != FALSE) {
- if (bRet == -1) {
- // handle the error and possibly exit
- } else {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
+#define WGL_PROC(type, func, name) \
+ func = (type) wglGetProcAddress(name); \
+ if (!func) { \
+ std::cerr << "error: failed to get pointer to " << name << "\n"; \
+ exit(1); \
}
- // Return the exit code
- return msg.wParam;
-}
-
-
-/**
- * Create a window on a separate thread.
- *
- * Each window is associated with one thread, which must process its events,
- * and certain operations like SetWindowPos will block until the message is
- * process, so the only way to guarantee that the window messages are processed
- * timely is by dedicating a thread to processing window events.
- *
- * TODO: Handle multiple windows on a single thread, instead of creating one
- * thread per each window.
- */
-static HWND
-createWindow(int nWidth, int nHeight)
-{
- // Create window class
- static bool first = TRUE;
- if (first) {
- WNDCLASS wc;
- memset(&wc, 0, sizeof wc);
- wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wc.lpfnWndProc = WndProc;
- wc.lpszClassName = "glretrace";
- wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
- RegisterClass(&wc);
- first = FALSE;
- }
- // Spawn window thread
- WindowThreadParam param;
- param.nWidth = nWidth;
- param.nHeight = nHeight;
- param.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- DWORD dwThreadId = 0;
- CreateThread(NULL, 0, &windowThreadFunction, (LPVOID)&param, 0, &dwThreadId);
+static bool has_WGL_ARB_pbuffer = false;
+static PFNWGLGETEXTENSIONSSTRINGARBPROC pfnWglGetExtensionsStringARB;
+static PFNWGLCREATEPBUFFERARBPROC pfnWglCreatePbufferARB;
+static PFNWGLGETPBUFFERDCARBPROC pfnWglGetPbufferDCARB;
+static PFNWGLCHOOSEPIXELFORMATARBPROC pfnWglChoosePixelFormatARB;
+static PFNWGLDESTROYPBUFFERARBPROC pfnWglDestroyPbufferARB;
+static PFNWGLRELEASEPBUFFERDCARBPROC pfnWglReleasePbufferDCARB;
- // Wait for window creation event
- WaitForSingleObject(param.hEvent, INFINITE);
- CloseHandle(param.hEvent);
-
- return param.hWnd;
-}
+static bool has_WGL_ARB_render_texture = false;
+static PFNWGLBINDTEXIMAGEARBPROC pfnWglBindTexImageARB;
+static PFNWGLRELEASETEXIMAGEARBPROC pfnWglReleaseTexImageARB;
+static PFNWGLSETPBUFFERATTRIBARBPROC pfnWglSetPbufferAttribARB;
class WglDrawable : public Drawable
{
public:
+ // Only one of hWnd and pbBuffer will be non-zero
HWND hWnd;
+ HPBUFFERARB hPBuffer;
HDC hDC;
- PIXELFORMATDESCRIPTOR pfd;
- int iPixelFormat;
- WglDrawable(const Visual *vis, int width, int height, bool pbuffer) :
- Drawable(vis, width, height, pbuffer)
+ WglDrawable(const Visual *vis, int width, int height,
+ const glws::pbuffer_info *pbInfo) :
+ Drawable(vis, width, height, pbInfo ? true : false)
{
- int x = 0, y = 0;
- RECT rect;
- BOOL bRet;
- rect.left = x;
- rect.top = y;
- rect.right = rect.left + width;
- rect.bottom = rect.top + height;
-
- AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
-
- hWnd = createWindow(rect.right - rect.left,
- rect.bottom - rect.top);
-
- hDC = GetDC(hWnd);
-
- memset(&pfd, 0, sizeof pfd);
- pfd.cColorBits = 4;
- pfd.cRedBits = 1;
- pfd.cGreenBits = 1;
- pfd.cBlueBits = 1;
- pfd.cAlphaBits = 1;
- pfd.cDepthBits = 1;
- pfd.cStencilBits = 1;
- pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
- pfd.iLayerType = PFD_MAIN_PLANE;
- pfd.iPixelType = PFD_TYPE_RGBA;
- pfd.nSize = sizeof(pfd);
- pfd.nVersion = 1;
-
- if (visual->doubleBuffer) {
- pfd.dwFlags |= PFD_DOUBLEBUFFER;
+ if (pbInfo) {
+ createPbuffer(vis, pbInfo, width, height);
+ hWnd = 0;
}
+ else {
+ hWnd = ws::createWindow("glretrace", width, height);
+
+ hDC = GetDC(hWnd);
+
+ PIXELFORMATDESCRIPTOR pfd;
+ ZeroMemory(&pfd, sizeof pfd);
+ pfd.nSize = sizeof pfd;
+ pfd.nVersion = 1;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ pfd.cColorBits = 3;
+ // XXX: ChoosePixelFormat will return a software pixelformat if we
+ // request alpha bits and the hardware driver doesn't advertise any
+ // pixel format with alpha bits (e.g. NVIDIA OpenGL driver on 16bpp
+ // screens.)
+ pfd.cAlphaBits = 1;
+ pfd.cDepthBits = 1;
+ pfd.cStencilBits = 1;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+
+ if (visual->doubleBuffer) {
+ pfd.dwFlags |= PFD_DOUBLEBUFFER;
+ }
- iPixelFormat = pfnChoosePixelFormat(hDC, &pfd);
- if (iPixelFormat <= 0) {
- std::cerr << "error: ChoosePixelFormat failed\n";
- exit(1);
- }
+ int iPixelFormat = pfnChoosePixelFormat(hDC, &pfd);
+ if (iPixelFormat <= 0) {
+ std::cerr << "error: ChoosePixelFormat failed\n";
+ exit(1);
+ }
- bRet = pfnSetPixelFormat(hDC, iPixelFormat, &pfd);
- if (!bRet) {
- std::cerr << "error: SetPixelFormat failed\n";
- exit(1);
+ pfnDescribePixelFormat(hDC, iPixelFormat, sizeof pfd, &pfd);
+ assert(pfd.dwFlags & PFD_SUPPORT_OPENGL);
+ if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
+ std::cerr << "warning: ChoosePixelFormat returned a pixel format supported by the GDI software implementation\n";
+ }
+
+ BOOL bRet = pfnSetPixelFormat(hDC, iPixelFormat, &pfd);
+ if (!bRet) {
+ std::cerr << "error: SetPixelFormat failed\n";
+ exit(1);
+ }
+
+ hPBuffer = 0;
}
}
~WglDrawable() {
- ReleaseDC(hWnd, hDC);
- DestroyWindow(hWnd);
+ if (hPBuffer) {
+ pfnWglReleasePbufferDCARB(hPBuffer, hDC);
+ pfnWglDestroyPbufferARB(hPBuffer);
+ }
+ else {
+ ReleaseDC(hWnd, hDC);
+ DestroyWindow(hWnd);
+ }
}
void
@@ -259,18 +167,7 @@ public:
Drawable::resize(w, h);
- RECT rClient, rWindow;
- GetClientRect(hWnd, &rClient);
- GetWindowRect(hWnd, &rWindow);
- w += (rWindow.right - rWindow.left) - rClient.right;
- h += (rWindow.bottom - rWindow.top) - rClient.bottom;
-
- UINT uFlags = SWP_NOMOVE
- | SWP_NOZORDER
- | SWP_NOACTIVATE
- | SWP_NOOWNERZORDER;
-
- SetWindowPos(hWnd, NULL, rWindow.left, rWindow.top, w, h, uFlags);
+ ws::resizeWindow(hWnd, w, h);
}
void show(void) {
@@ -278,18 +175,23 @@ public:
return;
}
- ShowWindow(hWnd, SW_SHOW);
+ ws::showWindow(hWnd);
Drawable::show();
}
void swapBuffers(void) {
+ assert(!pbuffer);
BOOL bRet;
bRet = pfnSwapBuffers(hDC);
if (!bRet) {
std::cerr << "warning: SwapBuffers failed\n";
}
}
+
+private:
+ bool createPbuffer(const Visual *vis,
+ const glws::pbuffer_info *pbInfo, int width, int height);
};
@@ -314,77 +216,160 @@ public:
}
bool
- create(WglDrawable *wglDrawable) {
- if (!hglrc) {
- HDC hDC = wglDrawable->hDC;
+ createARB(HDC hDC) {
+ bool required = profile.api != glprofile::API_GL ||
+ profile.versionGreaterOrEqual(3, 1);
- hglrc = wglCreateContext(hDC);
- if (!hglrc) {
- std::cerr << "error: wglCreateContext failed\n";
+ // We need to create context through WGL_ARB_create_context. This
+ // implies binding a temporary context to get the extensions strings
+ // and function pointers.
+
+ // This function is only called inside makeCurrent, so we don't need
+ // to save and restore the previous current context/drawable.
+ BOOL bRet = wglMakeCurrent(hDC, hglrc);
+ if (!bRet) {
+ std::cerr << "error: wglMakeCurrent failed\n";
+ exit(1);
+ }
+
+ pfnWglGetExtensionsStringARB =
+ (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
+ if (!pfnWglGetExtensionsStringARB) {
+ if (required) {
+ std::cerr << "error: WGL_ARB_extensions_string not supported\n";
exit(1);
+ } else {
+ return false;
}
+ }
+ const char * extensionsString = pfnWglGetExtensionsStringARB(hDC);
+ assert(extensionsString);
+
+ if (checkExtension("WGL_ARB_pbuffer", extensionsString)) {
+ has_WGL_ARB_pbuffer = true;
+ WGL_PROC(PFNWGLCREATEPBUFFERARBPROC,
+ pfnWglCreatePbufferARB, "wglCreatePbufferARB");
+ WGL_PROC(PFNWGLGETPBUFFERDCARBPROC,
+ pfnWglGetPbufferDCARB, "wglGetPbufferDCARB");
+ WGL_PROC(PFNWGLCHOOSEPIXELFORMATARBPROC,
+ pfnWglChoosePixelFormatARB, "wglChoosePixelFormatARB");
+ WGL_PROC(PFNWGLDESTROYPBUFFERARBPROC,
+ pfnWglDestroyPbufferARB, "wglDestroyPbufferARB");
+ WGL_PROC(PFNWGLRELEASEPBUFFERDCARBPROC,
+ pfnWglReleasePbufferDCARB, "wglReleasePbufferDCARB");
+ }
+ if (checkExtension("WGL_ARB_render_texture", extensionsString)) {
+ assert(has_WGL_ARB_pbuffer);
+ has_WGL_ARB_render_texture = true;
+ WGL_PROC(PFNWGLBINDTEXIMAGEARBPROC,
+ pfnWglBindTexImageARB, "wglBindTexImageARB");
+ WGL_PROC(PFNWGLRELEASETEXIMAGEARBPROC,
+ pfnWglReleaseTexImageARB, "wglReleaseTexImageARB");
+ WGL_PROC(PFNWGLSETPBUFFERATTRIBARBPROC,
+ pfnWglSetPbufferAttribARB, "wglSetPbufferAttribARB");
+ }
- if (shareContext) {
- shareContext->create(wglDrawable);
+ if (!checkExtension("WGL_ARB_create_context", extensionsString)) {
+ if (required) {
+ std::cerr << "error: WGL_ARB_create_context not supported\n";
+ exit(1);
+ } else {
+ return false;
}
+ }
- unsigned major, minor;
- bool core;
- getProfileVersion(profile, major, minor, core);
- if (major >= 3 || core) {
- // We need to create context through WGL_ARB_create_context. This
- // implies binding a temporary context to get the extensions strings
- // and function pointers.
-
- // This function is only called inside makeCurrent, so we don't need
- // to save and restore the previous current context/drawable.
- BOOL bRet = wglMakeCurrent(hDC, hglrc);
- if (!bRet) {
- std::cerr << "error: wglMakeCurrent failed\n";
- exit(1);
- }
+ PFNWGLCREATECONTEXTATTRIBSARBPROC pfnWglCreateContextAttribsARB =
+ (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
+ if (!pfnWglCreateContextAttribsARB) {
+ if (required) {
+ std::cerr << "error: failed to get pointer to wglCreateContextAttribsARB\n";
+ exit(1);
+ } else {
+ return false;
+ }
+ }
- PFNWGLGETEXTENSIONSSTRINGARBPROC pfnWglGetExtensionsStringARB =
- (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
- if (!pfnWglGetExtensionsStringARB) {
- std::cerr << "error: WGL_ARB_extensions_string not supported\n";
+ wglMakeCurrent(hDC, NULL);
+
+ Attributes<int> attribs;
+ int contextFlags = 0;
+ if (profile.api == glprofile::API_GL) {
+ attribs.add(WGL_CONTEXT_MAJOR_VERSION_ARB, profile.major);
+ attribs.add(WGL_CONTEXT_MINOR_VERSION_ARB, profile.minor);
+ if (profile.versionGreaterOrEqual(3, 2)) {
+ if (!checkExtension("WGL_ARB_create_context_profile", extensionsString)) {
+ assert(required);
+ std::cerr << "error: WGL_ARB_create_context_profile not supported\n";
exit(1);
}
- const char * extensionsString = pfnWglGetExtensionsStringARB(hDC);
- if (!checkExtension("WGL_ARB_create_context", extensionsString)) {
- std::cerr << "error: WGL_ARB_create_context not supported\n";
- exit(1);
+ int profileMask = profile.core ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ attribs.add(WGL_CONTEXT_PROFILE_MASK_ARB, profileMask);
+ if (profile.forwardCompatible) {
+ contextFlags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
}
+ }
+ } else if (profile.api == glprofile::API_GLES) {
+ if (checkExtension("WGL_EXT_create_context_es_profile", extensionsString)) {
+ attribs.add(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES_PROFILE_BIT_EXT);
+ attribs.add(WGL_CONTEXT_MAJOR_VERSION_ARB, profile.major);
+ attribs.add(WGL_CONTEXT_MINOR_VERSION_ARB, profile.minor);
+ } else if (profile.major != 2) {
+ std::cerr << "warning: OpenGL ES " << profile.major << " requested but WGL_EXT_create_context_es_profile not supported\n";
+ } else if (checkExtension("WGL_EXT_create_context_es2_profile", extensionsString)) {
+ assert(profile.major == 2);
+ attribs.add(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT);
+ attribs.add(WGL_CONTEXT_MAJOR_VERSION_ARB, profile.major);
+ attribs.add(WGL_CONTEXT_MINOR_VERSION_ARB, profile.minor);
+ } else {
+ std::cerr << "warning: OpenGL ES " << profile.major << " requested but WGL_EXT_create_context_es_profile or WGL_EXT_create_context_es2_profile not supported\n";
+ }
+ } else {
+ assert(0);
+ }
+ if (debug) {
+ contextFlags |= WGL_CONTEXT_DEBUG_BIT_ARB;
+ }
+ if (contextFlags) {
+ attribs.add(WGL_CONTEXT_FLAGS_ARB, contextFlags);
+ }
+ attribs.end();
- PFNWGLCREATECONTEXTATTRIBSARBPROC pfnWglCreateContextAttribsARB =
- (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
- if (!pfnWglCreateContextAttribsARB) {
- std::cerr << "error: failed to get pointer to wglCreateContextAttribsARB\n";
- exit(1);
- }
- wglMakeCurrent(hDC, NULL);
- wglDeleteContext(hglrc);
+ HGLRC new_hglrc;
+ new_hglrc = pfnWglCreateContextAttribsARB(hDC,
+ shareContext ? shareContext->hglrc : 0,
+ attribs);
+ if (!new_hglrc) {
+ if (required) {
+ std::cerr << "error: wglCreateContextAttribsARB failed\n";
+ exit(1);
+ } else {
+ return false;
+ }
+ }
- Attributes<int> attribs;
- attribs.add(WGL_CONTEXT_MAJOR_VERSION_ARB, major);
- attribs.add(WGL_CONTEXT_MINOR_VERSION_ARB, minor);
- if (core) {
- attribs.add(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
- }
- if (debug) {
- attribs.add(WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB);
- }
- attribs.end();
+ wglDeleteContext(hglrc);
+ hglrc = new_hglrc;
- hglrc = pfnWglCreateContextAttribsARB(hDC,
- shareContext ? shareContext->hglrc : 0,
- attribs);
- if (!hglrc) {
- std::cerr << "error: wglCreateContextAttribsARB failed\n";
- exit(1);
- }
- } else {
+ return true;
+ }
+
+ bool
+ create(WglDrawable *wglDrawable) {
+ if (!hglrc) {
+ HDC hDC = wglDrawable->hDC;
+
+ hglrc = wglCreateContext(hDC);
+ if (!hglrc) {
+ std::cerr << "error: wglCreateContext failed\n";
+ exit(1);
+ }
+
+ if (shareContext) {
+ shareContext->create(wglDrawable);
+ }
+
+ if (!createARB(hDC)) {
if (shareContext) {
BOOL bRet;
bRet = wglShareLists(shareContext->hglrc,
@@ -414,14 +399,22 @@ init(void) {
const char * libgl_filename = getenv("TRACE_LIBGL");
if (libgl_filename) {
- pfnChoosePixelFormat = &wglChoosePixelFormat;
- pfnSetPixelFormat = &wglSetPixelFormat;
- pfnSwapBuffers = &wglSwapBuffers;
+ _libGlHandle = LoadLibraryA(libgl_filename);
+ if (_libGlHandle) {
+ pfnChoosePixelFormat = (PFN_WGLCHOOSEPIXELFORMAT)GetProcAddress(_libGlHandle, "wglChoosePixelFormat");
+ assert(pfnChoosePixelFormat);
+ pfnDescribePixelFormat = (PFN_WGLDESCRIBEPIXELFORMAT)GetProcAddress(_libGlHandle, "wglDescribePixelFormat");
+ assert(pfnDescribePixelFormat);
+ pfnSetPixelFormat = (PFN_WGLSETPIXELFORMAT)GetProcAddress(_libGlHandle, "wglSetPixelFormat");
+ assert(pfnSetPixelFormat);
+ pfnSwapBuffers = (PFN_WGLSWAPBUFFERS)GetProcAddress(_libGlHandle, "wglSwapBuffers");
+ assert(pfnSwapBuffers);
+ }
} else {
libgl_filename = "OPENGL32";
+ _libGlHandle = LoadLibraryA(libgl_filename);
}
- _libGlHandle = LoadLibraryA(libgl_filename);
if (!_libGlHandle) {
std::cerr << "error: unable to open " << libgl_filename << "\n";
exit(1);
@@ -434,18 +427,6 @@ cleanup(void) {
Visual *
createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
- switch (profile) {
- case PROFILE_COMPAT:
- break;
- case PROFILE_ES1:
- return NULL;
- case PROFILE_ES2:
- std::cerr << "warning: ignoring OpenGL ES 2.0 profile request\n";
- break;
- default:
- break;
- }
-
Visual *visual = new Visual(profile);
visual->doubleBuffer = doubleBuffer;
@@ -454,9 +435,10 @@ createVisual(bool doubleBuffer, unsigned samples, Profile profile) {
}
Drawable *
-createDrawable(const Visual *visual, int width, int height, bool pbuffer)
+createDrawable(const Visual *visual, int width, int height,
+ const glws::pbuffer_info *pbInfo)
{
- return new WglDrawable(visual, width, height, pbuffer);
+ return new WglDrawable(visual, width, height, pbInfo);
}
Context *
@@ -466,7 +448,7 @@ createContext(const Visual *visual, Context *shareContext, bool debug)
}
bool
-makeCurrent(Drawable *drawable, Context *context)
+makeCurrentInternal(Drawable *drawable, Context *context)
{
if (!drawable || !context) {
return wglMakeCurrent(NULL, NULL);
@@ -481,20 +463,154 @@ makeCurrent(Drawable *drawable, Context *context)
}
bool
-processEvents(void) {
- MSG uMsg;
- while (PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE)) {
- if (uMsg.message == WM_QUIT) {
- return false;
+processEvents(void)
+{
+ return ws::processEvents();
+}
+
+
+bool
+glws::WglDrawable::createPbuffer(const Visual *vis,
+ const glws::pbuffer_info *pbInfo,
+ int width, int height)
+{
+ if (!has_WGL_ARB_pbuffer) {
+ std::cerr << "error: WGL_ARB_pbuffer extension is unsupported\n";
+ exit(1);
+ return false;
+ }
+
+ // choose pixel format
+ Attributes<int> attribs;
+ attribs.add(WGL_DRAW_TO_PBUFFER_ARB, true);
+ attribs.add(WGL_DEPTH_BITS_ARB, 24);
+ attribs.add(WGL_STENCIL_BITS_ARB, 8);
+ attribs.add(WGL_RED_BITS_ARB, 8);
+ attribs.add(WGL_GREEN_BITS_ARB, 8);
+ attribs.add(WGL_BLUE_BITS_ARB, 8);
+ attribs.add(WGL_ALPHA_BITS_ARB, 8);
+ attribs.add(WGL_COLOR_BITS_ARB, 32);
+ if (pbInfo->texFormat) {
+ if (pbInfo->texFormat == GL_RGBA)
+ attribs.add(WGL_BIND_TO_TEXTURE_RGBA_ARB, true);
+ else if (pbInfo->texFormat == GL_RGB)
+ attribs.add(WGL_BIND_TO_TEXTURE_RGB_ARB, true);
+ else {
+ std::cerr << "error: unexpected texture format.\n";
+ exit(1);
}
+ }
+ attribs.end();
+
+ int pixelFormats[20];
+ UINT numPixelFormats;
+ WglDrawable *wgl_draw = static_cast<WglDrawable *>(pbInfo->hdc_drawable);
+ HDC hdc = wgl_draw->hDC;
+ assert(hdc);
+
+ if (!pfnWglChoosePixelFormatARB(hdc, attribs, NULL,
+ 20, pixelFormats,
+ &numPixelFormats)) {
+ std::cerr << "error: wglChoosePixelFormatARB failed.\n";
+ exit(1);
+ }
- if (!TranslateAccelerator(uMsg.hwnd, NULL, &uMsg)) {
- TranslateMessage(&uMsg);
- DispatchMessage(&uMsg);
+ // create pbuffer
+ Attributes<int> pbAttribs;
+ if (pbInfo->texFormat) {
+ if (pbInfo->texFormat == GL_RGBA) {
+ pbAttribs.add(WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB);
+ } else if (pbInfo->texFormat == GL_RGB) {
+ pbAttribs.add(WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGB_ARB);
+ } else {
+ std::cerr << "error: unexpected texture format.\n";
+ exit(1);
+ }
+ }
+ if (pbInfo->texTarget) {
+ if (pbInfo->texTarget == GL_TEXTURE_1D) {
+ pbAttribs.add(WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_1D_ARB);
+ } else if (pbInfo->texTarget == GL_TEXTURE_2D) {
+ pbAttribs.add(WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB);
+ } else if (pbInfo->texTarget == GL_TEXTURE_CUBE_MAP) {
+ pbAttribs.add(WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_CUBE_MAP_ARB);
+ } else {
+ std::cerr << "error: unexpected texture targett.\n";
+ exit(1);
}
}
+ if (pbInfo->texMipmap) {
+ pbAttribs.add(WGL_MIPMAP_TEXTURE_ARB, pbInfo->texMipmap);
+ }
+ pbAttribs.end();
+
+ hPBuffer = pfnWglCreatePbufferARB(hdc, pixelFormats[0],
+ width, height, pbAttribs);
+ if (!hPBuffer) {
+ std::cerr << "error: wglCreatePbufferARB failed (format "
+ << pixelFormats[0] << ")\n";
+ DWORD er = GetLastError();
+ std::cerr << "error code " << er << "\n";
+ exit(1);
+ }
+ hDC = pfnWglGetPbufferDCARB(hPBuffer);
+ if (!hDC) {
+ std::cerr << "error: wglGetPbufferDCARB failed\n";
+ exit(1);
+ }
+
return true;
}
+static int
+enum_buffer_to_wgl_buffer(GLenum buffer)
+{
+ switch (buffer) {
+ case GL_FRONT_LEFT:
+ return WGL_FRONT_LEFT_ARB;
+ case GL_BACK_LEFT:
+ return WGL_BACK_LEFT_ARB;
+ case GL_FRONT_RIGHT:
+ return WGL_FRONT_RIGHT_ARB;
+ case GL_BACK_RIGHT:
+ return WGL_BACK_RIGHT_ARB;
+ case GL_AUX0:
+ return WGL_AUX0_ARB;
+ default:
+ std::cerr << "error: invalid buffer in enum_buffer_to_wgl_buffer()\n";
+ return WGL_FRONT_LEFT_ARB;
+ }
+}
+
+bool
+bindTexImage(Drawable *pBuffer, int buf) {
+ if (!has_WGL_ARB_render_texture) {
+ return false;
+ }
+ WglDrawable *wglDrawable = static_cast<WglDrawable *>(pBuffer);
+ return pfnWglBindTexImageARB(wglDrawable->hPBuffer,
+ enum_buffer_to_wgl_buffer(buf));
+}
+
+bool
+releaseTexImage(Drawable *pBuffer, int buf) {
+ if (!has_WGL_ARB_render_texture) {
+ return false;
+ }
+ WglDrawable *wglDrawable = static_cast<WglDrawable *>(pBuffer);
+ return pfnWglReleaseTexImageARB(wglDrawable->hPBuffer,
+ enum_buffer_to_wgl_buffer(buf));
+}
+
+bool
+setPbufferAttrib(Drawable *pBuffer, const int *attribList) {
+ if (!has_WGL_ARB_render_texture) {
+ return false;
+ }
+ WglDrawable *wglDrawable = static_cast<WglDrawable *>(pBuffer);
+ return pfnWglSetPbufferAttribARB(wglDrawable->hPBuffer, attribList);
+}
+
+
} /* namespace glws */
diff --git a/retrace/glws_xlib.cpp b/retrace/glws_xlib.cpp
index f6b92062..56bb043f 100644
--- a/retrace/glws_xlib.cpp
+++ b/retrace/glws_xlib.cpp
@@ -31,6 +31,7 @@
#include "glproc.hpp"
#include "glws.hpp"
+#include "ws.hpp"
namespace glws {
@@ -91,7 +92,15 @@ errorHandler(Display *dpy, XErrorEvent *error)
{
char buffer[512];
XGetErrorText(dpy, error->error_code, buffer, sizeof buffer);
- std::cerr << "error: xlib: " << buffer << "\n";
+ std::cerr << "error: xlib: " << buffer;
+
+ if (error->request_code < 128) {
+ std::string request_code = std::to_string(error->request_code);
+ XGetErrorDatabaseText(dpy, "XRequest", request_code.c_str(), "", buffer, sizeof buffer);
+ std::cerr << " in " << buffer;
+ }
+
+ std::cerr << "\n";
return 0;
}
@@ -101,6 +110,10 @@ static int (*oldErrorHandler)(Display *, XErrorEvent *) = NULL;
void
initX(void)
{
+#ifndef NDEBUG
+ _Xdebug = 1;
+#endif
+
XInitThreads();
oldErrorHandler = XSetErrorHandler(errorHandler);
@@ -224,9 +237,12 @@ resizeWindow(Window window, int w, int h)
void
showWindow(Window window)
{
- XMapWindow(display, window);
-
- waitForEvent(window, MapNotify);
+ // FIXME: This works for DRI drivers, but not NVIDIA proprietary drivers,
+ // for which the only solution seems to be to use Pbuffers.
+ if (true || !ws::headless) {
+ XMapWindow(display, window);
+ waitForEvent(window, MapNotify);
+ }
}
diff --git a/retrace/glws_xlib.hpp b/retrace/glws_xlib.hpp
index d703c931..68d32c20 100644
--- a/retrace/glws_xlib.hpp
+++ b/retrace/glws_xlib.hpp
@@ -27,8 +27,7 @@
* Common XLIB code, used by GLX and EGL.
*/
-#ifndef _GLWS_XLIB_HPP_
-#define _GLWS_XLIB_HPP_
+#pragma once
#include "glimports.hpp"
@@ -68,4 +67,3 @@ showWindow(Window window);
} /* namespace glws */
-#endif /* _GLWS_XLIB_HPP_ */
diff --git a/retrace/json.cpp b/retrace/json.cpp
index 850e37f9..bf1309e7 100644
--- a/retrace/json.cpp
+++ b/retrace/json.cpp
@@ -33,7 +33,6 @@
#include <sstream>
-#include "image.hpp"
#include "json.hpp"
@@ -127,8 +126,7 @@ escapeUnicodeString(std::ostream &os, const char *str) {
os << (unsigned char)c;
} else {
// unicode
- os << "\\u" << std::setfill('0') << std::hex << std::setw(4) << (unsigned)c;
- os << std::dec;
+ os << "\\u" << std::hex << std::setfill('0') << std::setw(4) << (unsigned)c << std::setfill(' ') << std::dec;
}
} while (src);
@@ -173,18 +171,14 @@ encodeBase64String(std::ostream &os, const unsigned char *bytes, size_t size) {
if (size > 0) {
c0 = bytes[0] >> 2;
c1 = ((bytes[0] & 0x03) << 4);
- buf[2] = '=';
- buf[3] = '=';
+ buf[3] = '=';
if (size > 1) {
c1 |= ((bytes[1] & 0xf0) >> 4);
c2 = ((bytes[1] & 0x0f) << 2);
- if (size > 2) {
- c2 |= ((bytes[2] & 0xc0) >> 6);
- c3 = bytes[2] & 0x3f;
- buf[3] = table64[c3];
- }
buf[2] = table64[c2];
+ } else {
+ buf[2] = '=';
}
buf[1] = table64[c1];
buf[0] = table64[c0];
@@ -300,38 +294,3 @@ JSONWriter::writeBool(bool b) {
value = true;
space = ' ';
}
-
-void
-JSONWriter::writeImage(image::Image *image, const char *format, unsigned depth)
-{
- if (!image) {
- writeNull();
- return;
- }
-
- beginObject();
-
- // Tell the GUI this is no ordinary object, but an image
- writeStringMember("__class__", "image");
-
- writeIntMember("__width__", image->width);
- writeIntMember("__height__", image->height / depth);
- writeIntMember("__depth__", depth);
-
- writeStringMember("__format__", format);
-
- beginMember("__data__");
- std::stringstream ss;
-
- if (image->channelType == image::TYPE_UNORM8) {
- image->writePNG(ss);
- } else {
- image->writePNM(ss);
- }
-
- const std::string & s = ss.str();
- writeBase64(s.data(), s.size());
- endMember(); // __data__
-
- endObject();
-}
diff --git a/retrace/json.hpp b/retrace/json.hpp
index 2c555dbb..7181c1e3 100644
--- a/retrace/json.hpp
+++ b/retrace/json.hpp
@@ -27,19 +27,14 @@
* JSON writing functions.
*/
-#ifndef _JSON_HPP_
-#define _JSON_HPP_
+
+#pragma once
+
#include <stddef.h>
#include <wchar.h>
-#ifdef _MSC_VER
-# include <float.h>
-# define isfinite _finite
-# define isnan _isnan
-#else
-# include <math.h> // isfinite, isnan
-#endif
+#include <cmath> // for std::isinf, std::isnan; as C99 macros are unavailable in C++11
#include <iomanip>
#include <limits>
@@ -47,11 +42,6 @@
#include <string>
-namespace image {
- class Image;
-}
-
-
class JSONWriter
{
private:
@@ -145,10 +135,10 @@ public:
void
writeFloat(T n) {
separator();
- if (isnan(n)) {
+ if (std::isnan(n)) {
// NaN is non-standard but widely supported
os << "NaN";
- } else if (!isfinite(n)) {
+ } else if (std::isinf(n)) {
// Infinite is non-standard but widely supported
if (n < 0) {
os << '-';
@@ -160,31 +150,4 @@ public:
value = true;
space = ' ';
}
-
- inline void
- writeStringMember(const char *name, const char *s) {
- beginMember(name);
- writeString(s);
- endMember();
- }
-
- inline void
- writeBoolMember(const char *name, bool b) {
- beginMember(name);
- writeBool(b);
- endMember();
- }
-
- template<class T>
- inline void
- writeIntMember(const char *name, T n) {
- beginMember(name);
- writeInt(n);
- endMember();
- }
-
- void
- writeImage(image::Image *image, const char *format, unsigned depth = 1);
};
-
-#endif /* _JSON_HPP_ */
diff --git a/retrace/metric_backend.hpp b/retrace/metric_backend.hpp
new file mode 100644
index 00000000..cf58e093
--- /dev/null
+++ b/retrace/metric_backend.hpp
@@ -0,0 +1,285 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+/**
+ * Profiling boundary.
+ */
+enum QueryBoundary {
+ QUERY_BOUNDARY_DRAWCALL = 0, /**< draw call boundary */
+ QUERY_BOUNDARY_FRAME, /**< frame boundary */
+ QUERY_BOUNDARY_CALL, /**< any call boundary */
+ QUERY_BOUNDARY_LIST_END
+};
+
+/**
+ * Numeric type of the metric.
+ */
+enum MetricNumType {
+ CNT_NUM_UINT = 0,
+ CNT_NUM_FLOAT,
+ CNT_NUM_UINT64,
+ CNT_NUM_DOUBLE,
+ CNT_NUM_BOOL,
+ CNT_NUM_INT64
+};
+
+/**
+ * Type of data metric represents.
+ */
+enum MetricType {
+ CNT_TYPE_GENERIC = 0, /**< generally a number, comparable type */
+ CNT_TYPE_NUM, /**< number, not necessarily comparable (e.g. event number) */
+ CNT_TYPE_DURATION, /**< duration */
+ CNT_TYPE_PERCENT, /**< percentage */
+ CNT_TYPE_TIMESTAMP, /**< timestamp (e.g. GL_TIMESTAMP in OpenGL) */
+ CNT_TYPE_OTHER /**< not listed above */
+};
+
+
+/**
+ * Metric interface.
+ *
+ * Each metric can be uniquely identified by a group id and a metric id.
+ * Each backend is assumed to implement its own version of Metric. It is also
+ * supposed to provide metric groups and corresponding metrics.
+ * This interface is used to communicate with backend and can be used
+ * to store internal data in backend.
+ *
+ * It is generally a good idea to cache some parameters (e.g. numeric type).
+ */
+class Metric
+{
+public:
+ virtual ~Metric() {}
+
+ /**
+ * Returns metric id
+ */
+ virtual unsigned id() = 0;
+
+ /**
+ * Returns metric group id
+ */
+ virtual unsigned groupId() = 0;
+
+ /**
+ * Returns metric name string
+ */
+ virtual std::string name() = 0;
+
+ /**
+ * Returns metric description string (or an empty string if not available)
+ */
+ virtual std::string description() = 0;
+
+ /**
+ * Returns metric numeric type
+ */
+ virtual MetricNumType numType() = 0;
+
+ /**
+ * Returns data type metric represents
+ */
+ virtual MetricType type() = 0;
+};
+
+/**
+ * Callbacks for use in backend interface.
+ * int error : error code (0 - no error)
+ * void* userData : arbitrary pointer
+ */
+typedef void (*enumGroupsCallback)(unsigned group, int error, void* userData);
+typedef void (*enumMetricsCallback)(Metric* metric, int error, void* userData);
+typedef void (*enumDataCallback)(Metric* metric, int event, void* data,
+ int error, void* userData);
+
+/**
+ * Backend interface.
+ *
+ * Abstraction for metric-collection system.
+ * Such system is supposed to have its own version of MetricBackend.
+ * Backend can be used to query available metrics, to profile calls/frames and
+ * to collect metrics.
+ * Backend is responsible for storing metric data.
+ *
+ * Unfortunately, not all collection systems allow to collect all metrics
+ * at the same time. Therefore multiple passes are needed, this interface provides
+ * the mean to implement such behaviour.
+ *
+ *
+ * Typical workflow example:
+ * MetricBackend* backend;
+ * backend->enableMetric(...);
+ * ...
+ * backend->enableMetric(...);
+ * for (i=0; i < backend->generatePasses(); i++) {
+ * backend->beginPass();
+ *
+ * backend->beginQuery(QUERY_BOUNDARY_FRAME);
+ *
+ * backend->beginQuery(QUERY_BOUNDARY_CALL or QUERY_BOUNDARY_DRAWCALL);
+ * ... profiled call ...
+ * backend->endQuery(QUERY_BOUNDARY_CALL or QUERY_BOUNDARY_DRAWCALL);
+ *
+ * ...
+ *
+ * backend->beginQuery(QUERY_BOUNDARY_CALL or QUERY_BOUNDARY_DRAWCALL);
+ * ... profiled call ...
+ * backend->endQuery(QUERY_BOUNDARY_CALL or QUERY_BOUNDARY_DRAWCALL);
+ *
+ * backend->endQuery(QUERY_BOUNDARY_FRAME);
+ *
+ * ... following frames ...
+ *
+ * backend->endPass();
+ * }
+ * // collect data
+ *
+ *
+ * It is generally a good idea to implement MetricBackend as a singleton.
+ */
+class MetricBackend
+{
+public:
+ virtual ~MetricBackend() {}
+
+ /**
+ * Returns true if MetricBackend is supported on current HW.
+ */
+ virtual bool isSupported() = 0;
+
+ /**
+ * Enumerates metric groups, calls callback for each group.
+ */
+ virtual void enumGroups(enumGroupsCallback callback,
+ void* userData = nullptr) = 0;
+
+ /**
+ * Enumerates metrics in specified group, calls callback for each metric.
+ * Callback receives pointer to the metric object among other params.
+ * Metric object is an object of class derived from Metric.
+ */
+ virtual void enumMetrics(unsigned group, enumMetricsCallback callback,
+ void* userData = nullptr) = 0;
+
+ /**
+ * Returns group name string (or an empty string if not available).
+ */
+ virtual std::string getGroupName(unsigned group) = 0;
+
+ /**
+ * Returns pointer to the metric object with given group id, metric id.
+ * Metric object is an object of class derived from Metric.
+ */
+ virtual std::unique_ptr<Metric> getMetricById(unsigned groupId, unsigned metricId) = 0;
+
+ /**
+ * Returns pointer to the metric object with given metric name string.
+ * Metric object is an object of class derived from Metric.
+ */
+ virtual std::unique_ptr<Metric> getMetricByName(std::string metricName) = 0;
+
+ /**
+ * Adds given metric object to the internal list of metrics
+ * to be profiled.
+ * pollingRule sets the boundary for collecting metric
+ * Returns error code (0 - no error).
+ */
+ virtual int enableMetric(Metric* metric, QueryBoundary pollingRule = QUERY_BOUNDARY_DRAWCALL) = 0;
+
+ /**
+ * Generates passes based on enabled metrics.
+ * Returns number of generated passes.
+ */
+ virtual unsigned generatePasses() = 0;
+
+ /**
+ * Begins pass. Subsequent calls begin next passes.
+ * A pass needs to be ended before starting a new one.
+ */
+ virtual void beginPass() = 0;
+
+ /**
+ * Ends pass.
+ */
+ virtual void endPass() = 0;
+
+ /**
+ * Pause pass with all the queries in progress.
+ * Backend decides what to do with the data of interrupted
+ * query.
+ * Can be used before the context switch in OpenGl.
+ */
+ virtual void pausePass() = 0;
+
+ /**
+ * Continue profiling the pass after pausePass().
+ * Backend decides whether to reprofile interrupted by pausePass() query.
+ * Can be used after the context switch in OpenGl.
+ */
+ virtual void continuePass() = 0;
+
+ /**
+ * Begins query (profiles unit, i.e. frames or calls). Subsequent calls
+ * begin next queries.
+ * Parameter boundary should be set to the type of boundary beginQuery/endQuery
+ * constructions enclose.
+ * A query needs to be ended before starting a new one.
+ */
+ virtual void beginQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL) = 0;
+
+ /**
+ * Ends query.
+ * Parameter boundary should be set to the type of boundary beginQuery/endQuery
+ * constructions enclose.
+ */
+ virtual void endQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL) = 0;
+
+ /**
+ * Enumerates collected metrics data for a given query id and given
+ * type of boundary.
+ * Query ids begin with 0 for first query.
+ * Metric data is passed to callback.
+ *
+ * The order in which metrics are returned can differ from the one in which
+ * metrics were enabled (via enableMetric(...)) . However, it should be
+ * guaranteed that order is the same for every query.
+ */
+ virtual void enumDataQueryId(unsigned id, enumDataCallback callback,
+ QueryBoundary boundary,
+ void* userData = nullptr) = 0;
+
+ /**
+ * Returns number of passes generated by generatePasses(...).
+ * If generatePasses(...) was not called returns 1.
+ */
+ virtual unsigned getNumPasses() = 0;
+
+};
diff --git a/retrace/metric_backend_amd_perfmon.cpp b/retrace/metric_backend_amd_perfmon.cpp
new file mode 100644
index 00000000..77a870b8
--- /dev/null
+++ b/retrace/metric_backend_amd_perfmon.cpp
@@ -0,0 +1,449 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "metric_backend_amd_perfmon.hpp"
+
+void Metric_AMD_perfmon::precache() {
+ GLenum type;
+ int length;
+ std::string name;
+
+ glGetPerfMonitorCounterInfoAMD(m_group, m_id, GL_COUNTER_TYPE_AMD, &type);
+ if (type == GL_UNSIGNED_INT) m_nType = CNT_NUM_UINT;
+ else if (type == GL_FLOAT || type == GL_PERCENTAGE_AMD) m_nType = CNT_NUM_FLOAT;
+ else if (type == GL_UNSIGNED_INT64_AMD) m_nType = CNT_NUM_UINT64;
+ else m_nType = CNT_NUM_UINT;
+
+ glGetPerfMonitorCounterStringAMD(m_group, m_id, 0, &length, nullptr);
+ name.resize(length);
+ glGetPerfMonitorCounterStringAMD(m_group, m_id, length, 0, &name[0]);
+ m_name = name;
+ m_precached = true;
+}
+
+unsigned Metric_AMD_perfmon::id() {
+ return m_id;
+}
+
+unsigned Metric_AMD_perfmon::groupId() {
+ return m_group;
+}
+
+std::string Metric_AMD_perfmon::name() {
+ if (!m_precached) precache();
+ return m_name;
+}
+
+std::string Metric_AMD_perfmon::description() {
+ return ""; // no description available
+}
+
+GLenum Metric_AMD_perfmon::size() {
+ GLenum type;
+ glGetPerfMonitorCounterInfoAMD(m_group, m_id, GL_COUNTER_TYPE_AMD, &type);
+ if (type == GL_UNSIGNED_INT) return sizeof(GLuint);
+ else if (type == GL_FLOAT || type == GL_PERCENTAGE_AMD) return sizeof(GLfloat);
+ else if (type == GL_UNSIGNED_INT64_AMD) return sizeof(uint64_t);
+ else return sizeof(GLuint);
+}
+
+MetricNumType Metric_AMD_perfmon::numType() {
+ if (!m_precached) precache();
+ return m_nType;
+}
+
+MetricType Metric_AMD_perfmon::type() {
+ GLenum type;
+ glGetPerfMonitorCounterInfoAMD(m_group, m_id, GL_COUNTER_TYPE_AMD, &type);
+ if ((type == GL_UNSIGNED_INT || type == GL_UNSIGNED_INT64_AMD) ||
+ (type == GL_FLOAT)) return CNT_TYPE_GENERIC;
+ else if (type == GL_PERCENTAGE_AMD) return CNT_TYPE_PERCENT;
+ else return CNT_TYPE_OTHER;
+}
+
+
+MetricBackend_AMD_perfmon::DataCollector::~DataCollector() {
+ for (auto &t1 : data) {
+ for (auto &t2 : t1) {
+ alloc.deallocate(t2, 1);
+ }
+ }
+}
+
+unsigned*
+MetricBackend_AMD_perfmon::DataCollector::newDataBuffer(unsigned event,
+ size_t size)
+{
+ // in case there is no data for previous events fill with nullptr
+ data[curPass].resize(event, nullptr);
+ data[curPass].push_back(alloc.allocate(size));
+ return data[curPass][event];
+}
+
+void MetricBackend_AMD_perfmon::DataCollector::endPass() {
+ curPass++;
+ data.push_back(mmapdeque<unsigned*>(alloc));
+}
+
+unsigned*
+MetricBackend_AMD_perfmon::DataCollector::getDataBuffer(unsigned pass,
+ unsigned event)
+{
+ if (event < data[pass].size()) {
+ return data[pass][event];
+ } else return nullptr;
+}
+
+
+MetricBackend_AMD_perfmon::MetricBackend_AMD_perfmon(glretrace::Context* context,
+ MmapAllocator<char> &alloc)
+ : numPasses(1), curPass(0), curEvent(0), collector(alloc) {
+ if (context->hasExtension("GL_AMD_performance_monitor")) {
+ supported = true;
+ } else {
+ supported = false;
+ }
+}
+
+bool MetricBackend_AMD_perfmon::isSupported() {
+ return supported;
+}
+
+void MetricBackend_AMD_perfmon::enumGroups(enumGroupsCallback callback,
+ void* userData)
+{
+ std::vector<unsigned> groups;
+ int num_groups;
+ glGetPerfMonitorGroupsAMD(&num_groups, 0, nullptr);
+ groups.resize(num_groups);
+ glGetPerfMonitorGroupsAMD(nullptr, num_groups, &groups[0]);
+ for(unsigned &g : groups) {
+ callback(g, 0, userData);
+ }
+}
+
+void MetricBackend_AMD_perfmon::enumMetrics(unsigned group,
+ enumMetricsCallback callback,
+ void* userData)
+{
+ std::vector<unsigned> metrics;
+ int num_metrics;
+ Metric_AMD_perfmon metric(0,0);
+ glGetPerfMonitorCountersAMD(group, &num_metrics, nullptr, 0, nullptr);
+ metrics.resize(num_metrics);
+ glGetPerfMonitorCountersAMD(group, nullptr, nullptr, num_metrics, &metrics[0]);
+ for(unsigned &c : metrics) {
+ metric = Metric_AMD_perfmon(group, c);
+ callback(&metric, 0, userData);
+ }
+}
+
+std::unique_ptr<Metric>
+MetricBackend_AMD_perfmon::getMetricById(unsigned groupId, unsigned metricId)
+{
+ std::unique_ptr<Metric> p(new Metric_AMD_perfmon(groupId, metricId));
+ return p;
+}
+
+void MetricBackend_AMD_perfmon::populateLookupGroups(unsigned group,
+ int error,
+ void* userData)
+{
+ reinterpret_cast<MetricBackend_AMD_perfmon*>(userData)->enumMetrics(group,
+ populateLookupMetrics);
+}
+
+void MetricBackend_AMD_perfmon::populateLookupMetrics(Metric* metric,
+ int error,
+ void* userData)
+{
+ nameLookup[metric->name()] = std::make_pair(metric->groupId(),
+ metric->id());
+}
+
+std::unique_ptr<Metric>
+MetricBackend_AMD_perfmon::getMetricByName(std::string metricName)
+{
+ if (nameLookup.empty()) {
+ enumGroups(populateLookupGroups, this);
+ }
+ if (nameLookup.count(metricName) > 0) {
+ std::unique_ptr<Metric> p(new Metric_AMD_perfmon(nameLookup[metricName].first,
+ nameLookup[metricName].second));
+ return p;
+ }
+ else return nullptr;
+}
+
+std::string MetricBackend_AMD_perfmon::getGroupName(unsigned group) {
+ int length;
+ std::string name;
+ glGetPerfMonitorGroupStringAMD(group, 0, &length, nullptr);
+ name.resize(length);
+ glGetPerfMonitorGroupStringAMD(group, length, 0, &name[0]);
+ return name;
+}
+
+int MetricBackend_AMD_perfmon::enableMetric(Metric* metric_, QueryBoundary pollingRule) {
+ unsigned id = metric_->id();
+ unsigned gid = metric_->groupId();
+ unsigned monitor;
+
+ // profiling only draw calls
+ if (pollingRule == QUERY_BOUNDARY_CALL) return 1;
+
+ // check that Metric is valid metric
+ glGenPerfMonitorsAMD(1, &monitor);
+ glGetError();
+ glSelectPerfMonitorCountersAMD(monitor, 1, gid, 1, &id);
+ GLenum err = glGetError();
+ glDeletePerfMonitorsAMD(1, &monitor);
+ if (err == GL_INVALID_VALUE) {
+ return 1;
+ }
+
+ Metric_AMD_perfmon metric(gid, id);
+ metric.numType(); // triggers metric vars precache (in case context changes)
+ metrics[pollingRule].push_back(metric);
+ return 0;
+}
+
+bool
+MetricBackend_AMD_perfmon::testMetrics(std::vector<Metric_AMD_perfmon>* metrics) {
+ unsigned monitor;
+ unsigned id;
+ glGenPerfMonitorsAMD(1, &monitor);
+ for (Metric_AMD_perfmon &c : *metrics) {
+ id = c.id();
+ glSelectPerfMonitorCountersAMD(monitor, 1, c.groupId(), 1, &id);
+ }
+ glGetError();
+ glBeginPerfMonitorAMD(monitor);
+ GLenum err = glGetError();
+ glEndPerfMonitorAMD(monitor);
+ glDeletePerfMonitorsAMD(1, &monitor);
+ if (err == GL_INVALID_OPERATION) {
+ return 0;
+ }
+ return 1;
+}
+
+void MetricBackend_AMD_perfmon::generatePassesBoundary(QueryBoundary boundary) {
+ std::vector<Metric_AMD_perfmon> copyMetrics(metrics[boundary]);
+ std::vector<Metric_AMD_perfmon> newPass;
+ while (!copyMetrics.empty()) {
+ std::vector<Metric_AMD_perfmon>::iterator it = copyMetrics.begin();
+ while (it != copyMetrics.end()) {
+ newPass.push_back(*it);
+ if (!testMetrics(&newPass)) {
+ newPass.pop_back();
+ break;
+ }
+ it = copyMetrics.erase(it);
+ }
+ passes.push_back(newPass);
+ newPass.clear();
+ }
+}
+
+unsigned MetricBackend_AMD_perfmon::generatePasses() {
+ generatePassesBoundary(QUERY_BOUNDARY_FRAME);
+ numFramePasses = passes.size();
+ generatePassesBoundary(QUERY_BOUNDARY_DRAWCALL);
+ nameLookup.clear(); // no need in it after all metrics are set up
+ numPasses = passes.size();
+ return passes.size();
+}
+
+void MetricBackend_AMD_perfmon::beginPass() {
+ if (!numPasses) return;
+ /* First process per-frame passes, then per-call passes */
+ if (curPass < numFramePasses) {
+ perFrame = true;
+ } else {
+ perFrame = false;
+ }
+ /* Generate monitor */
+ glGenPerfMonitorsAMD(NUM_MONITORS, monitors);
+ for (Metric_AMD_perfmon &c : passes[curPass]) {
+ unsigned id = c.id();
+ for (int k = 0; k < NUM_MONITORS; k++) {
+ glSelectPerfMonitorCountersAMD(monitors[k], 1, c.groupId(), 1, &id);
+ }
+ }
+ curMonitor = 0;
+ firstRound = true;
+ curEvent = 0;
+ supported = true; // can change if context is switched, so revert back
+}
+
+void MetricBackend_AMD_perfmon::endPass() {
+ if (supported && numPasses) {
+ for (unsigned k = 0; k < curMonitor; k++) {
+ freeMonitor(k);
+ }
+ glDeletePerfMonitorsAMD(NUM_MONITORS, monitors);
+ }
+ curPass++;
+ collector.endPass();
+}
+
+void MetricBackend_AMD_perfmon::pausePass() {
+ if (!supported || !numPasses) return;
+ // clear all queries and monitors
+ // ignore data from the query in progress
+ if (queryInProgress) {
+ glEndPerfMonitorAMD(monitors[curMonitor]);
+ curEvent++;
+ queryInProgress = false;
+ }
+ for (unsigned k = 0; k < curMonitor; k++) {
+ freeMonitor(k);
+ }
+ glDeletePerfMonitorsAMD(NUM_MONITORS, monitors);
+}
+
+void MetricBackend_AMD_perfmon::continuePass() {
+ // here new context might be used
+ // better to check if it supports AMD_perfmon extension
+ glretrace::Context* context = glretrace::getCurrentContext();
+ if (context && context->hasExtension("GL_AMD_performance_monitor")) {
+ supported = true;
+ } else {
+ supported = false;
+ }
+
+ if (supported && numPasses) {
+ // call begin pass and save/restore event id
+ unsigned tempId = curEvent;
+ beginPass();
+ curEvent = tempId;
+ }
+}
+
+void MetricBackend_AMD_perfmon::beginQuery(QueryBoundary boundary) {
+ if (!supported || !numPasses) return;
+ if (boundary == QUERY_BOUNDARY_CALL) return;
+ if ((boundary == QUERY_BOUNDARY_FRAME) && !perFrame) return;
+ if ((boundary == QUERY_BOUNDARY_DRAWCALL) && perFrame) return;
+
+ curMonitor %= NUM_MONITORS;
+ if (!firstRound) freeMonitor(curMonitor); // get existing data
+ monitorEvent[curMonitor] = curEvent; // save monitored event
+ glBeginPerfMonitorAMD(monitors[curMonitor]);
+ queryInProgress = true;
+}
+
+void MetricBackend_AMD_perfmon::endQuery(QueryBoundary boundary) {
+ if (!queryInProgress) return;
+ if (!supported || !numPasses) return;
+ if (boundary == QUERY_BOUNDARY_CALL) return;
+ if ((boundary == QUERY_BOUNDARY_FRAME) && !perFrame) return;
+ if ((boundary == QUERY_BOUNDARY_DRAWCALL) && perFrame) return;
+
+ curEvent++;
+ glEndPerfMonitorAMD(monitors[curMonitor]);
+ curMonitor++;
+ if (curMonitor == NUM_MONITORS) firstRound = 0;
+ queryInProgress = false;
+}
+
+void MetricBackend_AMD_perfmon::freeMonitor(unsigned monitorId) {
+ unsigned monitor = monitors[monitorId];
+ GLuint dataAvail = 0;
+ GLuint size;
+
+ glFlush();
+ while (!dataAvail) {
+ glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AVAILABLE_AMD,
+ sizeof(GLuint), &dataAvail, nullptr);
+ }
+ glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_SIZE_AMD,
+ sizeof(GLuint), &size, nullptr);
+ // collect data
+ unsigned* buf = collector.newDataBuffer(monitorEvent[monitorId],
+ size/sizeof(unsigned));
+ glGetPerfMonitorCounterDataAMD(monitor, GL_PERFMON_RESULT_AMD, size, buf, nullptr);
+
+ /* populate metricOffsets */
+ if (metricOffsets.size() < curPass + 1) {
+ std::map<std::pair<unsigned, unsigned>, unsigned> pairOffsets;
+ unsigned offset = 0;
+ unsigned id, gid;
+ for (int k = 0; k < passes[curPass].size(); k++) {
+ gid = buf[offset++];
+ id = buf[offset++];
+ pairOffsets[std::make_pair(gid, id)] = offset;
+ Metric_AMD_perfmon metric(gid, id);
+ offset += metric.size() / sizeof(unsigned);
+ }
+ // translate to existing metrics in passes variable
+ std::map<Metric_AMD_perfmon*, unsigned> temp;
+ for (auto &m : passes[curPass]) {
+ id = m.id();
+ gid = m.groupId();
+ temp[&m] = pairOffsets[std::make_pair(gid, id)];
+ }
+ metricOffsets.push_back(std::move(temp));
+ }
+}
+
+void
+MetricBackend_AMD_perfmon::enumDataQueryId(unsigned id,
+ enumDataCallback callback,
+ QueryBoundary boundary,
+ void* userData)
+{
+ /* Determine passes to return depending on the boundary */
+ if (boundary == QUERY_BOUNDARY_CALL) return;
+ unsigned j = 0;
+ unsigned nPasses = numFramePasses;
+ if (boundary == QUERY_BOUNDARY_DRAWCALL) {
+ j = numFramePasses;
+ nPasses = numPasses;
+ }
+ /* enum passes */
+ for (; j < nPasses; j++) {
+ unsigned* buf = collector.getDataBuffer(j, id);
+ for (auto &m : passes[j]) {
+ void* data = (buf) ? &buf[metricOffsets[j][&m]] : nullptr;
+ callback(&m, id, data, 0, userData);
+ }
+ }
+}
+
+unsigned MetricBackend_AMD_perfmon::getNumPasses() {
+ return numPasses;
+}
+
+MetricBackend_AMD_perfmon&
+MetricBackend_AMD_perfmon::getInstance(glretrace::Context* context,
+ MmapAllocator<char> &alloc) {
+ static MetricBackend_AMD_perfmon backend(context, alloc);
+ return backend;
+}
+
+
+std::map<std::string, std::pair<unsigned, unsigned>> MetricBackend_AMD_perfmon::nameLookup;
diff --git a/retrace/metric_backend_amd_perfmon.hpp b/retrace/metric_backend_amd_perfmon.hpp
new file mode 100644
index 00000000..39be7e9d
--- /dev/null
+++ b/retrace/metric_backend_amd_perfmon.hpp
@@ -0,0 +1,178 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <map>
+#include <string>
+
+#include "glproc.hpp"
+#include "metric_backend.hpp"
+#include "glretrace.hpp"
+#include "mmap_allocator.hpp"
+
+#define NUM_MONITORS 1 // number of max used AMD_perfmon monitors
+
+class Metric_AMD_perfmon : public Metric
+{
+private:
+ unsigned m_group, m_id;
+ MetricNumType m_nType;
+ std::string m_name;
+ bool m_precached;
+
+ void precache();
+
+public:
+ Metric_AMD_perfmon(unsigned g, unsigned i) : m_group(g), m_id(i),
+ m_nType(CNT_NUM_UINT),
+ m_precached(false) {}
+
+ GLenum size();
+
+
+ unsigned id();
+
+ unsigned groupId();
+
+ std::string name();
+
+ std::string description();
+
+ MetricNumType numType();
+
+ MetricType type();
+};
+
+
+class MetricBackend_AMD_perfmon : public MetricBackend
+{
+private:
+ class DataCollector
+ {
+ private:
+ MmapAllocator<unsigned> alloc; // allocator
+ // deque with custom allocator
+ template <class T>
+ using mmapdeque = std::deque<T, MmapAllocator<T>>;
+ // data storage
+ mmapdeque<mmapdeque<unsigned*>> data;
+ unsigned curPass;
+
+ public:
+ DataCollector(MmapAllocator<char> &alloc)
+ : alloc(alloc), data(1, mmapdeque<unsigned*>(alloc), alloc),
+ curPass(0) {}
+
+ ~DataCollector();
+
+ unsigned* newDataBuffer(unsigned event, size_t size);
+
+ void endPass();
+
+ unsigned* getDataBuffer(unsigned pass, unsigned event);
+ };
+
+private:
+ bool supported; // extension support (checked initially and w/ context switch)
+ bool firstRound; // first profiling round (no need to free monitors)
+ bool perFrame; // profiling frames?
+ bool queryInProgress;
+ unsigned monitors[NUM_MONITORS]; // For cycling
+ unsigned curMonitor;
+ unsigned monitorEvent[NUM_MONITORS]; // Event saved in monitor
+ unsigned numPasses; // all passes
+ unsigned numFramePasses; // frame passes
+ unsigned curPass;
+ unsigned curEvent; // Currently evaluated event
+ // metrics selected for profiling boundaries (frames, draw calls)
+ std::vector<Metric_AMD_perfmon> metrics[2];
+ // metric sets for each pass
+ std::vector<std::vector<Metric_AMD_perfmon>> passes;
+ // metric offsets in data for each pass
+ std::vector<std::map<Metric_AMD_perfmon*, unsigned>> metricOffsets;
+ DataCollector collector; // data storage
+ // lookup table (metric name -> (gid, id))
+ static std::map<std::string, std::pair<unsigned, unsigned>> nameLookup;
+
+ MetricBackend_AMD_perfmon(glretrace::Context* context, MmapAllocator<char> &alloc);
+
+ MetricBackend_AMD_perfmon(MetricBackend_AMD_perfmon const&) = delete;
+
+ void operator=(MetricBackend_AMD_perfmon const&) = delete;
+
+ // test if given set of metrics can be sampled in one pass
+ bool testMetrics(std::vector<Metric_AMD_perfmon>* metrics);
+
+ void freeMonitor(unsigned monitor); // collect metrics data from the monitor
+
+ static void populateLookupGroups(unsigned group, int error, void* userData);
+
+ static void populateLookupMetrics(Metric* metric, int error, void* userData);
+
+ void generatePassesBoundary(QueryBoundary boundary);
+
+public:
+ bool isSupported();
+
+ void enumGroups(enumGroupsCallback callback, void* userData = nullptr);
+
+ void enumMetrics(unsigned group, enumMetricsCallback callback,
+ void* userData = nullptr);
+
+ std::unique_ptr<Metric> getMetricById(unsigned groupId, unsigned metricId);
+
+ std::unique_ptr<Metric> getMetricByName(std::string metricName);
+
+ std::string getGroupName(unsigned group);
+
+ int enableMetric(Metric* metric, QueryBoundary pollingRule = QUERY_BOUNDARY_DRAWCALL);
+
+ unsigned generatePasses();
+
+ void beginPass();
+
+ void endPass();
+
+ void pausePass();
+
+ void continuePass();
+
+ void beginQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL);
+
+ void endQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL);
+
+ void enumDataQueryId(unsigned id, enumDataCallback callback,
+ QueryBoundary boundary,
+ void* userData = nullptr);
+
+ unsigned getNumPasses();
+
+ static MetricBackend_AMD_perfmon& getInstance(glretrace::Context* context,
+ MmapAllocator<char> &alloc);
+};
+
diff --git a/retrace/metric_backend_intel_perfquery.cpp b/retrace/metric_backend_intel_perfquery.cpp
new file mode 100644
index 00000000..a5d922cc
--- /dev/null
+++ b/retrace/metric_backend_intel_perfquery.cpp
@@ -0,0 +1,361 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "metric_backend_intel_perfquery.hpp"
+
+void Metric_INTEL_perfquery::precache() {
+ unsigned offset;
+ glGetPerfCounterInfoINTEL(m_group, m_id, 0, nullptr, 0, nullptr, &offset,
+ nullptr, nullptr, nullptr, nullptr);
+ this->m_offset = offset;
+
+ GLenum type;
+ glGetPerfCounterInfoINTEL(m_group, m_id, 0, nullptr, 0, nullptr, nullptr,
+ nullptr, nullptr, &type, nullptr);
+ if (type == GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL) m_nType = CNT_NUM_UINT;
+ else if (type == GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL) m_nType = CNT_NUM_FLOAT;
+ else if (type == GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL) m_nType = CNT_NUM_DOUBLE;
+ else if (type == GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL) m_nType = CNT_NUM_BOOL;
+ else if (type == GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL) m_nType = CNT_NUM_UINT64;
+ else m_nType = CNT_NUM_UINT;
+
+ char name[INTEL_NAME_LENGTH];
+ glGetPerfCounterInfoINTEL(m_group, m_id, INTEL_NAME_LENGTH, name, 0, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr);
+ m_name = std::string(name);
+
+ m_precached = true;
+}
+
+unsigned Metric_INTEL_perfquery::id() {
+ return m_id;
+}
+
+unsigned Metric_INTEL_perfquery::groupId() {
+ return m_group;
+}
+
+std::string Metric_INTEL_perfquery::name() {
+ if (!m_precached) precache();
+ return m_name;
+}
+
+std::string Metric_INTEL_perfquery::description() {
+ char desc[INTEL_DESC_LENGTH];
+ glGetPerfCounterInfoINTEL(m_group, m_id, 0, nullptr, INTEL_DESC_LENGTH, desc,
+ nullptr, nullptr, nullptr, nullptr, nullptr);
+ return std::string(desc);
+}
+
+unsigned Metric_INTEL_perfquery::offset() {
+ if (!m_precached) precache();
+ return m_offset;
+}
+
+MetricNumType Metric_INTEL_perfquery::numType() {
+ if (!m_precached) precache();
+ return m_nType;
+}
+
+MetricType Metric_INTEL_perfquery::type() {
+ GLenum type;
+ glGetPerfCounterInfoINTEL(m_group, m_id, 0, nullptr, 0, nullptr, nullptr,
+ nullptr, &type, nullptr, nullptr);
+ if (type == GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL) return CNT_TYPE_TIMESTAMP;
+ else if (type == GL_PERFQUERY_COUNTER_EVENT_INTEL) return CNT_TYPE_NUM;
+ else if (type == GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL ||
+ type == GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL) return CNT_TYPE_DURATION;
+ else if (type == GL_PERFQUERY_COUNTER_RAW_INTEL) return CNT_TYPE_GENERIC;
+ else if (type == GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL) return CNT_TYPE_GENERIC;
+ else return CNT_TYPE_OTHER;
+}
+
+MetricBackend_INTEL_perfquery::DataCollector::~DataCollector() {
+ for (auto &t1 : data) {
+ for (auto &t2 : t1) {
+ alloc.deallocate(t2, 1);
+ }
+ }
+}
+
+unsigned char*
+MetricBackend_INTEL_perfquery::DataCollector::newDataBuffer(unsigned event,
+ size_t size)
+{
+ // in case there is no data for previous events fill with nullptr
+ data[curPass].resize(event, nullptr);
+ data[curPass].push_back(alloc.allocate(size));
+ return data[curPass][event];
+}
+
+void MetricBackend_INTEL_perfquery::DataCollector::endPass() {
+ curPass++;
+ data.push_back(mmapdeque<unsigned char*>(alloc));
+}
+
+unsigned char*
+MetricBackend_INTEL_perfquery::DataCollector::getDataBuffer(unsigned pass,
+ unsigned event)
+{
+ if (event < data[pass].size()) {
+ return data[pass][event];
+ } else return nullptr;
+}
+
+MetricBackend_INTEL_perfquery::MetricBackend_INTEL_perfquery(glretrace::Context* context,
+ MmapAllocator<char> &alloc)
+ : numPasses(1), curPass(0), curEvent(0), collector(alloc) {
+ if (context->hasExtension("GL_INTEL_performance_query")) {
+ supported = true;
+ } else {
+ supported = false;
+ }
+}
+
+bool MetricBackend_INTEL_perfquery::isSupported() {
+ return supported;
+}
+
+void MetricBackend_INTEL_perfquery::enumGroups(enumGroupsCallback callback,
+ void* userData)
+{
+ unsigned gid;
+ glGetFirstPerfQueryIdINTEL(&gid);
+ while (gid) {
+ callback(gid, 0, userData);
+ glGetNextPerfQueryIdINTEL(gid, &gid);
+ }
+}
+
+void
+MetricBackend_INTEL_perfquery::enumMetrics(unsigned group,
+ enumMetricsCallback callback,
+ void* userData)
+{
+ unsigned numMetrics;
+ glGetPerfQueryInfoINTEL(group, 0, nullptr, nullptr, &numMetrics, nullptr, nullptr);
+ for (int i = 1; i <= numMetrics; i++) {
+ Metric_INTEL_perfquery metric = Metric_INTEL_perfquery(group, i);
+ callback(&metric, 0, userData);
+ }
+}
+
+std::unique_ptr<Metric>
+MetricBackend_INTEL_perfquery::getMetricById(unsigned groupId, unsigned metricId)
+{
+ std::unique_ptr<Metric> p(new Metric_INTEL_perfquery(groupId, metricId));
+ return p;
+}
+
+void MetricBackend_INTEL_perfquery::populateLookupGroups(unsigned group,
+ int error,
+ void* userData)
+{
+ reinterpret_cast<MetricBackend_INTEL_perfquery*>(userData)->enumMetrics(group, populateLookupMetrics);
+}
+
+void MetricBackend_INTEL_perfquery::populateLookupMetrics(Metric* metric,
+ int error,
+ void* userData)
+{
+ nameLookup[metric->name()] = std::make_pair(metric->groupId(),
+ metric->id());
+}
+
+std::unique_ptr<Metric>
+MetricBackend_INTEL_perfquery::getMetricByName(std::string metricName)
+{
+ if (nameLookup.empty()) {
+ enumGroups(populateLookupGroups, this);
+ }
+ if (nameLookup.count(metricName) > 0) {
+ std::unique_ptr<Metric> p(new Metric_INTEL_perfquery(nameLookup[metricName].first,
+ nameLookup[metricName].second));
+ return p;
+ }
+ else return nullptr;
+}
+
+std::string MetricBackend_INTEL_perfquery::getGroupName(unsigned group) {
+ char name[INTEL_NAME_LENGTH];
+ glGetPerfQueryInfoINTEL(group, INTEL_NAME_LENGTH, name, nullptr,
+ nullptr, nullptr, nullptr);
+ return std::string(name);
+}
+
+int MetricBackend_INTEL_perfquery::enableMetric(Metric* metric_, QueryBoundary pollingRule) {
+ if (pollingRule == QUERY_BOUNDARY_CALL) return 1;
+ unsigned id = metric_->id();
+ unsigned gid = metric_->groupId();
+ unsigned numCounters;
+
+ /* check that counter id is in valid range and group exists */
+ glGetError();
+ glGetPerfQueryInfoINTEL(gid, 0, nullptr, nullptr, &numCounters, nullptr, nullptr);
+ GLenum err = glGetError();
+ if (gid >= numCounters || err == GL_INVALID_VALUE) {
+ return 1;
+ }
+
+ Metric_INTEL_perfquery metric(gid, id);
+ metric.offset(); // triggers metric vars precache (in case context changes)
+ passes[pollingRule][gid].push_back(metric);
+ return 0;
+}
+
+unsigned MetricBackend_INTEL_perfquery::generatePasses() {
+ /* begin with passes that profile frames */
+ perFrame = true;
+ curQueryMetrics = passes[QUERY_BOUNDARY_FRAME].begin();
+ numFramePasses = passes[QUERY_BOUNDARY_FRAME].size();
+ numPasses = numFramePasses + passes[QUERY_BOUNDARY_DRAWCALL].size();
+ nameLookup.clear(); // no need in it after all metrics are set up
+ return numPasses;
+}
+
+void MetricBackend_INTEL_perfquery::beginPass() {
+ if (!numPasses || curQueryMetrics == passes[QUERY_BOUNDARY_DRAWCALL].end()) return;
+ /* advance to draw calls after frames */
+ if (curQueryMetrics == passes[QUERY_BOUNDARY_FRAME].end()) {
+ perFrame = false;
+ curQueryMetrics = passes[QUERY_BOUNDARY_DRAWCALL].begin();
+ }
+ glCreatePerfQueryINTEL(curQueryMetrics->first, &curQuery);
+ curEvent = 0;
+ supported = true; // can change if context is switched, so revert back
+}
+
+void MetricBackend_INTEL_perfquery::endPass() {
+ if (supported && numPasses) {
+ glDeletePerfQueryINTEL(curQuery);
+ }
+ curPass++;
+ curQueryMetrics++;
+ collector.endPass();
+}
+
+void MetricBackend_INTEL_perfquery::pausePass() {
+ if (!supported || !numPasses) return;
+ // end query
+ // ignore data from the query in progress
+ if (queryInProgress) {
+ glEndPerfQueryINTEL(curQuery);
+ curEvent++;
+ queryInProgress = false;
+ }
+ glDeletePerfQueryINTEL(curQuery);
+}
+
+void MetricBackend_INTEL_perfquery::continuePass() {
+ // here new context might be used
+ // better to check if it supports INTEL_perfquery extension
+ glretrace::Context* context = glretrace::getCurrentContext();
+ if (context && context->hasExtension("GL_INTEL_performance_query")) {
+ supported = true;
+ } else {
+ supported = false;
+ }
+
+ if (supported && numPasses) {
+ // call begin pass and save/restore event id
+ unsigned tempId = curEvent;
+ beginPass();
+ curEvent = tempId;
+ }
+}
+
+void MetricBackend_INTEL_perfquery::beginQuery(QueryBoundary boundary) {
+ if (!supported || !numPasses) return;
+ if (boundary == QUERY_BOUNDARY_CALL) return;
+ if ((boundary == QUERY_BOUNDARY_FRAME) && !perFrame) return;
+ if ((boundary == QUERY_BOUNDARY_DRAWCALL) && perFrame) return;
+ glBeginPerfQueryINTEL(curQuery);
+ queryInProgress = true;
+}
+
+void MetricBackend_INTEL_perfquery::endQuery(QueryBoundary boundary) {
+ if (!queryInProgress) return;
+ if (!supported || !numPasses) return;
+ if (boundary == QUERY_BOUNDARY_CALL) return;
+ if ((boundary == QUERY_BOUNDARY_FRAME) && !perFrame) return;
+ if ((boundary == QUERY_BOUNDARY_DRAWCALL) && perFrame) return;
+ glEndPerfQueryINTEL(curQuery);
+ freeQuery(curEvent++);
+ queryInProgress = false;
+}
+
+void MetricBackend_INTEL_perfquery::freeQuery(unsigned event) {
+ GLuint size;
+ GLuint bWritten;
+ glGetPerfQueryInfoINTEL(curQueryMetrics->first, 0, nullptr, &size,
+ nullptr, nullptr, nullptr);
+ unsigned char* data = collector.newDataBuffer(event, size);
+
+ glFlush();
+ glGetPerfQueryDataINTEL(curQuery, GL_PERFQUERY_WAIT_INTEL, size, data, &bWritten);
+ // bWritten != size -> should generate error TODO
+}
+
+void MetricBackend_INTEL_perfquery::enumDataQueryId(unsigned id,
+ enumDataCallback callback,
+ QueryBoundary boundary,
+ void* userData)
+{
+ /* Determine passes to return depending on the boundary */
+ if (boundary == QUERY_BOUNDARY_CALL) return;
+ auto queryIt = passes[QUERY_BOUNDARY_FRAME].begin();
+ unsigned j = 0;
+ unsigned nPasses = numFramePasses;
+ if (boundary == QUERY_BOUNDARY_DRAWCALL) {
+ queryIt = passes[QUERY_BOUNDARY_DRAWCALL].begin();
+ j = numFramePasses;
+ nPasses = numPasses;
+ }
+ for (; j < nPasses; j++) {
+ unsigned char* buf = collector.getDataBuffer(j, id);
+ for (auto &k : queryIt->second) {
+ if (buf) {
+ callback(&k, id, &buf[k.offset()], 0, userData);
+ } else { // No data buffer (in case event #id is not a draw call)
+ callback(&k, id, nullptr, 0, userData);
+ }
+ }
+ queryIt++;
+ }
+}
+
+unsigned MetricBackend_INTEL_perfquery::getNumPasses() {
+ return numPasses;
+}
+
+MetricBackend_INTEL_perfquery&
+MetricBackend_INTEL_perfquery::getInstance(glretrace::Context* context,
+ MmapAllocator<char> &alloc) {
+ static MetricBackend_INTEL_perfquery backend(context, alloc);
+ return backend;
+}
+
+
+std::map<std::string, std::pair<unsigned, unsigned>> MetricBackend_INTEL_perfquery::nameLookup;
diff --git a/retrace/metric_backend_intel_perfquery.hpp b/retrace/metric_backend_intel_perfquery.hpp
new file mode 100644
index 00000000..91be55b3
--- /dev/null
+++ b/retrace/metric_backend_intel_perfquery.hpp
@@ -0,0 +1,170 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <map>
+#include <string>
+
+#include "glproc.hpp"
+#include "metric_backend.hpp"
+#include "glretrace.hpp"
+
+#define INTEL_NAME_LENGTH 256 // metric name with max 256 chars
+#define INTEL_DESC_LENGTH 1024 // description max 1024 chars
+
+class Metric_INTEL_perfquery : public Metric
+{
+private:
+ unsigned m_group, m_id;
+ unsigned m_offset;
+ std:: string m_name;
+ MetricNumType m_nType;
+ bool m_precached;
+
+ void precache();
+
+public:
+ Metric_INTEL_perfquery(unsigned g, unsigned i) : m_group(g), m_id(i),
+ m_offset(0),
+ m_nType(CNT_NUM_UINT),
+ m_precached(false) {}
+
+ unsigned offset();
+
+
+ unsigned id();
+
+ unsigned groupId();
+
+ std::string name();
+
+ std::string description();
+
+ MetricNumType numType();
+
+ MetricType type();
+};
+
+
+class MetricBackend_INTEL_perfquery : public MetricBackend
+{
+private:
+ class DataCollector
+ {
+ private:
+ MmapAllocator<unsigned char> alloc;
+ // deque with custom allocator
+ template <class T>
+ using mmapdeque = std::deque<T, MmapAllocator<T>>;
+ // data storage
+ mmapdeque<mmapdeque<unsigned char*>> data;
+ unsigned curPass;
+
+ public:
+ DataCollector(MmapAllocator<char> &alloc)
+ : alloc(alloc), data(1, mmapdeque<unsigned char*>(alloc), alloc),
+ curPass(0) {}
+
+ ~DataCollector();
+
+ unsigned char* newDataBuffer(unsigned event, size_t size);
+
+ void endPass();
+
+ unsigned char* getDataBuffer(unsigned pass, unsigned event);
+ };
+
+private:
+ // map from query id to its Metric list
+ std::map<unsigned, std::vector<Metric_INTEL_perfquery>> passes[2];
+ /* curQueryMetrics -- iterator through passes */
+ std::map<unsigned, std::vector<Metric_INTEL_perfquery>>::iterator curQueryMetrics;
+ unsigned curQuery;
+ bool supported;
+ bool perFrame;
+ bool queryInProgress;
+ int numPasses;
+ int numFramePasses;
+ int curPass;
+ unsigned curEvent; // Currently evaluated event
+ DataCollector collector;
+ /* nameLookup for querying metrics by name */
+ static std::map<std::string, std::pair<unsigned, unsigned>> nameLookup;
+
+ MetricBackend_INTEL_perfquery(glretrace::Context* context, MmapAllocator<char> &alloc);
+
+ MetricBackend_INTEL_perfquery(MetricBackend_INTEL_perfquery const&) = delete;
+
+ void operator=(MetricBackend_INTEL_perfquery const&) = delete;
+
+ void freeQuery(unsigned event); // collect metrics data from the query
+
+ static void populateLookupGroups(unsigned group, int error, void* userData);
+
+ static void populateLookupMetrics(Metric* metric, int error, void* userData);
+
+public:
+ bool isSupported();
+
+ void enumGroups(enumGroupsCallback callback, void* userData = nullptr);
+
+ void enumMetrics(unsigned group, enumMetricsCallback callback,
+ void* userData = nullptr);
+
+ std::unique_ptr<Metric> getMetricById(unsigned groupId, unsigned metricId);
+
+ std::unique_ptr<Metric> getMetricByName(std::string metricName);
+
+ std::string getGroupName(unsigned group);
+
+ int enableMetric(Metric* metric, QueryBoundary pollingRule = QUERY_BOUNDARY_DRAWCALL);
+
+ unsigned generatePasses();
+
+ void beginPass();
+
+ void endPass();
+
+ void pausePass();
+
+ void continuePass();
+
+ void beginQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL);
+
+ void endQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL);
+
+ void enumDataQueryId(unsigned id, enumDataCallback callback,
+ QueryBoundary boundary,
+ void* userData = nullptr);
+
+ unsigned getNumPasses();
+
+ static MetricBackend_INTEL_perfquery& getInstance(glretrace::Context* context,
+ MmapAllocator<char> &alloc);
+};
+
diff --git a/retrace/metric_backend_opengl.cpp b/retrace/metric_backend_opengl.cpp
new file mode 100644
index 00000000..949c9222
--- /dev/null
+++ b/retrace/metric_backend_opengl.cpp
@@ -0,0 +1,481 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "metric_backend_opengl.hpp"
+#include "os_time.hpp"
+#include "os_memory.hpp"
+
+void
+MetricBackend_opengl::Storage::addData(QueryBoundary boundary, int64_t data) {
+ this->data[boundary].push_back(data);
+}
+
+int64_t* MetricBackend_opengl::Storage::getData(QueryBoundary boundary,
+ unsigned eventId)
+{
+ return &(data[boundary][eventId]);
+}
+
+Metric_opengl::Metric_opengl(unsigned gId, unsigned id, const std::string &name,
+ const std::string &desc, MetricNumType nT, MetricType t)
+ : m_gId(gId), m_id(id), m_name(name), m_desc(desc), m_nType(nT),
+ m_type(t), available(false)
+{
+ for (int i = 0; i < QUERY_BOUNDARY_LIST_END; i++) {
+ profiled[i] = false;
+ enabled[i] = false;
+ }
+}
+
+unsigned Metric_opengl::id() {
+ return m_id;
+}
+
+unsigned Metric_opengl::groupId() {
+ return m_gId;
+}
+
+std::string Metric_opengl::name() {
+ return m_name;
+}
+
+std::string Metric_opengl::description() {
+ return m_desc;
+}
+
+MetricNumType Metric_opengl::numType() {
+ return m_nType;
+}
+
+MetricType Metric_opengl::type() {
+ return m_type;
+}
+
+MetricBackend_opengl::MetricBackend_opengl(glretrace::Context* context,
+ MmapAllocator<char> &alloc)
+ : alloc(alloc)
+{
+ glprofile::Profile currentProfile = context->actualProfile();
+ supportsTimestamp = currentProfile.versionGreaterOrEqual(glprofile::API_GL, 3, 3) ||
+ context->hasExtension("GL_ARB_timer_query");
+ supportsElapsed = context->hasExtension("GL_EXT_timer_query") || supportsTimestamp;
+ supportsOcclusion = currentProfile.versionGreaterOrEqual(glprofile::API_GL, 1, 5);
+
+ #ifdef __APPLE__
+ // GL_TIMESTAMP doesn't work on Apple. GL_TIME_ELAPSED still does however.
+ // http://lists.apple.com/archives/mac-opengl/2014/Nov/threads.html#00001
+ supportsTimestamp = false;
+ #endif
+
+ // Add metrics below
+ metrics.emplace_back(0, 0, "CPU Start", "", CNT_NUM_INT64, CNT_TYPE_TIMESTAMP);
+ metrics.emplace_back(0, 1, "CPU Duration", "", CNT_NUM_INT64, CNT_TYPE_DURATION);
+ metrics.emplace_back(1, 0, "GPU Start", "", CNT_NUM_INT64, CNT_TYPE_TIMESTAMP);
+ metrics.emplace_back(1, 1, "GPU Duration", "", CNT_NUM_INT64, CNT_TYPE_DURATION);
+ metrics.emplace_back(1, 2, "Pixels Drawn", "", CNT_NUM_INT64, CNT_TYPE_GENERIC);
+ metrics.emplace_back(0, 2, "VSIZE Start", "", CNT_NUM_INT64, CNT_TYPE_GENERIC);
+ metrics.emplace_back(0, 3, "VSIZE Duration", "", CNT_NUM_INT64, CNT_TYPE_GENERIC);
+ metrics.emplace_back(0, 4, "RSS Start", "", CNT_NUM_INT64, CNT_TYPE_GENERIC);
+ metrics.emplace_back(0, 5, "RSS Duration", "", CNT_NUM_INT64, CNT_TYPE_GENERIC);
+
+ metrics[METRIC_CPU_START].available = true;
+ metrics[METRIC_CPU_DURATION].available = true;
+ metrics[METRIC_CPU_VSIZE_START].available = true;
+ metrics[METRIC_CPU_VSIZE_DURATION].available = true;
+ metrics[METRIC_CPU_RSS_START].available = true;
+ metrics[METRIC_CPU_RSS_DURATION].available = true;
+ if (supportsTimestamp) metrics[METRIC_GPU_START].available = true;
+ if (supportsElapsed) {
+ GLint bits = 0;
+ glGetQueryiv(GL_TIME_ELAPSED, GL_QUERY_COUNTER_BITS, &bits);
+ if (bits) metrics[METRIC_GPU_DURATION].available = true;
+ }
+ if (supportsOcclusion) {
+ metrics[METRIC_GPU_PIXELS].available = true;
+ }
+
+ // populate lookups
+ for (auto &m : metrics) {
+ idLookup[std::make_pair(m.groupId(), m.id())] = &m;
+ nameLookup[m.name()] = &m;
+ }
+}
+
+int64_t MetricBackend_opengl::getCurrentTime(void) {
+ if (supportsTimestamp && cpugpuSync) {
+ /* Get the current GL time without stalling */
+ GLint64 timestamp = 0;
+ glGetInteger64v(GL_TIMESTAMP, &timestamp);
+ return timestamp;
+ } else {
+ return os::getTime();
+ }
+}
+
+int64_t MetricBackend_opengl::getTimeFrequency(void) {
+ if (supportsTimestamp && cpugpuSync) {
+ return 1000000000;
+ } else {
+ return os::timeFrequency;
+ }
+}
+
+
+bool MetricBackend_opengl::isSupported() {
+ return true;
+ // though individual metrics might be not supported
+}
+
+void MetricBackend_opengl::enumGroups(enumGroupsCallback callback, void* userData) {
+ callback(0, 0, userData); // cpu group
+ callback(1, 0, userData); // gpu group
+}
+
+std::string MetricBackend_opengl::getGroupName(unsigned group) {
+ switch(group) {
+ case 0:
+ return "CPU";
+ case 1:
+ return "GPU";
+ default:
+ return "";
+ }
+}
+
+void MetricBackend_opengl::enumMetrics(unsigned group, enumMetricsCallback callback, void* userData) {
+ for (auto &m : metrics) {
+ if (m.groupId() == group && m.available) {
+ callback(&m, 0, userData);
+ }
+ }
+}
+
+std::unique_ptr<Metric>
+MetricBackend_opengl::getMetricById(unsigned groupId, unsigned metricId) {
+ auto entryToCopy = idLookup.find(std::make_pair(groupId, metricId));
+ if (entryToCopy != idLookup.end()) {
+ return std::unique_ptr<Metric>(new Metric_opengl(*entryToCopy->second));
+ } else {
+ return nullptr;
+ }
+}
+
+std::unique_ptr<Metric>
+MetricBackend_opengl::getMetricByName(std::string metricName) {
+ auto entryToCopy = nameLookup.find(metricName);
+ if (entryToCopy != nameLookup.end()) {
+ return std::unique_ptr<Metric>(new Metric_opengl(*entryToCopy->second));
+ } else {
+ return nullptr;
+ }
+}
+
+
+int MetricBackend_opengl::enableMetric(Metric* metric, QueryBoundary pollingRule) {
+ // metric is not necessarily the same object as in metrics[]
+ auto entry = idLookup.find(std::make_pair(metric->groupId(), metric->id()));
+ if ((entry != idLookup.end()) && entry->second->available) {
+ entry->second->enabled[pollingRule] = true;
+ return 0;
+ }
+ return 1;
+}
+
+unsigned MetricBackend_opengl::generatePasses() {
+ // draw calls profiling not needed if all calls are profiled
+ for (int i = 0; i < METRIC_LIST_END; i++) {
+ if (metrics[i].enabled[QUERY_BOUNDARY_CALL]) {
+ metrics[i].enabled[QUERY_BOUNDARY_DRAWCALL] = false;
+ }
+ }
+ // setup storage for profiled metrics
+ for (int i = 0; i < METRIC_LIST_END; i++) {
+ for (int j = 0; j < QUERY_BOUNDARY_LIST_END; j++) {
+ if (metrics[i].enabled[j]) {
+ data[i][j] = std::unique_ptr<Storage>(new Storage(alloc));
+ }
+ }
+ }
+ // check if GL queries are needed
+ glQueriesNeededAnyBoundary = false;
+ for (int i = 0; i < QUERY_BOUNDARY_LIST_END; i++) {
+ if (metrics[METRIC_GPU_START].enabled[i] ||
+ metrics[METRIC_GPU_DURATION].enabled[i] ||
+ metrics[METRIC_GPU_PIXELS].enabled[i])
+ {
+ glQueriesNeeded[i] = true;
+ glQueriesNeededAnyBoundary = true;
+ } else {
+ glQueriesNeeded[i] = false;
+ }
+ }
+ // check if CPU <-> GPU sync is required
+ // this is the case if any gpu time is requested
+ cpugpuSync = false;
+ for (int i = 0; i < QUERY_BOUNDARY_LIST_END; i++) {
+ if (metrics[METRIC_GPU_START].enabled[i] ||
+ metrics[METRIC_GPU_DURATION].enabled[i])
+ {
+ cpugpuSync = true;
+ break;
+ }
+ }
+ // check if two passes are needed
+ // GL_TIME_ELAPSED (gpu dur) and GL_SAMPLES_PASSED (pixels) cannot be nested
+ if (!supportsTimestamp &&
+ metrics[METRIC_GPU_DURATION].enabled[QUERY_BOUNDARY_FRAME] &&
+ (metrics[METRIC_GPU_DURATION].enabled[QUERY_BOUNDARY_CALL] ||
+ metrics[METRIC_GPU_DURATION].enabled[QUERY_BOUNDARY_DRAWCALL]))
+ {
+ twoPasses = true;
+ }
+ if (metrics[METRIC_GPU_PIXELS].enabled[QUERY_BOUNDARY_FRAME] &&
+ (metrics[METRIC_GPU_PIXELS].enabled[QUERY_BOUNDARY_CALL] ||
+ metrics[METRIC_GPU_PIXELS].enabled[QUERY_BOUNDARY_DRAWCALL]))
+ {
+ twoPasses = true;
+ }
+
+ curPass = 1;
+ return twoPasses ? 2 : 1;
+}
+
+void MetricBackend_opengl::beginPass() {
+ if (curPass == 1) {
+ for (int i = 0; i < QUERY_BOUNDARY_LIST_END; i++) {
+ for (auto &m : metrics) {
+ if (m.enabled[i]) m.profiled[i] = true;
+ }
+ }
+ // profile frames in first pass
+ if (twoPasses) {
+ if (!supportsTimestamp) {
+ metrics[METRIC_GPU_DURATION].profiled[QUERY_BOUNDARY_DRAWCALL] = false;
+ metrics[METRIC_GPU_DURATION].profiled[QUERY_BOUNDARY_CALL] = false;
+ }
+ metrics[METRIC_GPU_PIXELS].profiled[QUERY_BOUNDARY_DRAWCALL] = false;
+ metrics[METRIC_GPU_PIXELS].profiled[QUERY_BOUNDARY_CALL] = false;
+ }
+ }
+ else if (curPass == 2) {
+ for (int i = 0; i < QUERY_BOUNDARY_LIST_END; i++) {
+ for (auto &m : metrics) {
+ m.profiled[i] = false;
+ }
+ }
+ // profile calls/draw calls in second pass
+ if (!supportsTimestamp) {
+ if (metrics[METRIC_GPU_DURATION].enabled[QUERY_BOUNDARY_DRAWCALL]) {
+ metrics[METRIC_GPU_DURATION].profiled[QUERY_BOUNDARY_DRAWCALL] = true;
+ }
+ if (metrics[METRIC_GPU_DURATION].enabled[QUERY_BOUNDARY_CALL]) {
+ metrics[METRIC_GPU_DURATION].profiled[QUERY_BOUNDARY_CALL] = true;
+ }
+ }
+ if (metrics[METRIC_GPU_PIXELS].enabled[QUERY_BOUNDARY_DRAWCALL]) {
+ metrics[METRIC_GPU_PIXELS].profiled[QUERY_BOUNDARY_DRAWCALL] = true;
+ }
+ if (metrics[METRIC_GPU_PIXELS].enabled[QUERY_BOUNDARY_CALL]) {
+ metrics[METRIC_GPU_PIXELS].profiled[QUERY_BOUNDARY_CALL] = true;
+ }
+ }
+ // setup times
+ cpuTimeScale = 1.0E9 / getTimeFrequency();
+ baseTime = getCurrentTime() * cpuTimeScale;
+}
+
+void MetricBackend_opengl::processQueries() {
+ int64_t gpuStart, gpuEnd, pixels;
+ for (int i = 0; i < QUERY_BOUNDARY_LIST_END; i++) {
+ QueryBoundary boundary = static_cast<QueryBoundary>(i);
+ while (!queries[i].empty()) {
+ auto &query = queries[i].front();
+ if (metrics[METRIC_GPU_START].profiled[i]) {
+ glGetQueryObjecti64v(query[QUERY_GPU_START], GL_QUERY_RESULT,
+ &gpuStart);
+ int64_t value = gpuStart - baseTime;
+ data[METRIC_GPU_START][i]->addData(boundary, value);
+ }
+ if (metrics[METRIC_GPU_DURATION].profiled[i]) {
+ if (supportsTimestamp) {
+ glGetQueryObjecti64v(query[QUERY_GPU_DURATION], GL_QUERY_RESULT,
+ &gpuEnd);
+ gpuEnd -= gpuStart;
+ } else {
+ glGetQueryObjecti64vEXT(query[QUERY_GPU_DURATION], GL_QUERY_RESULT,
+ &gpuEnd);
+ }
+ data[METRIC_GPU_DURATION][i]->addData(boundary, gpuEnd);
+ }
+ if (metrics[METRIC_GPU_PIXELS].profiled[i]) {
+ if (supportsTimestamp) {
+ glGetQueryObjecti64v(query[QUERY_OCCLUSION], GL_QUERY_RESULT, &pixels);
+ } else if (supportsElapsed) {
+ glGetQueryObjecti64vEXT(query[QUERY_OCCLUSION], GL_QUERY_RESULT, &pixels);
+ } else {
+ uint32_t pixels32;
+ glGetQueryObjectuiv(query[QUERY_OCCLUSION], GL_QUERY_RESULT, &pixels32);
+ pixels = static_cast<int64_t>(pixels32);
+ }
+ data[METRIC_GPU_PIXELS][i]->addData(boundary, pixels);
+ }
+ glDeleteQueries(QUERY_LIST_END, query.data());
+ queries[i].pop();
+ }
+ }
+}
+
+void MetricBackend_opengl::endPass() {
+ // process rest of the queries (it can be the last frame)
+ processQueries();
+ curPass++;
+}
+
+void MetricBackend_opengl::pausePass() {
+ if (queryInProgress[QUERY_BOUNDARY_FRAME]) endQuery(QUERY_BOUNDARY_FRAME);
+ processQueries();
+}
+
+void MetricBackend_opengl::continuePass() {
+ // TODO if context switches check what it actually supports
+}
+
+void MetricBackend_opengl::beginQuery(QueryBoundary boundary) {
+ // GPU related
+ if (glQueriesNeeded[boundary]) {
+ std::array<GLuint, QUERY_LIST_END> query;
+ glGenQueries(QUERY_LIST_END, query.data());
+
+ if (metrics[METRIC_GPU_START].profiled[boundary] ||
+ (metrics[METRIC_GPU_DURATION].profiled[boundary] && supportsTimestamp))
+ {
+ glQueryCounter(query[QUERY_GPU_START], GL_TIMESTAMP);
+ }
+ if (metrics[METRIC_GPU_DURATION].profiled[boundary] && !supportsTimestamp) {
+ glBeginQuery(GL_TIME_ELAPSED, query[QUERY_GPU_DURATION]);
+ }
+ if (metrics[METRIC_GPU_PIXELS].profiled[boundary]) {
+ glBeginQuery(GL_SAMPLES_PASSED, query[QUERY_OCCLUSION]);
+ }
+ queries[boundary].push(std::move(query));
+ }
+
+
+ // CPU related
+ if (metrics[METRIC_CPU_START].profiled[boundary] ||
+ metrics[METRIC_CPU_DURATION].profiled[boundary])
+ {
+ cpuStart[boundary] = getCurrentTime();
+ if (metrics[METRIC_CPU_START].profiled[boundary]) {
+ int64_t time = cpuStart[boundary] * cpuTimeScale - baseTime;
+ data[METRIC_CPU_START][boundary]->addData(boundary, time);
+ }
+ }
+ if (metrics[METRIC_CPU_VSIZE_START].profiled[boundary] ||
+ metrics[METRIC_CPU_VSIZE_DURATION].profiled[boundary])
+ {
+ vsizeStart[boundary] = os::getVsize();
+ if (metrics[METRIC_CPU_VSIZE_START].profiled[boundary]) {
+ int64_t time = vsizeStart[boundary];
+ data[METRIC_CPU_VSIZE_START][boundary]->addData(boundary, time);
+ }
+ }
+ if (metrics[METRIC_CPU_RSS_START].profiled[boundary] ||
+ metrics[METRIC_CPU_RSS_DURATION].profiled[boundary])
+ {
+ rssStart[boundary] = os::getRss();
+ if (metrics[METRIC_CPU_RSS_START].profiled[boundary]) {
+ int64_t time = rssStart[boundary];
+ data[METRIC_CPU_RSS_START][boundary]->addData(boundary, time);
+ }
+ }
+ queryInProgress[boundary] = true;
+ // DRAWCALL is a CALL
+ if (boundary == QUERY_BOUNDARY_DRAWCALL) beginQuery(QUERY_BOUNDARY_CALL);
+}
+
+void MetricBackend_opengl::endQuery(QueryBoundary boundary) {
+ if (queryInProgress[boundary]) {
+ // CPU related
+ if (metrics[METRIC_CPU_DURATION].profiled[boundary])
+ {
+ cpuEnd[boundary] = getCurrentTime();
+ int64_t time = (cpuEnd[boundary] - cpuStart[boundary]) * cpuTimeScale;
+ data[METRIC_CPU_DURATION][boundary]->addData(boundary, time);
+ }
+ if (metrics[METRIC_CPU_VSIZE_DURATION].profiled[boundary])
+ {
+ vsizeEnd[boundary] = os::getVsize();
+ int64_t time = vsizeEnd[boundary] - vsizeStart[boundary];
+ data[METRIC_CPU_VSIZE_DURATION][boundary]->addData(boundary, time);
+ }
+ if (metrics[METRIC_CPU_RSS_DURATION].profiled[boundary])
+ {
+ rssEnd[boundary] = os::getRss();
+ int64_t time = rssEnd[boundary] - rssStart[boundary];
+ data[METRIC_CPU_RSS_DURATION][boundary]->addData(boundary, time);
+ }
+ // GPU related
+ if (glQueriesNeeded[boundary]) {
+ std::array<GLuint, QUERY_LIST_END> &query = queries[boundary].back();
+ if (metrics[METRIC_GPU_DURATION].profiled[boundary] && supportsTimestamp) {
+ // GL_TIME_ELAPSED cannot be used in nested queries
+ // so prefer this if timestamps are supported
+ glQueryCounter(query[QUERY_GPU_DURATION], GL_TIMESTAMP);
+ }
+ if (metrics[METRIC_GPU_PIXELS].profiled[boundary]) {
+ glEndQuery(GL_SAMPLES_PASSED);
+ }
+ }
+ queryInProgress[boundary] = false;
+ }
+ // DRAWCALL is a CALL
+ if (boundary == QUERY_BOUNDARY_DRAWCALL) endQuery(QUERY_BOUNDARY_CALL);
+ // clear queries after each frame
+ if (boundary == QUERY_BOUNDARY_FRAME && glQueriesNeededAnyBoundary) {
+ processQueries();
+ }
+}
+
+void MetricBackend_opengl::enumDataQueryId(unsigned id, enumDataCallback callback,
+ QueryBoundary boundary, void* userData) {
+ for (int i = 0; i < METRIC_LIST_END; i++) {
+ Metric_opengl &metric = metrics[i];
+ if (metric.enabled[boundary]) {
+ callback(&metric, id, data[i][boundary]->getData(boundary, id), 0,
+ userData);
+ }
+ }
+}
+
+unsigned MetricBackend_opengl::getNumPasses() {
+ return twoPasses ? 2 : 1;
+}
+
+MetricBackend_opengl&
+MetricBackend_opengl::getInstance(glretrace::Context* context, MmapAllocator<char> &alloc) {
+ static MetricBackend_opengl backend(context, alloc);
+ return backend;
+}
diff --git a/retrace/metric_backend_opengl.hpp b/retrace/metric_backend_opengl.hpp
new file mode 100644
index 00000000..61fe22f0
--- /dev/null
+++ b/retrace/metric_backend_opengl.hpp
@@ -0,0 +1,198 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+#include <vector>
+#include <string>
+#include <map>
+#include <queue>
+#include <array>
+
+#include "glproc.hpp"
+#include "metric_backend.hpp"
+#include "glretrace.hpp"
+#include "mmap_allocator.hpp"
+
+class Metric_opengl : public Metric
+{
+private:
+ unsigned m_gId, m_id;
+ std::string m_name, m_desc;
+ MetricNumType m_nType;
+ MetricType m_type;
+
+public:
+ Metric_opengl(unsigned gId, unsigned id, const std::string &name,
+ const std::string &desc, MetricNumType nT, MetricType t);
+
+ unsigned id();
+
+ unsigned groupId();
+
+ std::string name();
+
+ std::string description();
+
+ MetricNumType numType();
+
+ MetricType type();
+
+ // should be set by backend
+ bool available;
+ bool profiled[QUERY_BOUNDARY_LIST_END]; // profiled in cur pass
+ bool enabled[QUERY_BOUNDARY_LIST_END]; // enabled for profiling
+};
+
+class MetricBackend_opengl : public MetricBackend
+{
+private:
+ MmapAllocator<char> alloc;
+ // storage class
+ class Storage
+ {
+ private:
+ std::deque<int64_t, MmapAllocator<int64_t>> data[QUERY_BOUNDARY_LIST_END];
+
+ public:
+#ifdef _WIN32
+ Storage(MmapAllocator<char> &alloc) {
+ for (auto &d : data) {
+ d = std::deque<int64_t, MmapAllocator<int64_t>>(alloc);
+ }
+ }
+#else
+ Storage(MmapAllocator<char> &alloc)
+ : data{ std::deque<int64_t, MmapAllocator<int64_t>>(alloc),
+ std::deque<int64_t, MmapAllocator<int64_t>>(alloc),
+ std::deque<int64_t, MmapAllocator<int64_t>>(alloc) } {};
+#endif
+ void addData(QueryBoundary boundary, int64_t data);
+ int64_t* getData(QueryBoundary boundary, unsigned eventId);
+ };
+
+ // indexes into metrics vector
+ enum {
+ METRIC_CPU_START = 0,
+ METRIC_CPU_DURATION,
+ METRIC_GPU_START,
+ METRIC_GPU_DURATION,
+ METRIC_GPU_PIXELS,
+ METRIC_CPU_VSIZE_START,
+ METRIC_CPU_VSIZE_DURATION,
+ METRIC_CPU_RSS_START,
+ METRIC_CPU_RSS_DURATION,
+ METRIC_LIST_END
+ };
+
+ // indexes into queries
+ enum {
+ QUERY_GPU_START = 0,
+ QUERY_GPU_DURATION,
+ QUERY_OCCLUSION,
+ QUERY_LIST_END,
+ };
+
+ // lookup tables
+ std::map<std::pair<unsigned,unsigned>, Metric_opengl*> idLookup;
+ std::map<std::string, Metric_opengl*> nameLookup;
+
+ // bools
+ bool supportsTimestamp, supportsElapsed, supportsOcclusion;
+ bool glQueriesNeeded[QUERY_BOUNDARY_LIST_END];
+ bool glQueriesNeededAnyBoundary;
+ bool cpugpuSync;
+ bool twoPasses; // profiling in two passes
+ bool queryInProgress[QUERY_BOUNDARY_LIST_END];
+
+ unsigned curPass;
+
+ std::vector<Metric_opengl> metrics;
+ // storage for metrics
+ std::unique_ptr<Storage> data[METRIC_LIST_END][QUERY_BOUNDARY_LIST_END];
+
+ // Helper vars for metrics
+ std::queue<std::array<GLuint, QUERY_LIST_END>> queries[QUERY_BOUNDARY_LIST_END];
+ GLint64 baseTime;
+ double cpuTimeScale;
+ int64_t cpuStart[QUERY_BOUNDARY_LIST_END];
+ int64_t cpuEnd[QUERY_BOUNDARY_LIST_END];
+ int64_t vsizeStart[QUERY_BOUNDARY_LIST_END];
+ int64_t vsizeEnd[QUERY_BOUNDARY_LIST_END];
+ int64_t rssStart[QUERY_BOUNDARY_LIST_END];
+ int64_t rssEnd[QUERY_BOUNDARY_LIST_END];
+
+ MetricBackend_opengl(glretrace::Context* context, MmapAllocator<char> &alloc);
+
+ MetricBackend_opengl(MetricBackend_opengl const&) = delete;
+
+ void operator=(MetricBackend_opengl const&) = delete;
+
+public:
+ bool isSupported();
+
+ void enumGroups(enumGroupsCallback callback, void* userData = nullptr);
+
+ void enumMetrics(unsigned group, enumMetricsCallback callback, void* userData = nullptr);
+
+ std::unique_ptr<Metric> getMetricById(unsigned groupId, unsigned metricId);
+
+ std::unique_ptr<Metric> getMetricByName(std::string metricName);
+
+ std::string getGroupName(unsigned group);
+
+ int enableMetric(Metric* metric, QueryBoundary pollingRule = QUERY_BOUNDARY_DRAWCALL);
+
+ unsigned generatePasses();
+
+ void beginPass();
+
+ void endPass();
+
+ void pausePass();
+
+ void continuePass();
+
+ void beginQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL);
+
+ void endQuery(QueryBoundary boundary = QUERY_BOUNDARY_DRAWCALL);
+
+ void enumDataQueryId(unsigned id, enumDataCallback callback,
+ QueryBoundary boundary, void* userData = nullptr);
+
+ unsigned getNumPasses();
+
+ static MetricBackend_opengl& getInstance(glretrace::Context* context,
+ MmapAllocator<char> &alloc);
+
+
+private:
+ int64_t getCurrentTime(void);
+
+ int64_t getTimeFrequency(void);
+
+ void processQueries();
+};
+
diff --git a/retrace/metric_helper.cpp b/retrace/metric_helper.cpp
new file mode 100644
index 00000000..5c53db43
--- /dev/null
+++ b/retrace/metric_helper.cpp
@@ -0,0 +1,217 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <string>
+#include <cstring>
+#include <vector>
+#include <set>
+#include <iostream>
+
+#include "retrace.hpp"
+#include "metric_backend.hpp"
+#include "metric_writer.hpp"
+#include "metric_backend_amd_perfmon.hpp"
+#include "metric_backend_intel_perfquery.hpp"
+#include "metric_backend_opengl.hpp"
+#include "mmap_allocator.hpp"
+
+namespace glretrace {
+
+bool metricBackendsSetup = false;
+bool profilingContextAcquired = false;
+bool profilingBoundaries[QUERY_BOUNDARY_LIST_END] = {false};
+unsigned profilingBoundariesIndex[QUERY_BOUNDARY_LIST_END] = {0};
+std::vector<MetricBackend*> metricBackends; // to be populated in initContext()
+MetricBackend* curMetricBackend = nullptr; // backend active in the current pass
+MetricWriter profiler(metricBackends, MmapAllocator<char>());
+
+MetricBackend* getBackend(std::string backendName) {
+ // allocator for metric storage
+ MmapAllocator<char> alloc;
+ // to be populated with backends
+ Context *currentContext = getCurrentContext();
+ if (backendName == "GL_AMD_performance_monitor") return &MetricBackend_AMD_perfmon::getInstance(currentContext, alloc);
+ else if (backendName == "GL_INTEL_performance_query") return &MetricBackend_INTEL_perfquery::getInstance(currentContext, alloc);
+ else if (backendName == "opengl") return &MetricBackend_opengl::getInstance(currentContext, alloc);
+ else return nullptr;
+}
+
+bool
+isLastPass() {
+ return ( retrace::curPass + 1 >= retrace::numPasses );
+}
+
+/* Callbacks for listing metrics with --list-metrics */
+void listMetrics_metricCallback(Metric* c, int error, void* userData) {
+ static const std::string metricType[] = {"CNT_TYPE_GENERIC", "CNT_TYPE_NUM",
+ "CNT_TYPE_DURATION", "CNT_TYPE_PERCENT",
+ "CNT_TYPE_TIMESTAMP", "CNT_TYPE_OTHER"};
+ static const std::string metricNumType[] = {"CNT_NUM_UINT", "CNT_NUM_FLOAT",
+ "CNT_NUM_UINT64", "CNT_NUM_DOUBLE",
+ "CNT_NUM_BOOL", "CNT_NUM_INT64"};
+
+ std::cout << " Metric #" << c->id() << ": " << c->name()
+ << " (type: " << metricType[c->type()] << ", num. type: "
+ << metricNumType[c->numType()] << ").\n";
+ std::cout << " Description: " << c->description() << "\n";
+}
+
+void listMetrics_groupCallback(unsigned g, int error, void* userData) {
+ MetricBackend* b = reinterpret_cast<MetricBackend*>(userData);
+ std::cout << "\n Group #" << g << ": " << b->getGroupName(g) << ".\n";
+ b->enumMetrics(g, listMetrics_metricCallback, userData);
+}
+
+void listMetricsCLI() {
+ // backends is to be populated with backend names
+ std::string backends[] = {"GL_AMD_performance_monitor",
+ "GL_INTEL_performance_query",
+ "opengl"};
+ std::cout << "Available metrics: \n";
+ for (auto s : backends) {
+ auto b = getBackend(s);
+ if (!b->isSupported()) {
+ continue;
+ }
+ std::cout << "\nBackend " << s << ":\n";
+ b->enumGroups(listMetrics_groupCallback, b);
+ std::cout << std::endl;
+ }
+}
+
+void parseMetricsBlock(QueryBoundary pollingRule, const char* str,
+ std::size_t limit, MetricBackend* backend)
+{
+ const char* end;
+ bool lastItem = false;
+
+ while (((end = reinterpret_cast<const char*>(std::memchr(str, ',', limit))) != nullptr)
+ || !lastItem)
+ {
+ std::unique_ptr<Metric> p;
+ std::string metricName;
+
+ if (!end) {
+ lastItem = true;
+ end = str + limit;
+ }
+ std::size_t span = std::strspn(str, " ");
+ limit -= span;
+ str += span;
+ // parse [group, id]
+ if (*str == '[') {
+ std::string groupStr = std::string(str, 1, end-str-1);
+ limit -= end + 1 - str;
+ str = end + 1;
+ end = reinterpret_cast<const char*>(std::memchr(str, ']', limit));
+ std::string idStr = std::string(str, 0, end-str);
+ limit -= end + 1 - str;
+ str = end + 1;
+ const char* next = reinterpret_cast<const char*>(std::memchr(str, ',', limit));
+ if (next) {
+ end = next;
+ limit -= end + 1 - str;
+ str = end + 1;
+ }
+#if defined(ANDROID)
+ // http://stackoverflow.com/questions/17950814/how-to-use-stdstoul-and-stdstoull-in-android
+ unsigned groupId = strtoul(groupStr.c_str(), nullptr, 10);
+ unsigned metricId = strtoul(idStr.c_str(), nullptr, 10);
+#else
+ unsigned groupId = std::stoul(groupStr);
+ unsigned metricId = std::stoul(idStr);
+#endif
+ p = backend->getMetricById(groupId, metricId);
+ metricName = "[" + groupStr + ", " + idStr + "]";
+ // parse metricName
+ } else {
+ if (end - str) {
+ metricName = std::string(str, 0, end-str);
+ p = backend->getMetricByName(metricName);
+ }
+ limit -= end + (lastItem ? 0 : 1) - str;
+ str = end + (lastItem ? 0 : 1);
+ if (metricName.empty()) continue;
+ }
+ if (!p) {
+ std::cerr << "Warning: No metric \"" << metricName
+ << "\"." << std::endl;
+ continue;
+ }
+ int error = backend->enableMetric(p.get(), pollingRule);
+ if (error) {
+ std::cerr << "Warning: Metric " << metricName << " not enabled"
+ " (error " << error << ")." << std::endl;
+ } else {
+ profilingBoundaries[pollingRule] = true;
+ }
+ }
+}
+
+void parseBackendBlock(QueryBoundary pollingRule, const char* str,
+ std::size_t limit, std::set<MetricBackend*> &backendsHash)
+{
+ const char* delim = reinterpret_cast<const char*>(std::memchr(str, ':', limit));
+ if (delim) {
+ std::size_t span = std::strspn(str, " ");
+ std::string backendName = std::string(str, span, delim-str-span);
+ MetricBackend* backend = getBackend(backendName);
+ if (!backend) {
+ std::cerr << "Warning: No backend \"" << backendName << "\"."
+ << std::endl;
+ return;
+ }
+ if (!backend->isSupported()) {
+ std::cerr << "Warning: Backend \"" << backendName
+ << "\" is not supported." << std::endl;
+ return;
+ }
+
+ /**
+ * order in metricBackends is important for output
+ * also there should be no duplicates
+ */
+ if (backendsHash.find(backend) == backendsHash.end()) {
+ metricBackends.push_back(backend);
+ backendsHash.insert(backend);
+ }
+
+ limit -= (delim-str) + 1;
+ parseMetricsBlock(pollingRule, delim + 1, limit, backend);
+ }
+}
+
+void enableMetricsFromCLI(const char* metrics, QueryBoundary pollingRule) {
+ static std::set<MetricBackend*> backendsHash; // for not allowing duplicates
+ const char* end;
+
+ while ((end = std::strchr(metrics, ';')) != nullptr) {
+ parseBackendBlock(pollingRule, metrics, end-metrics, backendsHash);
+ metrics = end + 1;
+ }
+ parseBackendBlock(pollingRule, metrics, std::strlen(metrics), backendsHash);
+}
+
+} /* namespace glretrace */
diff --git a/retrace/metric_writer.cpp b/retrace/metric_writer.cpp
new file mode 100644
index 00000000..e923ed1d
--- /dev/null
+++ b/retrace/metric_writer.cpp
@@ -0,0 +1,224 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <iostream>
+
+#include "metric_writer.hpp"
+
+void ProfilerQuery::writeMetricHeaderCallback(Metric* metric, int event, void* data, int error,
+ void* userData) {
+ std::cout << "\t" << metric->name();
+}
+
+void ProfilerQuery::writeMetricEntryCallback(Metric* metric, int event, void* data, int error,
+ void* userData) {
+ if (error) {
+ std::cout << "\t" << "#ERR" << error;
+ return;
+ }
+ if (!data) {
+ std::cout << "\t" << "-";
+ return;
+ }
+ switch(metric->numType()) {
+ case CNT_NUM_UINT: std::cout << "\t" << *(reinterpret_cast<unsigned*>(data)); break;
+ case CNT_NUM_FLOAT: std::cout << "\t" << *(reinterpret_cast<float*>(data)); break;
+ case CNT_NUM_DOUBLE: std::cout << "\t" << *(reinterpret_cast<double*>(data)); break;
+ case CNT_NUM_BOOL: std::cout << "\t" << *(reinterpret_cast<bool*>(data)); break;
+ case CNT_NUM_UINT64: std::cout << "\t" << *(reinterpret_cast<uint64_t*>(data)); break;
+ case CNT_NUM_INT64: std::cout << "\t" << *(reinterpret_cast<int64_t*>(data)); break;
+ }
+}
+
+void ProfilerQuery::writeMetricHeader(QueryBoundary qb) const {
+ for (auto &a : *metricBackends) {
+ a->enumDataQueryId(eventId, &writeMetricHeaderCallback, qb);
+ }
+ std::cout << std::endl;
+}
+
+void ProfilerQuery::writeMetricEntry(QueryBoundary qb) const {
+ for (auto &a : *metricBackends) {
+ a->enumDataQueryId(eventId, &writeMetricEntryCallback, qb);
+ }
+ std::cout << std::endl;
+}
+
+template<typename T>
+T ProfilerCall::StringTable<T>::getId(const std::string &str) {
+ auto res = stringLookupTable.find(str);
+ T index;
+ if (res == stringLookupTable.end()) {
+ index = static_cast<T>(strings.size());
+ strings.push_back(str);
+ stringLookupTable[str] = index;
+ } else {
+ index = res->second;
+ }
+ return index;
+}
+
+template<typename T>
+std::string ProfilerCall::StringTable<T>::getString(T id) {
+ return strings[static_cast<typename decltype(stringLookupTable)::size_type>(id)];
+}
+
+
+ProfilerCall::ProfilerCall(unsigned eventId, const data* queryData)
+ : ProfilerQuery(QUERY_BOUNDARY_CALL, eventId)
+{
+ if (queryData) {
+ isFrameEnd = queryData->isFrameEnd;
+ no = queryData->no;
+ program = queryData->program;
+ nameTableEntry = nameTable.getId(queryData->name);
+ }
+}
+
+
+void ProfilerCall::writeHeader() const {
+ std::cout << "#\tcall no\tprogram\tname";
+ ProfilerQuery::writeMetricHeader(QUERY_BOUNDARY_CALL);
+}
+
+void ProfilerCall::writeEntry() const {
+ if (isFrameEnd) {
+ std::cout << "frame_end" << std::endl;
+ } else {
+ std::cout << "call"
+ << "\t" << no
+ << "\t" << program
+ << "\t" << nameTable.getString(nameTableEntry);
+ ProfilerQuery::writeMetricEntry(QUERY_BOUNDARY_CALL);
+ }
+}
+
+
+void ProfilerDrawcall::writeHeader() const {
+ std::cout << "#\tcall no\tprogram\tname";
+ ProfilerQuery::writeMetricHeader(QUERY_BOUNDARY_DRAWCALL);
+}
+
+void ProfilerDrawcall::writeEntry() const {
+ if (isFrameEnd) {
+ std::cout << "frame_end" << std::endl;
+ } else {
+ std::cout << "call"
+ << "\t" << no
+ << "\t" << program
+ << "\t" << nameTable.getString(nameTableEntry);
+ ProfilerQuery::writeMetricEntry(QUERY_BOUNDARY_DRAWCALL);
+ }
+}
+
+
+void ProfilerFrame::writeHeader() const {
+ std::cout << "#";
+ ProfilerQuery::writeMetricHeader(QUERY_BOUNDARY_FRAME);
+}
+
+void ProfilerFrame::writeEntry() const {
+ std::cout << "frame";
+ ProfilerQuery::writeMetricEntry(QUERY_BOUNDARY_FRAME);
+}
+
+
+MetricWriter::MetricWriter(std::vector<MetricBackend*> &metricBackends,
+ const MmapAllocator<char> &alloc)
+ : frameQueue(MmapAllocator<ProfilerCall>(alloc)),
+ callQueue(MmapAllocator<ProfilerCall>(alloc)),
+ drawcallQueue(MmapAllocator<ProfilerCall>(alloc))
+{
+ ProfilerQuery::metricBackends = &metricBackends;
+}
+
+void MetricWriter::addQuery(QueryBoundary boundary, unsigned eventId,
+ const void* queryData)
+{
+ switch (boundary) {
+ case QUERY_BOUNDARY_FRAME:
+ frameQueue.emplace_back(eventId);
+ break;
+ case QUERY_BOUNDARY_CALL:
+ callQueue.emplace_back(eventId,
+ reinterpret_cast<const ProfilerCall::data*>(queryData));
+ break;
+ case QUERY_BOUNDARY_DRAWCALL:
+ drawcallQueue.emplace_back(eventId,
+ reinterpret_cast<const ProfilerCall::data*>(queryData));
+ break;
+ default:
+ break;
+ }
+}
+
+void MetricWriter::writeQuery(QueryBoundary boundary) {
+ switch (boundary) {
+ case QUERY_BOUNDARY_FRAME:
+ frameQueue.front().writeEntry();
+ frameQueue.pop_front();
+ break;
+ case QUERY_BOUNDARY_CALL:
+ callQueue.front().writeEntry();
+ callQueue.pop_front();
+ break;
+ case QUERY_BOUNDARY_DRAWCALL:
+ drawcallQueue.front().writeEntry();
+ drawcallQueue.pop_front();
+ break;
+ default:
+ break;
+ }
+}
+
+void MetricWriter::writeAll(QueryBoundary boundary) {
+ switch (boundary) {
+ case QUERY_BOUNDARY_FRAME:
+ frameQueue.front().writeHeader();
+ while (!frameQueue.empty()) {
+ writeQuery(boundary);
+ }
+ break;
+ case QUERY_BOUNDARY_CALL:
+ callQueue.front().writeHeader();
+ while (!callQueue.empty()) {
+ writeQuery(boundary);
+ }
+ break;
+ case QUERY_BOUNDARY_DRAWCALL:
+ drawcallQueue.front().writeHeader();
+ while (!drawcallQueue.empty()) {
+ writeQuery(boundary);
+ }
+ break;
+ default:
+ break;
+ }
+ std::cout << std::endl;
+}
+
+std::vector<MetricBackend*>* ProfilerQuery::metricBackends = nullptr;
+
+ProfilerCall::StringTable<int16_t> ProfilerCall::nameTable;
diff --git a/retrace/metric_writer.hpp b/retrace/metric_writer.hpp
new file mode 100644
index 00000000..9162878a
--- /dev/null
+++ b/retrace/metric_writer.hpp
@@ -0,0 +1,124 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+#include <queue>
+#include <string>
+#include <unordered_map>
+
+#include "metric_backend.hpp"
+#include "mmap_allocator.hpp"
+
+class ProfilerQuery
+{
+private:
+ unsigned eventId;
+ static void writeMetricHeaderCallback(Metric* metric, int event, void* data, int error,
+ void* userData);
+ static void writeMetricEntryCallback(Metric* metric, int event, void* data, int error,
+ void* userData);
+
+public:
+ static std::vector<MetricBackend*>* metricBackends;
+
+ ProfilerQuery(QueryBoundary qb, unsigned eventId)
+ : eventId(eventId) {};
+ void writeMetricHeader(QueryBoundary qb) const;
+ void writeMetricEntry(QueryBoundary qb) const;
+};
+
+class ProfilerCall : public ProfilerQuery
+{
+public:
+ struct data {
+ bool isFrameEnd;
+ unsigned no;
+ unsigned program;
+ const char* name;
+ };
+
+protected:
+ template<typename T>
+ class StringTable
+ {
+ private:
+ std::deque<std::string> strings;
+ std::unordered_map<std::string, T> stringLookupTable;
+
+ public:
+ T getId(const std::string &str);
+ std::string getString(T id);
+ };
+
+ static StringTable<int16_t> nameTable;
+
+ int16_t nameTableEntry;
+ bool isFrameEnd;
+ unsigned no;
+ unsigned program;
+
+public:
+ ProfilerCall(unsigned eventId, const data* queryData = nullptr);
+ void writeHeader() const;
+ void writeEntry() const;
+};
+
+class ProfilerDrawcall : public ProfilerCall
+{
+public:
+ ProfilerDrawcall(unsigned eventId, const data* queryData)
+ : ProfilerCall( eventId, queryData) {};
+ void writeHeader() const;
+ void writeEntry() const;
+};
+
+class ProfilerFrame : public ProfilerQuery
+{
+public:
+ ProfilerFrame(unsigned eventId)
+ : ProfilerQuery(QUERY_BOUNDARY_FRAME, eventId) {};
+ void writeHeader() const;
+ void writeEntry() const;
+};
+
+class MetricWriter
+{
+private:
+ std::deque<ProfilerFrame, MmapAllocator<ProfilerFrame>> frameQueue;
+ std::deque<ProfilerCall, MmapAllocator<ProfilerCall>> callQueue;
+ std::deque<ProfilerDrawcall, MmapAllocator<ProfilerDrawcall>> drawcallQueue;
+
+public:
+ MetricWriter(std::vector<MetricBackend*> &metricBackends,
+ const MmapAllocator<char> &alloc);
+
+ void addQuery(QueryBoundary boundary, unsigned eventId,
+ const void* queryData = nullptr);
+
+ void writeQuery(QueryBoundary boundary);
+
+ void writeAll(QueryBoundary boundary);
+};
diff --git a/retrace/mmap_allocator.hpp b/retrace/mmap_allocator.hpp
new file mode 100644
index 00000000..adc08bbe
--- /dev/null
+++ b/retrace/mmap_allocator.hpp
@@ -0,0 +1,171 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Alexander Trukhin
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+#include <cstddef>
+#include <string>
+#include <iostream>
+#include <memory>
+#include <list>
+
+#ifdef __unix__
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define ALLOC_CHUNK_SIZE 64 * 1024 * 1024L
+
+/*
+ * Allocator that backs up memory with mmaped file
+ * File is grown by ALLOC_CHUNK_SIZE, this new region is mmaped then
+ * Nothing is deallocated
+*/
+
+class MmapedFileBuffer
+{
+private:
+ int fd;
+ off_t curChunkSize;
+ const size_t chunkSize;
+ std::list<void*> mmaps;
+ void* vptr;
+ std::string fileName;
+
+ MmapedFileBuffer(MmapedFileBuffer const&) = delete;
+
+ void operator=(MmapedFileBuffer const&) = delete;
+
+ void newMmap() {
+ int ret = ftruncate(fd, chunkSize * (mmaps.size() + 1));
+ if (ret < 0) {
+ abort();
+ }
+ vptr = mmap(NULL, chunkSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ chunkSize * mmaps.size());
+ mmaps.push_front(vptr);
+ curChunkSize = 0;
+ }
+
+public:
+ MmapedFileBuffer()
+ : curChunkSize(0),
+ chunkSize(ALLOC_CHUNK_SIZE & ~(sysconf(_SC_PAGE_SIZE) - 1))
+ {
+ char templ[] = ".pbtmpXXXXXX";
+ fd = mkstemp(templ);
+ fileName = templ;
+ newMmap();
+ }
+
+ ~MmapedFileBuffer() {
+ close(fd);
+ for (auto &m : mmaps) {
+ munmap(m, chunkSize);
+ }
+ unlink(fileName.c_str());
+ }
+
+ void* allocate(size_t size) {
+ if ((curChunkSize + size) > chunkSize) {
+ newMmap();
+ }
+ void* addr = static_cast<char*>(vptr) + curChunkSize;
+ curChunkSize += size;
+ return addr;
+ }
+};
+
+template <class T>
+class MmapAllocator
+{
+private:
+ std::shared_ptr<MmapedFileBuffer> file;
+ void* vptr;
+
+ template<class U>
+ friend class MmapAllocator;
+
+public:
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef size_t size_type;
+
+ MmapAllocator()
+ {
+ file = std::make_shared<MmapedFileBuffer>();
+ };
+
+ ~MmapAllocator() {
+ };
+
+ template <class U> MmapAllocator(const MmapAllocator<U>& other)
+ : file(other.file), vptr(other.vptr) {
+ };
+
+ T* allocate(std::size_t n) {
+ return reinterpret_cast<T*>(file->allocate(n * sizeof(T)));
+ };
+
+ void deallocate(T* p, std::size_t n) {};
+
+ template <typename U, typename... Args>
+ void construct(U* p, Args&&... args) {::new (static_cast<void*>(p) ) U (std::forward<Args> (args)...);}
+
+ template <typename U>
+ void destroy(U* p) {p->~U();}
+
+ size_type max_size() const {
+ return ALLOC_CHUNK_SIZE / sizeof(T);
+ }
+
+ template<typename U>
+ struct rebind
+ {
+ typedef MmapAllocator<U> other;
+ };
+};
+template <class T, class U>
+bool operator==(const MmapAllocator<T>&, const MmapAllocator<U>&) {
+ return true;
+}
+template <class T, class U>
+bool operator!=(const MmapAllocator<T>& a, const MmapAllocator<U>& b) {
+ return !(a==b);
+}
+
+#else
+// default allocator
+template<class T>
+using MmapAllocator = std::allocator<T>;
+
+#endif
diff --git a/retrace/retrace.cpp b/retrace/retrace.cpp
index cb2c3adc..d0067c2e 100644
--- a/retrace/retrace.cpp
+++ b/retrace/retrace.cpp
@@ -30,6 +30,10 @@
#include "os_time.hpp"
#include "retrace.hpp"
+#ifdef _WIN32
+#include <dxerr.h>
+#endif
+
namespace retrace {
@@ -59,6 +63,41 @@ std::ostream &warning(trace::Call &call) {
}
+#ifdef _WIN32
+void
+failed(trace::Call &call, HRESULT hr)
+{
+ std::ostream &os = warning(call);
+
+ os << "failed with 0x" << std::hex << hr << std::dec;
+
+ LPCSTR lpszErrorString = DXGetErrorStringA(hr);
+ assert(lpszErrorString);
+ os << " (" << lpszErrorString << "): ";
+
+ char szErrorDesc[512];
+ DXGetErrorDescriptionA(hr, szErrorDesc, sizeof szErrorDesc);
+ os << szErrorDesc;
+
+ os << "\n";
+}
+#endif /* _WIN32 */
+
+
+void
+checkMismatch(trace::Call &call, const char *expr, trace::Value *traceValue, long actualValue)
+{
+ assert(traceValue);
+ long traceIntValue = traceValue->toSInt();
+ if (traceIntValue == actualValue) {
+ return;
+ }
+
+ std::ostream &os = warning(call);
+ os << "mismatch in " << expr << ": expected " << traceIntValue << " but got " << actualValue << "\n";
+}
+
+
void ignore(trace::Call &call) {
(void)call;
}
diff --git a/retrace/retrace.hpp b/retrace/retrace.hpp
index 8f92d1c2..356ad316 100644
--- a/retrace/retrace.hpp
+++ b/retrace/retrace.hpp
@@ -25,8 +25,7 @@
*
**************************************************************************/
-#ifndef _RETRACE_HPP_
-#define _RETRACE_HPP_
+#pragma once
#include <assert.h>
#include <string.h>
@@ -35,6 +34,10 @@
#include <map>
#include <ostream>
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
#include "trace_model.hpp"
#include "trace_parser.hpp"
#include "trace_profiler.hpp"
@@ -47,11 +50,13 @@ namespace image {
class Image;
}
+class StateWriter;
+
namespace retrace {
-extern trace::Parser parser;
+extern trace::AbstractParser *parser;
extern trace::Profiler profiler;
@@ -62,10 +67,16 @@ public:
* Allocate an array with the same dimensions as the specified value.
*/
inline void *
- alloc(const trace::Value *value, size_t size) {
+ allocArray(const trace::Value *value, size_t elemSize) {
const trace::Array *array = value->toArray();
if (array) {
- return ::ScopedAllocator::alloc(array->size() * size);
+ size_t numElems = array->size();
+ size_t size = numElems * elemSize;
+ void *ptr = ::ScopedAllocator::alloc(size);
+ if (ptr) {
+ memset(ptr, 0, size);
+ }
+ return ptr;
}
const trace::Null *null = value->toNull();
if (null) {
@@ -75,6 +86,20 @@ public:
return NULL;
}
+ /**
+ * XXX: We must not compute sizeof(T) inside the function body! d3d8.h and
+ * d3d9.h have declarations of D3DPRESENT_PARAMETERS and D3DVOLUME_DESC
+ * structures with different size sizes. Multiple specializations of these
+ * will be produced (on debug builds, as on release builds the whole body
+ * is inlined.), and the linker will pick up one, leading to wrong results
+ * if the smallest specialization is picked.
+ */
+ template< class T >
+ inline T *
+ allocArray(const trace::Value *value, size_t sizeof_T = sizeof(T)) {
+ return static_cast<T *>(allocArray(value, sizeof_T));
+ }
+
};
@@ -89,14 +114,28 @@ extern int verbosity;
extern unsigned debug;
/**
- * Always force windowed, as there is no guarantee that the original display
- * mode is available.
+ * Call no markers.
*/
-static const bool forceWindowed = true;
+extern bool markers;
+
+/**
+ * Whether to force windowed. Recommeded, as there is no guarantee that the
+ * original display mode is available.
+ */
+extern bool forceWindowed;
/**
* Add profiling data to the dump when retracing.
*/
+extern unsigned curPass;
+extern unsigned numPasses;
+extern bool profilingWithBackends;
+extern char* profilingCallsMetricsString;
+extern char* profilingFramesMetricsString;
+extern char* profilingDrawCallsMetricsString;
+extern bool profilingListMetrics;
+extern bool profilingNumPasses;
+
extern bool profiling;
extern bool profilingCpuTimes;
extern bool profilingGpuTimes;
@@ -107,6 +146,7 @@ extern bool profilingMemoryUsage;
* State dumping.
*/
extern bool dumpingState;
+extern bool dumpingSnapshots;
enum Driver {
@@ -131,6 +171,11 @@ extern trace::DumpFlags dumpFlags;
std::ostream &warning(trace::Call &call);
+#ifdef _WIN32
+void failed(trace::Call &call, HRESULT hr);
+#endif
+
+void checkMismatch(trace::Call &call, const char *expr, trace::Value *traceValue, long actualValue);
void ignore(trace::Call &call);
void unsupported(trace::Call &call);
@@ -179,14 +224,13 @@ class Dumper
{
public:
virtual image::Image *
- getSnapshot(void) {
- return NULL;
- }
+ getSnapshot(void) = 0;
virtual bool
- dumpState(std::ostream &os) {
- return false;
- }
+ canDump(void) = 0;
+
+ virtual void
+ dumpState(StateWriter &) = 0;
};
@@ -227,4 +271,3 @@ cleanUp(void);
} /* namespace retrace */
-#endif /* _RETRACE_HPP_ */
diff --git a/retrace/retrace.py b/retrace/retrace.py
index 1cdb092e..d506abca 100644
--- a/retrace/retrace.py
+++ b/retrace/retrace.py
@@ -69,10 +69,10 @@ class ValueAllocator(stdapi.Visitor):
pass
def visitArray(self, array, lvalue, rvalue):
- print ' %s = static_cast<%s *>(_allocator.alloc(&%s, sizeof *%s));' % (lvalue, array.type, rvalue, lvalue)
+ print ' %s = _allocator.allocArray<%s>(&%s);' % (lvalue, array.type, rvalue)
def visitPointer(self, pointer, lvalue, rvalue):
- print ' %s = static_cast<%s *>(_allocator.alloc(&%s, sizeof *%s));' % (lvalue, pointer.type, rvalue, lvalue)
+ print ' %s = _allocator.allocArray<%s>(&%s);' % (lvalue, pointer.type, rvalue)
def visitIntPointer(self, pointer, lvalue, rvalue):
pass
@@ -124,13 +124,26 @@ class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
self.visit(bitmask.type, lvalue, rvalue)
def visitArray(self, array, lvalue, rvalue):
-
tmp = '_a_' + array.tag + '_' + str(self.seq)
self.seq += 1
- print ' if (%s) {' % (lvalue,)
- print ' const trace::Array *%s = (%s).toArray();' % (tmp, rvalue)
+ print ' const trace::Array *%s = (%s).toArray();' % (tmp, rvalue)
+ print ' if (%s) {' % (tmp,)
+
length = '%s->values.size()' % (tmp,)
+ if self.insideStruct:
+ if isinstance(array.length, int):
+ # Member is an array
+ print r' static_assert( std::is_array< std::remove_reference< decltype( %s ) >::type >::value , "lvalue must be an array" );' % lvalue
+ print r' static_assert( std::extent< std::remove_reference< decltype( %s ) >::type >::value == %s, "array size mismatch" );' % (lvalue, array.length)
+ print r' assert( %s );' % (tmp,)
+ print r' assert( %s->size() == %s );' % (tmp, array.length)
+ length = str(array.length)
+ else:
+ # Member is a pointer to an array, hence must be allocated
+ print r' static_assert( std::is_pointer< std::remove_reference< decltype( %s ) >::type >::value , "lvalue must be a pointer" );' % lvalue
+ print r' %s = _allocator.allocArray<%s>(&%s);' % (lvalue, array.type, rvalue)
+
index = '_j' + array.tag
print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
try:
@@ -154,7 +167,7 @@ class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, pointer, rvalue)
def visitObjPointer(self, pointer, lvalue, rvalue):
- print ' %s = static_cast<%s>(retrace::toObjPointer(call, %s));' % (lvalue, pointer, rvalue)
+ print ' %s = retrace::asObjPointer<%s>(call, %s);' % (lvalue, pointer.type, rvalue)
def visitLinearPointer(self, pointer, lvalue, rvalue):
print ' %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, pointer, rvalue)
@@ -186,16 +199,22 @@ class ValueDeserializer(stdapi.Visitor, stdapi.ExpanderMixin):
seq = 0
+ insideStruct = 0
+
def visitStruct(self, struct, lvalue, rvalue):
tmp = '_s_' + struct.tag + '_' + str(self.seq)
self.seq += 1
+ self.insideStruct += 1
+
print ' const trace::Struct *%s = (%s).toStruct();' % (tmp, rvalue)
print ' assert(%s);' % (tmp)
for i in range(len(struct.members)):
member = struct.members[i]
self.visitMember(member, lvalue, '*%s->members[%s]' % (tmp, i))
+ self.insideStruct -= 1
+
def visitPolymorphic(self, polymorphic, lvalue, rvalue):
if polymorphic.defaultType is None:
switchExpr = self.expand(polymorphic.switchExpr)
@@ -279,7 +298,7 @@ class SwizzledValueRegistrator(stdapi.Visitor, stdapi.ExpanderMixin):
def visitLinearPointer(self, pointer, lvalue, rvalue):
assert pointer.size is not None
if pointer.size is not None:
- print r' retrace::addRegion((%s).toUIntPtr(), %s, %s);' % (rvalue, lvalue, pointer.size)
+ print r' retrace::addRegion(call, (%s).toUIntPtr(), %s, %s);' % (rvalue, lvalue, pointer.size)
def visitReference(self, reference, lvalue, rvalue):
pass
@@ -396,7 +415,7 @@ class Retracer:
def deserializeThisPointer(self, interface):
print r' %s *_this;' % (interface.name,)
- print r' _this = static_cast<%s *>(retrace::toObjPointer(call, call.arg(0)));' % (interface.name,)
+ print r' _this = retrace::asObjPointer<%s>(call, call.arg(0));' % (interface.name,)
print r' if (!_this) {'
print r' return;'
print r' }'
@@ -472,34 +491,81 @@ class Retracer:
arg_names = ", ".join(function.argNames())
if function.type is not stdapi.Void:
print ' _result = %s(%s);' % (function.name, arg_names)
- print ' (void)_result;'
- self.checkResult(function.type)
+ self.checkResult(None, function)
else:
print ' %s(%s);' % (function.name, arg_names)
def invokeInterfaceMethod(self, interface, method):
- # On release our reference when we reach Release() == 0 call in the
- # trace.
- if method.name == 'Release':
- print ' if (call.ret->toUInt() == 0) {'
- print ' retrace::delObj(call.arg(0));'
- print ' }'
-
arg_names = ", ".join(method.argNames())
if method.type is not stdapi.Void:
print ' _result = _this->%s(%s);' % (method.name, arg_names)
- print ' (void)_result;'
- self.checkResult(method.type)
else:
print ' _this->%s(%s);' % (method.name, arg_names)
- def checkResult(self, resultType):
- if str(resultType) == 'HRESULT':
+ # Adjust reference count when QueryInterface fails. This is
+ # particularly useful when replaying traces on older Direct3D runtimes
+ # which might miss newer versions of interfaces, yet none of those
+ # methods are actually used.
+ #
+ # TODO: Generalize to other methods that return interfaces
+ if method.name == 'QueryInterface':
print r' if (FAILED(_result)) {'
- print ' static char szMessageBuffer[128];'
- print r' retrace::warning(call) << "call returned 0x" << std::hex << _result << std::dec << ": " << (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, _result, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szMessageBuffer, sizeof szMessageBuffer, NULL) ? szMessageBuffer : "???") << "\n";'
+ print r' IUnknown *pObj = retrace::asObjPointer<IUnknown>(call, *call.arg(2).toArray()->values[0]);'
+ print r' if (pObj) {'
+ print r' pObj->AddRef();'
+ print r' }'
print r' }'
+ if method.type is not stdapi.Void:
+ self.checkResult(interface, method)
+
+ # Debug COM reference counting. Disabled by default as reported
+ # reference counts depend on internal implementation details.
+ if method.name in ('AddRef', 'Release'):
+ print r' if (0) retrace::checkMismatch(call, "cRef", call.ret, _result);'
+
+ # On release our reference when we reach Release() == 0 call in the
+ # trace.
+ if method.name == 'Release':
+ print r' ULONG _orig_result = call.ret->toUInt();'
+ print r' if (_orig_result == 0 || _result == 0) {'
+ print r' if (_orig_result != 0) {'
+ print r' retrace::warning(call) << "unexpected object destruction\n";'
+ print r' }'
+ print r' retrace::delObj(call.arg(0));'
+ print r' }'
+
+ def checkResult(self, interface, methodOrFunction):
+ assert methodOrFunction.type is not stdapi.Void
+ if str(methodOrFunction.type) == 'HRESULT':
+ print r' if (FAILED(_result)) {'
+ print r' retrace::failed(call, _result);'
+ print r' return;'
+ print r' }'
+ else:
+ print r' (void)_result;'
+
+ def checkPitchMismatch(self, method):
+ # Warn for mismatches in 2D/3D mappings.
+ # FIXME: We should try to swizzle them. It's a bit of work, but possible.
+ for outArg in method.args:
+ if outArg.output \
+ and isinstance(outArg.type, stdapi.Pointer) \
+ and isinstance(outArg.type.type, stdapi.Struct):
+ print r' const trace::Array *_%s = call.arg(%u).toArray();' % (outArg.name, outArg.index)
+ print r' if (%s) {' % outArg.name
+ print r' const trace::Struct *_struct = _%s->values[0]->toStruct();' % (outArg.name)
+ print r' if (_struct) {'
+ struct = outArg.type.type
+ for memberIndex in range(len(struct.members)):
+ memberType, memberName = struct.members[memberIndex]
+ if memberName.endswith('Pitch'):
+ print r' if (%s->%s) {' % (outArg.name, memberName)
+ print r' retrace::checkMismatch(call, "%s", _struct->members[%u], %s->%s);' % (memberName, memberIndex, outArg.name, memberName)
+ print r' }'
+ print r' }'
+ print r' }'
+
def filterFunction(self, function):
return True
@@ -532,7 +598,7 @@ class Retracer:
self.retraceFunction(function)
interfaces = api.getAllInterfaces()
for interface in interfaces:
- for method in interface.iterMethods():
+ for method in interface.methods:
if method.sideeffects and not method.internal:
self.retraceInterfaceMethod(interface, method)
@@ -544,9 +610,9 @@ class Retracer:
else:
print ' {"%s", &retrace::ignore},' % (function.name,)
for interface in interfaces:
- for method in interface.iterMethods():
+ for base, method in interface.iterBaseMethods():
if method.sideeffects:
- print ' {"%s::%s", &retrace_%s__%s},' % (interface.name, method.name, interface.name, method.name)
+ print ' {"%s::%s", &retrace_%s__%s},' % (interface.name, method.name, base.name, method.name)
else:
print ' {"%s::%s", &retrace::ignore},' % (interface.name, method.name)
print ' {NULL, NULL}'
diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp
index 47b355d1..0c17026f 100644
--- a/retrace/retrace_main.cpp
+++ b/retrace/retrace_main.cpp
@@ -35,6 +35,7 @@
#endif
#include "os_binary.hpp"
+#include "os_crtdbg.hpp"
#include "os_time.hpp"
#include "os_thread.hpp"
#include "image.hpp"
@@ -42,12 +43,13 @@
#include "trace_dump.hpp"
#include "trace_option.hpp"
#include "retrace.hpp"
+#include "state_writer.hpp"
+#include "ws.hpp"
static bool waitOnFinish = false;
-static bool loopOnFinish = false;
-static const char *snapshotPrefix = NULL;
+static const char *snapshotPrefix = "";
static enum {
PNM_FMT,
RAW_RGB,
@@ -55,7 +57,7 @@ static enum {
} snapshotFormat = PNM_FMT;
static trace::CallSet snapshotFrequency;
-static trace::ParseBookmark lastFrameStart;
+static unsigned snapshotInterval = 0;
static unsigned dumpStateCallNo = ~0;
@@ -65,13 +67,16 @@ retrace::Retracer retracer;
namespace retrace {
-trace::Parser parser;
+trace::AbstractParser *parser;
trace::Profiler profiler;
int verbosity = 0;
unsigned debug = 1;
+bool markers = false;
+bool forceWindowed = true;
bool dumpingState = false;
+bool dumpingSnapshots = false;
Driver driver = DRIVER_DEFAULT;
const char *driverModule = NULL;
@@ -79,6 +84,15 @@ const char *driverModule = NULL;
bool doubleBuffer = true;
unsigned samples = 1;
+unsigned curPass = 0;
+unsigned numPasses = 1;
+bool profilingWithBackends = false;
+char* profilingCallsMetricsString;
+char* profilingFramesMetricsString;
+char* profilingDrawCallsMetricsString;
+bool profilingListMetrics = false;
+bool profilingNumPasses = false;
+
bool profiling = false;
bool profilingGpuTimes = false;
bool profilingCpuTimes = false;
@@ -91,17 +105,51 @@ unsigned frameNo = 0;
unsigned callNo = 0;
+static void
+takeSnapshot(unsigned call_no);
+
+
void
frameComplete(trace::Call &call) {
++frameNo;
+
+ if (!(call.flags & trace::CALL_FLAG_END_FRAME) &&
+ snapshotFrequency.contains(call)) {
+ // This call doesn't have the end of frame flag, so take any snapshot
+ // now.
+ takeSnapshot(call.no);
+ }
}
+class DefaultDumper: public Dumper
+{
+public:
+ image::Image *
+ getSnapshot(void) {
+ return NULL;
+ }
-static Dumper defaultDumper;
+ bool
+ canDump(void) {
+ return false;
+ }
+
+ void
+ dumpState(StateWriter &writer) {
+ assert(0);
+ }
+};
+
+
+static DefaultDumper defaultDumper;
Dumper *dumper = &defaultDumper;
+typedef StateWriter *(*StateWriterFactory)(std::ostream &);
+static StateWriterFactory stateWriterFactory = createJSONStateWriter;
+
+
/**
* Take snapshots.
*/
@@ -109,6 +157,7 @@ static void
takeSnapshot(unsigned call_no) {
static unsigned snapshot_no = 0;
+ assert(dumpingSnapshots);
assert(snapshotPrefix);
image::Image *src = dumper->getSnapshot();
@@ -117,7 +166,9 @@ takeSnapshot(unsigned call_no) {
return;
}
- if (snapshotPrefix) {
+ if ((snapshotInterval == 0 ||
+ (snapshot_no % snapshotInterval) == 0)) {
+
if (snapshotPrefix[0] == '-' && snapshotPrefix[1] == 0) {
char comment[21];
snprintf(comment, sizeof comment, "%u",
@@ -140,7 +191,13 @@ takeSnapshot(unsigned call_no) {
os::String filename = os::String::format("%s%010u.png",
snapshotPrefix,
useCallNos ? call_no : snapshot_no);
- if (src->writePNG(filename) && retrace::verbosity >= 0) {
+
+ // Alpha channel often has bogus data, so strip it when writing
+ // PNG images to disk to simplify visualization.
+ bool strip_alpha = true;
+
+ if (src->writePNG(filename, strip_alpha) &&
+ retrace::verbosity >= 0) {
std::cout << "Wrote " << filename << "\n";
}
}
@@ -162,6 +219,8 @@ takeSnapshot(unsigned call_no) {
*/
static void
retraceCall(trace::Call *call) {
+ callNo = call->no;
+
bool swapRenderTarget = call->flags &
trace::CALL_FLAG_SWAP_RENDERTARGET;
bool doSnapshot = snapshotFrequency.contains(*call);
@@ -180,14 +239,22 @@ retraceCall(trace::Call *call) {
}
}
- callNo = call->no;
retracer.retrace(*call);
- if (doSnapshot && !swapRenderTarget)
- takeSnapshot(call->no);
+ if (doSnapshot) {
+ if (!swapRenderTarget) {
+ takeSnapshot(call->no);
+ }
+ if (call->no >= snapshotFrequency.getLast()) {
+ exit(0);
+ }
+ }
if (call->no >= dumpStateCallNo &&
- dumper->dumpState(std::cout)) {
+ dumper->canDump()) {
+ StateWriter *writer = stateWriterFactory(std::cout);
+ dumper->dumpState(*writer);
+ delete writer;
exit(0);
}
}
@@ -261,7 +328,7 @@ private:
os::thread thread;
- static void *
+ static void
runnerThread(RelayRunner *_this);
public:
@@ -321,30 +388,13 @@ public:
/* Consume successive calls for this thread. */
do {
- bool callEndsFrame = false;
- static trace::ParseBookmark frameStart;
assert(call);
assert(call->thread_id == leg);
- if (loopOnFinish && call->flags & trace::CALL_FLAG_END_FRAME) {
- callEndsFrame = true;
- parser.getBookmark(frameStart);
- }
-
retraceCall(call);
delete call;
- call = parser.parse_call();
-
- /* Restart last frame if looping is requested. */
- if (loopOnFinish) {
- if (!call) {
- parser.setBookmark(lastFrameStart);
- call = parser.parse_call();
- } else if (callEndsFrame) {
- lastFrameStart = frameStart;
- }
- }
+ call = parser->parse_call();
} while (call && call->thread_id == leg);
@@ -377,7 +427,7 @@ public:
baton = call;
mutex.unlock();
- wake_cond.signal();
+ wake_cond.notify_one();
}
/**
@@ -391,15 +441,14 @@ public:
finished = true;
mutex.unlock();
- wake_cond.signal();
+ wake_cond.notify_one();
}
};
-void *
+void
RelayRunner::runnerThread(RelayRunner *_this) {
_this->runRace();
- return 0;
}
@@ -447,20 +496,12 @@ RelayRace::getRunner(unsigned leg) {
void
RelayRace::run(void) {
trace::Call *call;
- call = parser.parse_call();
+ call = parser->parse_call();
if (!call) {
/* Nothing to do */
return;
}
- /* If the user wants to loop we need to get a bookmark target. We
- * usually get this after replaying a call that ends a frame, but
- * for a trace that has only one frame we need to get it at the
- * beginning. */
- if (loopOnFinish) {
- parser.getBookmark(lastFrameStart);
- }
-
RelayRunner *foreRunner = getForeRunner();
if (call->thread_id == 0) {
/* We are the forerunner thread, so no need to pass baton */
@@ -524,10 +565,10 @@ mainLoop() {
if (singleThread) {
trace::Call *call;
- while ((call = parser.parse_call())) {
+ while ((call = parser->parse_call())) {
retraceCall(call);
delete call;
- };
+ }
} else {
RelayRace race;
race.run();
@@ -563,23 +604,33 @@ usage(const char *argv0) {
"\n"
" -b, --benchmark benchmark mode (no error checking or warning messages)\n"
" -d, --debug increase debugging checks\n"
+ " --markers insert call no markers in the command stream\n"
" --pcpu cpu profiling (cpu times per call)\n"
" --pgpu gpu profiling (gpu times per draw call)\n"
" --ppd pixels drawn profiling (pixels drawn per draw call)\n"
" --pmem memory usage profiling (vsize rss per call)\n"
+ " --pcalls call profiling metrics selection\n"
+ " --pframes frame profiling metrics selection\n"
+ " --pdrawcalls draw call profiling metrics selection\n"
+ " --list-metrics list all available metrics for TRACE\n"
+ " --gen-passes generate profiling passes and output passes number\n"
" --call-nos[=BOOL] use call numbers in snapshot filenames\n"
" --core use core profile\n"
" --db use a double buffer visual (default)\n"
" --samples=N use GL_ARB_multisample (default is 1)\n"
" --driver=DRIVER force driver type (`hw`, `sw`, `ref`, `null`, or driver module name)\n"
+ " --fullscreen allow fullscreen\n"
+ " --headless don't show windows\n"
" --sb use a single buffer visual\n"
" -s, --snapshot-prefix=PREFIX take snapshots; `-` for PNM stdout output\n"
" --snapshot-format=FMT use (PNM, RGB, or MD5; default is PNM) when writing to stdout output\n"
" -S, --snapshot=CALLSET calls to snapshot (default is every frame)\n"
+ " --snapshot-interval=N specify a frame interval when generating snaphots (default is 0)\n"
" -v, --verbose increase output verbosity\n"
" -D, --dump-state=CALL dump state at specific call no\n"
+ " --dump-format=FORMAT dump state format (`json` or `ubjson`)\n"
" -w, --wait waitOnFinish on final frame\n"
- " --loop continuously loop, replaying final frame.\n"
+ " --loop[=N] loop N times (N<0 continuously) replaying final frame.\n"
" --singlethread use a single thread to replay command stream\n";
}
@@ -589,14 +640,24 @@ enum {
DB_OPT,
SAMPLES_OPT,
DRIVER_OPT,
+ FULLSCREEN_OPT,
+ HEADLESS_OPT,
PCPU_OPT,
PGPU_OPT,
PPD_OPT,
PMEM_OPT,
+ PCALLS_OPT,
+ PFRAMES_OPT,
+ PDRAWCALLS_OPT,
+ PLMETRICS_OPT,
+ GENPASS_OPT,
SB_OPT,
SNAPSHOT_FORMAT_OPT,
LOOP_OPT,
- SINGLETHREAD_OPT
+ SINGLETHREAD_OPT,
+ SNAPSHOT_INTERVAL_OPT,
+ DUMP_FORMAT_OPT,
+ MARKERS_OPT
};
const static char *
@@ -606,24 +667,34 @@ const static struct option
longOptions[] = {
{"benchmark", no_argument, 0, 'b'},
{"debug", no_argument, 0, 'd'},
+ {"markers", no_argument, 0, MARKERS_OPT},
{"call-nos", optional_argument, 0, CALL_NOS_OPT },
{"core", no_argument, 0, CORE_OPT},
{"db", no_argument, 0, DB_OPT},
{"samples", required_argument, 0, SAMPLES_OPT},
{"driver", required_argument, 0, DRIVER_OPT},
{"dump-state", required_argument, 0, 'D'},
+ {"dump-format", required_argument, 0, DUMP_FORMAT_OPT},
+ {"fullscreen", no_argument, 0, FULLSCREEN_OPT},
+ {"headless", no_argument, 0, HEADLESS_OPT},
{"help", no_argument, 0, 'h'},
{"pcpu", no_argument, 0, PCPU_OPT},
{"pgpu", no_argument, 0, PGPU_OPT},
{"ppd", no_argument, 0, PPD_OPT},
{"pmem", no_argument, 0, PMEM_OPT},
+ {"pcalls", required_argument, 0, PCALLS_OPT},
+ {"pframes", required_argument, 0, PFRAMES_OPT},
+ {"pdrawcalls", required_argument, 0, PDRAWCALLS_OPT},
+ {"list-metrics", no_argument, 0, PLMETRICS_OPT},
+ {"gen-passes", no_argument, 0, GENPASS_OPT},
{"sb", no_argument, 0, SB_OPT},
{"snapshot-prefix", required_argument, 0, 's'},
{"snapshot-format", required_argument, 0, SNAPSHOT_FORMAT_OPT},
{"snapshot", required_argument, 0, 'S'},
+ {"snapshot-interval", required_argument, 0, SNAPSHOT_INTERVAL_OPT},
{"verbose", no_argument, 0, 'v'},
{"wait", no_argument, 0, 'w'},
- {"loop", no_argument, 0, LOOP_OPT},
+ {"loop", optional_argument, 0, LOOP_OPT},
{"singlethread", no_argument, 0, SINGLETHREAD_OPT},
{0, 0, 0, 0}
};
@@ -639,8 +710,11 @@ extern "C"
int main(int argc, char **argv)
{
using namespace retrace;
+ int loopCount = 0;
int i;
+ os::setDebugOutput(os::OUTPUT_STDERR);
+
assert(snapshotFrequency.empty());
int opt;
@@ -653,6 +727,9 @@ int main(int argc, char **argv)
retrace::debug = 0;
retrace::verbosity = -1;
break;
+ case MARKERS_OPT:
+ retrace::markers = true;
+ break;
case 'd':
++retrace::debug;
break;
@@ -664,6 +741,17 @@ int main(int argc, char **argv)
dumpingState = true;
retrace::verbosity = -2;
break;
+ case DUMP_FORMAT_OPT:
+ if (strcasecmp(optarg, "json") == 0) {
+ stateWriterFactory = &createJSONStateWriter;
+ } else if (strcasecmp(optarg, "ubjson") == 0) {
+ os::setBinaryMode(stdout);
+ stateWriterFactory = &createUBJSONStateWriter;
+ } else {
+ std::cerr << "error: unsupported dump format `" << optarg << "`\n";
+ return EXIT_FAILURE;
+ }
+ break;
case CORE_OPT:
retrace::setFeatureLevel("3_2_core");
break;
@@ -687,6 +775,12 @@ int main(int argc, char **argv)
driverModule = optarg;
}
break;
+ case FULLSCREEN_OPT:
+ retrace::forceWindowed = false;
+ break;
+ case HEADLESS_OPT:
+ ws::headless = true;
+ break;
case SB_OPT:
retrace::doubleBuffer = false;
break;
@@ -694,6 +788,7 @@ int main(int argc, char **argv)
retrace::singleThread = true;
break;
case 's':
+ dumpingSnapshots = true;
snapshotPrefix = optarg;
if (snapshotFrequency.empty()) {
snapshotFrequency = trace::CallSet(trace::FREQUENCY_FRAME);
@@ -729,10 +824,11 @@ int main(int argc, char **argv)
snapshotFormat = PNM_FMT;
break;
case 'S':
+ dumpingSnapshots = true;
snapshotFrequency.merge(optarg);
- if (snapshotPrefix == NULL) {
- snapshotPrefix = "";
- }
+ break;
+ case SNAPSHOT_INTERVAL_OPT:
+ snapshotInterval = atoi(optarg);
break;
case 'v':
++retrace::verbosity;
@@ -741,7 +837,7 @@ int main(int argc, char **argv)
waitOnFinish = true;
break;
case LOOP_OPT:
- loopOnFinish = true;
+ loopCount = trace::intOption(optarg, -1);
break;
case PGPU_OPT:
retrace::debug = 0;
@@ -771,6 +867,41 @@ int main(int argc, char **argv)
retrace::profilingMemoryUsage = true;
break;
+ case PCALLS_OPT:
+ retrace::debug = 0;
+ retrace::profiling = true;
+ retrace::verbosity = -1;
+ retrace::profilingWithBackends = true;
+ retrace::profilingCallsMetricsString = optarg;
+ break;
+ case PFRAMES_OPT:
+ retrace::debug = 0;
+ retrace::profiling = true;
+ retrace::verbosity = -1;
+ retrace::profilingWithBackends = true;
+ retrace::profilingFramesMetricsString = optarg;
+ break;
+ case PDRAWCALLS_OPT:
+ retrace::debug = 0;
+ retrace::profiling = true;
+ retrace::verbosity = -1;
+ retrace::profilingWithBackends = true;
+ retrace::profilingDrawCallsMetricsString = optarg;
+ break;
+ case PLMETRICS_OPT:
+ retrace::debug = 0;
+ retrace::profiling = true;
+ retrace::verbosity = -1;
+ retrace::profilingWithBackends = true;
+ retrace::profilingListMetrics = true;
+ break;
+ case GENPASS_OPT:
+ retrace::debug = 0;
+ retrace::profiling = true;
+ retrace::verbosity = -1;
+ retrace::profilingWithBackends = true;
+ retrace::profilingNumPasses = true;
+ break;
default:
std::cerr << "error: unknown option " << opt << "\n";
usage(argv[0]);
@@ -784,28 +915,56 @@ int main(int argc, char **argv)
}
#endif
+#ifdef _WIN32
+ // Set Windows timer resolution to the minimum period supported by the
+ // system
+ TIMECAPS tc;
+ MMRESULT mmRes = timeGetDevCaps(&tc, sizeof tc);
+ if (mmRes == MMSYSERR_NOERROR) {
+ mmRes = timeBeginPeriod(tc.wPeriodMin);
+ }
+#endif
+
retrace::setUp();
- if (retrace::profiling) {
+ if (retrace::profiling && !retrace::profilingWithBackends) {
retrace::profiler.setup(retrace::profilingCpuTimes, retrace::profilingGpuTimes, retrace::profilingPixelsDrawn, retrace::profilingMemoryUsage);
}
os::setExceptionCallback(exceptionCallback);
- for (i = optind; i < argc; ++i) {
- if (!retrace::parser.open(argv[i])) {
- return 1;
- }
+ for (retrace::curPass = 0; retrace::curPass < retrace::numPasses;
+ retrace::curPass++)
+ {
+ for (i = optind; i < argc; ++i) {
+ parser = new trace::Parser;
+ if (loopCount) {
+ parser = lastFrameLoopParser(parser, loopCount);
+ }
+
+ if (!parser->open(argv[i])) {
+ return 1;
+ }
- retrace::mainLoop();
+ retrace::mainLoop();
- retrace::parser.close();
+ parser->close();
+
+ delete parser;
+ parser = NULL;
+ }
}
-
+
os::resetExceptionCallback();
// XXX: X often hangs on XCloseDisplay
//retrace::cleanUp();
+#ifdef _WIN32
+ if (mmRes == MMSYSERR_NOERROR) {
+ timeEndPeriod(tc.wPeriodMin);
+ }
+#endif
+
return 0;
}
diff --git a/retrace/retrace_stdc.cpp b/retrace/retrace_stdc.cpp
index dd4d0f47..2a57ef04 100644
--- a/retrace/retrace_stdc.cpp
+++ b/retrace/retrace_stdc.cpp
@@ -28,6 +28,7 @@
#include <string.h>
#include <iostream>
+#include <algorithm>
#include "retrace.hpp"
#include "retrace_swizzle.hpp"
@@ -47,20 +48,37 @@ static void retrace_malloc(trace::Call &call) {
return;
}
- retrace::addRegion(address, buffer, size);
+ retrace::addRegion(call, address, buffer, size);
}
static void retrace_memcpy(trace::Call &call) {
- void * dest = retrace::toPointer(call.arg(0));
- void * src = retrace::toPointer(call.arg(1));
- size_t n = call.arg(2).toUInt();
+ void * destPtr;
+ size_t destLen;
+ retrace::toRange(call.arg(0), destPtr, destLen);
- if (!dest || !src || !n) {
+ void * srcPtr;
+ size_t srcLen;
+ retrace::toRange(call.arg(1), srcPtr, srcLen);
+
+ size_t n = call.arg(2).toUInt();
+
+ if (!destPtr || !srcPtr || !n) {
return;
}
- memcpy(dest, src, n);
+ if (n > destLen) {
+ retrace::warning(call) << "dest buffer overflow of " << n - destLen << " bytes\n";
+ }
+
+ if (n > srcLen) {
+ retrace::warning(call) << "src buffer overflow of " << n - srcLen << " bytes\n";
+ }
+
+ n = std::min(n, destLen);
+ n = std::min(n, srcLen);
+
+ memcpy(destPtr, srcPtr, n);
}
diff --git a/retrace/retrace_swizzle.cpp b/retrace/retrace_swizzle.cpp
index f1a10d5e..ce89276f 100644
--- a/retrace/retrace_swizzle.cpp
+++ b/retrace/retrace_swizzle.cpp
@@ -99,7 +99,7 @@ upperBound(unsigned long long address) {
}
void
-addRegion(unsigned long long address, void *buffer, unsigned long long size)
+addRegion(trace::Call &call, unsigned long long address, void *buffer, unsigned long long size)
{
if (retrace::verbosity >= 2) {
std::cout
@@ -118,21 +118,28 @@ addRegion(unsigned long long address, void *buffer, unsigned long long size)
return;
}
-#ifndef NDEBUG
- RegionMap::iterator start = lowerBound(address);
- RegionMap::iterator stop = upperBound(address + size - 1);
- if (0) {
- // Forget all regions that intersect this new one.
- regionMap.erase(start, stop);
- } else {
- for (RegionMap::iterator it = start; it != stop; ++it) {
- std::cerr << std::hex << "warning: "
- "region 0x" << address << "-0x" << (address + size) << " "
- "intersects existing region 0x" << it->first << "-0x" << (it->first + it->second.size) << "\n" << std::dec;
- assert(intersects(it, address, size));
+ const bool debug =
+#ifdef NDEBUG
+ false
+#else
+ true
+#endif
+ ;
+ if (debug) {
+ RegionMap::iterator start = lowerBound(address);
+ RegionMap::iterator stop = upperBound(address + size - 1);
+ if (0) {
+ // Forget all regions that intersect this new one.
+ regionMap.erase(start, stop);
+ } else {
+ for (RegionMap::iterator it = start; it != stop; ++it) {
+ warning(call) << std::hex <<
+ "region 0x" << address << "-0x" << (address + size) << " "
+ "intersects existing region 0x" << it->first << "-0x" << (it->first + it->second.size) << "\n" << std::dec;
+ assert(intersects(it, address, size));
+ }
}
}
-#endif
assert(buffer);
@@ -182,13 +189,15 @@ delRegionByPointer(void *ptr) {
assert(0);
}
-void *
-lookupAddress(unsigned long long address) {
+static void
+lookupAddress(unsigned long long address, void * & ptr, size_t & len) {
RegionMap::iterator it = lookupRegion(address);
if (it != regionMap.end()) {
unsigned long long offset = address - it->first;
assert(offset < it->second.size);
- void *addr = (char *)it->second.buffer + offset;
+
+ ptr = (char *)it->second.buffer + offset;
+ len = it->second.size - offset;
if (retrace::verbosity >= 2) {
std::cout
@@ -196,12 +205,12 @@ lookupAddress(unsigned long long address) {
<< std::hex
<< "0x" << address
<< " <- "
- << "0x" << (uintptr_t)addr
+ << "0x" << (uintptr_t)ptr
<< std::dec
<< "\n";
}
- return addr;
+ return;
}
if (retrace::debug && address >= 64 * 1024 * 1024) {
@@ -209,45 +218,63 @@ lookupAddress(unsigned long long address) {
std::cerr << "warning: passing high address 0x" << std::hex << address << std::dec << " as uintptr_t\n";
}
- return (void *)(uintptr_t)address;
+ ptr = (void *)(uintptr_t)address;
+ len = 0;
}
class Translator : protected trace::Visitor
{
protected:
- bool bind;
+ const bool bind;
- void *result;
+ void *ptr;
+ size_t len;
+protected:
void visit(trace::Null *) {
- result = NULL;
+ ptr = NULL;
+ len = 0;
}
void visit(trace::Blob *blob) {
- result = blob->toPointer(bind);
+ ptr = blob->toPointer(bind);
+ len = blob->size;
}
void visit(trace::Pointer *p) {
- result = lookupAddress(p->value);
+ lookupAddress(p->value, ptr, len);
}
public:
Translator(bool _bind) :
bind(_bind),
- result(NULL)
+ ptr(NULL),
+ len(0)
{}
- void * operator() (trace::Value *node) {
+ void
+ operator() (trace::Value *node, void * & _ptr, size_t & _len) {
_visit(node);
- return result;
+ _ptr = ptr;
+ _len = len;
}
};
+void
+toRange(trace::Value &value, void * & ptr, size_t & len) {
+ Translator(false) (&value, ptr, len);
+}
+
void *
toPointer(trace::Value &value, bool bind) {
- return Translator(bind) (&value);
+ void * ptr;
+ size_t len;
+ Translator translator(bind);
+ translator(&value, ptr, len);
+ (void)len;
+ return ptr;
}
@@ -281,7 +308,7 @@ delObj(trace::Value &value) {
unsigned long long address = value.toUIntPtr();
_obj_map.erase(address);
if (retrace::verbosity >= 2) {
- std::cout << std::hex << "obj 0x" << address << " del\n";
+ std::cout << std::hex << "obj 0x" << address << std::dec << " del\n";
}
}
diff --git a/retrace/retrace_swizzle.hpp b/retrace/retrace_swizzle.hpp
index 86ae169c..74589719 100644
--- a/retrace/retrace_swizzle.hpp
+++ b/retrace/retrace_swizzle.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _RETRACE_SWIZZLE_HPP_
-#define _RETRACE_SWIZZLE_HPP_
+#pragma once
#include <map>
@@ -56,6 +55,15 @@ private:
base_type base;
public:
+ typedef typename base_type::const_iterator const_iterator;
+
+ const_iterator end(void) const {
+ return base.end();
+ }
+
+ const_iterator find(const T & key) const {
+ return base.find(key);
+ }
T & operator[] (const T &key) {
typename base_type::iterator it;
@@ -99,11 +107,14 @@ public:
void
-addRegion(unsigned long long address, void *buffer, unsigned long long size);
+addRegion(trace::Call &call, unsigned long long address, void *buffer, unsigned long long size);
void
delRegionByPointer(void *ptr);
+void
+toRange(trace::Value &value, void * & ptr, size_t & len);
+
void *
toPointer(trace::Value &value, bool bind = false);
@@ -120,11 +131,10 @@ toObjPointer(trace::Call &call, trace::Value &value);
template< class T >
inline T *
asObjPointer(trace::Call &call, trace::Value &value) {
- return reinterpret_cast<T *>(toObjPointer(call, value));
+ return static_cast<T *>(toObjPointer(call, value));
}
} /* namespace retrace */
-#endif /* _RETRACE_SWIZZLE_HPP_ */
diff --git a/retrace/scoped_allocator.hpp b/retrace/scoped_allocator.hpp
index 3dbf059e..b0066f58 100644
--- a/retrace/scoped_allocator.hpp
+++ b/retrace/scoped_allocator.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _SCOPED_ALLOCATOR_HPP_
-#define _SCOPED_ALLOCATOR_HPP_
+#pragma once
#include <assert.h>
@@ -63,10 +62,11 @@ public:
return static_cast<void *>(&buf[1]);
}
+ /* XXX: See comment in retrace::ScopedAllocator::allocArray template. */
template< class T >
inline T *
- alloc(size_t size = 1) {
- return static_cast<T *>(alloc(sizeof(T) * size));
+ alloc(size_t size = 1, size_t sizeof_T = sizeof(T)) {
+ return static_cast<T *>(alloc(sizeof_T * size));
}
/**
@@ -98,4 +98,3 @@ public:
};
-#endif /* _SCOPED_ALLOCATOR_HPP_ */
diff --git a/retrace/state_writer.cpp b/retrace/state_writer.cpp
new file mode 100644
index 00000000..7e491c6c
--- /dev/null
+++ b/retrace/state_writer.cpp
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "state_writer.hpp"
+
+#include <assert.h>
+
+#include <sstream>
+
+#include "image.hpp"
+
+
+StateWriter::~StateWriter()
+{
+}
+
+
+void
+StateWriter::writeImage(image::Image *image,
+ const ImageDesc & desc)
+{
+ assert(image);
+ if (!image) {
+ writeNull();
+ return;
+ }
+
+ beginObject();
+
+ // Tell the GUI this is no ordinary object, but an image
+ writeStringMember("__class__", "image");
+
+ writeIntMember("__width__", image->width);
+ writeIntMember("__height__", image->height / desc.depth);
+ writeIntMember("__depth__", desc.depth);
+
+ writeStringMember("__format__", desc.format.c_str());
+
+ if (!image->label.empty()) {
+ writeStringMember("__label__", image->label.c_str());
+ }
+
+ beginMember("__data__");
+ std::stringstream ss;
+
+ if (image->channelType == image::TYPE_UNORM8) {
+ image->writePNG(ss);
+ } else {
+ image->writePNM(ss);
+ }
+
+ const std::string & s = ss.str();
+ writeBlob(s.data(), s.size());
+ endMember(); // __data__
+
+ endObject();
+}
diff --git a/retrace/state_writer.hpp b/retrace/state_writer.hpp
new file mode 100644
index 00000000..440fca4f
--- /dev/null
+++ b/retrace/state_writer.hpp
@@ -0,0 +1,182 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+
+#include <stddef.h>
+#include <wchar.h>
+
+#include <ostream>
+#include <type_traits>
+#include <string>
+
+
+namespace image {
+ class Image;
+}
+
+
+/*
+ * Abstract base class for writing state.
+ */
+class StateWriter
+{
+public:
+ virtual ~StateWriter();
+
+ virtual void
+ beginObject(void) = 0;
+
+ virtual void
+ endObject(void) = 0;
+
+ virtual void
+ beginMember(const char * name) = 0;
+
+ inline void
+ beginMember(const std::string &name) {
+ beginMember(name.c_str());
+ }
+
+ virtual void
+ endMember(void) = 0;
+
+ virtual void
+ beginArray(void) = 0;
+
+ virtual void
+ endArray(void) = 0;
+
+ virtual void
+ writeString(const char *) = 0;
+
+ inline void
+ writeString(const std::string &s) {
+ writeString(s.c_str());
+ }
+
+ virtual void
+ writeBlob(const void *bytes, size_t size) = 0;
+
+ virtual void
+ writeNull(void) = 0;
+
+ virtual void
+ writeBool(bool) = 0;
+
+ // FIXME: always using long long is inneficient,
+ // but providing overloaded methods for different size types requires extreme care to avoid ambigiuity
+
+ virtual void
+ writeSInt(signed long long) = 0;
+
+ virtual void
+ writeUInt(unsigned long long) = 0;
+
+ template<typename T>
+ inline void
+ writeInt(T i, typename std::enable_if<std::is_signed<T>::value>::type* = 0) {
+ writeSInt(i);
+ }
+
+ template<typename T>
+ inline void
+ writeInt(T u, typename std::enable_if<std::is_unsigned<T>::value>::type* = 0) {
+ writeUInt(u);
+ }
+
+ template<typename T>
+ inline void
+ writeInt(T e, typename std::enable_if<std::is_enum<T>::value>::type* = 0) {
+ writeSInt(static_cast<signed long long>(e));
+ }
+
+ virtual void
+ writeFloat(float) = 0;
+
+ virtual void
+ writeFloat(double) = 0;
+
+ inline void
+ writeStringMember(const char *name, const char *s) {
+ beginMember(name);
+ writeString(s);
+ endMember();
+ }
+
+ inline void
+ writeBoolMember(const char *name, bool b) {
+ beginMember(name);
+ writeBool(b);
+ endMember();
+ }
+
+ template<typename T>
+ inline void
+ writeFloatMember(const char *name, T f) {
+ beginMember(name);
+ writeFloat(f);
+ endMember();
+ }
+
+ template<typename T>
+ inline void
+ writeIntMember(const char *name, T n) {
+ beginMember(name);
+ writeInt(n);
+ endMember();
+ }
+
+ struct ImageDesc {
+ unsigned depth;
+ std::string format;
+
+ ImageDesc() :
+ depth(1),
+ format("UNKNOWN")
+ {}
+ };
+
+ void
+ writeImage(image::Image *image, const ImageDesc & desc);
+
+ inline void
+ writeImage(image::Image *image) {
+ ImageDesc desc;
+ writeImage(image, desc);
+ }
+
+};
+
+
+StateWriter *
+createJSONStateWriter(std::ostream &os);
+
+
+StateWriter *
+createUBJSONStateWriter(std::ostream &os);
diff --git a/retrace/state_writer_json.cpp b/retrace/state_writer_json.cpp
new file mode 100644
index 00000000..4a10f055
--- /dev/null
+++ b/retrace/state_writer_json.cpp
@@ -0,0 +1,126 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "state_writer.hpp"
+
+#include "json.hpp"
+
+
+namespace {
+
+
+class JSONStateWriter : public StateWriter
+{
+private:
+ JSONWriter json;
+
+public:
+ JSONStateWriter(std::ostream &os) :
+ json(os)
+ {
+ }
+
+ void
+ beginObject(void) {
+ json.beginObject();
+ }
+
+ void
+ endObject(void) {
+ json.endObject();
+ }
+
+ void
+ beginMember(const char * name) {
+ json.beginMember(name);
+ }
+
+ void
+ endMember(void) {
+ json.endMember();
+ }
+
+ void
+ beginArray(void) {
+ json.beginArray();
+ }
+
+ void
+ endArray(void) {
+ json.endArray();
+ }
+
+ void
+ writeString(const char *s) {
+ json.writeString(s);
+ }
+
+ void
+ writeBlob(const void *bytes, size_t size) {
+ json.writeBase64(bytes, size);
+ }
+
+ void
+ writeNull(void) {
+ json.writeNull();
+ }
+
+ void
+ writeBool(bool b) {
+ json.writeBool(b);
+ }
+
+ void
+ writeSInt(signed long long i) {
+ json.writeInt(i);
+ }
+
+ void
+ writeUInt(unsigned long long u) {
+ json.writeInt(u);
+ }
+
+ void
+ writeFloat(float f) {
+ json.writeFloat(f);
+ }
+
+ void
+ writeFloat(double f) {
+ json.writeFloat(f);
+ }
+};
+
+
+}
+
+
+StateWriter *
+createJSONStateWriter(std::ostream &os)
+{
+ return new JSONStateWriter(os);
+}
diff --git a/retrace/state_writer_ubjson.cpp b/retrace/state_writer_ubjson.cpp
new file mode 100644
index 00000000..00871dd7
--- /dev/null
+++ b/retrace/state_writer_ubjson.cpp
@@ -0,0 +1,220 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "state_writer.hpp"
+
+#include <string.h>
+#include <stdint.h>
+
+#include "ubjson.hpp"
+
+
+namespace {
+
+
+using namespace ubjson;
+
+
+class UBJSONStateWriter : public StateWriter
+{
+private:
+ std::ostream &os;
+
+public:
+ UBJSONStateWriter(std::ostream &_os) :
+ os(_os)
+ {
+ beginObject();
+ }
+
+ ~UBJSONStateWriter()
+ {
+ endObject();
+ }
+
+ void
+ beginObject(void) {
+ os.put(MARKER_OBJECT_BEGIN);
+ }
+
+ void
+ endObject(void) {
+ os.put(MARKER_OBJECT_END);
+ }
+
+ inline void
+ _writeString(const char *s, size_t len) {
+ writeUInt(len);
+ // TODO: convert string from locale encoding to UTF-8
+ for (size_t i = 0; i < len; ++i) {
+ char c = s[i];
+ os.put((signed char)c >= 0 ? c : '?');
+ }
+ }
+
+ void
+ _writeString(const char *s) {
+ }
+
+ void
+ beginMember(const char * name) {
+ size_t len = strlen(name);
+ _writeString(name, len);
+ }
+
+ void
+ endMember(void) {
+ }
+
+ void
+ beginArray(void) {
+ os.put(MARKER_ARRAY_BEGIN);
+ }
+
+ void
+ endArray(void) {
+ os.put(MARKER_ARRAY_END);
+ }
+
+ void
+ writeString(const char *s) {
+ size_t len = strlen(s);
+ if (len == 1 && (signed char)s[0] >= 0) {
+ os.put(MARKER_CHAR);
+ os.put(s[0]);
+ return;
+ }
+ os.put(MARKER_STRING);
+ _writeString(s, len);
+ }
+
+ void
+ writeBlob(const void *bytes, size_t size) {
+ // Encode as a strongly-typed array of uint8 values
+ // http://ubjson.org/type-reference/binary-data/
+ // http://ubjson.org/type-reference/container-types/#optimized-format
+ beginArray();
+ os.put(MARKER_TYPE);
+ os.put(MARKER_UINT8);
+ os.put(MARKER_COUNT);
+ writeUInt(size);
+ os.write((const char *)bytes, size);
+ }
+
+ void
+ writeNull(void) {
+ os.put(MARKER_NULL);
+ }
+
+ void
+ writeBool(bool b) {
+ os.put(b ? MARKER_TRUE : MARKER_FALSE);
+ }
+
+ void
+ writeSInt(signed long long i) {
+ if (INT8_MIN <= i && i <= INT8_MAX) {
+ os.put(MARKER_INT8);
+ os.put((char)i);
+ return;
+ }
+ if (0 <= i && i <= UINT8_MAX) {
+ os.put(MARKER_UINT8);
+ os.put((char)i);
+ return;
+ }
+ if (INT16_MIN <= i && i <= INT16_MAX) {
+ os.put(MARKER_INT16);
+ uint16_t u16 = bigEndian16((int16_t)i);
+ os.write((const char *)&u16, sizeof u16);
+ return;
+ }
+ if (INT32_MIN <= i && i <= INT32_MAX) {
+ os.put(MARKER_INT32);
+ uint32_t u32 = bigEndian32((int32_t)i);
+ os.write((const char *)&u32, sizeof u32);
+ return;
+ }
+ os.put(MARKER_INT64);
+ uint64_t u64 = bigEndian64(i);
+ os.write((const char *)&u64, sizeof u64);
+ }
+
+ void
+ writeUInt(unsigned long long u) {
+ if (u <= UINT8_MAX) {
+ os.put(MARKER_UINT8);
+ uint8_t u8 = u;
+ os.put(u8);
+ return;
+ }
+ if (u <= INT16_MAX) {
+ os.put(MARKER_INT16);
+ uint16_t u16 = bigEndian16(u);
+ os.write((const char *)&u16, sizeof u16);
+ return;
+ }
+ if (u <= INT32_MAX) {
+ os.put(MARKER_INT32);
+ uint32_t u32 = bigEndian32(u);
+ os.write((const char *)&u32, sizeof u32);
+ return;
+ }
+ os.put(MARKER_INT64);
+ u = bigEndian64(u);
+ // XXX: We should fall back to high-precision when INT64_MAX < u <= UINT64_MAX?
+ os.write((const char *)&u, sizeof u);
+ }
+
+ void
+ writeFloat(float f) {
+ os.put(MARKER_FLOAT32);
+ Float32 u;
+ u.f = f;
+ u.i = bigEndian32(u.i);
+ os.write((const char *)&u.i, sizeof u.i);
+ }
+
+ void
+ writeFloat(double f) {
+ os.put(MARKER_FLOAT64);
+ Float64 u;
+ u.f = f;
+ u.i = bigEndian64(u.i);
+ os.write((const char *)&u.i, sizeof u.i);
+ }
+};
+
+
+}
+
+
+StateWriter *
+createUBJSONStateWriter(std::ostream &os)
+{
+ return new UBJSONStateWriter(os);
+}
diff --git a/retrace/ws.cpp b/retrace/ws.cpp
new file mode 100644
index 00000000..4b9aa246
--- /dev/null
+++ b/retrace/ws.cpp
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "ws.hpp"
+
+
+namespace ws {
+
+
+bool
+headless = false;
+
+
+} // namespace ws
+
diff --git a/retrace/ws.hpp b/retrace/ws.hpp
new file mode 100644
index 00000000..d2c367dd
--- /dev/null
+++ b/retrace/ws.hpp
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+
+namespace ws {
+
+
+extern bool
+headless;
+
+
+} // namespace ws
diff --git a/retrace/ws_win32.cpp b/retrace/ws_win32.cpp
new file mode 100644
index 00000000..819a129c
--- /dev/null
+++ b/retrace/ws_win32.cpp
@@ -0,0 +1,234 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "ws_win32.hpp"
+
+#include <assert.h>
+#include <process.h>
+
+#include "ws.hpp"
+
+
+namespace ws {
+
+
+static LRESULT CALLBACK
+WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ MINMAXINFO *pMMI;
+ switch (uMsg) {
+ case WM_KEYDOWN:
+ switch (wParam) {
+ case VK_ESCAPE:
+ PostMessage(hWnd, WM_CLOSE, 0, 0);
+ break;
+ }
+ break;
+ case WM_GETMINMAXINFO:
+ // Allow to create a window bigger than the desktop
+ pMMI = (MINMAXINFO *)lParam;
+ pMMI->ptMaxSize.x = 60000;
+ pMMI->ptMaxSize.y = 60000;
+ pMMI->ptMaxTrackSize.x = 60000;
+ pMMI->ptMaxTrackSize.y = 60000;
+ break;
+ case WM_CLOSE:
+ exit(0);
+ break;
+ default:
+ break;
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+static const DWORD dwExStyle = 0;
+static const DWORD dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
+
+static LPCSTR g_lpszClassName = "retrace";
+
+
+struct WindowThreadParam
+{
+ LPCSTR lpszWindowName;
+ int nWidth;
+ int nHeight;
+
+ HANDLE hEvent;
+
+ HWND hWnd;
+};
+
+
+static unsigned __stdcall
+windowThreadFunction( LPVOID _lpParam )
+{
+ WindowThreadParam *lpParam = (WindowThreadParam *)_lpParam;
+
+ // Actually create the window
+ lpParam->hWnd = CreateWindowExA(dwExStyle,
+ g_lpszClassName,
+ lpParam->lpszWindowName,
+ dwStyle,
+ 0, // x
+ 0, // y
+ lpParam->nWidth,
+ lpParam->nHeight,
+ NULL, // hWndParent
+ NULL, // hMenu
+ NULL, // hInstance
+ NULL); // lpParam
+
+ // Notify parent thread that window has been created
+ SetEvent(lpParam->hEvent);
+
+ BOOL bRet;
+ MSG msg;
+ while ((bRet = GetMessage(&msg, NULL, 0, 0 )) != FALSE) {
+ if (bRet == -1) {
+ // handle the error and possibly exit
+ } else {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ // Return the exit code
+ return msg.wParam;
+}
+
+
+/**
+ * Create a window on a separate thread.
+ *
+ * Each window is associated with one thread, which must process its events,
+ * and certain operations like SetWindowPos will block until the message is
+ * process, so the only way to guarantee that the window messages are processed
+ * timely is by dedicating a thread to processing window events.
+ *
+ * TODO: Handle multiple windows on a single thread, instead of creating one
+ * thread per each window.
+ */
+HWND
+createWindow(LPCSTR lpszWindowName, int nWidth, int nHeight)
+{
+ // Create window class
+ static bool first = TRUE;
+ if (first) {
+ WNDCLASS wc;
+ ZeroMemory(&wc, sizeof wc);
+ wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.lpfnWndProc = WndProc;
+ wc.lpszClassName = g_lpszClassName;
+ wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+ RegisterClass(&wc);
+ first = FALSE;
+ }
+
+ RECT rect;
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = nWidth;
+ rect.bottom = nHeight;
+ AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
+
+ // Spawn window thread
+ WindowThreadParam param;
+ param.lpszWindowName = lpszWindowName;
+ param.nWidth = rect.right - rect.left;
+ param.nHeight = rect.bottom - rect.top;
+ param.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ _beginthreadex(NULL, 0, &windowThreadFunction, (LPVOID)&param, 0, NULL);
+
+ // Wait for window creation event
+ WaitForSingleObject(param.hEvent, INFINITE);
+ CloseHandle(param.hEvent);
+
+ RECT rClient;
+ GetClientRect(param.hWnd, &rClient);
+ assert(rClient.right - rClient.left >= nWidth);
+ assert(rClient.bottom - rClient.top >= nHeight);
+
+ return param.hWnd;
+}
+
+
+void
+showWindow(HWND hWnd)
+{
+ if (!headless) {
+ ShowWindow(hWnd, SW_SHOW);
+ }
+}
+
+
+void
+resizeWindow(HWND hWnd, int width, int height)
+{
+ RECT rClient;
+ GetClientRect(hWnd, &rClient);
+ if (width == rClient.right - rClient.left &&
+ height == rClient.bottom - rClient.top) {
+ return;
+ }
+
+ RECT rWindow;
+ GetWindowRect(hWnd, &rWindow);
+ width += (rWindow.right - rWindow.left) - rClient.right;
+ height += (rWindow.bottom - rWindow.top) - rClient.bottom;
+
+ UINT uFlags = SWP_NOMOVE
+ | SWP_NOZORDER
+ | SWP_NOACTIVATE
+ | SWP_NOOWNERZORDER;
+
+ SetWindowPos(hWnd, NULL, rWindow.left, rWindow.top, width, height, uFlags);
+}
+
+
+bool
+processEvents(void)
+{
+ MSG uMsg;
+ while (PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE)) {
+ if (uMsg.message == WM_QUIT) {
+ return false;
+ }
+
+ if (!TranslateAccelerator(uMsg.hwnd, NULL, &uMsg)) {
+ TranslateMessage(&uMsg);
+ DispatchMessage(&uMsg);
+ }
+ }
+ return true;
+}
+
+
+} // namespace ws
+
diff --git a/retrace/ws_win32.hpp b/retrace/ws_win32.hpp
new file mode 100644
index 00000000..1b71a0e7
--- /dev/null
+++ b/retrace/ws_win32.hpp
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#pragma once
+
+
+#include <windows.h>
+
+
+namespace ws {
+
+
+HWND
+createWindow(LPCSTR lpszWindowName, int nWidth, int nHeight);
+
+void
+showWindow(HWND hWnd);
+
+void
+resizeWindow(HWND hWnd, int width, int height);
+
+bool
+processEvents(void);
+
+
+} // namespace ws
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
new file mode 100644
index 00000000..11384a44
--- /dev/null
+++ b/scripts/CMakeLists.txt
@@ -0,0 +1,10 @@
+file (GLOB SCRIPTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.py)
+
+install (
+ PROGRAMS ${SCRIPTS}
+ DESTINATION ${SCRIPTS_INSTALL_DIR}
+)
+install (
+ FILES apitrace.PIXExp
+ DESTINATION ${SCRIPTS_INSTALL_DIR}
+)
diff --git a/scripts/convert.py b/scripts/convert.py
index 3dacd72c..5f338d80 100755
--- a/scripts/convert.py
+++ b/scripts/convert.py
@@ -35,6 +35,27 @@ import platform
import sys
+def callProcess(cmd):
+ if options.verbose:
+ sys.stderr.write(' '.join(cmd) + '\n')
+ ret = subprocess.call(cmd)
+ if ret:
+ exeName = os.path.basename(cmd[0])
+ sys.stderr.write('error: %s failed with exit code %u\n' % (exeName, ret))
+ sys.exit(ret)
+ return ret
+
+
+def verifyTrace(outTrace):
+ if os.path.exists(outTrace):
+ sys.stderr.write('info: %s written\n' % outTrace)
+ if options.verify:
+ callProcess([options.retrace, os.path.abspath(outTrace)])
+ else:
+ sys.stderr.write('error: %s not written\n' % outTrace)
+ sys.exit(1)
+
+
def getPixExe():
try:
programFiles = os.environ['ProgramFiles(x86)']
@@ -48,19 +69,8 @@ def getPixExe():
return pixExe
-def callProcess(cmd):
- if options.verbose:
- sys.stderr.write(' '.join(cmd) + '\n')
- ret = subprocess.call(cmd)
- if ret:
- exeName = os.path.basename(cmd[0])
- sys.stderr.write('error: %s failed with exit code %u\n' % (exeName, ret))
- sys.exit(ret)
- return ret
-
-
def convertToPix(inTrace, outPixrun):
- pix = getPixExe()
+ pixExe = getPixExe()
pixExp = os.path.join(os.path.dirname(__file__), 'apitrace.PIXExp')
@@ -80,44 +90,130 @@ def convertToPix(inTrace, outPixrun):
if os.path.exists(outPixrun):
sys.stderr.write('info: %s written\n' % outPixrun)
if options.verify:
- subprocess.call([pix, os.path.abspath(outPixrun)])
+ subprocess.call([pixExe, os.path.abspath(outPixrun)])
else:
sys.stderr.write('error: %s not written\n' % outPixrun)
sys.exit(1)
+def detectApiFromCsv(inCsv):
+ import csv
+ csvReader = csv.reader(open(inCsv, 'rt'), )
+ for row in csvReader:
+ print row
+ event = row[2]
+ print event
+ if event.startswith("Direct3DCreate9"):
+ return "d3d9"
+ if event.startswith("CreateDXGIFactory"):
+ return "dxgi"
+ if event.startswith("D3D10CreateDevice"):
+ return "d3d10"
+ if event.startswith("D3D11CreateDevice"):
+ return "d3d11"
+ assert False
+
+
def convertFromPix(inPix, outTrace):
pixExe = getPixExe()
- if False:
- # TODO: Use -exporttocsv option to detect which API to use
+ api = options.api
+
+ if True:
+ # Use -exporttocsv option to detect which API to use
cmd = [
pixExe,
inPix,
- '-exporttocsv', # XXX: output filename is ignored
+ '-exporttocsv',
]
+
+ # XXX: output filename is ignored
+ inPixDir, inPixFileName = os.path.split(inPix)
+ inPixName, inPixExt = os.path.splitext(inPixFileName)
+ outCsv = os.path.join(inPixDir, inPixName + '.csv')
+
+ if os.path.exists(outCsv):
+ os.remove(outCsv)
+
callProcess(cmd)
+ if os.path.isfile(outCsv):
+ api = detectApiFromCsv(outCsv)
+
cmd = [
options.apitrace,
'trace',
- '-a', options.api,
+ '-a', api,
'-o', outTrace,
pixExe,
inPix,
- '-playstandalone',
]
+
+ # XXX: Autodetect somehow
+ if not options.single_frame:
+ # Full capture
+ cmd += ['-playstandalone']
+ else:
+ # Single-frame capture
+ cmd += ['-autorenderto', 'nul:']
callProcess(cmd)
- if os.path.exists(outTrace):
- sys.stderr.write('info: %s written\n' % outTrace)
+ verifyTrace(outTrace)
+
+
+def getDxcapExe():
+ winDir = os.environ['windir']
+ if 'ProgramFiles(x86)' in os.environ:
+ sysSubDir = 'SysWOW64'
+ else:
+ sysSubDir = 'System32'
+ dxcapExe = os.path.join(winDir, sysSubDir, 'dxcap.exe')
+ return dxcapExe
+
+
+def convertToDxcap(inTrace, outDxcaprun):
+ # https://msdn.microsoft.com/en-us/library/vstudio/dn774939.aspx
+
+ dxcapExe = getDxcapExe()
+
+ cmd = [
+ getDxcapExe(),
+ '-rawmode',
+ '-file', os.path.abspath(outDxcaprun),
+ '-c',
+ options.retrace,
+ '-b',
+ os.path.abspath(inTrace),
+ ]
+
+ callProcess(cmd)
+ if os.path.exists(outDxcaprun):
+ sys.stderr.write('info: %s written\n' % outDxcaprun)
if options.verify:
- subprocess.call([options.retrace, os.path.abspath(outTrace)])
+ callProcess([dxcapExe, '-p', os.path.abspath(outDxcaprun)])
else:
- sys.stderr.write('error: %s not written\n' % outTrace)
+ sys.stderr.write('error: %s not written\n' % outDxcaprun)
sys.exit(1)
+def convertFromDxcap(inDxcap, outTrace):
+ dxcapExe = getDxcapExe()
+
+ cmd = [
+ options.apitrace,
+ 'trace',
+ '-a', options.api,
+ '-o', outTrace,
+ '--',
+ dxcapExe,
+ '-rawmode',
+ '-p', inDxcap,
+ ]
+
+ callProcess(cmd)
+ verifyTrace(outTrace)
+
+
def main():
global options
@@ -131,7 +227,7 @@ def main():
help='path to apitrace command [default: %default]')
optparser.add_option(
'-a', '--api', metavar='API',
- type='string', dest='api', default='d3d9',
+ type='string', dest='api', default='dxgi',
help='api [default: %default]')
optparser.add_option(
'-r', '--retrace', metavar='PROGRAM',
@@ -146,6 +242,10 @@ def main():
type="string", dest="output",
help="output file [default: stdout]")
optparser.add_option(
+ '--single-frame',
+ action='store_true', dest='single_frame', default=False,
+ help='single-frame PIXRun capture')
+ optparser.add_option(
'--verify',
action='store_true', dest='verify', default=False,
help='verify output by replaying it')
@@ -156,10 +256,16 @@ def main():
for inFile in args:
name, inExt = os.path.splitext(os.path.basename(inFile))
- inExt = inExt
if inExt.lower() == '.trace':
- convert = convertToPix
- outExt = '.PIXRun'
+ convert = convertToDxcap
+ outExt = '.vsglog'
+ if options.output:
+ _, outExt = os.path.splitext(options.output)
+ if outExt.lower() == '.pixrun':
+ convert = convertToPix
+ elif inExt.lower() == '.vsglog':
+ convert = convertFromDxcap
+ outExt = '.trace'
elif inExt.lower() == '.pixrun':
convert = convertFromPix
outExt = '.trace'
@@ -169,6 +275,9 @@ def main():
outFile = options.output
else:
outFile = name + outExt
+
+ if os.path.exists(outFile):
+ os.remove(outFile)
convert(inFile, outFile)
diff --git a/scripts/jsondiff.py b/scripts/jsondiff.py
index bd45fdba..3b1f9110 100755
--- a/scripts/jsondiff.py
+++ b/scripts/jsondiff.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
##########################################################################
#
+# Copyright 2015 VMware, Inc.
# Copyright 2011 Jose Fonseca
# All Rights Reserved.
#
@@ -28,6 +29,7 @@
import json
import optparse
import re
+import difflib
import sys
@@ -131,7 +133,7 @@ class Dumper(Visitor):
self._write(']')
def visitValue(self, node):
- self._write(json.dumps(node))
+ self._write(json.dumps(node, allow_nan=True))
@@ -175,7 +177,12 @@ class Comparer(Visitor):
def visitValue(self, a, b):
if isinstance(a, float) and isinstance(b, (int, long, float)) or \
isinstance(b, float) and isinstance(a, (int, long, float)):
- if a == 0:
+ if a is b:
+ # NaNs take this path
+ return True
+ elif a == b:
+ return True
+ elif a == 0:
return abs(b) < self.tolerance
else:
return abs((b - a)/a) < self.tolerance
@@ -247,10 +254,38 @@ class Differ(Visitor):
self.replace(a, b)
def replace(self, a, b):
+ if self.isMultilineString(a) or self.isMultilineString(b):
+ a = str(a)
+ b = str(b)
+ a = a.splitlines()
+ b = b.splitlines()
+ differ = difflib.Differ()
+ result = differ.compare(a, b)
+ self.dumper.level += 1
+ for entry in result:
+ self.dumper._newline()
+ self.dumper._indent()
+ tag = entry[:2]
+ text = entry[2:]
+ if tag == '? ':
+ tag = ' '
+ prefix = ' '
+ text = text.rstrip()
+ suffix = ''
+ else:
+ prefix = '"'
+ suffix = '\\n"'
+ line = tag + prefix + text + suffix
+ self.dumper._write(line)
+ self.dumper.level -= 1
+ return
self.dumper.visit(a)
self.dumper._write(' -> ')
self.dumper.visit(b)
+ def isMultilineString(self, value):
+ return isinstance(value, basestring) and '\n' in value
+
#
# Unfortunately JSON standard does not include comments, but this is a quite
@@ -301,6 +336,10 @@ def main():
optparser = optparse.OptionParser(
usage="\n\t%prog [options] <ref_json> <src_json>")
optparser.add_option(
+ '--ignore-added',
+ action="store_true", dest="ignore_added", default=False,
+ help="ignore added state")
+ optparser.add_option(
'--keep-images',
action="store_false", dest="strip_images", default=True,
help="compare images")
@@ -310,14 +349,14 @@ def main():
if len(args) != 2:
optparser.error('incorrect number of arguments')
- a = load(open(sys.argv[1], 'rt'), options.strip_images)
- b = load(open(sys.argv[2], 'rt'), options.strip_images)
+ a = load(open(args[0], 'rt'), options.strip_images)
+ b = load(open(args[1], 'rt'), options.strip_images)
if False:
dumper = Dumper()
dumper.visit(a)
- differ = Differ()
+ differ = Differ(ignore_added = options.ignore_added)
differ.visit(a, b)
diff --git a/scripts/jsonextractimages.py b/scripts/jsonextractimages.py
index c47ffc8c..ea1c927d 100755
--- a/scripts/jsonextractimages.py
+++ b/scripts/jsonextractimages.py
@@ -34,12 +34,31 @@ import base64
import sys
+pngSignature = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"
+
+
def dumpSurfaces(state, memberName):
for name, imageObj in state[memberName].iteritems():
data = imageObj['__data__']
data = base64.b64decode(data)
- imageName = '%s.png' % name
+ if data.startswith(pngSignature):
+ extName = 'png'
+ else:
+ magic = data[:2]
+ if magic in ('P1', 'P4'):
+ extName = 'pbm'
+ elif magic in ('P2', 'P5'):
+ extName = 'pgm'
+ elif magic in ('P3', 'P6'):
+ extName = 'ppm'
+ elif magic in ('Pf', 'PF'):
+ extName = 'pfm'
+ else:
+ sys.stderr.write('warning: unsupport Netpbm format %s\n' % magic)
+ continue
+
+ imageName = '%s.%s' % (name, extName)
open(imageName, 'wb').write(data)
sys.stderr.write('Wrote %s\n' % imageName)
diff --git a/scripts/leaks.py b/scripts/leaks.py
new file mode 100755
index 00000000..68dcd944
--- /dev/null
+++ b/scripts/leaks.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2014-2016 VMware, Inc.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+##########################################################################/
+
+
+import subprocess
+import sys
+import os.path
+import optparse
+import re
+
+import unpickle
+
+
+class LeakDetector(unpickle.Unpickler):
+
+ def __init__(self, apitrace, trace):
+
+ cmd = [apitrace, 'pickle', '--symbolic', trace]
+ p = subprocess.Popen(args = cmd, stdout = subprocess.PIPE)
+
+ unpickle.Unpickler.__init__(self, p.stdout)
+
+ self.numContexts = 0
+
+ # a map of maps
+ self.objectDicts = {}
+
+ def parse(self):
+ unpickle.Unpickler.parse(self)
+
+ # Reached the end of the trace -- dump any live objects
+ self.dumpLeaks("<EOF>")
+
+ genDelRegExp = re.compile('^gl(Gen|Delete)(Buffers|Textures|FrameBuffers|RenderBuffers)[A-Z]*$')
+
+ def handleCall(self, call):
+ # Ignore calls without side effects
+ if call.flags & unpickle.CALL_FLAG_NO_SIDE_EFFECTS:
+ return
+
+ # Dump call for debugging:
+ if 0:
+ sys.stderr.write('%s\n' % call)
+
+ mo = self.genDelRegExp.match(call.functionName)
+ if mo:
+ verb = mo.group(1)
+ subject = mo.group(2)
+
+ subject = subject.lower().rstrip('s')
+ objectDict = self.objectDicts.setdefault(subject, {})
+
+ if verb == 'Gen':
+ self.handleGenerate(call, objectDict)
+ elif verb == 'Delete':
+ self.handleDelete(call, objectDict)
+ else:
+ assert 0
+
+ # TODO: Track labels via glObjectLabel* calls
+
+ if call.functionName in [
+ 'CGLCreateContext',
+ 'eglCreateContext',
+ 'glXCreateContext',
+ 'glXCreateContextAttribsARB',
+ 'glXCreateContextWithConfigSGIX',
+ 'wglCreateContext',
+ 'wglCreateContextAttribsARB',
+ ]:
+ # FIXME: Ignore failing context creation calls
+ self.numContexts += 1
+
+ if call.functionName in [
+ 'CGLDestroyContext',
+ 'glXDestroyContext',
+ 'eglDestroyContext',
+ 'wglDeleteContext',
+ ]:
+ assert self.numContexts > 0
+ self.numContexts -= 1
+ if self.numContexts == 0:
+ self.dumpLeaks(call.no)
+
+ def handleGenerate(self, call, objectDict):
+ n, names = call.argValues()
+ for i in range(n):
+ name = names[i]
+ objectDict[name] = call.no
+ # TODO: Keep track of call stack backtrace too
+
+ def handleDelete(self, call, objectDict):
+ n, names = call.argValues()
+ for i in range(n):
+ name = names[i]
+ try:
+ del objectDict[name]
+ except KeyError:
+ # Ignore if texture name was never generated
+ pass
+
+ def dumpLeaks(self, currentCallNo):
+ for kind, objectDict in self.objectDicts.iteritems():
+ self.dumpNamespaceLeaks(currentCallNo, objectDict, kind)
+
+ def dumpNamespaceLeaks(self, currentCallNo, objectDict, kind):
+ for name, creationCallNo in (sorted(objectDict.iteritems(),key=lambda t: t[1])):
+ sys.stderr.write('%u: error: %s %u was not destroyed until %s\n' % (creationCallNo, kind, name, currentCallNo))
+ objectDict.clear()
+
+
+def main():
+ '''Main program.
+ '''
+
+ # Parse command line options
+ optparser = optparse.OptionParser(
+ usage='\n\t%prog [options] TRACE',
+ version='%%prog')
+ optparser.add_option(
+ '-a', '--apitrace', metavar='PROGRAM',
+ type='string', dest='apitrace', default='apitrace',
+ help='apitrace command [default: %default]')
+
+ options, args = optparser.parse_args(sys.argv[1:])
+ if len(args) != 1:
+ optparser.error("incorrect number of arguments")
+
+ inTrace = args[0]
+ if not os.path.isfile(inTrace):
+ sys.stderr.write("error: `%s` does not exist\n" % inTrace)
+ sys.exit(1)
+
+ detector = LeakDetector(options.apitrace, inTrace)
+ detector.parse()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/retracediff.py b/scripts/retracediff.py
index e1958126..bb5aa7f5 100755
--- a/scripts/retracediff.py
+++ b/scripts/retracediff.py
@@ -350,6 +350,7 @@ def main():
height, width, channels = diffImage.shape
square_error = numpy.sum(diffImage)
+ square_error += numpy.finfo(numpy.float32).eps
rel_error = square_error / float(height*width*channels)
bits = -math.log(rel_error)/math.log(2.0)
precision = bits
diff --git a/scripts/tracediff.py b/scripts/tracediff.py
index 22a26265..f111322a 100755
--- a/scripts/tracediff.py
+++ b/scripts/tracediff.py
@@ -48,10 +48,10 @@ class Differ:
self.apitrace = apitrace
self.isatty = sys.stdout.isatty()
- def setRefTrace(self, ref_trace, ref_calls):
+ def setRefTrace(self, refTrace, ref_calls):
raise NotImplementedError
- def setSrcTrace(self, src_trace, src_calls):
+ def setSrcTrace(self, srcTrace, src_calls):
raise NotImplementedError
def diff(self):
@@ -99,25 +99,41 @@ class ExternalDiffer(Differ):
start_insert = '\33[32m'
end_insert = '\33[0m'
- def __init__(self, apitrace, tool, width=None, callNos = False):
+ def __init__(self, apitrace, options):
Differ.__init__(self, apitrace)
+ tool = options.tool
+ callNos = options.callNos
+
self.diff_args = [tool]
if tool == 'diff':
self.diff_args += [
'--speed-large-files',
]
if self.isatty:
+ if options.suppressCommonLines:
+ self.diff_args += ['--unchanged-line-format=']
+ else:
+ self.diff_args += ['--unchanged-line-format=%l\n']
self.diff_args += [
'--old-line-format=' + self.start_delete + '%l' + self.end_delete + '\n',
'--new-line-format=' + self.start_insert + '%l' + self.end_insert + '\n',
]
+ else:
+ if options.suppressCommonLines:
+ self.diff_args += ['--unchanged-line-format=']
+ else:
+ self.diff_args += ['--unchanged-line-format= %l\n']
+ self.diff_args += [
+ '--old-line-format=- %l\n',
+ '--new-line-format=+ %l\n',
+ ]
elif tool == 'sdiff':
- if width is None:
+ if options.width is None:
import curses
curses.setupterm()
- width = curses.tigetnum('cols')
+ options.width = curses.tigetnum('cols')
self.diff_args += [
- '--width=%u' % width,
+ '--width=%u' % options.width,
'--speed-large-files',
]
elif tool == 'wdiff':
@@ -136,11 +152,11 @@ class ExternalDiffer(Differ):
assert False
self.callNos = callNos
- def setRefTrace(self, ref_trace, ref_calls):
- self.ref_dumper = AsciiDumper(self.apitrace, ref_trace, ref_calls, self.callNos)
+ def setRefTrace(self, refTrace, ref_calls):
+ self.ref_dumper = AsciiDumper(self.apitrace, refTrace, ref_calls, self.callNos)
- def setSrcTrace(self, src_trace, src_calls):
- self.src_dumper = AsciiDumper(self.apitrace, src_trace, src_calls, self.callNos)
+ def setSrcTrace(self, srcTrace, src_calls):
+ self.src_dumper = AsciiDumper(self.apitrace, srcTrace, src_calls, self.callNos)
def diff(self):
diff_args = self.diff_args + [
@@ -240,7 +256,7 @@ class Loader(Unpickler):
class PythonDiffer(Differ):
- def __init__(self, apitrace, callNos = False):
+ def __init__(self, apitrace, options):
Differ.__init__(self, apitrace)
self.a = None
self.b = None
@@ -250,16 +266,17 @@ class PythonDiffer(Differ):
self.highlighter = PlainHighlighter()
self.delete_color = self.highlighter.red
self.insert_color = self.highlighter.green
- self.callNos = callNos
+ self.callNos = options.callNos
+ self.suppressCommonLines = options.suppressCommonLines
self.aSpace = 0
self.bSpace = 0
self.dumper = Dumper()
- def setRefTrace(self, ref_trace, ref_calls):
- self.a = self.readTrace(ref_trace, ref_calls)
+ def setRefTrace(self, refTrace, ref_calls):
+ self.a = self.readTrace(refTrace, ref_calls)
- def setSrcTrace(self, src_trace, src_calls):
- self.b = self.readTrace(src_trace, src_calls)
+ def setSrcTrace(self, srcTrace, src_calls):
+ self.b = self.readTrace(srcTrace, src_calls)
def readTrace(self, trace, calls):
p = subprocess.Popen(
@@ -341,14 +358,16 @@ class PythonDiffer(Differ):
for j in xrange(numArgs):
self.highlighter.write(sep)
try:
- a_arg = a_call.args[j]
+ a_argName, a_argVal = a_call.args[j]
except IndexError:
pass
try:
- b_arg = b_call.args[j]
+ b_argName, b_argVal = b_call.args[j]
except IndexError:
pass
- self.replace_value(a_arg, b_arg)
+ self.replace_value(a_argName, b_argName)
+ self.highlighter.write(' = ')
+ self.replace_value(a_argVal, b_argVal)
sep = ', '
self.highlighter.write(')')
if a_call.ret is not None or b_call.ret is not None:
@@ -373,7 +392,7 @@ class PythonDiffer(Differ):
self.highlighter.color(self.delete_color)
self.highlighter.write(self.dumper.visit(a))
self.highlighter.normal()
- self.highlighter.write(" ")
+ self.highlighter.write(" -> ")
self.highlighter.color(self.insert_color)
self.highlighter.write(self.dumper.visit(b))
self.highlighter.normal()
@@ -402,6 +421,8 @@ class PythonDiffer(Differ):
self.dumpCall(call)
def equal(self, alo, ahi, blo, bhi):
+ if self.suppressCommonLines:
+ return
assert alo < ahi and blo < bhi
assert ahi - alo == bhi - blo
for i in xrange(0, bhi - blo):
@@ -449,7 +470,7 @@ class PythonDiffer(Differ):
self.highlighter.bold(True)
self.highlighter.write(call.functionName)
self.highlighter.bold(False)
- self.highlighter.write('(' + ', '.join(itertools.imap(self.dumper.visit, call.args)) + ')')
+ self.highlighter.write('(' + self.dumper.visitItems(call.args) + ')')
if call.ret is not None:
self.highlighter.write(' = ' + self.dumper.visit(call.ret))
self.highlighter.normal()
@@ -502,18 +523,23 @@ def main():
help="calls to compare [default: %default]")
optparser.add_option(
'--ref-calls', metavar='CALLSET',
- type="string", dest="ref_calls", default=None,
+ type="string", dest="refCalls", default=None,
help="calls to compare from reference trace")
optparser.add_option(
'--src-calls', metavar='CALLSET',
- type="string", dest="src_calls", default=None,
+ type="string", dest="srcCalls", default=None,
help="calls to compare from source trace")
optparser.add_option(
'--call-nos',
action="store_true",
- dest="call_nos", default=False,
+ dest="callNos", default=False,
help="dump call numbers")
optparser.add_option(
+ '--suppress-common-lines',
+ action="store_true",
+ dest="suppressCommonLines", default=False,
+ help="do not output common lines")
+ optparser.add_option(
'-w', '--width', metavar='NUM',
type="int", dest="width",
help="columns [default: auto]")
@@ -536,19 +562,20 @@ def main():
sys.stderr.write('warning: sdiff not found\n')
options.tool = 'diff'
- if options.ref_calls is None:
- options.ref_calls = options.calls
- if options.src_calls is None:
- options.src_calls = options.calls
+ if options.refCalls is None:
+ options.refCalls = options.calls
+ if options.srcCalls is None:
+ options.srcCalls = options.calls
- ref_trace, src_trace = args
+ refTrace, srcTrace = args
if options.tool == 'python':
- differ = PythonDiffer(options.apitrace, options.call_nos)
+ factory = PythonDiffer
else:
- differ = ExternalDiffer(options.apitrace, options.tool, options.width, options.call_nos)
- differ.setRefTrace(ref_trace, options.ref_calls)
- differ.setSrcTrace(src_trace, options.src_calls)
+ factory = ExternalDiffer
+ differ = factory(options.apitrace, options)
+ differ.setRefTrace(refTrace, options.refCalls)
+ differ.setSrcTrace(srcTrace, options.srcCalls)
differ.diff()
diff --git a/scripts/unpickle.py b/scripts/unpickle.py
index 50d8480a..d2b38228 100755
--- a/scripts/unpickle.py
+++ b/scripts/unpickle.py
@@ -41,6 +41,31 @@ import re
import cPickle as pickle
+# Same as trace_model.hpp's call flags
+CALL_FLAG_FAKE = (1 << 0)
+CALL_FLAG_NON_REPRODUCIBLE = (1 << 1)
+CALL_FLAG_NO_SIDE_EFFECTS = (1 << 2)
+CALL_FLAG_RENDER = (1 << 3)
+CALL_FLAG_SWAP_RENDERTARGET = (1 << 4)
+CALL_FLAG_END_FRAME = (1 << 5)
+CALL_FLAG_INCOMPLETE = (1 << 6)
+CALL_FLAG_VERBOSE = (1 << 7)
+CALL_FLAG_MARKER = (1 << 8)
+CALL_FLAG_MARKER_PUSH = (1 << 9)
+CALL_FLAG_MARKER_POP = (1 << 10)
+
+
+class Pointer(long):
+
+ def __str__(self):
+ if self == 0L:
+ return 'NULL'
+ else:
+ return hex(self).rstrip('L')
+
+ __repr__ = __str__
+
+
class Visitor:
def __init__(self):
@@ -55,9 +80,10 @@ class Visitor:
self.dispatch[list] = self.visitList
self.dispatch[dict] = self.visitDict
self.dispatch[bytearray] = self.visitByteArray
+ self.dispatch[Pointer] = self.visitPointer
def visit(self, obj):
- method = self.dispatch.get(type(obj), self.visitObj)
+ method = self.dispatch.get(obj.__class__, self.visitObj)
return method(obj)
def visitObj(self, obj):
@@ -91,11 +117,14 @@ class Visitor:
return self.visitIterable(obj)
def visitDict(self, obj):
- raise NotImplementedError
+ return self.visitIterable(obj)
def visitByteArray(self, obj):
raise NotImplementedError
+ def visitPointer(self, obj):
+ return self.visitAtom(obj)
+
class Dumper(Visitor):
@@ -111,10 +140,18 @@ class Dumper(Visitor):
return repr(obj)
def visitTuple(self, obj):
- return '[' + ', '.join(itertools.imap(self.visit, obj)) + ']'
+ return '(' + ', '.join(itertools.imap(self.visit, obj)) + ')'
def visitList(self, obj):
- return '(' + ', '.join(itertools.imap(self.visit, obj)) + ')'
+ if len(obj) == 1:
+ return '&' + self.visit(obj[0])
+ return '{' + ', '.join(itertools.imap(self.visit, obj)) + '}'
+
+ def visitItems(self, items):
+ return ', '.join(['%s = %s' % (name, self.visit(value)) for name, value in items])
+
+ def visitDict(self, obj):
+ return '{' + self.visitItems(obj.iteritems()) + '}'
def visitByteArray(self, obj):
return 'blob(%u)' % len(obj)
@@ -163,7 +200,7 @@ class Rebuilder(Visitor):
class Call:
def __init__(self, callTuple):
- self.no, self.functionName, self.args, self.ret = callTuple
+ self.no, self.functionName, self.args, self.ret, self.flags = callTuple
self._hash = None
def __str__(self):
@@ -171,7 +208,7 @@ class Call:
if self.no is not None:
s = str(self.no) + ' ' + s
dumper = Dumper()
- s += '(' + ', '.join(itertools.imap(dumper.visit, self.args)) + ')'
+ s += '(' + dumper.visitItems(self.args) + ')'
if self.ret is not None:
s += ' = '
s += dumper.visit(self.ret)
@@ -190,6 +227,17 @@ class Call:
self._hash = hash(hashable)
return self._hash
+ def arg(self, argName):
+ '''Lookup argument by name.'''
+ for name, value in self.args:
+ if name == argName:
+ return value
+ raise NameError(argName)
+
+ def argValues(self):
+ '''Return the arg values'''
+ return [value for name, value in self.args]
+
class Unpickler:
@@ -209,8 +257,12 @@ class Unpickler:
return False
else:
call = self.callFactory(callTuple)
- self.handleCall(call)
- return True
+ try:
+ self.handleCall(call)
+ except StopIteration:
+ return False
+ else:
+ return True
def handleCall(self, call):
pass
diff --git a/specs/cglapi.py b/specs/cglapi.py
index 8ce9313c..69faeeb4 100644
--- a/specs/cglapi.py
+++ b/specs/cglapi.py
@@ -80,7 +80,7 @@ CGLPixelFormatAttributes = [
("kCGLPFAOpenGLProfile", CGLOpenGLProfile),
("kCGLPFASupportsAutomaticGraphicsSwitching", None),
("kCGLPFAVirtualScreenCount", Int),
- ("kCGLPFAAuxBuffers", None),
+ ("kCGLPFAAuxBuffers", Int),
("kCGLPFAAccumSize", Int),
("kCGLPFAAuxDepthStencil", None),
("kCGLPFAOffScreen", None),
@@ -165,6 +165,10 @@ CGLContextParameter = Enum("CGLContextParameter", [
"kCGLCPGPUFragmentProcessing",
"kCGLCPHasDrawable",
"kCGLCPMPSwapsInFlight",
+ # CGLProfiler.h
+ "kCGLCPComment",
+ "kCGLCPDumpState",
+ "kCGLCPEnableForceFlush",
])
CGLGlobalOption = Enum("CGLGlobalOption", [
@@ -174,6 +178,49 @@ CGLGlobalOption = Enum("CGLGlobalOption", [
"kCGLGOResetLibrary",
"kCGLGOUseErrorHandler",
"kCGLGOUseBuildCache",
+ # CGLProfiler.h
+ "kCGLGOComment",
+ "kCGLGOEnableFunctionTrace",
+ "kCGLGOEnableFunctionStatistics",
+ "kCGLGOResetFunctionTrace",
+ "kCGLGOPageBreak",
+ "kCGLGOResetFunctionStatistics",
+ "kCGLGOEnableDebugAttach",
+ "kCGLGOHideObjects",
+ "kCGLGOEnableBreakpoint",
+ "kCGLGOForceSlowRenderingPath",
+ "kCGLGODisableImmediateRenderPath",
+ "kCGLGODisableCVARenderPath",
+ "kCGLGODisableVARRenderPath",
+ "kCGLGOForceWireframeRendering",
+ "kCGLGOSubmitOnImmediateRenderCommand",
+ "kCGLGOSubmitOnCVARenderCommand",
+ "kCGLGOSubmitOnVAORenderCommand",
+ "kCGLGOSubmitOnClearCommand",
+ "kCGLGOForceSoftwareTransformLighting",
+ "kCGLGOForceSoftwareTexgen",
+ "kCGLGOForceSoftwareTRUFORM_ATI",
+ "kCGLGOForceSoftwareVertexShaders",
+ "kCGLGODisableFragmentShaders_ATI",
+ "kCGLGODisableTexturing",
+ "kCGLGOOutlineTexture",
+ "kCGLGOOutlineTextureColor",
+ "kCGLGOForceSlowBitmapPath",
+ "kCGLGODisableBitmap",
+ "kCGLGOForceSlowReadPixelsPath",
+ "kCGLGODisableReadPixels",
+ "kCGLGOOutlineReadPixelsBuffer",
+ "kCGLGOOutlineReadPixelsBufferColor",
+ "kCGLGOForceSlowDrawPixelsPath",
+ "kCGLGODisableDrawPixels",
+ "kCGLGOOutlineDrawPixelsBuffer",
+ "kCGLGOOutlineDrawPixelsBufferColor",
+ "kCGLGOForceSlowCopyPixelsPath",
+ "kCGLGODisableCopyPixels",
+ "kCGLGOOutlineCopyPixelsBuffer",
+ "kCGLGOOutlineCopyPixelsBufferColor",
+ "kCGLGOMakeAllGLObjectsRequireUpdate",
+ "kCGLGOMakeAllGLStateRequireUpdate",
])
CGLError = Enum("CGLError", [
diff --git a/specs/d2d1.py b/specs/d2d1.py
index e532e468..dacbea69 100644
--- a/specs/d2d1.py
+++ b/specs/d2d1.py
@@ -1,5 +1,6 @@
##########################################################################
#
+# Copyright 2015 VMware, Inc
# Copyright 2011 Jose Fonseca
# All Rights Reserved.
#
@@ -25,14 +26,142 @@
from winapi import *
-from dxgiformat import DXGI_FORMAT
-from dxgi import IDXGISurface
-from d2derr import *
-from d2dbasetypes import *
+from dxgi import DXGI_FORMAT, IDXGISurface
from dwrite import *
+
+#
+# D2D
+#
+
+HRESULT = MAKE_HRESULT(errors = [
+ "D2DERR_UNSUPPORTED_PIXEL_FORMAT",
+ "D2DERR_INSUFFICIENT_BUFFER",
+ "D2DERR_WRONG_STATE",
+ "D2DERR_NOT_INITIALIZED",
+ "D2DERR_UNSUPPORTED_OPERATION",
+ "D2DERR_SCANNER_FAILED",
+ "D2DERR_SCREEN_ACCESS_DENIED",
+ "D2DERR_DISPLAY_STATE_INVALID",
+ "D2DERR_ZERO_VECTOR",
+ "D2DERR_INTERNAL_ERROR",
+ "D2DERR_DISPLAY_FORMAT_NOT_SUPPORTED",
+ "D2DERR_INVALID_CALL",
+ "D2DERR_NO_HARDWARE_DEVICE",
+ "D2DERR_RECREATE_TARGET",
+ "D2DERR_TOO_MANY_SHADER_ELEMENTS",
+ "D2DERR_SHADER_COMPILE_FAILED",
+ "D2DERR_MAX_TEXTURE_SIZE_EXCEEDED",
+ "D2DERR_UNSUPPORTED_VERSION",
+ "D2DERR_BAD_NUMBER",
+ "D2DERR_WRONG_FACTORY",
+ "D2DERR_LAYER_ALREADY_IN_USE",
+ "D2DERR_POP_CALL_DID_NOT_MATCH_PUSH",
+ "D2DERR_WRONG_RESOURCE_DOMAIN",
+ "D2DERR_PUSH_POP_UNBALANCED",
+ "D2DERR_RENDER_TARGET_HAS_LAYER_OR_CLIPRECT",
+ "D2DERR_INCOMPATIBLE_BRUSH_TYPES",
+ "D2DERR_WIN32_ERROR",
+ "D2DERR_TARGET_NOT_GDI_COMPATIBLE",
+ "D2DERR_TEXT_EFFECT_IS_WRONG_TYPE",
+ "D2DERR_TEXT_RENDERER_NOT_RELEASED",
+ "D2DERR_EXCEEDS_MAX_BITMAP_SIZE",
+])
+
+D3DCOLORVALUE = Struct("D3DCOLORVALUE", [
+ (FLOAT, "r"),
+ (FLOAT, "g"),
+ (FLOAT, "b"),
+ (FLOAT, "a"),
+])
+
+D2D_POINT_2U = Struct("D2D_POINT_2U", [
+ (UINT32, "x"),
+ (UINT32, "y"),
+])
+
+D2D_POINT_2F = Struct("D2D_POINT_2F", [
+ (FLOAT, "x"),
+ (FLOAT, "y"),
+])
+
+D2D_POINT_2L = Alias("D2D_POINT_2L", POINT)
+
+D2D_VECTOR_2F = Struct("D2D_VECTOR_2F", [
+ (FLOAT, "x"),
+ (FLOAT, "y"),
+])
+
+D2D_VECTOR_3F = Struct("D2D_VECTOR_3F", [
+ (FLOAT, "x"),
+ (FLOAT, "y"),
+ (FLOAT, "z"),
+])
+
+D2D_VECTOR_4F = Struct("D2D_VECTOR_4F", [
+ (FLOAT, "x"),
+ (FLOAT, "y"),
+ (FLOAT, "z"),
+ (FLOAT, "w"),
+])
+
+D2D_RECT_F = Struct("D2D_RECT_F", [
+ (FLOAT, "left"),
+ (FLOAT, "top"),
+ (FLOAT, "right"),
+ (FLOAT, "bottom"),
+])
+
+D2D_RECT_U = Struct("D2D_RECT_U", [
+ (UINT32, "left"),
+ (UINT32, "top"),
+ (UINT32, "right"),
+ (UINT32, "bottom"),
+])
+
+D2D_RECT_L = Alias("D2D_RECT_L", RECT)
+
+D2D_SIZE_F = Struct("D2D_SIZE_F", [
+ (FLOAT, "width"),
+ (FLOAT, "height"),
+])
+
+D2D_SIZE_U = Struct("D2D_SIZE_U", [
+ (UINT32, "width"),
+ (UINT32, "height"),
+])
+
+D2D_COLOR_F = Alias("D2D_COLOR_F", D3DCOLORVALUE)
+D2D_MATRIX_3X2_F = Struct("D2D_MATRIX_3X2_F", [
+ (FLOAT, "_11"),
+ (FLOAT, "_12"),
+ (FLOAT, "_21"),
+ (FLOAT, "_22"),
+ (FLOAT, "_31"),
+ (FLOAT, "_32"),
+])
+
+D2D_MATRIX_4X3_F = Struct("D2D_MATRIX_4X3_F", [
+ (Array(Array(FLOAT, 3), 4), "m"),
+])
+
+D2D_MATRIX_4X4_F = Struct("D2D_MATRIX_4X4_F", [
+ (Array(Array(FLOAT, 4), 4), "m"),
+])
+
+D2D_MATRIX_5X4_F = Struct("D2D_MATRIX_5X4_F", [
+ (Array(Array(FLOAT, 4), 5), "m"),
+])
+
+
+
+#
+# D2D1
+#
+
ID2D1Resource = Interface("ID2D1Resource", IUnknown)
+ID2D1Image = Interface("ID2D1Image", ID2D1Resource)
ID2D1Bitmap = Interface("ID2D1Bitmap", ID2D1Resource)
ID2D1GradientStopCollection = Interface("ID2D1GradientStopCollection", ID2D1Resource)
ID2D1Brush = Interface("ID2D1Brush", ID2D1Resource)
@@ -375,27 +504,27 @@ ID2D1Resource.methods += [
]
ID2D1Bitmap.methods += [
- StdMethod(D2D1_SIZE_F, "GetSize", [], const=True),
- StdMethod(D2D1_SIZE_U, "GetPixelSize", [], const=True),
- StdMethod(D2D1_PIXEL_FORMAT, "GetPixelFormat", [], const=True),
- StdMethod(Void, "GetDpi", [Out(Pointer(FLOAT), "dpiX"), Out(Pointer(FLOAT), "dpiY")], const=True),
+ StdMethod(D2D1_SIZE_F, "GetSize", [], const=True, sideeffects=False),
+ StdMethod(D2D1_SIZE_U, "GetPixelSize", [], const=True, sideeffects=False),
+ StdMethod(D2D1_PIXEL_FORMAT, "GetPixelFormat", [], const=True, sideeffects=False),
+ StdMethod(Void, "GetDpi", [Out(Pointer(FLOAT), "dpiX"), Out(Pointer(FLOAT), "dpiY")], const=True, sideeffects=False),
StdMethod(HRESULT, "CopyFromBitmap", [(Pointer(Const(D2D1_POINT_2U)), "destPoint"), (ObjPointer(ID2D1Bitmap), "bitmap"), (Pointer(Const(D2D1_RECT_U)), "srcRect")]),
StdMethod(HRESULT, "CopyFromRenderTarget", [(Pointer(Const(D2D1_POINT_2U)), "destPoint"), (ObjPointer(ID2D1RenderTarget), "renderTarget"), (Pointer(Const(D2D1_RECT_U)), "srcRect")]),
StdMethod(HRESULT, "CopyFromMemory", [(Pointer(Const(D2D1_RECT_U)), "dstRect"), (OpaquePointer(Const(Void)), "srcData"), (UINT32, "pitch")]),
]
ID2D1GradientStopCollection.methods += [
- StdMethod(UINT32, "GetGradientStopCount", [], const=True),
- StdMethod(Void, "GetGradientStops", [Out(Pointer(D2D1_GRADIENT_STOP), "gradientStops"), (UINT, "gradientStopsCount")], const=True),
- StdMethod(D2D1_GAMMA, "GetColorInterpolationGamma", [], const=True),
- StdMethod(D2D1_EXTEND_MODE, "GetExtendMode", [], const=True),
+ StdMethod(UINT32, "GetGradientStopCount", [], const=True, sideeffects=False),
+ StdMethod(Void, "GetGradientStops", [Out(Pointer(D2D1_GRADIENT_STOP), "gradientStops"), (UINT, "gradientStopsCount")], const=True, sideeffects=False),
+ StdMethod(D2D1_GAMMA, "GetColorInterpolationGamma", [], const=True, sideeffects=False),
+ StdMethod(D2D1_EXTEND_MODE, "GetExtendMode", [], const=True, sideeffects=False),
]
ID2D1Brush.methods += [
StdMethod(Void, "SetOpacity", [(FLOAT, "opacity")]),
StdMethod(Void, "SetTransform", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "transform")]),
- StdMethod(FLOAT, "GetOpacity", [], const=True),
- StdMethod(Void, "GetTransform", [Out(Pointer(D2D1_MATRIX_3X2_F), "transform")], const=True),
+ StdMethod(FLOAT, "GetOpacity", [], const=True, sideeffects=False),
+ StdMethod(Void, "GetTransform", [Out(Pointer(D2D1_MATRIX_3X2_F), "transform")], const=True, sideeffects=False),
]
ID2D1BitmapBrush.methods += [
@@ -403,22 +532,22 @@ ID2D1BitmapBrush.methods += [
StdMethod(Void, "SetExtendModeY", [(D2D1_EXTEND_MODE, "extendModeY")]),
StdMethod(Void, "SetInterpolationMode", [(D2D1_BITMAP_INTERPOLATION_MODE, "interpolationMode")]),
StdMethod(Void, "SetBitmap", [(ObjPointer(ID2D1Bitmap), "bitmap")]),
- StdMethod(D2D1_EXTEND_MODE, "GetExtendModeX", [], const=True),
- StdMethod(D2D1_EXTEND_MODE, "GetExtendModeY", [], const=True),
- StdMethod(D2D1_BITMAP_INTERPOLATION_MODE, "GetInterpolationMode", [], const=True),
+ StdMethod(D2D1_EXTEND_MODE, "GetExtendModeX", [], const=True, sideeffects=False),
+ StdMethod(D2D1_EXTEND_MODE, "GetExtendModeY", [], const=True, sideeffects=False),
+ StdMethod(D2D1_BITMAP_INTERPOLATION_MODE, "GetInterpolationMode", [], const=True, sideeffects=False),
StdMethod(Void, "GetBitmap", [Out(Pointer(ObjPointer(ID2D1Bitmap)), "bitmap")], const=True),
]
ID2D1SolidColorBrush.methods += [
StdMethod(Void, "SetColor", [(Pointer(Const(D2D1_COLOR_F)), "color")]),
- StdMethod(D2D1_COLOR_F, "GetColor", [], const=True),
+ StdMethod(D2D1_COLOR_F, "GetColor", [], const=True, sideeffects=False),
]
ID2D1LinearGradientBrush.methods += [
StdMethod(Void, "SetStartPoint", [(D2D1_POINT_2F, "startPoint")]),
StdMethod(Void, "SetEndPoint", [(D2D1_POINT_2F, "endPoint")]),
- StdMethod(D2D1_POINT_2F, "GetStartPoint", [], const=True),
- StdMethod(D2D1_POINT_2F, "GetEndPoint", [], const=True),
+ StdMethod(D2D1_POINT_2F, "GetStartPoint", [], const=True, sideeffects=False),
+ StdMethod(D2D1_POINT_2F, "GetEndPoint", [], const=True, sideeffects=False),
StdMethod(Void, "GetGradientStopCollection", [Out(Pointer(ObjPointer(ID2D1GradientStopCollection)), "gradientStopCollection")], const=True),
]
@@ -427,62 +556,62 @@ ID2D1RadialGradientBrush.methods += [
StdMethod(Void, "SetGradientOriginOffset", [(D2D1_POINT_2F, "gradientOriginOffset")]),
StdMethod(Void, "SetRadiusX", [(FLOAT, "radiusX")]),
StdMethod(Void, "SetRadiusY", [(FLOAT, "radiusY")]),
- StdMethod(D2D1_POINT_2F, "GetCenter", [], const=True),
- StdMethod(D2D1_POINT_2F, "GetGradientOriginOffset", [], const=True),
- StdMethod(FLOAT, "GetRadiusX", [], const=True),
- StdMethod(FLOAT, "GetRadiusY", [], const=True),
+ StdMethod(D2D1_POINT_2F, "GetCenter", [], const=True, sideeffects=False),
+ StdMethod(D2D1_POINT_2F, "GetGradientOriginOffset", [], const=True, sideeffects=False),
+ StdMethod(FLOAT, "GetRadiusX", [], const=True, sideeffects=False),
+ StdMethod(FLOAT, "GetRadiusY", [], const=True, sideeffects=False),
StdMethod(Void, "GetGradientStopCollection", [Out(Pointer(ObjPointer(ID2D1GradientStopCollection)), "gradientStopCollection")], const=True),
]
ID2D1StrokeStyle.methods += [
- StdMethod(D2D1_CAP_STYLE, "GetStartCap", [], const=True),
- StdMethod(D2D1_CAP_STYLE, "GetEndCap", [], const=True),
- StdMethod(D2D1_CAP_STYLE, "GetDashCap", [], const=True),
- StdMethod(FLOAT, "GetMiterLimit", [], const=True),
- StdMethod(D2D1_LINE_JOIN, "GetLineJoin", [], const=True),
- StdMethod(FLOAT, "GetDashOffset", [], const=True),
- StdMethod(D2D1_DASH_STYLE, "GetDashStyle", [], const=True),
- StdMethod(UINT32, "GetDashesCount", [], const=True),
- StdMethod(Void, "GetDashes", [Out(Array(FLOAT, "dashesCount"), "dashes"), (UINT, "dashesCount")], const=True),
+ StdMethod(D2D1_CAP_STYLE, "GetStartCap", [], const=True, sideeffects=False),
+ StdMethod(D2D1_CAP_STYLE, "GetEndCap", [], const=True, sideeffects=False),
+ StdMethod(D2D1_CAP_STYLE, "GetDashCap", [], const=True, sideeffects=False),
+ StdMethod(FLOAT, "GetMiterLimit", [], const=True, sideeffects=False),
+ StdMethod(D2D1_LINE_JOIN, "GetLineJoin", [], const=True, sideeffects=False),
+ StdMethod(FLOAT, "GetDashOffset", [], const=True, sideeffects=False),
+ StdMethod(D2D1_DASH_STYLE, "GetDashStyle", [], const=True, sideeffects=False),
+ StdMethod(UINT32, "GetDashesCount", [], const=True, sideeffects=False),
+ StdMethod(Void, "GetDashes", [Out(Array(FLOAT, "dashesCount"), "dashes"), (UINT, "dashesCount")], const=True, sideeffects=False),
]
ID2D1Geometry.methods += [
- StdMethod(HRESULT, "GetBounds", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), Out(Pointer(D2D1_RECT_F), "bounds")], const=True),
- StdMethod(HRESULT, "GetWidenedBounds", [(FLOAT, "strokeWidth"), (ObjPointer(ID2D1StrokeStyle), "strokeStyle"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(D2D1_RECT_F), "bounds")], const=True),
- StdMethod(HRESULT, "StrokeContainsPoint", [(D2D1_POINT_2F, "point"), (FLOAT, "strokeWidth"), (ObjPointer(ID2D1StrokeStyle), "strokeStyle"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(BOOL), "contains")], const=True),
- StdMethod(HRESULT, "FillContainsPoint", [(D2D1_POINT_2F, "point"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(BOOL), "contains")], const=True),
- StdMethod(HRESULT, "CompareWithGeometry", [(ObjPointer(ID2D1Geometry), "inputGeometry"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "inputGeometryTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(D2D1_GEOMETRY_RELATION), "relation")], const=True),
- StdMethod(HRESULT, "Simplify", [(D2D1_GEOMETRY_SIMPLIFICATION_OPTION, "simplificationOption"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True),
- StdMethod(HRESULT, "Tessellate", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1TessellationSink), "tessellationSink")], const=True),
- StdMethod(HRESULT, "CombineWithGeometry", [(ObjPointer(ID2D1Geometry), "inputGeometry"), (D2D1_COMBINE_MODE, "combineMode"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "inputGeometryTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True),
- StdMethod(HRESULT, "Outline", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True),
- StdMethod(HRESULT, "ComputeArea", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(FLOAT), "area")], const=True),
- StdMethod(HRESULT, "ComputeLength", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(FLOAT), "length")], const=True),
- StdMethod(HRESULT, "ComputePointAtLength", [(FLOAT, "length"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(D2D1_POINT_2F), "point"), Out(Pointer(D2D1_POINT_2F), "unitTangentVector")], const=True),
- StdMethod(HRESULT, "Widen", [(FLOAT, "strokeWidth"), (ObjPointer(ID2D1StrokeStyle), "strokeStyle"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True),
+ StdMethod(HRESULT, "GetBounds", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), Out(Pointer(D2D1_RECT_F), "bounds")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetWidenedBounds", [(FLOAT, "strokeWidth"), (ObjPointer(ID2D1StrokeStyle), "strokeStyle"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(D2D1_RECT_F), "bounds")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "StrokeContainsPoint", [(D2D1_POINT_2F, "point"), (FLOAT, "strokeWidth"), (ObjPointer(ID2D1StrokeStyle), "strokeStyle"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(BOOL), "contains")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "FillContainsPoint", [(D2D1_POINT_2F, "point"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(BOOL), "contains")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "CompareWithGeometry", [(ObjPointer(ID2D1Geometry), "inputGeometry"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "inputGeometryTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(D2D1_GEOMETRY_RELATION), "relation")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "Simplify", [(D2D1_GEOMETRY_SIMPLIFICATION_OPTION, "simplificationOption"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "Tessellate", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1TessellationSink), "tessellationSink")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "CombineWithGeometry", [(ObjPointer(ID2D1Geometry), "inputGeometry"), (D2D1_COMBINE_MODE, "combineMode"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "inputGeometryTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "Outline", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "ComputeArea", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(FLOAT), "area")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "ComputeLength", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(FLOAT), "length")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "ComputePointAtLength", [(FLOAT, "length"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(D2D1_POINT_2F), "point"), Out(Pointer(D2D1_POINT_2F), "unitTangentVector")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "Widen", [(FLOAT, "strokeWidth"), (ObjPointer(ID2D1StrokeStyle), "strokeStyle"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (ObjPointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True, sideeffects=False),
]
ID2D1RectangleGeometry.methods += [
- StdMethod(Void, "GetRect", [Out(Pointer(D2D1_RECT_F), "rect")], const=True),
+ StdMethod(Void, "GetRect", [Out(Pointer(D2D1_RECT_F), "rect")], const=True, sideeffects=False),
]
ID2D1RoundedRectangleGeometry.methods += [
- StdMethod(Void, "GetRoundedRect", [Out(Pointer(D2D1_ROUNDED_RECT), "roundedRect")], const=True),
+ StdMethod(Void, "GetRoundedRect", [Out(Pointer(D2D1_ROUNDED_RECT), "roundedRect")], const=True, sideeffects=False),
]
ID2D1EllipseGeometry.methods += [
- StdMethod(Void, "GetEllipse", [Out(Pointer(D2D1_ELLIPSE), "ellipse")], const=True),
+ StdMethod(Void, "GetEllipse", [Out(Pointer(D2D1_ELLIPSE), "ellipse")], const=True, sideeffects=False),
]
ID2D1GeometryGroup.methods += [
- StdMethod(D2D1_FILL_MODE, "GetFillMode", [], const=True),
- StdMethod(UINT32, "GetSourceGeometryCount", [], const=True),
- StdMethod(Void, "GetSourceGeometries", [Out(Array(ObjPointer(ID2D1Geometry), "geometriesCount"), "geometries"), (UINT, "geometriesCount")], const=True),
+ StdMethod(D2D1_FILL_MODE, "GetFillMode", [], const=True, sideeffects=False),
+ StdMethod(UINT32, "GetSourceGeometryCount", [], const=True, sideeffects=False),
+ StdMethod(Void, "GetSourceGeometries", [Out(Array(ObjPointer(ID2D1Geometry), "geometriesCount"), "geometries"), (UINT, "geometriesCount")], const=True, sideeffects=False),
]
ID2D1TransformedGeometry.methods += [
StdMethod(Void, "GetSourceGeometry", [Out(Pointer(ObjPointer(ID2D1Geometry)), "sourceGeometry")], const=True),
- StdMethod(Void, "GetTransform", [Out(Pointer(D2D1_MATRIX_3X2_F), "transform")], const=True),
+ StdMethod(Void, "GetTransform", [Out(Pointer(D2D1_MATRIX_3X2_F), "transform")], const=True, sideeffects=False),
]
ID2D1SimplifiedGeometrySink.methods += [
@@ -510,9 +639,9 @@ ID2D1TessellationSink.methods += [
ID2D1PathGeometry.methods += [
StdMethod(HRESULT, "Open", [Out(Pointer(ObjPointer(ID2D1GeometrySink)), "geometrySink")]),
- StdMethod(HRESULT, "Stream", [(ObjPointer(ID2D1GeometrySink), "geometrySink")], const=True),
- StdMethod(HRESULT, "GetSegmentCount", [Out(Pointer(UINT32), "count")], const=True),
- StdMethod(HRESULT, "GetFigureCount", [Out(Pointer(UINT32), "count")], const=True),
+ StdMethod(HRESULT, "Stream", [(ObjPointer(ID2D1GeometrySink), "geometrySink")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetSegmentCount", [Out(Pointer(UINT32), "count")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetFigureCount", [Out(Pointer(UINT32), "count")], const=True, sideeffects=False),
]
ID2D1Mesh.methods += [
@@ -520,11 +649,11 @@ ID2D1Mesh.methods += [
]
ID2D1Layer.methods += [
- StdMethod(D2D1_SIZE_F, "GetSize", [], const=True),
+ StdMethod(D2D1_SIZE_F, "GetSize", [], const=True, sideeffects=False),
]
ID2D1DrawingStateBlock.methods += [
- StdMethod(Void, "GetDescription", [Out(Pointer(D2D1_DRAWING_STATE_DESCRIPTION), "stateDescription")], const=True),
+ StdMethod(Void, "GetDescription", [Out(Pointer(D2D1_DRAWING_STATE_DESCRIPTION), "stateDescription")], const=True, sideeffects=False),
StdMethod(Void, "SetDescription", [(Pointer(Const(D2D1_DRAWING_STATE_DESCRIPTION)), "stateDescription")]),
StdMethod(Void, "SetTextRenderingParams", [(ObjPointer(IDWriteRenderingParams), "textRenderingParams")]),
StdMethod(Void, "GetTextRenderingParams", [Out(Pointer(ObjPointer(IDWriteRenderingParams)), "textRenderingParams")], const=True),
@@ -554,36 +683,36 @@ ID2D1RenderTarget.methods += [
StdMethod(Void, "FillMesh", [(ObjPointer(ID2D1Mesh), "mesh"), (ObjPointer(ID2D1Brush), "brush")]),
StdMethod(Void, "FillOpacityMask", [(ObjPointer(ID2D1Bitmap), "opacityMask"), (ObjPointer(ID2D1Brush), "brush"), (D2D1_OPACITY_MASK_CONTENT, "content"), (Pointer(Const(D2D1_RECT_F)), "destinationRectangle"), (Pointer(Const(D2D1_RECT_F)), "sourceRectangle")]),
StdMethod(Void, "DrawBitmap", [(ObjPointer(ID2D1Bitmap), "bitmap"), (Pointer(Const(D2D1_RECT_F)), "destinationRectangle"), (FLOAT, "opacity"), (D2D1_BITMAP_INTERPOLATION_MODE, "interpolationMode"), (Pointer(Const(D2D1_RECT_F)), "sourceRectangle")]),
- StdMethod(Void, "DrawText", [(Pointer(Const(WCHAR)), "string"), (UINT, "stringLength"), (ObjPointer(IDWriteTextFormat), "textFormat"), (Pointer(Const(D2D1_RECT_F)), "layoutRect"), (ObjPointer(ID2D1Brush), "defaultForegroundBrush"), (D2D1_DRAW_TEXT_OPTIONS, "options"), (DWRITE_MEASURING_MODE, "measuringMode")]),
+ StdMethod(Void, "DrawText", [(String(Const(WCHAR), "stringLength", wide=True), "string"), (UINT, "stringLength"), (ObjPointer(IDWriteTextFormat), "textFormat"), (Pointer(Const(D2D1_RECT_F)), "layoutRect"), (ObjPointer(ID2D1Brush), "defaultForegroundBrush"), (D2D1_DRAW_TEXT_OPTIONS, "options"), (DWRITE_MEASURING_MODE, "measuringMode")]),
StdMethod(Void, "DrawTextLayout", [(D2D1_POINT_2F, "origin"), (ObjPointer(IDWriteTextLayout), "textLayout"), (ObjPointer(ID2D1Brush), "defaultForegroundBrush"), (D2D1_DRAW_TEXT_OPTIONS, "options")]),
StdMethod(Void, "DrawGlyphRun", [(D2D1_POINT_2F, "baselineOrigin"), (Pointer(Const(DWRITE_GLYPH_RUN)), "glyphRun"), (ObjPointer(ID2D1Brush), "foregroundBrush"), (DWRITE_MEASURING_MODE, "measuringMode")]),
StdMethod(Void, "SetTransform", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "transform")]),
- StdMethod(Void, "GetTransform", [Out(Pointer(D2D1_MATRIX_3X2_F), "transform")], const=True),
+ StdMethod(Void, "GetTransform", [Out(Pointer(D2D1_MATRIX_3X2_F), "transform")], const=True, sideeffects=False),
StdMethod(Void, "SetAntialiasMode", [(D2D1_ANTIALIAS_MODE, "antialiasMode")]),
- StdMethod(D2D1_ANTIALIAS_MODE, "GetAntialiasMode", [], const=True),
+ StdMethod(D2D1_ANTIALIAS_MODE, "GetAntialiasMode", [], const=True, sideeffects=False),
StdMethod(Void, "SetTextAntialiasMode", [(D2D1_TEXT_ANTIALIAS_MODE, "textAntialiasMode")]),
- StdMethod(D2D1_TEXT_ANTIALIAS_MODE, "GetTextAntialiasMode", [], const=True),
+ StdMethod(D2D1_TEXT_ANTIALIAS_MODE, "GetTextAntialiasMode", [], const=True, sideeffects=False),
StdMethod(Void, "SetTextRenderingParams", [(ObjPointer(IDWriteRenderingParams), "textRenderingParams")]),
StdMethod(Void, "GetTextRenderingParams", [Out(Pointer(ObjPointer(IDWriteRenderingParams)), "textRenderingParams")], const=True),
StdMethod(Void, "SetTags", [(D2D1_TAG, "tag1"), (D2D1_TAG, "tag2")]),
- StdMethod(Void, "GetTags", [Out(Pointer(D2D1_TAG), "tag1"), Out(Pointer(D2D1_TAG), "tag2")], const=True),
+ StdMethod(Void, "GetTags", [Out(Pointer(D2D1_TAG), "tag1"), Out(Pointer(D2D1_TAG), "tag2")], const=True, sideeffects=False),
StdMethod(Void, "PushLayer", [(Pointer(Const(D2D1_LAYER_PARAMETERS)), "layerParameters"), (ObjPointer(ID2D1Layer), "layer")]),
StdMethod(Void, "PopLayer", []),
StdMethod(HRESULT, "Flush", [Out(Pointer(D2D1_TAG), "tag1"), Out(Pointer(D2D1_TAG), "tag2")]),
- StdMethod(Void, "SaveDrawingState", [(ObjPointer(ID2D1DrawingStateBlock), "drawingStateBlock")], const=True),
+ StdMethod(Void, "SaveDrawingState", [(ObjPointer(ID2D1DrawingStateBlock), "drawingStateBlock")], const=True, sideeffects=False),
StdMethod(Void, "RestoreDrawingState", [(ObjPointer(ID2D1DrawingStateBlock), "drawingStateBlock")]),
StdMethod(Void, "PushAxisAlignedClip", [(Pointer(Const(D2D1_RECT_F)), "clipRect"), (D2D1_ANTIALIAS_MODE, "antialiasMode")]),
StdMethod(Void, "PopAxisAlignedClip", []),
StdMethod(Void, "Clear", [(Pointer(Const(D2D1_COLOR_F)), "clearColor")]),
StdMethod(Void, "BeginDraw", []),
StdMethod(HRESULT, "EndDraw", [Out(Pointer(D2D1_TAG), "tag1"), Out(Pointer(D2D1_TAG), "tag2")]),
- StdMethod(D2D1_PIXEL_FORMAT, "GetPixelFormat", [], const=True),
+ StdMethod(D2D1_PIXEL_FORMAT, "GetPixelFormat", [], const=True, sideeffects=False),
StdMethod(Void, "SetDpi", [(FLOAT, "dpiX"), (FLOAT, "dpiY")]),
- StdMethod(Void, "GetDpi", [Out(Pointer(FLOAT), "dpiX"), Out(Pointer(FLOAT), "dpiY")], const=True),
- StdMethod(D2D1_SIZE_F, "GetSize", [], const=True),
- StdMethod(D2D1_SIZE_U, "GetPixelSize", [], const=True),
- StdMethod(UINT32, "GetMaximumBitmapSize", [], const=True),
- StdMethod(BOOL, "IsSupported", [(Pointer(Const(D2D1_RENDER_TARGET_PROPERTIES)), "renderTargetProperties")], const=True),
+ StdMethod(Void, "GetDpi", [Out(Pointer(FLOAT), "dpiX"), Out(Pointer(FLOAT), "dpiY")], const=True, sideeffects=False),
+ StdMethod(D2D1_SIZE_F, "GetSize", [], const=True, sideeffects=False),
+ StdMethod(D2D1_SIZE_U, "GetPixelSize", [], const=True, sideeffects=False),
+ StdMethod(UINT32, "GetMaximumBitmapSize", [], const=True, sideeffects=False),
+ StdMethod(BOOL, "IsSupported", [(Pointer(Const(D2D1_RENDER_TARGET_PROPERTIES)), "renderTargetProperties")], const=True, sideeffects=False),
]
ID2D1BitmapRenderTarget.methods += [
@@ -593,7 +722,7 @@ ID2D1BitmapRenderTarget.methods += [
ID2D1HwndRenderTarget.methods += [
StdMethod(D2D1_WINDOW_STATE, "CheckWindowState", []),
StdMethod(HRESULT, "Resize", [(Pointer(Const(D2D1_SIZE_U)), "pixelSize")]),
- StdMethod(HWND, "GetHwnd", [], const=True),
+ StdMethod(HWND, "GetHwnd", [], const=True, sideeffects=False),
]
ID2D1GdiInteropRenderTarget.methods += [
@@ -611,7 +740,7 @@ ID2D1Factory.methods += [
StdMethod(HRESULT, "CreateRectangleGeometry", [(Pointer(Const(D2D1_RECT_F)), "rectangle"), Out(Pointer(ObjPointer(ID2D1RectangleGeometry)), "rectangleGeometry")]),
StdMethod(HRESULT, "CreateRoundedRectangleGeometry", [(Pointer(Const(D2D1_ROUNDED_RECT)), "roundedRectangle"), Out(Pointer(ObjPointer(ID2D1RoundedRectangleGeometry)), "roundedRectangleGeometry")]),
StdMethod(HRESULT, "CreateEllipseGeometry", [(Pointer(Const(D2D1_ELLIPSE)), "ellipse"), Out(Pointer(ObjPointer(ID2D1EllipseGeometry)), "ellipseGeometry")]),
- StdMethod(HRESULT, "CreateGeometryGroup", [(D2D1_FILL_MODE, "fillMode"), (Pointer(ObjPointer(ID2D1Geometry)), "geometries"), (UINT, "geometriesCount"), Out(Pointer(ObjPointer(ID2D1GeometryGroup)), "geometryGroup")]),
+ StdMethod(HRESULT, "CreateGeometryGroup", [(D2D1_FILL_MODE, "fillMode"), (Array(ObjPointer(ID2D1Geometry), "geometriesCount"), "geometries"), (UINT, "geometriesCount"), Out(Pointer(ObjPointer(ID2D1GeometryGroup)), "geometryGroup")]),
StdMethod(HRESULT, "CreateTransformedGeometry", [(ObjPointer(ID2D1Geometry), "sourceGeometry"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "transform"), Out(Pointer(ObjPointer(ID2D1TransformedGeometry)), "transformedGeometry")]),
StdMethod(HRESULT, "CreatePathGeometry", [Out(Pointer(ObjPointer(ID2D1PathGeometry)), "pathGeometry")]),
StdMethod(HRESULT, "CreateStrokeStyle", [(Pointer(Const(D2D1_STROKE_STYLE_PROPERTIES)), "strokeStyleProperties"), (Pointer(Const(FLOAT)), "dashes"), (UINT, "dashesCount"), Out(Pointer(ObjPointer(ID2D1StrokeStyle)), "strokeStyle")]),
@@ -633,3 +762,499 @@ d2d1.addFunctions([
StdFunction(BOOL, "D2D1IsMatrixInvertible", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "matrix")]),
StdFunction(BOOL, "D2D1InvertMatrix", [InOut(Pointer(D2D1_MATRIX_3X2_F), "matrix")]),
])
+
+
+
+#
+# D2D1.1
+#
+
+
+ID2D1GdiMetafileSink = Interface("ID2D1GdiMetafileSink", IUnknown)
+ID2D1GdiMetafile = Interface("ID2D1GdiMetafile", ID2D1Resource)
+ID2D1CommandSink = Interface("ID2D1CommandSink", IUnknown)
+ID2D1CommandList = Interface("ID2D1CommandList", ID2D1Image)
+ID2D1PrintControl = Interface("ID2D1PrintControl", IUnknown)
+ID2D1ImageBrush = Interface("ID2D1ImageBrush", ID2D1Brush)
+ID2D1BitmapBrush1 = Interface("ID2D1BitmapBrush1", ID2D1BitmapBrush)
+ID2D1StrokeStyle1 = Interface("ID2D1StrokeStyle1", ID2D1StrokeStyle)
+ID2D1PathGeometry1 = Interface("ID2D1PathGeometry1", ID2D1PathGeometry)
+ID2D1Properties = Interface("ID2D1Properties", IUnknown)
+ID2D1Effect = Interface("ID2D1Effect", ID2D1Properties)
+ID2D1Bitmap1 = Interface("ID2D1Bitmap1", ID2D1Bitmap)
+ID2D1ColorContext = Interface("ID2D1ColorContext", ID2D1Resource)
+ID2D1GradientStopCollection1 = Interface("ID2D1GradientStopCollection1", ID2D1GradientStopCollection)
+ID2D1DrawingStateBlock1 = Interface("ID2D1DrawingStateBlock1", ID2D1DrawingStateBlock)
+ID2D1DeviceContext = Interface("ID2D1DeviceContext", ID2D1RenderTarget)
+ID2D1Device = Interface("ID2D1Device", ID2D1Resource)
+ID2D1Factory1 = Interface("ID2D1Factory1", ID2D1Factory)
+ID2D1Multithread = Interface("ID2D1Multithread", IUnknown)
+
+
+D2D1_RECT_L = Alias("D2D1_RECT_L", D2D_RECT_L)
+D2D1_POINT_2L = Alias("D2D1_POINT_2L", D2D_POINT_2L)
+
+
+D2D1_PROPERTY_INDEX = FakeEnum(UINT32, [
+ "D2D1_INVALID_PROPERTY_INDEX",
+])
+
+D2D1_PROPERTY_TYPE = Enum("D2D1_PROPERTY_TYPE", [
+ "D2D1_PROPERTY_TYPE_UNKNOWN",
+ "D2D1_PROPERTY_TYPE_STRING",
+ "D2D1_PROPERTY_TYPE_BOOL",
+ "D2D1_PROPERTY_TYPE_UINT32",
+ "D2D1_PROPERTY_TYPE_INT32",
+ "D2D1_PROPERTY_TYPE_FLOAT",
+ "D2D1_PROPERTY_TYPE_VECTOR2",
+ "D2D1_PROPERTY_TYPE_VECTOR3",
+ "D2D1_PROPERTY_TYPE_VECTOR4",
+ "D2D1_PROPERTY_TYPE_BLOB",
+ "D2D1_PROPERTY_TYPE_IUNKNOWN",
+ "D2D1_PROPERTY_TYPE_ENUM",
+ "D2D1_PROPERTY_TYPE_ARRAY",
+ "D2D1_PROPERTY_TYPE_CLSID",
+ "D2D1_PROPERTY_TYPE_MATRIX_3X2",
+ "D2D1_PROPERTY_TYPE_MATRIX_4X3",
+ "D2D1_PROPERTY_TYPE_MATRIX_4X4",
+ "D2D1_PROPERTY_TYPE_MATRIX_5X4",
+ "D2D1_PROPERTY_TYPE_COLOR_CONTEXT",
+ "D2D1_PROPERTY_TYPE_FORCE_DWORD",
+])
+
+D2D1_PROPERTY = Enum("D2D1_PROPERTY", [
+ "D2D1_PROPERTY_CLSID",
+ "D2D1_PROPERTY_DISPLAYNAME",
+ "D2D1_PROPERTY_AUTHOR",
+ "D2D1_PROPERTY_CATEGORY",
+ "D2D1_PROPERTY_DESCRIPTION",
+ "D2D1_PROPERTY_INPUTS",
+ "D2D1_PROPERTY_CACHED",
+ "D2D1_PROPERTY_PRECISION",
+ "D2D1_PROPERTY_MIN_INPUTS",
+ "D2D1_PROPERTY_MAX_INPUTS",
+ "D2D1_PROPERTY_FORCE_DWORD",
+])
+
+D2D1_SUBPROPERTY = Enum("D2D1_SUBPROPERTY", [
+ "D2D1_SUBPROPERTY_DISPLAYNAME",
+ "D2D1_SUBPROPERTY_ISREADONLY",
+ "D2D1_SUBPROPERTY_MIN",
+ "D2D1_SUBPROPERTY_MAX",
+ "D2D1_SUBPROPERTY_DEFAULT",
+ "D2D1_SUBPROPERTY_FIELDS",
+ "D2D1_SUBPROPERTY_INDEX",
+ "D2D1_SUBPROPERTY_FORCE_DWORD",
+])
+
+D2D1_BITMAP_OPTIONS = Enum("D2D1_BITMAP_OPTIONS", [
+ "D2D1_BITMAP_OPTIONS_NONE",
+ "D2D1_BITMAP_OPTIONS_TARGET",
+ "D2D1_BITMAP_OPTIONS_CANNOT_DRAW",
+ "D2D1_BITMAP_OPTIONS_CPU_READ",
+ "D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE",
+ "D2D1_BITMAP_OPTIONS_FORCE_DWORD",
+])
+
+D2D1_COMPOSITE_MODE = Enum("D2D1_COMPOSITE_MODE", [
+ "D2D1_COMPOSITE_MODE_SOURCE_OVER",
+ "D2D1_COMPOSITE_MODE_DESTINATION_OVER",
+ "D2D1_COMPOSITE_MODE_SOURCE_IN",
+ "D2D1_COMPOSITE_MODE_DESTINATION_IN",
+ "D2D1_COMPOSITE_MODE_SOURCE_OUT",
+ "D2D1_COMPOSITE_MODE_DESTINATION_OUT",
+ "D2D1_COMPOSITE_MODE_SOURCE_ATOP",
+ "D2D1_COMPOSITE_MODE_DESTINATION_ATOP",
+ "D2D1_COMPOSITE_MODE_XOR",
+ "D2D1_COMPOSITE_MODE_PLUS",
+ "D2D1_COMPOSITE_MODE_SOURCE_COPY",
+ "D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY",
+ "D2D1_COMPOSITE_MODE_MASK_INVERT",
+ "D2D1_COMPOSITE_MODE_FORCE_DWORD",
+])
+
+D2D1_BUFFER_PRECISION = Enum("D2D1_BUFFER_PRECISION", [
+ "D2D1_BUFFER_PRECISION_UNKNOWN",
+ "D2D1_BUFFER_PRECISION_8BPC_UNORM",
+ "D2D1_BUFFER_PRECISION_8BPC_UNORM_SRGB",
+ "D2D1_BUFFER_PRECISION_16BPC_UNORM",
+ "D2D1_BUFFER_PRECISION_16BPC_FLOAT",
+ "D2D1_BUFFER_PRECISION_32BPC_FLOAT",
+ "D2D1_BUFFER_PRECISION_FORCE_DWORD",
+])
+
+D2D1_MAP_OPTIONS = Enum("D2D1_MAP_OPTIONS", [
+ "D2D1_MAP_OPTIONS_NONE",
+ "D2D1_MAP_OPTIONS_READ",
+ "D2D1_MAP_OPTIONS_WRITE",
+ "D2D1_MAP_OPTIONS_DISCARD",
+ "D2D1_MAP_OPTIONS_FORCE_DWORD",
+])
+
+D2D1_INTERPOLATION_MODE = Enum("D2D1_INTERPOLATION_MODE", [
+ "D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR",
+ "D2D1_INTERPOLATION_MODE_LINEAR",
+ "D2D1_INTERPOLATION_MODE_CUBIC",
+ "D2D1_INTERPOLATION_MODE_MULTI_SAMPLE_LINEAR",
+ "D2D1_INTERPOLATION_MODE_ANISOTROPIC",
+ "D2D1_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC",
+ "D2D1_INTERPOLATION_MODE_FORCE_DWORD",
+])
+
+D2D1_UNIT_MODE = Enum("D2D1_UNIT_MODE", [
+ "D2D1_UNIT_MODE_DIPS",
+ "D2D1_UNIT_MODE_PIXELS",
+ "D2D1_UNIT_MODE_FORCE_DWORD",
+])
+
+D2D1_COLOR_SPACE = Enum("D2D1_COLOR_SPACE", [
+ "D2D1_COLOR_SPACE_CUSTOM",
+ "D2D1_COLOR_SPACE_SRGB",
+ "D2D1_COLOR_SPACE_SCRGB",
+ "D2D1_COLOR_SPACE_FORCE_DWORD",
+])
+
+D2D1_DEVICE_CONTEXT_OPTIONS = Enum("D2D1_DEVICE_CONTEXT_OPTIONS", [
+ "D2D1_DEVICE_CONTEXT_OPTIONS_NONE",
+ "D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS",
+ "D2D1_DEVICE_CONTEXT_OPTIONS_FORCE_DWORD",
+])
+
+D2D1_STROKE_TRANSFORM_TYPE = Enum("D2D1_STROKE_TRANSFORM_TYPE", [
+ "D2D1_STROKE_TRANSFORM_TYPE_NORMAL",
+ "D2D1_STROKE_TRANSFORM_TYPE_FIXED",
+ "D2D1_STROKE_TRANSFORM_TYPE_HAIRLINE",
+ "D2D1_STROKE_TRANSFORM_TYPE_FORCE_DWORD",
+])
+
+D2D1_PRIMITIVE_BLEND = Enum("D2D1_PRIMITIVE_BLEND", [
+ "D2D1_PRIMITIVE_BLEND_SOURCE_OVER",
+ "D2D1_PRIMITIVE_BLEND_COPY",
+ "D2D1_PRIMITIVE_BLEND_MIN",
+ "D2D1_PRIMITIVE_BLEND_ADD",
+ "D2D1_PRIMITIVE_BLEND_FORCE_DWORD",
+])
+
+D2D1_THREADING_MODE = Enum("D2D1_THREADING_MODE", [
+ "D2D1_THREADING_MODE_SINGLE_THREADED",
+ "D2D1_THREADING_MODE_MULTI_THREADED",
+ "D2D1_THREADING_MODE_FORCE_DWORD",
+])
+
+D2D1_COLOR_INTERPOLATION_MODE = Enum("D2D1_COLOR_INTERPOLATION_MODE", [
+ "D2D1_COLOR_INTERPOLATION_MODE_STRAIGHT",
+ "D2D1_COLOR_INTERPOLATION_MODE_PREMULTIPLIED",
+ "D2D1_COLOR_INTERPOLATION_MODE_FORCE_DWORD",
+])
+
+D2D1_VECTOR_2F = Alias("D2D1_VECTOR_2F", D2D_VECTOR_2F)
+D2D1_VECTOR_3F = Alias("D2D1_VECTOR_3F", D2D_VECTOR_3F)
+D2D1_VECTOR_4F = Alias("D2D1_VECTOR_4F", D2D_VECTOR_4F)
+D2D1_BITMAP_PROPERTIES1 = Struct("D2D1_BITMAP_PROPERTIES1", [
+ (D2D1_PIXEL_FORMAT, "pixelFormat"),
+ (FLOAT, "dpiX"),
+ (FLOAT, "dpiY"),
+ (D2D1_BITMAP_OPTIONS, "bitmapOptions"),
+ (ObjPointer(ID2D1ColorContext), "colorContext"),
+])
+
+D2D1_MAPPED_RECT = Struct("D2D1_MAPPED_RECT", [
+ (UINT32, "pitch"),
+ (Pointer(BYTE), "bits"),
+])
+
+D2D1_RENDERING_CONTROLS = Struct("D2D1_RENDERING_CONTROLS", [
+ (D2D1_BUFFER_PRECISION, "bufferPrecision"),
+ (D2D1_SIZE_U, "tileSize"),
+])
+
+D2D1_EFFECT_INPUT_DESCRIPTION = Struct("D2D1_EFFECT_INPUT_DESCRIPTION", [
+ (ObjPointer(ID2D1Effect), "effect"),
+ (UINT32, "inputIndex"),
+ (D2D1_RECT_F, "inputRectangle"),
+])
+
+D2D1_MATRIX_4X3_F = Alias("D2D1_MATRIX_4X3_F", D2D_MATRIX_4X3_F)
+D2D1_MATRIX_4X4_F = Alias("D2D1_MATRIX_4X4_F", D2D_MATRIX_4X4_F)
+D2D1_MATRIX_5X4_F = Alias("D2D1_MATRIX_5X4_F", D2D_MATRIX_5X4_F)
+D2D1_POINT_DESCRIPTION = Struct("D2D1_POINT_DESCRIPTION", [
+ (D2D1_POINT_2F, "point"),
+ (D2D1_POINT_2F, "unitTangentVector"),
+ (UINT32, "endSegment"),
+ (UINT32, "endFigure"),
+ (FLOAT, "lengthToEndSegment"),
+])
+
+D2D1_IMAGE_BRUSH_PROPERTIES = Struct("D2D1_IMAGE_BRUSH_PROPERTIES", [
+ (D2D1_RECT_F, "sourceRectangle"),
+ (D2D1_EXTEND_MODE, "extendModeX"),
+ (D2D1_EXTEND_MODE, "extendModeY"),
+ (D2D1_INTERPOLATION_MODE, "interpolationMode"),
+])
+
+D2D1_BITMAP_BRUSH_PROPERTIES1 = Struct("D2D1_BITMAP_BRUSH_PROPERTIES1", [
+ (D2D1_EXTEND_MODE, "extendModeX"),
+ (D2D1_EXTEND_MODE, "extendModeY"),
+ (D2D1_INTERPOLATION_MODE, "interpolationMode"),
+])
+
+D2D1_STROKE_STYLE_PROPERTIES1 = Struct("D2D1_STROKE_STYLE_PROPERTIES1", [
+ (D2D1_CAP_STYLE, "startCap"),
+ (D2D1_CAP_STYLE, "endCap"),
+ (D2D1_CAP_STYLE, "dashCap"),
+ (D2D1_LINE_JOIN, "lineJoin"),
+ (FLOAT, "miterLimit"),
+ (D2D1_DASH_STYLE, "dashStyle"),
+ (FLOAT, "dashOffset"),
+ (D2D1_STROKE_TRANSFORM_TYPE, "transformType"),
+])
+
+D2D1_LAYER_OPTIONS1 = Enum("D2D1_LAYER_OPTIONS1", [
+ "D2D1_LAYER_OPTIONS1_NONE",
+ "D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND",
+ "D2D1_LAYER_OPTIONS1_IGNORE_ALPHA",
+ "D2D1_LAYER_OPTIONS1_FORCE_DWORD",
+])
+
+D2D1_LAYER_PARAMETERS1 = Struct("D2D1_LAYER_PARAMETERS1", [
+ (D2D1_RECT_F, "contentBounds"),
+ (ObjPointer(ID2D1Geometry), "geometricMask"),
+ (D2D1_ANTIALIAS_MODE, "maskAntialiasMode"),
+ (D2D1_MATRIX_3X2_F, "maskTransform"),
+ (FLOAT, "opacity"),
+ (ObjPointer(ID2D1Brush), "opacityBrush"),
+ (D2D1_LAYER_OPTIONS1, "layerOptions"),
+])
+
+D2D1_PRINT_FONT_SUBSET_MODE = Enum("D2D1_PRINT_FONT_SUBSET_MODE", [
+ "D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT",
+ "D2D1_PRINT_FONT_SUBSET_MODE_EACHPAGE",
+ "D2D1_PRINT_FONT_SUBSET_MODE_NONE",
+ "D2D1_PRINT_FONT_SUBSET_MODE_FORCE_DWORD",
+])
+
+D2D1_DRAWING_STATE_DESCRIPTION1 = Struct("D2D1_DRAWING_STATE_DESCRIPTION1", [
+ (D2D1_ANTIALIAS_MODE, "antialiasMode"),
+ (D2D1_TEXT_ANTIALIAS_MODE, "textAntialiasMode"),
+ (D2D1_TAG, "tag1"),
+ (D2D1_TAG, "tag2"),
+ (D2D1_MATRIX_3X2_F, "transform"),
+ (D2D1_PRIMITIVE_BLEND, "primitiveBlend"),
+ (D2D1_UNIT_MODE, "unitMode"),
+])
+
+D2D1_PRINT_CONTROL_PROPERTIES = Struct("D2D1_PRINT_CONTROL_PROPERTIES", [
+ (D2D1_PRINT_FONT_SUBSET_MODE, "fontSubset"),
+ (FLOAT, "rasterDPI"),
+ (D2D1_COLOR_SPACE, "colorSpace"),
+])
+
+D2D1_CREATION_PROPERTIES = Struct("D2D1_CREATION_PROPERTIES", [
+ (D2D1_THREADING_MODE, "threadingMode"),
+ (D2D1_DEBUG_LEVEL, "debugLevel"),
+ (D2D1_DEVICE_CONTEXT_OPTIONS, "options"),
+])
+
+ID2D1GdiMetafileSink.methods += [
+ StdMethod(HRESULT, "ProcessRecord", [(DWORD, "recordType"), (OpaqueBlob(Const(Void), "recordDataSize"), "recordData"), (DWORD, "recordDataSize")]),
+]
+
+ID2D1GdiMetafile.methods += [
+ StdMethod(HRESULT, "Stream", [(ObjPointer(ID2D1GdiMetafileSink), "sink")]),
+ StdMethod(HRESULT, "GetBounds", [Out(Pointer(D2D1_RECT_F), "bounds")]),
+]
+
+ID2D1CommandSink.methods += [
+ StdMethod(HRESULT, "BeginDraw", []),
+ StdMethod(HRESULT, "EndDraw", []),
+ StdMethod(HRESULT, "SetAntialiasMode", [(D2D1_ANTIALIAS_MODE, "antialiasMode")]),
+ StdMethod(HRESULT, "SetTags", [(D2D1_TAG, "tag1"), (D2D1_TAG, "tag2")]),
+ StdMethod(HRESULT, "SetTextAntialiasMode", [(D2D1_TEXT_ANTIALIAS_MODE, "textAntialiasMode")]),
+ StdMethod(HRESULT, "SetTextRenderingParams", [(ObjPointer(IDWriteRenderingParams), "textRenderingParams")]),
+ StdMethod(HRESULT, "SetTransform", [(Pointer(Const(D2D1_MATRIX_3X2_F)), "transform")]),
+ StdMethod(HRESULT, "SetPrimitiveBlend", [(D2D1_PRIMITIVE_BLEND, "primitiveBlend")]),
+ StdMethod(HRESULT, "SetUnitMode", [(D2D1_UNIT_MODE, "unitMode")]),
+ StdMethod(HRESULT, "Clear", [(Pointer(Const(D2D1_COLOR_F)), "color")]),
+ StdMethod(HRESULT, "DrawGlyphRun", [(D2D1_POINT_2F, "baselineOrigin"), (Pointer(Const(DWRITE_GLYPH_RUN)), "glyphRun"), (Pointer(Const(DWRITE_GLYPH_RUN_DESCRIPTION)), "glyphRunDescription"), (ObjPointer(ID2D1Brush), "foregroundBrush"), (DWRITE_MEASURING_MODE, "measuringMode")]),
+ StdMethod(HRESULT, "DrawLine", [(D2D1_POINT_2F, "point0"), (D2D1_POINT_2F, "point1"), (ObjPointer(ID2D1Brush), "brush"), (FLOAT, "strokeWidth"), (ObjPointer(ID2D1StrokeStyle), "strokeStyle")]),
+ StdMethod(HRESULT, "DrawGeometry", [(ObjPointer(ID2D1Geometry), "geometry"), (ObjPointer(ID2D1Brush), "brush"), (FLOAT, "strokeWidth"), (ObjPointer(ID2D1StrokeStyle), "strokeStyle")]),
+ StdMethod(HRESULT, "DrawRectangle", [(Pointer(Const(D2D1_RECT_F)), "rect"), (ObjPointer(ID2D1Brush), "brush"), (FLOAT, "strokeWidth"), (ObjPointer(ID2D1StrokeStyle), "strokeStyle")]),
+ StdMethod(HRESULT, "DrawBitmap", [(ObjPointer(ID2D1Bitmap), "bitmap"), (Pointer(Const(D2D1_RECT_F)), "destinationRectangle"), (FLOAT, "opacity"), (D2D1_INTERPOLATION_MODE, "interpolationMode"), (Pointer(Const(D2D1_RECT_F)), "sourceRectangle"), (Pointer(Const(D2D1_MATRIX_4X4_F)), "perspectiveTransform")]),
+ StdMethod(HRESULT, "DrawImage", [(ObjPointer(ID2D1Image), "image"), (Pointer(Const(D2D1_POINT_2F)), "targetOffset"), (Pointer(Const(D2D1_RECT_F)), "imageRectangle"), (D2D1_INTERPOLATION_MODE, "interpolationMode"), (D2D1_COMPOSITE_MODE, "compositeMode")]),
+ StdMethod(HRESULT, "DrawGdiMetafile", [(ObjPointer(ID2D1GdiMetafile), "gdiMetafile"), (Pointer(Const(D2D1_POINT_2F)), "targetOffset")]),
+ StdMethod(HRESULT, "FillMesh", [(ObjPointer(ID2D1Mesh), "mesh"), (ObjPointer(ID2D1Brush), "brush")]),
+ StdMethod(HRESULT, "FillOpacityMask", [(ObjPointer(ID2D1Bitmap), "opacityMask"), (ObjPointer(ID2D1Brush), "brush"), (Pointer(Const(D2D1_RECT_F)), "destinationRectangle"), (Pointer(Const(D2D1_RECT_F)), "sourceRectangle")]),
+ StdMethod(HRESULT, "FillGeometry", [(ObjPointer(ID2D1Geometry), "geometry"), (ObjPointer(ID2D1Brush), "brush"), (ObjPointer(ID2D1Brush), "opacityBrush")]),
+ StdMethod(HRESULT, "FillRectangle", [(Pointer(Const(D2D1_RECT_F)), "rect"), (ObjPointer(ID2D1Brush), "brush")]),
+ StdMethod(HRESULT, "PushAxisAlignedClip", [(Pointer(Const(D2D1_RECT_F)), "clipRect"), (D2D1_ANTIALIAS_MODE, "antialiasMode")]),
+ StdMethod(HRESULT, "PushLayer", [(Pointer(Const(D2D1_LAYER_PARAMETERS1)), "layerParameters1"), (ObjPointer(ID2D1Layer), "layer")]),
+ StdMethod(HRESULT, "PopAxisAlignedClip", []),
+ StdMethod(HRESULT, "PopLayer", []),
+]
+
+ID2D1CommandList.methods += [
+ StdMethod(HRESULT, "Stream", [(ObjPointer(ID2D1CommandSink), "sink")]),
+ StdMethod(HRESULT, "Close", []),
+]
+
+ID2D1PrintControl.methods += [
+ StdMethod(HRESULT, "AddPage", [(ObjPointer(ID2D1CommandList), "commandList"), (D2D_SIZE_F, "pageSize"), (Opaque("IStream *"), "pagePrintTicketStream"), Out(Pointer(D2D1_TAG), "tag1"), Out(Pointer(D2D1_TAG), "tag2")]),
+ StdMethod(HRESULT, "Close", []),
+]
+
+ID2D1ImageBrush.methods += [
+ StdMethod(Void, "SetImage", [(ObjPointer(ID2D1Image), "image")]),
+ StdMethod(Void, "SetExtendModeX", [(D2D1_EXTEND_MODE, "extendModeX")]),
+ StdMethod(Void, "SetExtendModeY", [(D2D1_EXTEND_MODE, "extendModeY")]),
+ StdMethod(Void, "SetInterpolationMode", [(D2D1_INTERPOLATION_MODE, "interpolationMode")]),
+ StdMethod(Void, "SetSourceRectangle", [(Pointer(Const(D2D1_RECT_F)), "sourceRectangle")]),
+ StdMethod(Void, "GetImage", [(Pointer(ObjPointer(ID2D1Image)), "image")], const=True, sideeffects=False),
+ StdMethod(D2D1_EXTEND_MODE, "GetExtendModeX", [], const=True, sideeffects=False),
+ StdMethod(D2D1_EXTEND_MODE, "GetExtendModeY", [], const=True, sideeffects=False),
+ StdMethod(D2D1_INTERPOLATION_MODE, "GetInterpolationMode", [], const=True, sideeffects=False),
+ StdMethod(Void, "GetSourceRectangle", [Out(Pointer(D2D1_RECT_F), "sourceRectangle")], const=True, sideeffects=False),
+]
+
+ID2D1BitmapBrush1.methods += [
+ StdMethod(Void, "SetInterpolationMode1", [(D2D1_INTERPOLATION_MODE, "interpolationMode")]),
+ StdMethod(D2D1_INTERPOLATION_MODE, "GetInterpolationMode1", [], const=True, sideeffects=False),
+]
+
+ID2D1StrokeStyle1.methods += [
+ StdMethod(D2D1_STROKE_TRANSFORM_TYPE, "GetStrokeTransformType", [], const=True, sideeffects=False),
+]
+
+ID2D1PathGeometry1.methods += [
+ StdMethod(HRESULT, "ComputePointAndSegmentAtLength", [(FLOAT, "length"), (UINT32, "startSegment"), (Pointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(Pointer(D2D1_POINT_DESCRIPTION), "pointDescription")], const=True, sideeffects=False),
+]
+
+ID2D1Properties.methods += [
+ StdMethod(UINT32, "GetPropertyCount", [], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetPropertyName", [(UINT32, "index"), Out(PWSTR, "name"), (UINT32, "nameCount")], const=True, sideeffects=False),
+ StdMethod(UINT32, "GetPropertyNameLength", [(UINT32, "index")], const=True, sideeffects=False),
+ StdMethod(D2D1_PROPERTY_TYPE, "GetType", [(UINT32, "index")], const=True, sideeffects=False),
+ StdMethod(D2D1_PROPERTY_INDEX, "GetPropertyIndex", [(PCWSTR, "name")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "SetValueByName", [(PCWSTR, "name"), (D2D1_PROPERTY_TYPE, "type"), (Pointer(Const(BYTE)), "data"), (UINT32, "dataSize")]),
+ StdMethod(HRESULT, "SetValue", [(UINT32, "index"), (D2D1_PROPERTY_TYPE, "type"), (Pointer(Const(BYTE)), "data"), (UINT32, "dataSize")]),
+ StdMethod(HRESULT, "GetValueByName", [(PCWSTR, "name"), (D2D1_PROPERTY_TYPE, "type"), Out(Pointer(BYTE), "data"), (UINT32, "dataSize")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetValue", [(UINT32, "index"), (D2D1_PROPERTY_TYPE, "type"), Out(Pointer(BYTE), "data"), (UINT32, "dataSize")], const=True, sideeffects=False),
+ StdMethod(UINT32, "GetValueSize", [(UINT32, "index")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetSubProperties", [(UINT32, "index"), Out(Pointer(ObjPointer(ID2D1Properties)), "subProperties")], const=True),
+]
+
+ID2D1Effect.methods += [
+ StdMethod(Void, "SetInput", [(UINT32, "index"), (ObjPointer(ID2D1Image), "input"), (BOOL, "invalidate")]),
+ StdMethod(HRESULT, "SetInputCount", [(UINT32, "inputCount")]),
+ StdMethod(Void, "GetInput", [(UINT32, "index"), Out(Pointer(ObjPointer(ID2D1Image)), "input")], const=True),
+ StdMethod(UINT32, "GetInputCount", [], const=True, sideeffects=False),
+ StdMethod(Void, "GetOutput", [(Pointer(ObjPointer(ID2D1Image)), "outputImage")], const=True, sideeffects=False),
+]
+
+ID2D1Bitmap1.methods += [
+ StdMethod(Void, "GetColorContext", [(Pointer(ObjPointer(ID2D1ColorContext)), "colorContext")], const=True, sideeffects=False),
+ StdMethod(D2D1_BITMAP_OPTIONS, "GetOptions", [], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetSurface", [(Pointer(ObjPointer(IDXGISurface)), "dxgiSurface")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "Map", [(D2D1_MAP_OPTIONS, "options"), Out(Pointer(D2D1_MAPPED_RECT), "mappedRect")]),
+ StdMethod(HRESULT, "Unmap", []),
+]
+
+ID2D1ColorContext.methods += [
+ StdMethod(D2D1_COLOR_SPACE, "GetColorSpace", [], const=True, sideeffects=False),
+ StdMethod(UINT32, "GetProfileSize", [], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetProfile", [Out(Pointer(BYTE), "profile"), (UINT32, "profileSize")], const=True, sideeffects=False),
+]
+
+ID2D1GradientStopCollection1.methods += [
+ StdMethod(Void, "GetGradientStops1", [Out(Array(D2D1_GRADIENT_STOP, "gradientStopsCount"), "gradientStops"), (UINT32, "gradientStopsCount")], const=True, sideeffects=False),
+ StdMethod(D2D1_COLOR_SPACE, "GetPreInterpolationSpace", [], const=True, sideeffects=False),
+ StdMethod(D2D1_COLOR_SPACE, "GetPostInterpolationSpace", [], const=True, sideeffects=False),
+ StdMethod(D2D1_BUFFER_PRECISION, "GetBufferPrecision", [], const=True, sideeffects=False),
+ StdMethod(D2D1_COLOR_INTERPOLATION_MODE, "GetColorInterpolationMode", [], const=True, sideeffects=False),
+]
+
+ID2D1DrawingStateBlock1.methods += [
+ StdMethod(Void, "GetDescription", [Out(Pointer(D2D1_DRAWING_STATE_DESCRIPTION1), "stateDescription")], const=True, sideeffects=False),
+ StdMethod(Void, "SetDescription", [(Pointer(Const(D2D1_DRAWING_STATE_DESCRIPTION1)), "stateDescription")]),
+]
+
+ID2D1DeviceContext.methods += [
+ StdMethod(HRESULT, "CreateBitmap", [(D2D1_SIZE_U, "size"), (OpaquePointer(Const(Void)), "sourceData"), (UINT32, "pitch"), (Pointer(Const(D2D1_BITMAP_PROPERTIES1)), "bitmapProperties"), Out(Pointer(ObjPointer(ID2D1Bitmap1)), "bitmap")]),
+ StdMethod(HRESULT, "CreateBitmapFromWicBitmap", [(Opaque("IWICBitmapSource *"), "wicBitmapSource"), (Pointer(Const(D2D1_BITMAP_PROPERTIES1)), "bitmapProperties"), Out(Pointer(ObjPointer(ID2D1Bitmap1)), "bitmap")]),
+ StdMethod(HRESULT, "CreateColorContext", [(D2D1_COLOR_SPACE, "space"), (Pointer(Const(BYTE)), "profile"), (UINT32, "profileSize"), Out(Pointer(ObjPointer(ID2D1ColorContext)), "colorContext")]),
+ StdMethod(HRESULT, "CreateColorContextFromFilename", [(PCWSTR, "filename"), Out(Pointer(ObjPointer(ID2D1ColorContext)), "colorContext")]),
+ StdMethod(HRESULT, "CreateColorContextFromWicColorContext", [(Opaque("IWICColorContext *"), "wicColorContext"), Out(Pointer(ObjPointer(ID2D1ColorContext)), "colorContext")]),
+ StdMethod(HRESULT, "CreateBitmapFromDxgiSurface", [(ObjPointer(IDXGISurface), "surface"), (Pointer(Const(D2D1_BITMAP_PROPERTIES1)), "bitmapProperties"), Out(Pointer(ObjPointer(ID2D1Bitmap1)), "bitmap")]),
+ StdMethod(HRESULT, "CreateEffect", [(REFCLSID, "effectId"), Out(Pointer(ObjPointer(ID2D1Effect)), "effect")]),
+ StdMethod(HRESULT, "CreateGradientStopCollection", [(Pointer(Const(D2D1_GRADIENT_STOP)), "straightAlphaGradientStops"), (UINT32, "straightAlphaGradientStopsCount"), (D2D1_COLOR_SPACE, "preInterpolationSpace"), (D2D1_COLOR_SPACE, "postInterpolationSpace"), (D2D1_BUFFER_PRECISION, "bufferPrecision"), (D2D1_EXTEND_MODE, "extendMode"), (D2D1_COLOR_INTERPOLATION_MODE, "colorInterpolationMode"), Out(Pointer(ObjPointer(ID2D1GradientStopCollection1)), "gradientStopCollection1")]),
+ StdMethod(HRESULT, "CreateImageBrush", [(ObjPointer(ID2D1Image), "image"), (Pointer(Const(D2D1_IMAGE_BRUSH_PROPERTIES)), "imageBrushProperties"), (Pointer(Const(D2D1_BRUSH_PROPERTIES)), "brushProperties"), Out(Pointer(ObjPointer(ID2D1ImageBrush)), "imageBrush")]),
+ StdMethod(HRESULT, "CreateBitmapBrush", [(ObjPointer(ID2D1Bitmap), "bitmap"), (Pointer(Const(D2D1_BITMAP_BRUSH_PROPERTIES1)), "bitmapBrushProperties"), (Pointer(Const(D2D1_BRUSH_PROPERTIES)), "brushProperties"), Out(Pointer(ObjPointer(ID2D1BitmapBrush1)), "bitmapBrush")]),
+ StdMethod(HRESULT, "CreateCommandList", [(Pointer(ObjPointer(ID2D1CommandList)), "commandList")]),
+ StdMethod(BOOL, "IsDxgiFormatSupported", [(DXGI_FORMAT, "format")], const=True, sideeffects=False),
+ StdMethod(BOOL, "IsBufferPrecisionSupported", [(D2D1_BUFFER_PRECISION, "bufferPrecision")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetImageLocalBounds", [(ObjPointer(ID2D1Image), "image"), Out(Pointer(D2D1_RECT_F), "localBounds")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetImageWorldBounds", [(ObjPointer(ID2D1Image), "image"), Out(Pointer(D2D1_RECT_F), "worldBounds")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetGlyphRunWorldBounds", [(D2D1_POINT_2F, "baselineOrigin"), (Pointer(Const(DWRITE_GLYPH_RUN)), "glyphRun"), (DWRITE_MEASURING_MODE, "measuringMode"), Out(Pointer(D2D1_RECT_F), "bounds")], const=True, sideeffects=False),
+ StdMethod(Void, "GetDevice", [(Pointer(ObjPointer(ID2D1Device)), "device")], const=True, sideeffects=False),
+ StdMethod(Void, "SetTarget", [(ObjPointer(ID2D1Image), "image")]),
+ StdMethod(Void, "GetTarget", [(Pointer(ObjPointer(ID2D1Image)), "image")], const=True, sideeffects=False),
+ StdMethod(Void, "SetRenderingControls", [(Pointer(Const(D2D1_RENDERING_CONTROLS)), "renderingControls")]),
+ StdMethod(Void, "GetRenderingControls", [Out(Pointer(D2D1_RENDERING_CONTROLS), "renderingControls")], const=True, sideeffects=False),
+ StdMethod(Void, "SetPrimitiveBlend", [(D2D1_PRIMITIVE_BLEND, "primitiveBlend")]),
+ StdMethod(D2D1_PRIMITIVE_BLEND, "GetPrimitiveBlend", [], const=True, sideeffects=False),
+ StdMethod(Void, "SetUnitMode", [(D2D1_UNIT_MODE, "unitMode")]),
+ StdMethod(D2D1_UNIT_MODE, "GetUnitMode", [], const=True, sideeffects=False),
+ StdMethod(Void, "DrawGlyphRun", [(D2D1_POINT_2F, "baselineOrigin"), (Pointer(Const(DWRITE_GLYPH_RUN)), "glyphRun"), (Pointer(Const(DWRITE_GLYPH_RUN_DESCRIPTION)), "glyphRunDescription"), (ObjPointer(ID2D1Brush), "foregroundBrush"), (DWRITE_MEASURING_MODE, "measuringMode")]),
+ StdMethod(Void, "DrawImage", [(ObjPointer(ID2D1Image), "image"), (Pointer(Const(D2D1_POINT_2F)), "targetOffset"), (Pointer(Const(D2D1_RECT_F)), "imageRectangle"), (D2D1_INTERPOLATION_MODE, "interpolationMode"), (D2D1_COMPOSITE_MODE, "compositeMode")]),
+ StdMethod(Void, "DrawGdiMetafile", [(ObjPointer(ID2D1GdiMetafile), "gdiMetafile"), (Pointer(Const(D2D1_POINT_2F)), "targetOffset")]),
+ StdMethod(Void, "DrawBitmap", [(ObjPointer(ID2D1Bitmap), "bitmap"), (Pointer(Const(D2D1_RECT_F)), "destinationRectangle"), (FLOAT, "opacity"), (D2D1_INTERPOLATION_MODE, "interpolationMode"), (Pointer(Const(D2D1_RECT_F)), "sourceRectangle"), (Pointer(Const(D2D1_MATRIX_4X4_F)), "perspectiveTransform")]),
+ StdMethod(Void, "PushLayer", [(Pointer(Const(D2D1_LAYER_PARAMETERS1)), "layerParameters"), (ObjPointer(ID2D1Layer), "layer")]),
+ StdMethod(HRESULT, "InvalidateEffectInputRectangle", [(ObjPointer(ID2D1Effect), "effect"), (UINT32, "input"), (Pointer(Const(D2D1_RECT_F)), "inputRectangle")]),
+ StdMethod(HRESULT, "GetEffectInvalidRectangleCount", [(ObjPointer(ID2D1Effect), "effect"), Out(Pointer(UINT32), "rectangleCount")]),
+ StdMethod(HRESULT, "GetEffectInvalidRectangles", [(ObjPointer(ID2D1Effect), "effect"), Out(Pointer(D2D1_RECT_F), "rectangles"), (UINT32, "rectanglesCount")]),
+ StdMethod(HRESULT, "GetEffectRequiredInputRectangles", [(ObjPointer(ID2D1Effect), "renderEffect"), (Pointer(Const(D2D1_RECT_F)), "renderImageRectangle"), (Pointer(Const(D2D1_EFFECT_INPUT_DESCRIPTION)), "inputDescriptions"), Out(Pointer(D2D1_RECT_F), "requiredInputRects"), (UINT32, "inputCount")]),
+ StdMethod(Void, "FillOpacityMask", [(ObjPointer(ID2D1Bitmap), "opacityMask"), (ObjPointer(ID2D1Brush), "brush"), (Pointer(Const(D2D1_RECT_F)), "destinationRectangle"), (Pointer(Const(D2D1_RECT_F)), "sourceRectangle")]),
+]
+
+ID2D1Device.methods += [
+ StdMethod(HRESULT, "CreateDeviceContext", [(D2D1_DEVICE_CONTEXT_OPTIONS, "options"), Out(Pointer(ObjPointer(ID2D1DeviceContext)), "deviceContext")]),
+ StdMethod(HRESULT, "CreatePrintControl", [(Opaque("IWICImagingFactory *"), "wicFactory"), (Opaque("IPrintDocumentPackageTarget *"), "documentTarget"), (Pointer(Const(D2D1_PRINT_CONTROL_PROPERTIES)), "printControlProperties"), Out(Pointer(ObjPointer(ID2D1PrintControl)), "printControl")]),
+ StdMethod(Void, "SetMaximumTextureMemory", [(UINT64, "maximumInBytes")]),
+ StdMethod(UINT64, "GetMaximumTextureMemory", [], const=True, sideeffects=False),
+ StdMethod(Void, "ClearResources", [(UINT32, "millisecondsSinceUse")]),
+]
+
+D2D1_PROPERTY_BINDING = Struct("D2D1_PROPERTY_BINDING", [])
+
+PD2D1_EFFECT_FACTORY = Opaque("PD2D1_EFFECT_FACTORY")
+
+ID2D1Factory1.methods += [
+ StdMethod(HRESULT, "CreateDevice", [(Opaque("IDXGIDevice *"), "dxgiDevice"), Out(Pointer(ObjPointer(ID2D1Device)), "d2dDevice")]),
+ StdMethod(HRESULT, "CreateStrokeStyle", [(Pointer(Const(D2D1_STROKE_STYLE_PROPERTIES1)), "strokeStyleProperties"), (Pointer(Const(FLOAT)), "dashes"), (UINT32, "dashesCount"), Out(Pointer(ObjPointer(ID2D1StrokeStyle1)), "strokeStyle")]),
+ StdMethod(HRESULT, "CreatePathGeometry", [(Pointer(ObjPointer(ID2D1PathGeometry1)), "pathGeometry")]),
+ StdMethod(HRESULT, "CreateDrawingStateBlock", [(Pointer(Const(D2D1_DRAWING_STATE_DESCRIPTION1)), "drawingStateDescription"), (ObjPointer(IDWriteRenderingParams), "textRenderingParams"), Out(Pointer(ObjPointer(ID2D1DrawingStateBlock1)), "drawingStateBlock")]),
+ StdMethod(HRESULT, "CreateGdiMetafile", [(Opaque("IStream *"), "metafileStream"), Out(Pointer(ObjPointer(ID2D1GdiMetafile)), "metafile")]),
+ StdMethod(HRESULT, "RegisterEffectFromStream", [(REFCLSID, "classId"), (Opaque("IStream *"), "propertyXml"), (Pointer(Const(D2D1_PROPERTY_BINDING)), "bindings"), (UINT32, "bindingsCount"), (Const(PD2D1_EFFECT_FACTORY), "effectFactory")]),
+ StdMethod(HRESULT, "RegisterEffectFromString", [(REFCLSID, "classId"), (PCWSTR, "propertyXml"), (Pointer(Const(D2D1_PROPERTY_BINDING)), "bindings"), (UINT32, "bindingsCount"), (Const(PD2D1_EFFECT_FACTORY), "effectFactory")]),
+ StdMethod(HRESULT, "UnregisterEffect", [(REFCLSID, "classId")]),
+ StdMethod(HRESULT, "GetRegisteredEffects", [Out(Pointer(CLSID), "effects"), (UINT32, "effectsCount"), Out(Pointer(UINT32), "effectsReturned"), Out(Pointer(UINT32), "effectsRegistered")], const=True, sideeffects=False),
+ StdMethod(HRESULT, "GetEffectProperties", [(REFCLSID, "effectId"), Out(Pointer(ObjPointer(ID2D1Properties)), "properties")], const=True),
+]
+
+ID2D1Multithread.methods += [
+ StdMethod(BOOL, "GetMultithreadProtected", [], const=True, sideeffects=False),
+ StdMethod(Void, "Enter", []),
+ StdMethod(Void, "Leave", []),
+]
+
+d2d1.addInterfaces([
+ ID2D1Factory1,
+ ID2D1Multithread,
+])
+d2d1.addFunctions([
+ StdFunction(HRESULT, "D2D1CreateDevice", [(Opaque("IDXGIDevice *"), "dxgiDevice"), (Pointer(Const(D2D1_CREATION_PROPERTIES)), "creationProperties"), Out(Pointer(ObjPointer(ID2D1Device)), "d2dDevice")]),
+ StdFunction(HRESULT, "D2D1CreateDeviceContext", [(ObjPointer(IDXGISurface), "dxgiSurface"), (Pointer(Const(D2D1_CREATION_PROPERTIES)), "creationProperties"), Out(Pointer(ObjPointer(ID2D1DeviceContext)), "d2dDeviceContext")]),
+ StdFunction(D2D1_COLOR_F, "D2D1ConvertColorSpace", [(D2D1_COLOR_SPACE, "sourceColorSpace"), (D2D1_COLOR_SPACE, "destinationColorSpace"), (Pointer(Const(D2D1_COLOR_F)), "color")]),
+ StdFunction(Void, "D2D1SinCos", [(FLOAT, "angle"), Out(Pointer(FLOAT), "s"), Out(Pointer(FLOAT), "c")]),
+ StdFunction(FLOAT, "D2D1Tan", [(FLOAT, "angle")]),
+ StdFunction(FLOAT, "D2D1Vec3Length", [(FLOAT, "x"), (FLOAT, "y"), (FLOAT, "z")]),
+])
diff --git a/specs/d2dbasetypes.py b/specs/d2dbasetypes.py
deleted file mode 100644
index 86ba7943..00000000
--- a/specs/d2dbasetypes.py
+++ /dev/null
@@ -1,80 +0,0 @@
-##########################################################################
-#
-# Copyright 2011 Jose Fonseca
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-
-from winapi import *
-
-
-D3DCOLORVALUE = Struct("D3DCOLORVALUE", [
- (FLOAT, "r"),
- (FLOAT, "g"),
- (FLOAT, "b"),
- (FLOAT, "a"),
-])
-
-D2D_POINT_2U = Struct("D2D_POINT_2U", [
- (UINT32, "x"),
- (UINT32, "y"),
-])
-
-D2D_POINT_2F = Struct("D2D_POINT_2F", [
- (FLOAT, "x"),
- (FLOAT, "y"),
-])
-
-D2D_RECT_F = Struct("D2D_RECT_F", [
- (FLOAT, "left"),
- (FLOAT, "top"),
- (FLOAT, "right"),
- (FLOAT, "bottom"),
-])
-
-D2D_RECT_U = Struct("D2D_RECT_U", [
- (UINT32, "left"),
- (UINT32, "top"),
- (UINT32, "right"),
- (UINT32, "bottom"),
-])
-
-D2D_SIZE_F = Struct("D2D_SIZE_F", [
- (FLOAT, "width"),
- (FLOAT, "height"),
-])
-
-D2D_SIZE_U = Struct("D2D_SIZE_U", [
- (UINT32, "width"),
- (UINT32, "height"),
-])
-
-D2D_COLOR_F = Alias("D2D_COLOR_F", D3DCOLORVALUE)
-D2D_MATRIX_3X2_F = Struct("D2D_MATRIX_3X2_F", [
- (FLOAT, "_11"),
- (FLOAT, "_12"),
- (FLOAT, "_21"),
- (FLOAT, "_22"),
- (FLOAT, "_31"),
- (FLOAT, "_32"),
-])
-
diff --git a/specs/d2derr.py b/specs/d2derr.py
deleted file mode 100644
index 35898ac2..00000000
--- a/specs/d2derr.py
+++ /dev/null
@@ -1,62 +0,0 @@
-##########################################################################
-#
-# Copyright 2011 Jose Fonseca
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-
-from winapi import *
-
-
-HRESULT = Enum("HRESULT", [
- "D2DERR_UNSUPPORTED_PIXEL_FORMAT",
- "D2DERR_INSUFFICIENT_BUFFER",
- "D2DERR_WRONG_STATE",
- "D2DERR_NOT_INITIALIZED",
- "D2DERR_UNSUPPORTED_OPERATION",
- "D2DERR_SCANNER_FAILED",
- "D2DERR_SCREEN_ACCESS_DENIED",
- "D2DERR_DISPLAY_STATE_INVALID",
- "D2DERR_ZERO_VECTOR",
- "D2DERR_INTERNAL_ERROR",
- "D2DERR_DISPLAY_FORMAT_NOT_SUPPORTED",
- "D2DERR_INVALID_CALL",
- "D2DERR_NO_HARDWARE_DEVICE",
- "D2DERR_RECREATE_TARGET",
- "D2DERR_TOO_MANY_SHADER_ELEMENTS",
- "D2DERR_SHADER_COMPILE_FAILED",
- "D2DERR_MAX_TEXTURE_SIZE_EXCEEDED",
- "D2DERR_UNSUPPORTED_VERSION",
- "D2DERR_BAD_NUMBER",
- "D2DERR_WRONG_FACTORY",
- "D2DERR_LAYER_ALREADY_IN_USE",
- "D2DERR_POP_CALL_DID_NOT_MATCH_PUSH",
- "D2DERR_WRONG_RENDER_TARGET",
- "D2DERR_PUSH_POP_UNBALANCED",
- "D2DERR_RENDER_TARGET_HAS_LAYER_OR_CLIPRECT",
- "D2DERR_INCOMPATIBLE_BRUSH_TYPES",
- "D2DERR_WIN32_ERROR",
- "D2DERR_TARGET_NOT_GDI_COMPATIBLE",
- "D2DERR_TEXT_EFFECT_IS_WRONG_TYPE",
- "D2DERR_TEXT_RENDERER_NOT_RELEASED",
- "D2DERR_EXCEEDS_MAX_BITMAP_SIZE",
-])
diff --git a/specs/d3d.py b/specs/d3d.py
index 61c8d048..0dde09f4 100644
--- a/specs/d3d.py
+++ b/specs/d3d.py
@@ -179,7 +179,7 @@ LPDIRECT3DVERTEXBUFFER7 = ObjPointer(IDirect3DVertexBuffer7)
IDirect3D.methods += [
StdMethod(HRESULT, "Initialize", [(REFCLSID, "riid")]),
- StdMethod(HRESULT, "EnumDevices", [(LPD3DENUMDEVICESCALLBACK, "lpEnumDevicesCallback"), (LPVOID, "lpUserArg")]),
+ StdMethod(HRESULT, "EnumDevices", [(LPD3DENUMDEVICESCALLBACK, "lpEnumDevicesCallback"), (LPVOID, "lpUserArg")], sideeffects=False),
StdMethod(HRESULT, "CreateLight", [Out(Pointer(LPDIRECT3DLIGHT), "lplpDirect3DLight"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(HRESULT, "CreateMaterial", [Out(Pointer(LPDIRECT3DMATERIAL), "lplpDirect3DMaterial"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(HRESULT, "CreateViewport", [Out(Pointer(LPDIRECT3DVIEWPORT), "lplpD3DViewport"), (LPUNKNOWN, "pUnkOuter")]),
@@ -187,7 +187,7 @@ IDirect3D.methods += [
]
IDirect3D2.methods += [
- StdMethod(HRESULT, "EnumDevices", [(LPD3DENUMDEVICESCALLBACK, "lpEnumDevicesCallback"), (LPVOID, "lpUserArg")]),
+ StdMethod(HRESULT, "EnumDevices", [(LPD3DENUMDEVICESCALLBACK, "lpEnumDevicesCallback"), (LPVOID, "lpUserArg")], sideeffects=False),
StdMethod(HRESULT, "CreateLight", [Out(Pointer(LPDIRECT3DLIGHT), "lplpDirect3DLight"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(HRESULT, "CreateMaterial", [Out(Pointer(LPDIRECT3DMATERIAL2), "lplpDirect3DMaterial2"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(HRESULT, "CreateViewport", [Out(Pointer(LPDIRECT3DVIEWPORT2), "lplpD3DViewport2"), (LPUNKNOWN, "pUnkOuter")]),
@@ -196,41 +196,41 @@ IDirect3D2.methods += [
]
IDirect3D3.methods += [
- StdMethod(HRESULT, "EnumDevices", [(LPD3DENUMDEVICESCALLBACK, "lpEnumDevicesCallback"), (LPVOID, "lpUserArg")]),
+ StdMethod(HRESULT, "EnumDevices", [(LPD3DENUMDEVICESCALLBACK, "lpEnumDevicesCallback"), (LPVOID, "lpUserArg")], sideeffects=False),
StdMethod(HRESULT, "CreateLight", [Out(Pointer(LPDIRECT3DLIGHT), "lplpDirect3DLight"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(HRESULT, "CreateMaterial", [Out(Pointer(LPDIRECT3DMATERIAL3), "lplpDirect3DMaterial3"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(HRESULT, "CreateViewport", [Out(Pointer(LPDIRECT3DVIEWPORT3), "lplpD3DViewport3"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(HRESULT, "FindDevice", [(LPD3DFINDDEVICESEARCH, "lpD3DDFS"), Out(LPD3DFINDDEVICERESULT, "lpD3DFDR")]),
StdMethod(HRESULT, "CreateDevice", [(REFCLSID, "rclsid"), (LPDIRECTDRAWSURFACE4, "lpDDS"), Out(Pointer(LPDIRECT3DDEVICE3), "lplpD3DDevice3"), (LPUNKNOWN, "lpUnk")]),
StdMethod(HRESULT, "CreateVertexBuffer", [(LPD3DVERTEXBUFFERDESC, "lpD3DVertBufDesc"), Out(Pointer(LPDIRECT3DVERTEXBUFFER), "lplpD3DVertBuf"), (DWORD, "dwFlags"), (LPUNKNOWN, "lpUnk")]),
- StdMethod(HRESULT, "EnumZBufferFormats", [(REFCLSID, "riidDevice"), (LPD3DENUMPIXELFORMATSCALLBACK, "lpEnumCallback"), (LPVOID, "lpContext")]),
+ StdMethod(HRESULT, "EnumZBufferFormats", [(REFCLSID, "riidDevice"), (LPD3DENUMPIXELFORMATSCALLBACK, "lpEnumCallback"), (LPVOID, "lpContext")], sideeffects=False),
StdMethod(HRESULT, "EvictManagedTextures", []),
]
IDirect3D7.methods += [
- StdMethod(HRESULT, "EnumDevices", [(LPD3DENUMDEVICESCALLBACK7, "lpEnumDevicesCallback"), (LPVOID, "lpUserArg")]),
+ StdMethod(HRESULT, "EnumDevices", [(LPD3DENUMDEVICESCALLBACK7, "lpEnumDevicesCallback"), (LPVOID, "lpUserArg")], sideeffects=False),
StdMethod(HRESULT, "CreateDevice", [(REFCLSID, "rclsid"), (LPDIRECTDRAWSURFACE7, "lpDDS"), Out(Pointer(LPDIRECT3DDEVICE7), "lplpD3DDevice")]),
StdMethod(HRESULT, "CreateVertexBuffer", [(LPD3DVERTEXBUFFERDESC, "lpD3DVertBufDesc"), Out(Pointer(LPDIRECT3DVERTEXBUFFER7), "lplpD3DVertBuf"), (DWORD, "dwFlags")]),
- StdMethod(HRESULT, "EnumZBufferFormats", [(REFCLSID, "riidDevice"), (LPD3DENUMPIXELFORMATSCALLBACK, "lpEnumCallback"), (LPVOID, "lpContext")]),
+ StdMethod(HRESULT, "EnumZBufferFormats", [(REFCLSID, "riidDevice"), (LPD3DENUMPIXELFORMATSCALLBACK, "lpEnumCallback"), (LPVOID, "lpContext")], sideeffects=False),
StdMethod(HRESULT, "EvictManagedTextures", []),
]
IDirect3DDevice.methods += [
StdMethod(HRESULT, "Initialize", [(LPDIRECT3D, "lpDirect3D"), (LPGUID, "lpGUID"), (LPD3DDEVICEDESC, "lpD3DDVDesc")]),
- StdMethod(HRESULT, "GetCaps", [Out(LPD3DDEVICEDESC, "lpD3DHWDevDesc"), Out(LPD3DDEVICEDESC, "lpD3DHELDevDesc")]),
+ StdMethod(HRESULT, "GetCaps", [Out(LPD3DDEVICEDESC, "lpD3DHWDevDesc"), Out(LPD3DDEVICEDESC, "lpD3DHELDevDesc")], sideeffects=False),
StdMethod(HRESULT, "SwapTextureHandles", [(LPDIRECT3DTEXTURE, "lpD3Dtex1"), (LPDIRECT3DTEXTURE, "lpD3DTex2")]),
StdMethod(HRESULT, "CreateExecuteBuffer", [(LPD3DEXECUTEBUFFERDESC, "lpDesc"), Out(Pointer(LPDIRECT3DEXECUTEBUFFER), "lplpDirect3DExecuteBuffer"), (LPUNKNOWN, "pUnkOuter")]),
- StdMethod(HRESULT, "GetStats", [(LPD3DSTATS, "lpD3DStats")]),
+ StdMethod(HRESULT, "GetStats", [(LPD3DSTATS, "lpD3DStats")], sideeffects=False),
StdMethod(HRESULT, "Execute", [(LPDIRECT3DEXECUTEBUFFER, "lpDirect3DExecuteBuffer"), (LPDIRECT3DVIEWPORT, "lpDirect3DViewport"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "AddViewport", [(LPDIRECT3DVIEWPORT, "lpDirect3DViewport")]),
StdMethod(HRESULT, "DeleteViewport", [(LPDIRECT3DVIEWPORT, "lpDirect3DViewport")]),
StdMethod(HRESULT, "NextViewport", [(LPDIRECT3DVIEWPORT, "lpDirect3DViewport"), Out(Pointer(LPDIRECT3DVIEWPORT), "lplpDirect3DViewport"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "Pick", [(LPDIRECT3DEXECUTEBUFFER, "lpDirect3DExecuteBuffer"), (LPDIRECT3DVIEWPORT, "lpDirect3DViewport"), (DWORD, "dwFlags"), (LPD3DRECT, "lpRect")]),
- StdMethod(HRESULT, "GetPickRecords", [(LPDWORD, "lpCount"), (LPD3DPICKRECORD, "lpD3DPickRec")]),
- StdMethod(HRESULT, "EnumTextureFormats", [(LPD3DENUMTEXTUREFORMATSCALLBACK, "lpD3DEnumTextureProc"), (LPVOID, "lpArg")]),
+ StdMethod(HRESULT, "GetPickRecords", [(LPDWORD, "lpCount"), (LPD3DPICKRECORD, "lpD3DPickRec")], sideeffects=False),
+ StdMethod(HRESULT, "EnumTextureFormats", [(LPD3DENUMTEXTUREFORMATSCALLBACK, "lpD3DEnumTextureProc"), (LPVOID, "lpArg")], sideeffects=False),
StdMethod(HRESULT, "CreateMatrix", [Out(LPD3DMATRIXHANDLE, "lpD3DMatHandle")]),
StdMethod(HRESULT, "SetMatrix", [(D3DMATRIXHANDLE, "D3DMatHandle"), (Const(LPD3DMATRIX), "lpD3DMatrix")]),
- StdMethod(HRESULT, "GetMatrix", [(D3DMATRIXHANDLE, "D3DMatHandle"), Out(LPD3DMATRIX, "lpD3DMatrix")]),
+ StdMethod(HRESULT, "GetMatrix", [(D3DMATRIXHANDLE, "D3DMatHandle"), Out(LPD3DMATRIX, "lpD3DMatrix")], sideeffects=False),
StdMethod(HRESULT, "DeleteMatrix", [(D3DMATRIXHANDLE, "D3DMatHandle")]),
StdMethod(HRESULT, "BeginScene", []),
StdMethod(HRESULT, "EndScene", []),
@@ -238,18 +238,18 @@ IDirect3DDevice.methods += [
]
IDirect3DDevice2.methods += [
- StdMethod(HRESULT, "GetCaps", [Out(LPD3DDEVICEDESC, "lpD3DHWDevDesc"), Out(LPD3DDEVICEDESC, "lpD3DHELDevDesc")]),
+ StdMethod(HRESULT, "GetCaps", [Out(LPD3DDEVICEDESC, "lpD3DHWDevDesc"), Out(LPD3DDEVICEDESC, "lpD3DHELDevDesc")], sideeffects=False),
StdMethod(HRESULT, "SwapTextureHandles", [(LPDIRECT3DTEXTURE2, "lpD3DTex1"), (LPDIRECT3DTEXTURE2, "lpD3DTex2")]),
- StdMethod(HRESULT, "GetStats", [Out(LPD3DSTATS, "lpD3DStats")]),
+ StdMethod(HRESULT, "GetStats", [Out(LPD3DSTATS, "lpD3DStats")], sideeffects=False),
StdMethod(HRESULT, "AddViewport", [(LPDIRECT3DVIEWPORT2, "lpDirect3DViewport2")]),
StdMethod(HRESULT, "DeleteViewport", [(LPDIRECT3DVIEWPORT2, "lpDirect3DViewport2")]),
StdMethod(HRESULT, "NextViewport", [(LPDIRECT3DVIEWPORT2, "lpDirect3DViewport2"), Out(Pointer(LPDIRECT3DVIEWPORT2), "lplpDirect3DViewport2"), (DWORD, "dwFlags")]),
- StdMethod(HRESULT, "EnumTextureFormats", [(LPD3DENUMTEXTUREFORMATSCALLBACK, "lpD3DEnumTextureProc"), (LPVOID, "lpArg")]),
+ StdMethod(HRESULT, "EnumTextureFormats", [(LPD3DENUMTEXTUREFORMATSCALLBACK, "lpD3DEnumTextureProc"), (LPVOID, "lpArg")], sideeffects=False),
StdMethod(HRESULT, "BeginScene", []),
StdMethod(HRESULT, "EndScene", []),
StdMethod(HRESULT, "GetDirect3D", [Out(Pointer(LPDIRECT3D2), "lplpDirect3D2")]),
StdMethod(HRESULT, "SetCurrentViewport", [(LPDIRECT3DVIEWPORT2, "lpDirect3DViewport2")]),
- StdMethod(HRESULT, "GetCurrentViewport", [Out(Pointer(LPDIRECT3DVIEWPORT2), "lplpDirect3DViewport2")]),
+ StdMethod(HRESULT, "GetCurrentViewport", [Out(Pointer(LPDIRECT3DVIEWPORT2), "lplpDirect3DViewport2")], sideeffects=False),
StdMethod(HRESULT, "SetRenderTarget", [(LPDIRECTDRAWSURFACE, "lpNewRenderTarget"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "GetRenderTarget", [Out(Pointer(LPDIRECTDRAWSURFACE), "lplpRenderTarget")]),
StdMethod(HRESULT, "Begin", [(D3DPRIMITIVETYPE, "d3dpt"), (D3DVERTEXTYPE, "dwVertexTypeDesc"), (DWORD, "dwFlags")]),
@@ -257,31 +257,31 @@ IDirect3DDevice2.methods += [
StdMethod(HRESULT, "Vertex", [(LPVOID, "lpVertexType")]),
StdMethod(HRESULT, "Index", [(WORD, "wVertexIndex")]),
StdMethod(HRESULT, "End", [(DWORD, "dwFlags")]),
- StdMethod(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "dwRenderStateType"), Out(LPDWORD, "lpdwRenderState")]),
+ StdMethod(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "dwRenderStateType"), Out(LPDWORD, "lpdwRenderState")], sideeffects=False),
StdMethod(HRESULT, "SetRenderState", [(D3DRENDERSTATETYPE, "dwRenderStateType"), (DWORD, "dwRenderState")]),
- StdMethod(HRESULT, "GetLightState", [(D3DLIGHTSTATETYPE, "dwLightStateType"), Out(LPDWORD, "lpdwLightState")]),
+ StdMethod(HRESULT, "GetLightState", [(D3DLIGHTSTATETYPE, "dwLightStateType"), Out(LPDWORD, "lpdwLightState")], sideeffects=False),
StdMethod(HRESULT, "SetLightState", [(D3DLIGHTSTATETYPE, "dwLightStateType"), (DWORD, "dwLightState")]),
StdMethod(HRESULT, "SetTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), (LPD3DMATRIX, "lpD3DMatrix")]),
- StdMethod(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), Out(LPD3DMATRIX, "lpD3DMatrix")]),
+ StdMethod(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), Out(LPD3DMATRIX, "lpD3DMatrix")], sideeffects=False),
StdMethod(HRESULT, "MultiplyTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), (LPD3DMATRIX, "lpD3DMatrix")]),
StdMethod(HRESULT, "DrawPrimitive", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (D3DVERTEXTYPE, "d3dvtVertexType"), (LPVOID, "lpvVertices"), (DWORD, "dwVertexCount"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "DrawIndexedPrimitive", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (D3DVERTEXTYPE, "d3dvtVertexType"), (LPVOID, "lpvVertices"), (DWORD, "dwVertexCount"), (LPWORD, "dwIndices"), (DWORD, "dwIndexCount"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "SetClipStatus", [(LPD3DCLIPSTATUS, "lpD3DClipStatus")]),
- StdMethod(HRESULT, "GetClipStatus", [(LPD3DCLIPSTATUS, "lpD3DClipStatus")]),
+ StdMethod(HRESULT, "GetClipStatus", [(LPD3DCLIPSTATUS, "lpD3DClipStatus")], sideeffects=False),
]
IDirect3DDevice3.methods += [
- StdMethod(HRESULT, "GetCaps", [Out(LPD3DDEVICEDESC, "lpD3DHWDevDesc"), Out(LPD3DDEVICEDESC, "lpD3DHELDevDesc")]),
- StdMethod(HRESULT, "GetStats", [Out(LPD3DSTATS, "lpD3DStats")]),
+ StdMethod(HRESULT, "GetCaps", [Out(LPD3DDEVICEDESC, "lpD3DHWDevDesc"), Out(LPD3DDEVICEDESC, "lpD3DHELDevDesc")], sideeffects=False),
+ StdMethod(HRESULT, "GetStats", [Out(LPD3DSTATS, "lpD3DStats")], sideeffects=False),
StdMethod(HRESULT, "AddViewport", [(LPDIRECT3DVIEWPORT3, "lpDirect3DViewport3")]),
StdMethod(HRESULT, "DeleteViewport", [(LPDIRECT3DVIEWPORT3, "lpDirect3DViewport3")]),
StdMethod(HRESULT, "NextViewport", [(LPDIRECT3DVIEWPORT3, "lpDirect3DViewport3"), Out(Pointer(LPDIRECT3DVIEWPORT3), "lplpDirect3DViewport3"), (DWORD, "dwFlags")]),
- StdMethod(HRESULT, "EnumTextureFormats", [(LPD3DENUMPIXELFORMATSCALLBACK, "lpD3DEnumPixelProc"), (LPVOID, "lpArg")]),
+ StdMethod(HRESULT, "EnumTextureFormats", [(LPD3DENUMPIXELFORMATSCALLBACK, "lpD3DEnumPixelProc"), (LPVOID, "lpArg")], sideeffects=False),
StdMethod(HRESULT, "BeginScene", []),
StdMethod(HRESULT, "EndScene", []),
StdMethod(HRESULT, "GetDirect3D", [Out(Pointer(LPDIRECT3D3), "lplpDirect3D3")]),
StdMethod(HRESULT, "SetCurrentViewport", [(LPDIRECT3DVIEWPORT3, "lpDirect3DViewport3")]),
- StdMethod(HRESULT, "GetCurrentViewport", [Out(Pointer(LPDIRECT3DVIEWPORT3), "lplpDirect3DViewport3")]),
+ StdMethod(HRESULT, "GetCurrentViewport", [Out(Pointer(LPDIRECT3DVIEWPORT3), "lplpDirect3DViewport3")], sideeffects=False),
StdMethod(HRESULT, "SetRenderTarget", [(LPDIRECTDRAWSURFACE4, "lpNewRenderTarget"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "GetRenderTarget", [Out(Pointer(LPDIRECTDRAWSURFACE4), "lplpRenderTarget")]),
StdMethod(HRESULT, "Begin", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (DWORD, "dwVertexTypeDesc"), (DWORD, "dwFlags")]),
@@ -289,17 +289,17 @@ IDirect3DDevice3.methods += [
StdMethod(HRESULT, "Vertex", [(LPVOID, "lpVertexType")]),
StdMethod(HRESULT, "Index", [(WORD, "wVertexIndex")]),
StdMethod(HRESULT, "End", [(DWORD, "dwFlags")]),
- StdMethod(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "dwRenderStateType"), Out(LPDWORD, "lpdwRenderState")]),
+ StdMethod(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "dwRenderStateType"), Out(LPDWORD, "lpdwRenderState")], sideeffects=False),
StdMethod(HRESULT, "SetRenderState", [(D3DRENDERSTATETYPE, "dwRenderStateType"), (DWORD, "dwRenderState")]),
- StdMethod(HRESULT, "GetLightState", [(D3DLIGHTSTATETYPE, "dwLightStateType"), Out(LPDWORD, "lpdwLightState")]),
+ StdMethod(HRESULT, "GetLightState", [(D3DLIGHTSTATETYPE, "dwLightStateType"), Out(LPDWORD, "lpdwLightState")], sideeffects=False),
StdMethod(HRESULT, "SetLightState", [(D3DLIGHTSTATETYPE, "dwLightStateType"), (DWORD, "dwLightState")]),
StdMethod(HRESULT, "SetTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), (LPD3DMATRIX, "lpD3DMatrix")]),
- StdMethod(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), Out(LPD3DMATRIX, "lpD3DMatrix")]),
+ StdMethod(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), Out(LPD3DMATRIX, "lpD3DMatrix")], sideeffects=False),
StdMethod(HRESULT, "MultiplyTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), (LPD3DMATRIX, "lpD3DMatrix")]),
StdMethod(HRESULT, "DrawPrimitive", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (DWORD, "d3dvtVertexType"), (LPVOID, "lpvVertices"), (DWORD, "dwVertexCount"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "DrawIndexedPrimitive", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (DWORD, "d3dvtVertexType"), (LPVOID, "lpvVertices"), (DWORD, "dwVertexCount"), (LPWORD, "dwIndices"), (DWORD, "dwIndexCount"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "SetClipStatus", [(LPD3DCLIPSTATUS, "lpD3DClipStatus")]),
- StdMethod(HRESULT, "GetClipStatus", [Out(LPD3DCLIPSTATUS, "lpD3DClipStatus")]),
+ StdMethod(HRESULT, "GetClipStatus", [Out(LPD3DCLIPSTATUS, "lpD3DClipStatus")], sideeffects=False),
StdMethod(HRESULT, "DrawPrimitiveStrided", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (DWORD, "dwVertexType"), (LPD3DDRAWPRIMITIVESTRIDEDDATA, "lpD3DDrawPrimStrideData"), (DWORD, "dwVertexCount"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "DrawIndexedPrimitiveStrided", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (DWORD, "dwVertexType"), (LPD3DDRAWPRIMITIVESTRIDEDDATA, "lpD3DDrawPrimStrideData"), (DWORD, "dwVertexCount"), (LPWORD, "lpIndex"), (DWORD, "dwIndexCount"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "DrawPrimitiveVB", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (LPDIRECT3DVERTEXBUFFER, "lpD3DVertexBuf"), (DWORD, "dwStartVertex"), (DWORD, "dwNumVertices"), (DWORD, "dwFlags")]),
@@ -307,38 +307,38 @@ IDirect3DDevice3.methods += [
StdMethod(HRESULT, "ComputeSphereVisibility", [(LPD3DVECTOR, "lpCenters"), (LPD3DVALUE, "lpRadii"), (DWORD, "dwNumSpheres"), (DWORD, "dwFlags"), (LPDWORD, "lpdwReturnValues")]),
StdMethod(HRESULT, "GetTexture", [(DWORD, "dwStage"), Out(Pointer(LPDIRECT3DTEXTURE2), "lplpTexture2")]),
StdMethod(HRESULT, "SetTexture", [(DWORD, "dwStage"), (LPDIRECT3DTEXTURE2, "lpTexture2")]),
- StdMethod(HRESULT, "GetTextureStageState", [(DWORD, "dwStage"), (D3DTEXTURESTAGESTATETYPE, "d3dTexStageStateType"), Out(LPDWORD, "lpdwState")]),
+ StdMethod(HRESULT, "GetTextureStageState", [(DWORD, "dwStage"), (D3DTEXTURESTAGESTATETYPE, "d3dTexStageStateType"), Out(LPDWORD, "lpdwState")], sideeffects=False),
StdMethod(HRESULT, "SetTextureStageState", [(DWORD, "dwStage"), (D3DTEXTURESTAGESTATETYPE, "d3dTexStageStateType"), (DWORD, "dwState")]),
StdMethod(HRESULT, "ValidateDevice", [(LPDWORD, "lpdwPasses")]),
]
IDirect3DDevice7.methods += [
- StdMethod(HRESULT, "GetCaps", [Out(LPD3DDEVICEDESC7, "lpD3DHELDevDesc")]),
- StdMethod(HRESULT, "EnumTextureFormats", [(LPD3DENUMPIXELFORMATSCALLBACK, "lpD3DEnumPixelProc"), (LPVOID, "lpArg")]),
+ StdMethod(HRESULT, "GetCaps", [Out(LPD3DDEVICEDESC7, "lpD3DHELDevDesc")], sideeffects=False),
+ StdMethod(HRESULT, "EnumTextureFormats", [(LPD3DENUMPIXELFORMATSCALLBACK, "lpD3DEnumPixelProc"), (LPVOID, "lpArg")], sideeffects=False),
StdMethod(HRESULT, "BeginScene", []),
StdMethod(HRESULT, "EndScene", []),
StdMethod(HRESULT, "GetDirect3D", [Out(Pointer(LPDIRECT3D7), "lplpDirect3D3")]),
StdMethod(HRESULT, "SetRenderTarget", [(LPDIRECTDRAWSURFACE7, "lpNewRenderTarget"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "GetRenderTarget", [Out(Pointer(LPDIRECTDRAWSURFACE7), "lplpRenderTarget")]),
- StdMethod(HRESULT, "Clear", [(DWORD, "dwCount"), (LPD3DRECT, "lpRects"), (DWORD, "dwFlags"), (D3DCOLOR, "dwColor"), (D3DVALUE, "dvZ"), (DWORD, "dwStencil")]),
+ StdMethod(HRESULT, "Clear", [(DWORD, "dwCount"), (Array(D3DRECT, "dwCount"), "lpRects"), (D3DCLEAR, "dwFlags"), (D3DCOLOR, "dwColor"), (D3DVALUE, "dvZ"), (DWORD, "dwStencil")]),
StdMethod(HRESULT, "SetTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), (LPD3DMATRIX, "lpD3DMatrix")]),
- StdMethod(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), Out(LPD3DMATRIX, "lpD3DMatrix")]),
+ StdMethod(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), Out(LPD3DMATRIX, "lpD3DMatrix")], sideeffects=False),
StdMethod(HRESULT, "SetViewport", [(LPD3DVIEWPORT7, "lpData")]),
StdMethod(HRESULT, "MultiplyTransform", [(D3DTRANSFORMSTATETYPE, "dtstTransformStateType"), (LPD3DMATRIX, "lpD3DMatrix")]),
- StdMethod(HRESULT, "GetViewport", [Out(LPD3DVIEWPORT7, "lpData")]),
+ StdMethod(HRESULT, "GetViewport", [Out(LPD3DVIEWPORT7, "lpData")], sideeffects=False),
StdMethod(HRESULT, "SetMaterial", [(LPD3DMATERIAL7, "lpMat")]),
- StdMethod(HRESULT, "GetMaterial", [Out(LPD3DMATERIAL7, "lpMat")]),
+ StdMethod(HRESULT, "GetMaterial", [Out(LPD3DMATERIAL7, "lpMat")], sideeffects=False),
StdMethod(HRESULT, "SetLight", [(DWORD, "dwLightIndex"), (LPD3DLIGHT7, "lpLight")]),
- StdMethod(HRESULT, "GetLight", [(DWORD, "dwLightIndex"), (LPD3DLIGHT7, "lpLight")]),
+ StdMethod(HRESULT, "GetLight", [(DWORD, "dwLightIndex"), (LPD3DLIGHT7, "lpLight")], sideeffects=False),
StdMethod(HRESULT, "SetRenderState", [(D3DRENDERSTATETYPE, "dwRenderStateType"), (DWORD, "dwRenderState")]),
- StdMethod(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "dwRenderStateType"), Out(LPDWORD, "lpdwRenderState")]),
+ StdMethod(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "dwRenderStateType"), Out(LPDWORD, "lpdwRenderState")], sideeffects=False),
StdMethod(HRESULT, "BeginStateBlock", []),
StdMethod(HRESULT, "EndStateBlock", [Out(LPDWORD, "lpdwBlockHandle")]),
StdMethod(HRESULT, "PreLoad", [(LPDIRECTDRAWSURFACE7, "lpddsTexture")]),
- StdMethod(HRESULT, "DrawPrimitive", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (D3DFVF, "d3dvtVertexType"), (LPVOID, "lpvVertices"), (DWORD, "dwVertexCount"), (DWORD, "dwFlags")]),
- StdMethod(HRESULT, "DrawIndexedPrimitive", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (D3DFVF, "d3dvtVertexType"), (LPVOID, "lpvVertices"), (DWORD, "dwVertexCount"), (LPWORD, "dwIndices"), (DWORD, "dwIndexCount"), (DWORD, "dwFlags")]),
+ StdMethod(HRESULT, "DrawPrimitive", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (D3DFVF, "d3dvtVertexType"), (Blob(VOID, "dwVertexCount * _getVertexSize(d3dvtVertexType)"), "lpvVertices"), (DWORD, "dwVertexCount"), (DWORD, "dwFlags")]),
+ StdMethod(HRESULT, "DrawIndexedPrimitive", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (D3DFVF, "d3dvtVertexType"), (Blob(VOID, "dwVertexCount * _getVertexSize(d3dvtVertexType)"), "lpvVertices"), (DWORD, "dwVertexCount"), (LPWORD, "dwIndices"), (DWORD, "dwIndexCount"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "SetClipStatus", [(LPD3DCLIPSTATUS, "lpD3DClipStatus")]),
- StdMethod(HRESULT, "GetClipStatus", [Out(LPD3DCLIPSTATUS, "lpD3DClipStatus")]),
+ StdMethod(HRESULT, "GetClipStatus", [Out(LPD3DCLIPSTATUS, "lpD3DClipStatus")], sideeffects=False),
StdMethod(HRESULT, "DrawPrimitiveStrided", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (D3DFVF, "dwVertexType"), (LPD3DDRAWPRIMITIVESTRIDEDDATA, "lpD3DDrawPrimStrideData"), (DWORD, "dwVertexCount"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "DrawIndexedPrimitiveStrided", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (D3DFVF, "dwVertexType"), (LPD3DDRAWPRIMITIVESTRIDEDDATA, "lpD3DDrawPrimStrideData"), (DWORD, "dwVertexCount"), (LPWORD, "lpIndex"), (DWORD, "dwIndexCount"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "DrawPrimitiveVB", [(D3DPRIMITIVETYPE, "d3dptPrimitiveType"), (LPDIRECT3DVERTEXBUFFER7, "lpD3DVertexBuf"), (DWORD, "dwStartVertex"), (DWORD, "dwNumVertices"), (DWORD, "dwFlags")]),
@@ -346,7 +346,7 @@ IDirect3DDevice7.methods += [
StdMethod(HRESULT, "ComputeSphereVisibility", [(LPD3DVECTOR, "lpCenters"), (LPD3DVALUE, "lpRadii"), (DWORD, "dwNumSpheres"), (DWORD, "dwFlags"), (LPDWORD, "lpdwReturnValues")]),
StdMethod(HRESULT, "GetTexture", [(DWORD, "dwStage"), Out(Pointer(LPDIRECTDRAWSURFACE7), "lpTexture")]),
StdMethod(HRESULT, "SetTexture", [(DWORD, "dwStage"), (LPDIRECTDRAWSURFACE7, "lpTexture")]),
- StdMethod(HRESULT, "GetTextureStageState", [(DWORD, "dwStage"), (D3DTEXTURESTAGESTATETYPE, "d3dTexStageStateType"), Out(LPDWORD, "lpdwState")]),
+ StdMethod(HRESULT, "GetTextureStageState", [(DWORD, "dwStage"), (D3DTEXTURESTAGESTATETYPE, "d3dTexStageStateType"), Out(LPDWORD, "lpdwState")], sideeffects=False),
StdMethod(HRESULT, "SetTextureStageState", [(DWORD, "dwStage"), (D3DTEXTURESTAGESTATETYPE, "d3dTexStageStateType"), (DWORD, "dwState")]),
StdMethod(HRESULT, "ValidateDevice", [Out(LPDWORD, "lpdwPasses")]),
StdMethod(HRESULT, "ApplyStateBlock", [(DWORD, "dwBlockHandle")]),
@@ -355,10 +355,10 @@ IDirect3DDevice7.methods += [
StdMethod(HRESULT, "CreateStateBlock", [(D3DSTATEBLOCKTYPE, "d3dsbType"), Out(LPDWORD, "lpdwBlockHandle")]),
StdMethod(HRESULT, "Load", [(LPDIRECTDRAWSURFACE7, "lpDestTex"), (LPPOINT, "lpDestPoint"), (LPDIRECTDRAWSURFACE7, "lpSrcTex"), (LPRECT, "lprcSrcRect"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "LightEnable", [(DWORD, "dwLightIndex"), (BOOL, "bEnable")]),
- StdMethod(HRESULT, "GetLightEnable", [(DWORD, "dwLightIndex"), Out(Pointer(BOOL), "pbEnable")]),
- StdMethod(HRESULT, "SetClipPlane", [(DWORD, "dwIndex"), (Pointer(D3DVALUE), "pPlaneEquation")]),
- StdMethod(HRESULT, "GetClipPlane", [(DWORD, "dwIndex"), Out(Pointer(D3DVALUE), "pPlaneEquation")]),
- StdMethod(HRESULT, "GetInfo", [(DWORD, "dwDevInfoID"), Out(LPVOID, "pDevInfoStruct"), (DWORD, "dwSize")]),
+ StdMethod(HRESULT, "GetLightEnable", [(DWORD, "dwLightIndex"), Out(Pointer(BOOL), "pbEnable")], sideeffects=False),
+ StdMethod(HRESULT, "SetClipPlane", [(DWORD, "dwIndex"), (Array(D3DVALUE, 4), "pPlaneEquation")]),
+ StdMethod(HRESULT, "GetClipPlane", [(DWORD, "dwIndex"), Out(Array(D3DVALUE, 4), "pPlaneEquation")], sideeffects=False),
+ StdMethod(HRESULT, "GetInfo", [(DWORD, "dwDevInfoID"), Out(LPVOID, "pDevInfoStruct"), (DWORD, "dwSize")], sideeffects=False),
]
IDirect3DExecuteBuffer.methods += [
@@ -366,7 +366,7 @@ IDirect3DExecuteBuffer.methods += [
StdMethod(HRESULT, "Lock", [(LPD3DEXECUTEBUFFERDESC, "lpDesc")]),
StdMethod(HRESULT, "Unlock", []),
StdMethod(HRESULT, "SetExecuteData", [(LPD3DEXECUTEDATA, "lpData")]),
- StdMethod(HRESULT, "GetExecuteData", [Out(LPD3DEXECUTEDATA, "lpData")]),
+ StdMethod(HRESULT, "GetExecuteData", [Out(LPD3DEXECUTEDATA, "lpData")], sideeffects=False),
StdMethod(HRESULT, "Validate", [(LPDWORD, "lpdwOffset"), (LPD3DVALIDATECALLBACK, "lpFunc"), (LPVOID, "lpUserArg"), (DWORD, "dwReserved")]),
StdMethod(HRESULT, "Optimize", [(DWORD, "dwDummy")]),
]
@@ -374,13 +374,13 @@ IDirect3DExecuteBuffer.methods += [
IDirect3DLight.methods += [
StdMethod(HRESULT, "Initialize", [(LPDIRECT3D, "lpDirect3D")]),
StdMethod(HRESULT, "SetLight", [(LPD3DLIGHT, "lpLight")]),
- StdMethod(HRESULT, "GetLight", [Out(LPD3DLIGHT, "lpLight")]),
+ StdMethod(HRESULT, "GetLight", [Out(LPD3DLIGHT, "lpLight")], sideeffects=False),
]
IDirect3DMaterial.methods += [
StdMethod(HRESULT, "Initialize", [(LPDIRECT3D, "lpDirect3D")]),
StdMethod(HRESULT, "SetMaterial", [(LPD3DMATERIAL, "lpMat")]),
- StdMethod(HRESULT, "GetMaterial", [Out(LPD3DMATERIAL, "lpMat")]),
+ StdMethod(HRESULT, "GetMaterial", [Out(LPD3DMATERIAL, "lpMat")], sideeffects=False),
StdMethod(HRESULT, "GetHandle", [(LPDIRECT3DDEVICE, "lpDirect3DDevice"), Out(LPD3DMATERIALHANDLE, "lpHandle")]),
StdMethod(HRESULT, "Reserve", []),
StdMethod(HRESULT, "Unreserve", []),
@@ -388,13 +388,13 @@ IDirect3DMaterial.methods += [
IDirect3DMaterial2.methods += [
StdMethod(HRESULT, "SetMaterial", [(LPD3DMATERIAL, "lpMat")]),
- StdMethod(HRESULT, "GetMaterial", [Out(LPD3DMATERIAL, "lpMat")]),
+ StdMethod(HRESULT, "GetMaterial", [Out(LPD3DMATERIAL, "lpMat")], sideeffects=False),
StdMethod(HRESULT, "GetHandle", [(LPDIRECT3DDEVICE2, "lpDirect3DDevice2"), Out(LPD3DMATERIALHANDLE, "lpHandle")]),
]
IDirect3DMaterial3.methods += [
StdMethod(HRESULT, "SetMaterial", [(LPD3DMATERIAL, "lpMat")]),
- StdMethod(HRESULT, "GetMaterial", [Out(LPD3DMATERIAL, "lpMat")]),
+ StdMethod(HRESULT, "GetMaterial", [Out(LPD3DMATERIAL, "lpMat")], sideeffects=False),
StdMethod(HRESULT, "GetHandle", [(LPDIRECT3DDEVICE3, "lpDirect3DDevice3"), Out(LPD3DMATERIALHANDLE, "lpHandle")]),
]
@@ -414,44 +414,44 @@ IDirect3DTexture2.methods += [
IDirect3DViewport.methods += [
StdMethod(HRESULT, "Initialize", [(LPDIRECT3D, "lpDirect3D")]),
- StdMethod(HRESULT, "GetViewport", [Out(LPD3DVIEWPORT, "lpData")]),
+ StdMethod(HRESULT, "GetViewport", [Out(LPD3DVIEWPORT, "lpData")], sideeffects=False),
StdMethod(HRESULT, "SetViewport", [(LPD3DVIEWPORT, "lpData")]),
StdMethod(HRESULT, "TransformVertices", [(DWORD, "dwVertexCount"), (LPD3DTRANSFORMDATA, "lpData"), (DWORD, "dwFlags"), (LPDWORD, "lpOffScreen")]),
StdMethod(HRESULT, "LightElements", [(DWORD, "dwElementCount"), (LPD3DLIGHTDATA, "lpData")]),
StdMethod(HRESULT, "SetBackground", [(D3DMATERIALHANDLE, "hMat")]),
- StdMethod(HRESULT, "GetBackground", [Out(LPD3DMATERIALHANDLE, "lphMat"), Out(LPBOOL, "lpValid")]),
+ StdMethod(HRESULT, "GetBackground", [Out(LPD3DMATERIALHANDLE, "lphMat"), Out(LPBOOL, "lpValid")], sideeffects=False),
StdMethod(HRESULT, "SetBackgroundDepth", [(LPDIRECTDRAWSURFACE, "lpDDSurface")]),
StdMethod(HRESULT, "GetBackgroundDepth", [Out(Pointer(LPDIRECTDRAWSURFACE), "lplpDDSurface"), Out(LPBOOL, "lpValid")]),
- StdMethod(HRESULT, "Clear", [(DWORD, "dwCount"), (LPD3DRECT, "lpRects"), (DWORD, "dwFlags")]),
+ StdMethod(HRESULT, "Clear", [(DWORD, "dwCount"), (Array(D3DRECT, "dwCount"), "lpRects"), (D3DCLEAR, "dwFlags")]),
StdMethod(HRESULT, "AddLight", [(LPDIRECT3DLIGHT, "lpDirect3DLight")]),
StdMethod(HRESULT, "DeleteLight", [(LPDIRECT3DLIGHT, "lpDirect3DLight")]),
StdMethod(HRESULT, "NextLight", [(LPDIRECT3DLIGHT, "lpDirect3DLight"), Out(Pointer(LPDIRECT3DLIGHT), "lplpDirect3DLight"), (DWORD, "dwFlags")]),
]
IDirect3DViewport2.methods += [
- StdMethod(HRESULT, "GetViewport2", [Out(LPD3DVIEWPORT2, "lpData")]),
+ StdMethod(HRESULT, "GetViewport2", [Out(LPD3DVIEWPORT2, "lpData")], sideeffects=False),
StdMethod(HRESULT, "SetViewport2", [(LPD3DVIEWPORT2, "lpData")]),
]
IDirect3DViewport3.methods += [
StdMethod(HRESULT, "SetBackgroundDepth2", [(LPDIRECTDRAWSURFACE4, "lpDDS")]),
StdMethod(HRESULT, "GetBackgroundDepth2", [Out(Pointer(LPDIRECTDRAWSURFACE4), "lplpDDS"), (LPBOOL, "lpValid")]),
- StdMethod(HRESULT, "Clear2", [(DWORD, "dwCount"), (LPD3DRECT, "lpRects"), (DWORD, "dwFlags"), (D3DCOLOR, "dwColor"), (D3DVALUE, "dvZ"), (DWORD, "dwStencil")]),
+ StdMethod(HRESULT, "Clear2", [(DWORD, "dwCount"), (Array(D3DRECT, "dwCount"), "lpRects"), (D3DCLEAR, "dwFlags"), (D3DCOLOR, "dwColor"), (D3DVALUE, "dvZ"), (DWORD, "dwStencil")]),
]
IDirect3DVertexBuffer.methods += [
- StdMethod(HRESULT, "Lock", [(DWORD, "dwFlags"), Out(Pointer(LPVOID), "lplpData"), (LPDWORD, "lpdwSize")]),
+ StdMethod(HRESULT, "Lock", [(DirectDrawSurfaceLockFlags, "dwFlags"), Out(Pointer(LPVOID), "lplpData"), (LPDWORD, "lpdwSize")]),
StdMethod(HRESULT, "Unlock", []),
StdMethod(HRESULT, "ProcessVertices", [(DWORD, "dwVertexOp"), (DWORD, "dwDestIndex"), (DWORD, "dwCount"), (LPDIRECT3DVERTEXBUFFER, "lpSrcBuffer"), (DWORD, "dwSrcIndex"), (LPDIRECT3DDEVICE3, "lpD3DDevice"), (DWORD, "dwFlags")]),
- StdMethod(HRESULT, "GetVertexBufferDesc", [Out(LPD3DVERTEXBUFFERDESC, "lpD3DVertexBufferDesc")]),
+ StdMethod(HRESULT, "GetVertexBufferDesc", [Out(LPD3DVERTEXBUFFERDESC, "lpD3DVertexBufferDesc")], sideeffects=False),
StdMethod(HRESULT, "Optimize", [(LPDIRECT3DDEVICE3, "lpD3DDevice"), (DWORD, "dwFlags")]),
]
IDirect3DVertexBuffer7.methods += [
- StdMethod(HRESULT, "Lock", [(DWORD, "dwFlags"), Out(Pointer(LPVOID), "lplpData"), (LPDWORD, "lpdwSize")]),
+ StdMethod(HRESULT, "Lock", [(DirectDrawSurfaceLockFlags, "dwFlags"), Out(Pointer(LPVOID), "lplpData"), (LPDWORD, "lpdwSize")]),
StdMethod(HRESULT, "Unlock", []),
StdMethod(HRESULT, "ProcessVertices", [(DWORD, "dwVertexOp"), (DWORD, "dwDestIndex"), (DWORD, "dwCount"), (LPDIRECT3DVERTEXBUFFER7, "lpSrcBuffer"), (DWORD, "dwSrcIndex"), (LPDIRECT3DDEVICE7, "lpD3DDevice"), (DWORD, "dwFlags")]),
- StdMethod(HRESULT, "GetVertexBufferDesc", [Out(LPD3DVERTEXBUFFERDESC, "lpD3DVertexBufferDesc")]),
+ StdMethod(HRESULT, "GetVertexBufferDesc", [Out(LPD3DVERTEXBUFFERDESC, "lpD3DVertexBufferDesc")], sideeffects=False),
StdMethod(HRESULT, "Optimize", [(LPDIRECT3DDEVICE7, "lpD3DDevice"), (DWORD, "dwFlags")]),
StdMethod(HRESULT, "ProcessVerticesStrided", [(DWORD, "dwVertexOp"), (DWORD, "dwDestIndex"), (DWORD, "dwCount"), (LPD3DDRAWPRIMITIVESTRIDEDDATA, "lpStrideData"), (DWORD, "dwVertexTypeDesc"), (LPDIRECT3DDEVICE7, "lpD3DDevice"), (DWORD, "dwFlags")]),
]
diff --git a/specs/d3d10.py b/specs/d3d10.py
index 0bf2348b..2161a5fd 100644
--- a/specs/d3d10.py
+++ b/specs/d3d10.py
@@ -25,7 +25,7 @@
from dxgi import *
-from d3dcommon import *
+from d3d10sdklayers import *
HRESULT = MAKE_HRESULT([
@@ -35,6 +35,19 @@ HRESULT = MAKE_HRESULT([
"D3DERR_WASSTILLDRAWING",
])
+D3D10_PRIMITIVE_TOPOLOGY = Enum("D3D10_PRIMITIVE_TOPOLOGY", [
+ "D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED",
+ "D3D10_PRIMITIVE_TOPOLOGY_POINTLIST",
+ "D3D10_PRIMITIVE_TOPOLOGY_LINELIST",
+ "D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP",
+ "D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST",
+ "D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP",
+ "D3D10_PRIMITIVE_TOPOLOGY_LINELIST_ADJ",
+ "D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ",
+ "D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ",
+ "D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ",
+])
+
D3D10_BLEND = Enum("D3D10_BLEND", [
"D3D10_BLEND_ZERO",
"D3D10_BLEND_ONE",
@@ -466,15 +479,15 @@ D3D10_RENDER_TARGET_VIEW_DESC = Struct("D3D10_RENDER_TARGET_VIEW_DESC", [
D3D10_SRV_DIMENSION = Enum("D3D10_SRV_DIMENSION", [
"D3D10_SRV_DIMENSION_UNKNOWN",
- "D3D10_SRV_DIMENSION_BUFFER",
- "D3D10_SRV_DIMENSION_TEXTURE1D",
- "D3D10_SRV_DIMENSION_TEXTURE1DARRAY",
- "D3D10_SRV_DIMENSION_TEXTURE2D",
- "D3D10_SRV_DIMENSION_TEXTURE2DARRAY",
- "D3D10_SRV_DIMENSION_TEXTURE2DMS",
- "D3D10_SRV_DIMENSION_TEXTURE2DMSARRAY",
- "D3D10_SRV_DIMENSION_TEXTURE3D",
- "D3D10_SRV_DIMENSION_TEXTURECUBE",
+ "D3D10_SRV_DIMENSION_BUFFER",
+ "D3D10_SRV_DIMENSION_TEXTURE1D",
+ "D3D10_SRV_DIMENSION_TEXTURE1DARRAY",
+ "D3D10_SRV_DIMENSION_TEXTURE2D",
+ "D3D10_SRV_DIMENSION_TEXTURE2DARRAY",
+ "D3D10_SRV_DIMENSION_TEXTURE2DMS",
+ "D3D10_SRV_DIMENSION_TEXTURE2DMSARRAY",
+ "D3D10_SRV_DIMENSION_TEXTURE3D",
+ "D3D10_SRV_DIMENSION_TEXTURECUBE",
])
D3D10_BUFFER_SRV = Struct("D3D10_BUFFER_SRV", [
@@ -532,7 +545,7 @@ D3D10_SHADER_RESOURCE_VIEW_DESC = Struct("D3D10_SHADER_RESOURCE_VIEW_DESC", [
("D3D10_SRV_DIMENSION_BUFFER", D3D10_BUFFER_SRV, "Buffer"),
("D3D10_SRV_DIMENSION_TEXTURE1D", D3D10_TEX1D_SRV, "Texture1D"),
("D3D10_SRV_DIMENSION_TEXTURE1DARRAY", D3D10_TEX1D_ARRAY_SRV, "Texture1DArray"),
- ("D3D10_SRV_DIMENSION_TEXTURE2D", D3D10_TEX2D_SRV, "Texture2D"),
+ ("D3D10_SRV_DIMENSION_TEXTURE2D", D3D10_TEX2D_SRV, "Texture2D"),
("D3D10_SRV_DIMENSION_TEXTURE2DARRAY", D3D10_TEX2D_ARRAY_SRV, "Texture2DArray"),
("D3D10_SRV_DIMENSION_TEXTURE2DMS", D3D10_TEX2DMS_SRV, "Texture2DMS"),
("D3D10_SRV_DIMENSION_TEXTURE2DMSARRAY", D3D10_TEX2DMS_ARRAY_SRV, "Texture2DMSArray"),
@@ -676,6 +689,39 @@ D3D10_QUERY_DATA_SO_STATISTICS = Struct("D3D10_QUERY_DATA_SO_STATISTICS", [
(UINT64, "PrimitivesStorageNeeded"),
])
+D3D10_QUERY_DATA = Polymorphic("_getQueryType(_this)", [
+ ("D3D10_QUERY_EVENT", Pointer(BOOL)),
+ ("D3D10_QUERY_OCCLUSION", Pointer(UINT64)),
+ ("D3D10_QUERY_TIMESTAMP", Pointer(UINT64)),
+ ("D3D10_QUERY_TIMESTAMP_DISJOINT", Pointer(D3D10_QUERY_DATA_TIMESTAMP_DISJOINT)),
+ ("D3D10_QUERY_PIPELINE_STATISTICS", Pointer(D3D10_QUERY_DATA_PIPELINE_STATISTICS)),
+ ("D3D10_QUERY_OCCLUSION_PREDICATE", Pointer(BOOL)),
+ ("D3D10_QUERY_SO_STATISTICS", Pointer(D3D10_QUERY_DATA_SO_STATISTICS)),
+ ("D3D10_QUERY_SO_OVERFLOW_PREDICATE", Pointer(BOOL)),
+], Blob(Void, "DataSize"), contextLess=False)
+
+# TODO: Handle ID3D10Counter::GetData too.
+D3D10_COUNTER_DATA = Polymorphic("_getCounterType(_this)", [
+ ("D3D10_COUNTER_GPU_IDLE", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_VERTEX_PROCESSING", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_GEOMETRY_PROCESSING", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_PIXEL_PROCESSING", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_OTHER_GPU_PROCESSING", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_HOST_ADAPTER_BANDWIDTH_UTILIZATION", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_LOCAL_VIDMEM_BANDWIDTH_UTILIZATION", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_VERTEX_THROUGHPUT_UTILIZATION", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_TRIANGLE_SETUP_THROUGHPUT_UTILIZATION", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_FILLRATE_THROUGHPUT_UTILIZATION", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_VS_MEMORY_LIMITED", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_VS_COMPUTATION_LIMITED", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_GS_MEMORY_LIMITED", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_GS_COMPUTATION_LIMITED", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_PS_MEMORY_LIMITED", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_PS_COMPUTATION_LIMITED", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_POST_TRANSFORM_CACHE_HIT_RATE", Pointer(FLOAT32)),
+ ("D3D10_COUNTER_TEXTURE_CACHE_HIT_RATE", Pointer(FLOAT32)),
+], Blob(Void, "DataSize"), contextLess=False)
+
D3D10_CREATE_DEVICE_FLAG = Flags(UINT, [
"D3D10_CREATE_DEVICE_SINGLETHREADED",
"D3D10_CREATE_DEVICE_DEBUG",
@@ -721,7 +767,7 @@ ID3D10Multithread = Interface("ID3D10Multithread", IUnknown)
ID3D10DeviceChild.methods += [
StdMethod(Void, "GetDevice", [Out(Pointer(ObjPointer(ID3D10Device)), "ppDevice")]),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "guid"), Out(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "guid"), InOut(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "guid"), (UINT, "DataSize"), (OpaqueBlob(Const(Void), "DataSize"), "pData")], sideeffects=False),
StdMethod(HRESULT, "SetPrivateDataInterface", [(REFGUID, "guid"), (OpaquePointer(Const(IUnknown)), "pData")], sideeffects=False),
]
@@ -791,7 +837,7 @@ ID3D10SamplerState.methods += [
ID3D10Asynchronous.methods += [
StdMethod(Void, "Begin", []),
StdMethod(Void, "End", []),
- StdMethod(HRESULT, "GetData", [Out(Blob(Void, "DataSize"), "pData"), (UINT, "DataSize"), (D3D10_ASYNC_GETDATA_FLAG, "GetDataFlags")], sideeffects=False),
+ StdMethod(HRESULT, "GetData", [Out(D3D10_QUERY_DATA, "pData"), (UINT, "DataSize"), (D3D10_ASYNC_GETDATA_FLAG, "GetDataFlags")], sideeffects=False),
StdMethod(UINT, "GetDataSize", [], sideeffects=False),
]
@@ -862,17 +908,17 @@ ID3D10Device.methods += [
StdMethod(Void, "OMGetDepthStencilState", [Out(Pointer(ObjPointer(ID3D10DepthStencilState)), "ppDepthStencilState"), Out(Pointer(UINT), "pStencilRef")]),
StdMethod(Void, "SOGetTargets", [(UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D10Buffer), "NumBuffers"), "ppSOTargets"), Out(Array(UINT, "NumBuffers"), "pOffsets")]),
StdMethod(Void, "RSGetState", [Out(Pointer(ObjPointer(ID3D10RasterizerState)), "ppRasterizerState")]),
- StdMethod(Void, "RSGetViewports", [Out(Pointer(UINT), "NumViewports"), Out(Array(D3D10_VIEWPORT, "*NumViewports"), "pViewports")], sideeffects=False),
- StdMethod(Void, "RSGetScissorRects", [Out(Pointer(UINT), "NumRects"), Out(Array(D3D10_RECT, "*NumRects"), "pRects")], sideeffects=False),
+ StdMethod(Void, "RSGetViewports", [InOut(Pointer(UINT), "pNumViewports"), Out(Array(D3D10_VIEWPORT, "*pNumViewports"), "pViewports")], sideeffects=False),
+ StdMethod(Void, "RSGetScissorRects", [InOut(Pointer(UINT), "pNumRects"), Out(Array(D3D10_RECT, "*pNumRects"), "pRects")], sideeffects=False),
StdMethod(HRESULT, "GetDeviceRemovedReason", [], sideeffects=False),
StdMethod(HRESULT, "SetExceptionMode", [(D3D10_RAISE_FLAG, "RaiseFlags")]),
StdMethod(D3D10_RAISE_FLAG, "GetExceptionMode", [], sideeffects=False),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "guid"), Out(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "guid"), InOut(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "guid"), (UINT, "DataSize"), (OpaqueBlob(Const(Void), "DataSize"), "pData")], sideeffects=False),
StdMethod(HRESULT, "SetPrivateDataInterface", [(REFGUID, "guid"), (OpaquePointer(Const(IUnknown)), "pData")], sideeffects=False),
StdMethod(Void, "ClearState", []),
StdMethod(Void, "Flush", []),
- StdMethod(HRESULT, "CreateBuffer", [(Pointer(Const(D3D10_BUFFER_DESC)), "pDesc"), (Array(Const(D3D10_SUBRESOURCE_DATA), "1"), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Buffer)), "ppBuffer")]),
+ StdMethod(HRESULT, "CreateBuffer", [(Pointer(Const(D3D10_BUFFER_DESC)), "pDesc"), (Array(Const(D3D10_SUBRESOURCE_DATA), 1), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Buffer)), "ppBuffer")]),
StdMethod(HRESULT, "CreateTexture1D", [(Pointer(Const(D3D10_TEXTURE1D_DESC)), "pDesc"), (Array(Const(D3D10_SUBRESOURCE_DATA), "_getNumSubResources(pDesc)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Texture1D)), "ppTexture1D")]),
StdMethod(HRESULT, "CreateTexture2D", [(Pointer(Const(D3D10_TEXTURE2D_DESC)), "pDesc"), (Array(Const(D3D10_SUBRESOURCE_DATA), "_getNumSubResources(pDesc)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Texture2D)), "ppTexture2D")]),
StdMethod(HRESULT, "CreateTexture3D", [(Pointer(Const(D3D10_TEXTURE3D_DESC)), "pDesc"), (Array(Const(D3D10_SUBRESOURCE_DATA), "_getNumSubResources(pDesc)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Texture3D)), "ppTexture3D")]),
@@ -908,9 +954,128 @@ ID3D10Multithread.methods += [
StdMethod(BOOL, "GetMultithreadProtected", [], sideeffects=False),
]
+D3D10_DRIVER_TYPE = Enum("D3D10_DRIVER_TYPE", [
+ "D3D10_DRIVER_TYPE_HARDWARE",
+ "D3D10_DRIVER_TYPE_REFERENCE",
+ "D3D10_DRIVER_TYPE_NULL",
+ "D3D10_DRIVER_TYPE_SOFTWARE",
+ "D3D10_DRIVER_TYPE_WARP",
+])
+
d3d10 = Module("d3d10")
+d3d10.addFunctions([
+ StdFunction(HRESULT, "D3D10CreateDevice", [(ObjPointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (D3D10_CREATE_DEVICE_FLAG, "Flags"), (UINT, "SDKVersion"), Out(Pointer(ObjPointer(ID3D10Device)), "ppDevice")]),
+ StdFunction(HRESULT, "D3D10CreateDeviceAndSwapChain", [(ObjPointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (D3D10_CREATE_DEVICE_FLAG, "Flags"), (UINT, "SDKVersion"), (Pointer(DXGI_SWAP_CHAIN_DESC), "pSwapChainDesc"), Out(Pointer(ObjPointer(IDXGISwapChain)), "ppSwapChain"), Out(Pointer(ObjPointer(ID3D10Device)), "ppDevice")]),
+])
-from d3d10sdklayers import *
-import d3d10misc
+d3d10.addInterfaces([
+ ID3D10Debug,
+ ID3D10InfoQueue,
+ ID3D10Multithread,
+ ID3D10SwitchToRef,
+])
+
+
+#
+# D3D10.1
+#
+
+
+D3D10_FEATURE_LEVEL1 = Enum("D3D10_FEATURE_LEVEL1", [
+ "D3D10_FEATURE_LEVEL_10_0",
+ "D3D10_FEATURE_LEVEL_10_1",
+ "D3D10_FEATURE_LEVEL_9_1",
+ "D3D10_FEATURE_LEVEL_9_2",
+ "D3D10_FEATURE_LEVEL_9_3",
+])
+
+D3D10_RENDER_TARGET_BLEND_DESC1 = Struct("D3D10_RENDER_TARGET_BLEND_DESC1", [
+ (BOOL, "BlendEnable"),
+ (D3D10_BLEND, "SrcBlend"),
+ (D3D10_BLEND, "DestBlend"),
+ (D3D10_BLEND_OP, "BlendOp"),
+ (D3D10_BLEND, "SrcBlendAlpha"),
+ (D3D10_BLEND, "DestBlendAlpha"),
+ (D3D10_BLEND_OP, "BlendOpAlpha"),
+ (UINT8, "RenderTargetWriteMask"),
+])
+
+D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT = 8
+
+D3D10_BLEND_DESC1 = Struct("D3D10_BLEND_DESC1", [
+ (BOOL, "AlphaToCoverageEnable"),
+ (BOOL, "IndependentBlendEnable"),
+ (Array(D3D10_RENDER_TARGET_BLEND_DESC1, D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT), "RenderTarget"),
+])
+
+ID3D10BlendState1 = Interface("ID3D10BlendState1", ID3D10BlendState)
+ID3D10BlendState1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D10_BLEND_DESC1), "pDesc")], sideeffects=False),
+]
+
+D3D10_SRV_DIMENSION1 = Enum("D3D10_SRV_DIMENSION1", [
+ "D3D10_1_SRV_DIMENSION_UNKNOWN",
+ "D3D10_1_SRV_DIMENSION_BUFFER",
+ "D3D10_1_SRV_DIMENSION_TEXTURE1D",
+ "D3D10_1_SRV_DIMENSION_TEXTURE1DARRAY",
+ "D3D10_1_SRV_DIMENSION_TEXTURE2D",
+ "D3D10_1_SRV_DIMENSION_TEXTURE2DARRAY",
+ "D3D10_1_SRV_DIMENSION_TEXTURE2DMS",
+ "D3D10_1_SRV_DIMENSION_TEXTURE2DMSARRAY",
+ "D3D10_1_SRV_DIMENSION_TEXTURE3D",
+ "D3D10_1_SRV_DIMENSION_TEXTURECUBE",
+ "D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY",
+])
+
+D3D10_TEXCUBE_ARRAY_SRV1 = Struct("D3D10_TEXCUBE_ARRAY_SRV1", [
+ (UINT, "MostDetailedMip"),
+ (UINT, "MipLevels"),
+ (UINT, "First2DArrayFace"),
+ (UINT, "NumCubes"),
+])
+
+D3D10_SHADER_RESOURCE_VIEW_DESC1 = Struct("D3D10_SHADER_RESOURCE_VIEW_DESC1", [
+ (DXGI_FORMAT, "Format"),
+ (D3D10_SRV_DIMENSION1, "ViewDimension"),
+ (Union("{self}.ViewDimension", [
+ ("D3D10_1_SRV_DIMENSION_BUFFER", D3D10_BUFFER_SRV, "Buffer"),
+ ("D3D10_1_SRV_DIMENSION_TEXTURE1D", D3D10_TEX1D_SRV, "Texture1D"),
+ ("D3D10_1_SRV_DIMENSION_TEXTURE1DARRAY", D3D10_TEX1D_ARRAY_SRV, "Texture1DArray"),
+ ("D3D10_1_SRV_DIMENSION_TEXTURE2D", D3D10_TEX2D_SRV, "Texture2D"),
+ ("D3D10_1_SRV_DIMENSION_TEXTURE2DARRAY", D3D10_TEX2D_ARRAY_SRV, "Texture2DArray"),
+ ("D3D10_1_SRV_DIMENSION_TEXTURE2DMS", D3D10_TEX2DMS_SRV, "Texture2DMS"),
+ ("D3D10_1_SRV_DIMENSION_TEXTURE2DMSARRAY", D3D10_TEX2DMS_ARRAY_SRV, "Texture2DMSArray"),
+ ("D3D10_1_SRV_DIMENSION_TEXTURE3D", D3D10_TEX3D_SRV, "Texture3D"),
+ ("D3D10_1_SRV_DIMENSION_TEXTURECUBE", D3D10_TEXCUBE_SRV, "TextureCube"),
+ ("D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY", D3D10_TEXCUBE_ARRAY_SRV1, "TextureCubeArray"),
+ ]), None),
+])
+
+ID3D10ShaderResourceView1 = Interface("ID3D10ShaderResourceView1", ID3D10ShaderResourceView)
+ID3D10ShaderResourceView1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D10_SHADER_RESOURCE_VIEW_DESC1), "pDesc")], sideeffects=False),
+]
+
+ID3D10Device1 = Interface("ID3D10Device1", ID3D10Device)
+ID3D10Device1.methods += [
+ StdMethod(HRESULT, "CreateShaderResourceView1", [(ObjPointer(ID3D10Resource), "pResource"), (Pointer(Const(D3D10_SHADER_RESOURCE_VIEW_DESC1)), "pDesc"), Out(Pointer(ObjPointer(ID3D10ShaderResourceView1)), "ppSRView")]),
+ StdMethod(HRESULT, "CreateBlendState1", [(Pointer(Const(D3D10_BLEND_DESC1)), "pBlendStateDesc"), Out(Pointer(ObjPointer(ID3D10BlendState1)), "ppBlendState")]),
+ StdMethod(D3D10_FEATURE_LEVEL1, "GetFeatureLevel", [], sideeffects=False),
+]
+
+
+d3d10_1 = Module("d3d10_1")
+
+d3d10_1.addFunctions([
+ StdFunction(HRESULT, "D3D10CreateDevice1", [(ObjPointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (D3D10_CREATE_DEVICE_FLAG, "Flags"), (D3D10_FEATURE_LEVEL1, "HardwareLevel"), (UINT, "SDKVersion"), Out(Pointer(ObjPointer(ID3D10Device1)), "ppDevice")]),
+ StdFunction(HRESULT, "D3D10CreateDeviceAndSwapChain1", [(ObjPointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (D3D10_CREATE_DEVICE_FLAG, "Flags"), (D3D10_FEATURE_LEVEL1, "HardwareLevel"), (UINT, "SDKVersion"), (Pointer(DXGI_SWAP_CHAIN_DESC), "pSwapChainDesc"), Out(Pointer(ObjPointer(IDXGISwapChain)), "ppSwapChain"), Out(Pointer(ObjPointer(ID3D10Device1)), "ppDevice")]),
+])
+
+d3d10_1.addInterfaces([
+ ID3D10Debug,
+ ID3D10InfoQueue,
+ ID3D10Multithread,
+ ID3D10SwitchToRef,
+])
diff --git a/specs/d3d10_1.py b/specs/d3d10_1.py
deleted file mode 100644
index 2d549cf9..00000000
--- a/specs/d3d10_1.py
+++ /dev/null
@@ -1,119 +0,0 @@
-##########################################################################
-#
-# Copyright 2008-2012 VMware, Inc.
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-"""d3d10_1.h"""
-
-from winapi import *
-from d3d10 import *
-
-D3D10_DRIVER_TYPE = Enum("D3D10_DRIVER_TYPE", [
- "D3D10_DRIVER_TYPE_HARDWARE",
- "D3D10_DRIVER_TYPE_REFERENCE",
- "D3D10_DRIVER_TYPE_NULL",
- "D3D10_DRIVER_TYPE_SOFTWARE",
- "D3D10_DRIVER_TYPE_WARP",
-])
-
-D3D10_FEATURE_LEVEL1 = Enum("D3D10_FEATURE_LEVEL1", [
- "D3D10_FEATURE_LEVEL_10_0",
- "D3D10_FEATURE_LEVEL_10_1",
- "D3D10_FEATURE_LEVEL_9_1",
- "D3D10_FEATURE_LEVEL_9_2",
- "D3D10_FEATURE_LEVEL_9_3",
-])
-
-D3D10_RENDER_TARGET_BLEND_DESC1 = Struct("D3D10_RENDER_TARGET_BLEND_DESC1", [
- (BOOL, "BlendEnable"),
- (D3D10_BLEND, "SrcBlend"),
- (D3D10_BLEND, "DestBlend"),
- (D3D10_BLEND_OP, "BlendOp"),
- (D3D10_BLEND, "SrcBlendAlpha"),
- (D3D10_BLEND, "DestBlendAlpha"),
- (D3D10_BLEND_OP, "BlendOpAlpha"),
- (UINT8, "RenderTargetWriteMask"),
-])
-
-D3D10_BLEND_DESC1 = Struct("D3D10_BLEND_DESC1", [
- (BOOL, "AlphaToCoverageEnable"),
- (BOOL, "IndependentBlendEnable"),
- (Array(D3D10_RENDER_TARGET_BLEND_DESC1, "D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT"), "RenderTarget"),
-])
-
-ID3D10BlendState1 = Interface("ID3D10BlendState1", ID3D10BlendState)
-ID3D10BlendState1.methods += [
- StdMethod(Void, "GetDesc1", [Out(Pointer(D3D10_BLEND_DESC1), "pDesc")], sideeffects=False),
-]
-
-D3D10_TEXCUBE_ARRAY_SRV1 = Struct("D3D10_TEXCUBE_ARRAY_SRV1", [
- (UINT, "MostDetailedMip"),
- (UINT, "MipLevels"),
- (UINT, "First2DArrayFace"),
- (UINT, "NumCubes"),
-])
-
-D3D10_SHADER_RESOURCE_VIEW_DESC1 = Struct("D3D10_SHADER_RESOURCE_VIEW_DESC1", [
- (DXGI_FORMAT, "Format"),
- (D3D10_SRV_DIMENSION1, "ViewDimension"),
- (Union("{self}.ViewDimension", [
- ("D3D10_1_SRV_DIMENSION_BUFFER", D3D10_BUFFER_SRV, "Buffer"),
- ("D3D10_1_SRV_DIMENSION_TEXTURE1D", D3D10_TEX1D_SRV, "Texture1D"),
- ("D3D10_1_SRV_DIMENSION_TEXTURE1DARRAY", D3D10_TEX1D_ARRAY_SRV, "Texture1DArray"),
- ("D3D10_1_SRV_DIMENSION_TEXTURE2D", D3D10_TEX2D_SRV, "Texture2D"),
- ("D3D10_1_SRV_DIMENSION_TEXTURE2DARRAY", D3D10_TEX2D_ARRAY_SRV, "Texture2DArray"),
- ("D3D10_1_SRV_DIMENSION_TEXTURE2DMS", D3D10_TEX2DMS_SRV, "Texture2DMS"),
- ("D3D10_1_SRV_DIMENSION_TEXTURE2DMSARRAY", D3D10_TEX2DMS_ARRAY_SRV, "Texture2DMSArray"),
- ("D3D10_1_SRV_DIMENSION_TEXTURE3D", D3D10_TEX3D_SRV, "Texture3D"),
- ("D3D10_1_SRV_DIMENSION_TEXTURECUBE", D3D10_TEXCUBE_SRV, "TextureCube"),
- ("D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY", D3D10_TEXCUBE_ARRAY_SRV1, "TextureCubeArray"),
- ]), None),
-])
-
-ID3D10ShaderResourceView1 = Interface("ID3D10ShaderResourceView1", ID3D10ShaderResourceView)
-ID3D10ShaderResourceView1.methods += [
- StdMethod(Void, "GetDesc1", [Out(Pointer(D3D10_SHADER_RESOURCE_VIEW_DESC1), "pDesc")], sideeffects=False),
-]
-
-ID3D10Device1 = Interface("ID3D10Device1", ID3D10Device)
-ID3D10Device1.methods += [
- StdMethod(HRESULT, "CreateShaderResourceView1", [(ObjPointer(ID3D10Resource), "pResource"), (Pointer(Const(D3D10_SHADER_RESOURCE_VIEW_DESC1)), "pDesc"), Out(Pointer(ObjPointer(ID3D10ShaderResourceView1)), "ppSRView")]),
- StdMethod(HRESULT, "CreateBlendState1", [(Pointer(Const(D3D10_BLEND_DESC1)), "pBlendStateDesc"), Out(Pointer(ObjPointer(ID3D10BlendState1)), "ppBlendState")]),
- StdMethod(D3D10_FEATURE_LEVEL1, "GetFeatureLevel", [], sideeffects=False),
-]
-
-d3d10_1 = Module("d3d10_1")
-d3d10_1.addFunctions([
- StdFunction(HRESULT, "D3D10CreateDevice1", [(ObjPointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (D3D10_CREATE_DEVICE_FLAG, "Flags"), (D3D10_FEATURE_LEVEL1, "HardwareLevel"), (UINT, "SDKVersion"), Out(Pointer(ObjPointer(ID3D10Device1)), "ppDevice")]),
- StdFunction(HRESULT, "D3D10CreateDeviceAndSwapChain1", [(ObjPointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (D3D10_CREATE_DEVICE_FLAG, "Flags"), (D3D10_FEATURE_LEVEL1, "HardwareLevel"), (UINT, "SDKVersion"), (Pointer(DXGI_SWAP_CHAIN_DESC), "pSwapChainDesc"), Out(Pointer(ObjPointer(IDXGISwapChain)), "ppSwapChain"), Out(Pointer(ObjPointer(ID3D10Device1)), "ppDevice")]),
-])
-
-d3d10_1.addInterfaces([
- IDXGIAdapter1,
- IDXGIDevice1,
- IDXGIResource,
- ID3D10Debug,
- ID3D10InfoQueue,
- ID3D10Multithread,
- ID3D10SwitchToRef,
-])
diff --git a/specs/d3d10misc.py b/specs/d3d10misc.py
deleted file mode 100644
index 08795b3a..00000000
--- a/specs/d3d10misc.py
+++ /dev/null
@@ -1,55 +0,0 @@
-##########################################################################
-#
-# Copyright 2008-2009 VMware, Inc.
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-"""d3d10misc.h"""
-
-from winapi import *
-from d3d10 import *
-
-
-D3D10_DRIVER_TYPE = Enum("D3D10_DRIVER_TYPE", [
- "D3D10_DRIVER_TYPE_HARDWARE",
- "D3D10_DRIVER_TYPE_REFERENCE",
- "D3D10_DRIVER_TYPE_NULL",
- "D3D10_DRIVER_TYPE_SOFTWARE",
- "D3D10_DRIVER_TYPE_WARP",
-])
-
-
-d3d10.addFunctions([
- StdFunction(HRESULT, "D3D10CreateDevice", [(ObjPointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (D3D10_CREATE_DEVICE_FLAG, "Flags"), (UINT, "SDKVersion"), Out(Pointer(ObjPointer(ID3D10Device)), "ppDevice")]),
- StdFunction(HRESULT, "D3D10CreateDeviceAndSwapChain", [(ObjPointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (D3D10_CREATE_DEVICE_FLAG, "Flags"), (UINT, "SDKVersion"), (Pointer(DXGI_SWAP_CHAIN_DESC), "pSwapChainDesc"), Out(Pointer(ObjPointer(IDXGISwapChain)), "ppSwapChain"), Out(Pointer(ObjPointer(ID3D10Device)), "ppDevice")]),
-])
-
-d3d10.addInterfaces([
- IDXGIAdapter1,
- IDXGIDevice1,
- IDXGIResource,
- ID3D10Debug,
- ID3D10InfoQueue,
- ID3D10Multithread,
- ID3D10SwitchToRef,
-])
-
diff --git a/specs/d3d10sdklayers.py b/specs/d3d10sdklayers.py
index c38ab955..aad53f04 100644
--- a/specs/d3d10sdklayers.py
+++ b/specs/d3d10sdklayers.py
@@ -23,8 +23,9 @@
#
##########################################################################/
+
from dxgi import *
-from d3d10 import HRESULT
+
D3D10_DEBUG_FEATURE = Flags(UINT, [
"D3D10_DEBUG_FEATURE_FLUSH_PER_RENDER_OP",
@@ -35,7 +36,7 @@ D3D10_DEBUG_FEATURE = Flags(UINT, [
ID3D10Debug = Interface("ID3D10Debug", IUnknown)
ID3D10Debug.methods += [
StdMethod(HRESULT, "SetFeatureMask", [(D3D10_DEBUG_FEATURE, "Mask")]),
- StdMethod(UINT, "GetFeatureMask", [], sideeffects=False),
+ StdMethod(D3D10_DEBUG_FEATURE, "GetFeatureMask", [], sideeffects=False),
StdMethod(HRESULT, "SetPresentPerRenderOpDelay", [(UINT, "Milliseconds")]),
StdMethod(UINT, "GetPresentPerRenderOpDelay", [], sideeffects=False),
StdMethod(HRESULT, "SetSwapChain", [(ObjPointer(IDXGISwapChain), "pSwapChain")]),
@@ -567,11 +568,11 @@ D3D10_MESSAGE = Struct("D3D10_MESSAGE", [
D3D10_INFO_QUEUE_FILTER_DESC = Struct("D3D10_INFO_QUEUE_FILTER_DESC", [
(UINT, "NumCategories"),
- (Pointer(D3D10_MESSAGE_CATEGORY), "pCategoryList"),
+ (Array(D3D10_MESSAGE_CATEGORY, "{self}.NumCategories"), "pCategoryList"),
(UINT, "NumSeverities"),
- (Pointer(D3D10_MESSAGE_SEVERITY), "pSeverityList"),
+ (Array(D3D10_MESSAGE_SEVERITY, "{self}.NumSeverities"), "pSeverityList"),
(UINT, "NumIDs"),
- (OpaquePointer(D3D10_MESSAGE_ID), "pIDList"), # TODO: Array
+ (Array(D3D10_MESSAGE_ID, "{self}.NumIDs"), "pIDList"),
])
D3D10_INFO_QUEUE_FILTER = Struct("D3D10_INFO_QUEUE_FILTER", [
diff --git a/specs/d3d11.py b/specs/d3d11.py
index 7d1e1d77..f704b062 100644
--- a/specs/d3d11.py
+++ b/specs/d3d11.py
@@ -25,7 +25,6 @@
from dxgi import *
-from d3dcommon import *
from d3d11sdklayers import *
@@ -70,6 +69,51 @@ ID3D11CommandList = Interface("ID3D11CommandList", ID3D11DeviceChild)
ID3D11Device = Interface("ID3D11Device", IUnknown)
+D3D11_PRIMITIVE_TOPOLOGY = Enum("D3D11_PRIMITIVE_TOPOLOGY", [
+ "D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED",
+ "D3D11_PRIMITIVE_TOPOLOGY_POINTLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_LINELIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP",
+ "D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP",
+ "D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ",
+ "D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ",
+ "D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ",
+ "D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ",
+ "D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST",
+ "D3D11_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST",
+])
+
D3D11_INPUT_CLASSIFICATION = Enum("D3D11_INPUT_CLASSIFICATION", [
"D3D11_INPUT_PER_VERTEX_DATA",
"D3D11_INPUT_PER_INSTANCE_DATA",
@@ -275,6 +319,8 @@ D3D11_BIND_FLAG = Flags(UINT, [
"D3D11_BIND_RENDER_TARGET",
"D3D11_BIND_DEPTH_STENCIL",
"D3D11_BIND_UNORDERED_ACCESS",
+ "D3D11_BIND_DECODER",
+ "D3D11_BIND_VIDEO_ENCODER",
])
D3D11_CPU_ACCESS_FLAG = Flags(UINT, [
@@ -292,6 +338,14 @@ D3D11_RESOURCE_MISC_FLAG = Flags(UINT, [
"D3D11_RESOURCE_MISC_RESOURCE_CLAMP",
"D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX",
"D3D11_RESOURCE_MISC_GDI_COMPATIBLE",
+ "D3D11_RESOURCE_MISC_SHARED_NTHANDLE",
+ "D3D11_RESOURCE_MISC_RESTRICTED_CONTENT",
+ "D3D11_RESOURCE_MISC_RESTRICT_SHARED_RESOURCE",
+ "D3D11_RESOURCE_MISC_RESTRICT_SHARED_RESOURCE_DRIVER",
+ "D3D11_RESOURCE_MISC_GUARDED",
+ "D3D11_RESOURCE_MISC_TILE_POOL",
+ "D3D11_RESOURCE_MISC_TILED",
+ "D3D11_RESOURCE_MISC_HW_PROTECTED",
])
D3D11_MAP = Enum("D3D11_MAP", [
@@ -327,8 +381,8 @@ D3D11_BOX = Struct("D3D11_BOX", [
ID3D11DeviceChild.methods += [
StdMethod(Void, "GetDevice", [Out(Pointer(ObjPointer(ID3D11Device)), "ppDevice")]),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "guid"), Out(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
- StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "guid"), (UINT, "DataSize"), (OpaqueBlob(Const(Void), "DataSize"), "pData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "guid"), InOut(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
+ StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "guid"), (UINT, "DataSize"), (OpaqueBlob(Const(Void), "DataSize"), "pData")]),
StdMethod(HRESULT, "SetPrivateDataInterface", [(REFGUID, "guid"), (OpaquePointer(Const(IUnknown)), "pData")], sideeffects=False),
]
@@ -619,7 +673,7 @@ D3D11_SHADER_RESOURCE_VIEW_DESC = Struct("D3D11_SHADER_RESOURCE_VIEW_DESC", [
("D3D11_SRV_DIMENSION_BUFFER", D3D11_BUFFER_SRV, "Buffer"),
("D3D11_SRV_DIMENSION_TEXTURE1D", D3D11_TEX1D_SRV, "Texture1D"),
("D3D11_SRV_DIMENSION_TEXTURE1DARRAY", D3D11_TEX1D_ARRAY_SRV, "Texture1DArray"),
- ("D3D11_SRV_DIMENSION_TEXTURE2D", D3D11_TEX2D_SRV, "Texture2D"),
+ ("D3D11_SRV_DIMENSION_TEXTURE2D", D3D11_TEX2D_SRV, "Texture2D"),
("D3D11_SRV_DIMENSION_TEXTURE2DARRAY", D3D11_TEX2D_ARRAY_SRV, "Texture2DArray"),
("D3D11_SRV_DIMENSION_TEXTURE2DMS", D3D11_TEX2DMS_SRV, "Texture2DMS"),
("D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY", D3D11_TEX2DMS_ARRAY_SRV, "Texture2DMSArray"),
@@ -819,6 +873,24 @@ D3D11_FILTER = Enum("D3D11_FILTER", [
"D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT",
"D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR",
"D3D11_FILTER_COMPARISON_ANISOTROPIC",
+ "D3D11_FILTER_MINIMUM_MIN_MAG_MIP_POINT",
+ "D3D11_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR",
+ "D3D11_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT",
+ "D3D11_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR",
+ "D3D11_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT",
+ "D3D11_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR",
+ "D3D11_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT",
+ "D3D11_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR",
+ "D3D11_FILTER_MINIMUM_ANISOTROPIC",
+ "D3D11_FILTER_MAXIMUM_MIN_MAG_MIP_POINT",
+ "D3D11_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR",
+ "D3D11_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT",
+ "D3D11_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR",
+ "D3D11_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT",
+ "D3D11_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR",
+ "D3D11_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT",
+ "D3D11_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR",
+ "D3D11_FILTER_MAXIMUM_ANISOTROPIC",
])
D3D11_FILTER_TYPE = Enum("D3D11_FILTER_TYPE", [
@@ -879,6 +951,10 @@ D3D11_FORMAT_SUPPORT = Flags(UINT, [
"D3D11_FORMAT_SUPPORT_BACK_BUFFER_CAST",
"D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW",
"D3D11_FORMAT_SUPPORT_SHADER_GATHER_COMPARISON",
+ "D3D11_FORMAT_SUPPORT_DECODER_OUTPUT",
+ "D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_OUTPUT",
+ "D3D11_FORMAT_SUPPORT_VIDEO_PROCESSOR_INPUT",
+ "D3D11_FORMAT_SUPPORT_VIDEO_ENCODER",
])
D3D11_FORMAT_SUPPORT2 = Enum("D3D11_FORMAT_SUPPORT2", [
@@ -890,6 +966,9 @@ D3D11_FORMAT_SUPPORT2 = Enum("D3D11_FORMAT_SUPPORT2", [
"D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX",
"D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD",
"D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE",
+ "D3D11_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP",
+ "D3D11_FORMAT_SUPPORT2_TILED",
+ "D3D11_FORMAT_SUPPORT2_SHAREABLE",
])
ID3D11Asynchronous.methods += [
@@ -956,6 +1035,25 @@ D3D11_QUERY_DATA_SO_STATISTICS = Struct("D3D11_QUERY_DATA_SO_STATISTICS", [
(UINT64, "PrimitivesStorageNeeded"),
])
+D3D11_QUERY_DATA = Polymorphic("_getQueryType(pAsync)", [
+ ("D3D11_QUERY_EVENT", Pointer(BOOL)),
+ ("D3D11_QUERY_OCCLUSION", Pointer(UINT64)),
+ ("D3D11_QUERY_TIMESTAMP", Pointer(UINT64)),
+ ("D3D11_QUERY_TIMESTAMP_DISJOINT", Pointer(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT)),
+ ("D3D11_QUERY_PIPELINE_STATISTICS", Pointer(D3D11_QUERY_DATA_PIPELINE_STATISTICS)),
+ ("D3D11_QUERY_OCCLUSION_PREDICATE", Pointer(BOOL)),
+ ("D3D11_QUERY_SO_STATISTICS", Pointer(D3D11_QUERY_DATA_SO_STATISTICS)),
+ ("D3D11_QUERY_SO_OVERFLOW_PREDICATE", Pointer(BOOL)),
+ ("D3D11_QUERY_SO_STATISTICS_STREAM0", Pointer(D3D11_QUERY_DATA_SO_STATISTICS)),
+ ("D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0", Pointer(BOOL)),
+ ("D3D11_QUERY_SO_STATISTICS_STREAM1", Pointer(D3D11_QUERY_DATA_SO_STATISTICS)),
+ ("D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1", Pointer(BOOL)),
+ ("D3D11_QUERY_SO_STATISTICS_STREAM2", Pointer(D3D11_QUERY_DATA_SO_STATISTICS)),
+ ("D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2", Pointer(BOOL)),
+ ("D3D11_QUERY_SO_STATISTICS_STREAM3", Pointer(D3D11_QUERY_DATA_SO_STATISTICS)),
+ ("D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3", Pointer(BOOL)),
+], Blob(Void, "DataSize"), contextLess=False)
+
D3D11_COUNTER = Enum("D3D11_COUNTER", [
"D3D11_COUNTER_DEVICE_DEPENDENT_0",
])
@@ -1043,12 +1141,118 @@ D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS = Struct("D3D11_FEATURE_DATA_D3D10_X
(BOOL, "ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x"),
])
+D3D11_FEATURE_DATA_D3D11_OPTIONS = Struct("D3D11_FEATURE_DATA_D3D11_OPTIONS", [
+ (BOOL, "OutputMergerLogicOp"),
+ (BOOL, "UAVOnlyRenderingForcedSampleCount"),
+ (BOOL, "DiscardAPIsSeenByDriver"),
+ (BOOL, "FlagsForUpdateAndCopySeenByDriver"),
+ (BOOL, "ClearView"),
+ (BOOL, "CopyWithOverlap"),
+ (BOOL, "ConstantBufferPartialUpdate"),
+ (BOOL, "ConstantBufferOffsetting"),
+ (BOOL, "MapNoOverwriteOnDynamicConstantBuffer"),
+ (BOOL, "MapNoOverwriteOnDynamicBufferSRV"),
+ (BOOL, "MultisampleRTVWithForcedSampleCountOne"),
+ (BOOL, "SAD4ShaderInstructions"),
+ (BOOL, "ExtendedDoublesShaderInstructions"),
+ (BOOL, "ExtendedResourceSharing"),
+])
+
+D3D11_FEATURE_DATA_ARCHITECTURE_INFO = Struct("D3D11_FEATURE_DATA_ARCHITECTURE_INFO", [
+ (BOOL, "TileBasedDeferredRenderer"),
+])
+
+D3D11_FEATURE_DATA_D3D9_OPTIONS = Struct("D3D11_FEATURE_DATA_D3D9_OPTIONS", [
+ (BOOL, "FullNonPow2TextureSupport"),
+])
+
+D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT = Struct("D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT", [
+ (BOOL, "SupportsDepthAsTextureWithLessEqualComparisonFilter"),
+])
+
+D3D11_SHADER_MIN_PRECISION_SUPPORT = Enum("D3D11_SHADER_MIN_PRECISION_SUPPORT", [
+ "D3D11_SHADER_MIN_PRECISION_10_BIT",
+ "D3D11_SHADER_MIN_PRECISION_16_BIT",
+])
+
+D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT = Struct("D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT", [
+ (UINT, "PixelShaderMinPrecision"),
+ (UINT, "AllOtherShaderStagesMinPrecision"),
+])
+
+D3D11_TILED_RESOURCES_TIER = Enum("D3D11_TILED_RESOURCES_TIER", [
+ "D3D11_TILED_RESOURCES_NOT_SUPPORTED",
+ "D3D11_TILED_RESOURCES_TIER_1",
+ "D3D11_TILED_RESOURCES_TIER_2",
+])
+
+D3D11_FEATURE_DATA_D3D11_OPTIONS1 = Struct("D3D11_FEATURE_DATA_D3D11_OPTIONS1", [
+ (D3D11_TILED_RESOURCES_TIER, "TiledResourcesTier"),
+ (BOOL, "MinMaxFiltering"),
+ (BOOL, "ClearViewAlsoSupportsDepthOnlyFormats"),
+ (BOOL, "MapOnDefaultBuffers"),
+])
+
+D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT = Struct("D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT", [
+ (BOOL, "SimpleInstancingSupported"),
+])
+
+D3D11_FEATURE_DATA_MARKER_SUPPORT = Struct("D3D11_FEATURE_DATA_MARKER_SUPPORT", [
+ (BOOL, "Profile"),
+])
+
+D3D11_FEATURE_DATA_D3D9_OPTIONS1 = Struct("D3D11_FEATURE_DATA_D3D9_OPTIONS1", [
+ (BOOL, "FullNonPow2TextureSupported"),
+ (BOOL, "DepthAsTextureWithLessEqualComparisonFilterSupported"),
+ (BOOL, "SimpleInstancingSupported"),
+ (BOOL, "TextureCubeFaceRenderTargetWithNonCubeDepthStencilSupported"),
+])
+
+D3D11_CONSERVATIVE_RASTERIZATION_TIER = Enum("D3D11_CONSERVATIVE_RASTERIZATION_TIER", [
+ "D3D11_CONSERVATIVE_RASTERIZATION_NOT_SUPPORTED",
+ "D3D11_CONSERVATIVE_RASTERIZATION_TIER_1",
+ "D3D11_CONSERVATIVE_RASTERIZATION_TIER_2",
+ "D3D11_CONSERVATIVE_RASTERIZATION_TIER_3",
+])
+
+D3D11_FEATURE_DATA_D3D11_OPTIONS2 = Struct("D3D11_FEATURE_DATA_D3D11_OPTIONS2", [
+ (BOOL, "PSSpecifiedStencilRefSupported"),
+ (BOOL, "TypedUAVLoadAdditionalFormats"),
+ (BOOL, "ROVsSupported"),
+ (D3D11_CONSERVATIVE_RASTERIZATION_TIER, "ConservativeRasterizationTier"),
+ (D3D11_TILED_RESOURCES_TIER, "TiledResourcesTier"),
+ (BOOL, "MapOnDefaultTextures"),
+ (BOOL, "StandardSwizzle"),
+ (BOOL, "UnifiedMemoryArchitecture"),
+])
+
+D3D11_FEATURE_DATA_D3D11_OPTIONS3 = Struct("D3D11_FEATURE_DATA_D3D11_OPTIONS3", [
+ (BOOL, "VPAndRTArrayIndexFromAnyShaderFeedingRasterizer"),
+])
+
+D3D11_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT = Struct("D3D11_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT", [
+ (UINT, "MaxGPUVirtualAddressBitsPerResource"),
+ (UINT, "MaxGPUVirtualAddressBitsPerProcess"),
+])
+
D3D11_FEATURE, D3D11_FEATURE_DATA = EnumPolymorphic("D3D11_FEATURE", "Feature", [
("D3D11_FEATURE_THREADING", Pointer(D3D11_FEATURE_DATA_THREADING)),
("D3D11_FEATURE_DOUBLES", Pointer(D3D11_FEATURE_DATA_DOUBLES)),
("D3D11_FEATURE_FORMAT_SUPPORT", Pointer(D3D11_FEATURE_DATA_FORMAT_SUPPORT)),
("D3D11_FEATURE_FORMAT_SUPPORT2", Pointer(D3D11_FEATURE_DATA_FORMAT_SUPPORT2)),
("D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS", Pointer(D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS)),
+ ("D3D11_FEATURE_D3D11_OPTIONS", Pointer(D3D11_FEATURE_DATA_D3D11_OPTIONS)),
+ ("D3D11_FEATURE_ARCHITECTURE_INFO", Pointer(D3D11_FEATURE_DATA_ARCHITECTURE_INFO)),
+ ("D3D11_FEATURE_D3D9_OPTIONS", Pointer(D3D11_FEATURE_DATA_D3D9_OPTIONS)),
+ ("D3D11_FEATURE_SHADER_MIN_PRECISION_SUPPORT", Pointer(D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT)),
+ ("D3D11_FEATURE_D3D9_SHADOW_SUPPORT", Pointer(D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT)),
+ ("D3D11_FEATURE_D3D11_OPTIONS1", Pointer(D3D11_FEATURE_DATA_D3D11_OPTIONS1)),
+ ("D3D11_FEATURE_D3D9_SIMPLE_INSTANCING_SUPPORT", Pointer(D3D11_FEATURE_DATA_D3D9_SIMPLE_INSTANCING_SUPPORT)),
+ ("D3D11_FEATURE_MARKER_SUPPORT", Pointer(D3D11_FEATURE_DATA_MARKER_SUPPORT)),
+ ("D3D11_FEATURE_D3D9_OPTIONS1", Pointer(D3D11_FEATURE_DATA_D3D9_OPTIONS1)),
+ ("D3D11_FEATURE_D3D11_OPTIONS2", Pointer(D3D11_FEATURE_DATA_D3D11_OPTIONS2)),
+ ("D3D11_FEATURE_D3D11_OPTIONS3", Pointer(D3D11_FEATURE_DATA_D3D11_OPTIONS3)),
+ ("D3D11_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT", Pointer(D3D11_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT)),
], Blob(Void, "FeatureSupportDataSize"), False)
ID3D11DeviceContext.methods += [
@@ -1074,7 +1278,7 @@ ID3D11DeviceContext.methods += [
StdMethod(Void, "VSSetSamplers", [(UINT, "StartSlot"), (UINT, "NumSamplers"), (Array(Const(ObjPointer(ID3D11SamplerState)), "NumSamplers"), "ppSamplers")]),
StdMethod(Void, "Begin", [(ObjPointer(ID3D11Asynchronous), "pAsync")]),
StdMethod(Void, "End", [(ObjPointer(ID3D11Asynchronous), "pAsync")]),
- StdMethod(HRESULT, "GetData", [(ObjPointer(ID3D11Asynchronous), "pAsync"), Out(OpaqueBlob(Void, "DataSize"), "pData"), (UINT, "DataSize"), (D3D11_ASYNC_GETDATA_FLAG, "GetDataFlags")], sideeffects=False),
+ StdMethod(HRESULT, "GetData", [(ObjPointer(ID3D11Asynchronous), "pAsync"), Out(D3D11_QUERY_DATA, "pData"), (UINT, "DataSize"), (D3D11_ASYNC_GETDATA_FLAG, "GetDataFlags")], sideeffects=False),
StdMethod(Void, "SetPredication", [(ObjPointer(ID3D11Predicate), "pPredicate"), (BOOL, "PredicateValue")]),
StdMethod(Void, "GSSetShaderResources", [(UINT, "StartSlot"), (UINT, "NumViews"), (Array(Const(ObjPointer(ID3D11ShaderResourceView)), "NumViews"), "ppShaderResourceViews")]),
StdMethod(Void, "GSSetSamplers", [(UINT, "StartSlot"), (UINT, "NumSamplers"), (Array(Const(ObjPointer(ID3D11SamplerState)), "NumSamplers"), "ppSamplers")]),
@@ -1119,15 +1323,15 @@ ID3D11DeviceContext.methods += [
StdMethod(Void, "CSSetConstantBuffers", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers")]),
StdMethod(Void, "VSGetConstantBuffers", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers")]),
StdMethod(Void, "PSGetShaderResources", [(UINT, "StartSlot"), (UINT, "NumViews"), Out(Array(ObjPointer(ID3D11ShaderResourceView), "NumViews"), "ppShaderResourceViews")]),
- StdMethod(Void, "PSGetShader", [Out(Pointer(ObjPointer(ID3D11PixelShader)), "ppPixelShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), Out(Pointer(UINT), "pNumClassInstances")]),
+ StdMethod(Void, "PSGetShader", [Out(Pointer(ObjPointer(ID3D11PixelShader)), "ppPixelShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), InOut(Pointer(UINT), "pNumClassInstances")]),
StdMethod(Void, "PSGetSamplers", [(UINT, "StartSlot"), (UINT, "NumSamplers"), Out(Array(ObjPointer(ID3D11SamplerState), "NumSamplers"), "ppSamplers")]),
- StdMethod(Void, "VSGetShader", [Out(Pointer(ObjPointer(ID3D11VertexShader)), "ppVertexShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), Out(Pointer(UINT), "pNumClassInstances")]),
+ StdMethod(Void, "VSGetShader", [Out(Pointer(ObjPointer(ID3D11VertexShader)), "ppVertexShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), InOut(Pointer(UINT), "pNumClassInstances")]),
StdMethod(Void, "PSGetConstantBuffers", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers")]),
StdMethod(Void, "IAGetInputLayout", [Out(Pointer(ObjPointer(ID3D11InputLayout)), "ppInputLayout")]),
StdMethod(Void, "IAGetVertexBuffers", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppVertexBuffers"), Out(Array(UINT, "NumBuffers"), "pStrides"), Out(Array(UINT, "NumBuffers"), "pOffsets")]),
StdMethod(Void, "IAGetIndexBuffer", [Out(Pointer(ObjPointer(ID3D11Buffer)), "pIndexBuffer"), Out(Pointer(DXGI_FORMAT), "Format"), Out(Pointer(UINT), "Offset")]),
StdMethod(Void, "GSGetConstantBuffers", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers")]),
- StdMethod(Void, "GSGetShader", [Out(Pointer(ObjPointer(ID3D11GeometryShader)), "ppGeometryShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), Out(Pointer(UINT), "pNumClassInstances")]),
+ StdMethod(Void, "GSGetShader", [Out(Pointer(ObjPointer(ID3D11GeometryShader)), "ppGeometryShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), InOut(Pointer(UINT), "pNumClassInstances")]),
StdMethod(Void, "IAGetPrimitiveTopology", [Out(Pointer(D3D11_PRIMITIVE_TOPOLOGY), "pTopology")], sideeffects=False),
StdMethod(Void, "VSGetShaderResources", [(UINT, "StartSlot"), (UINT, "NumViews"), Out(Array(ObjPointer(ID3D11ShaderResourceView), "NumViews"), "ppShaderResourceViews")]),
StdMethod(Void, "VSGetSamplers", [(UINT, "StartSlot"), (UINT, "NumSamplers"), Out(Array(ObjPointer(ID3D11SamplerState), "NumSamplers"), "ppSamplers")]),
@@ -1140,19 +1344,19 @@ ID3D11DeviceContext.methods += [
StdMethod(Void, "OMGetDepthStencilState", [Out(Pointer(ObjPointer(ID3D11DepthStencilState)), "ppDepthStencilState"), Out(Pointer(UINT), "pStencilRef")]),
StdMethod(Void, "SOGetTargets", [(UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppSOTargets")]),
StdMethod(Void, "RSGetState", [Out(Pointer(ObjPointer(ID3D11RasterizerState)), "ppRasterizerState")]),
- StdMethod(Void, "RSGetViewports", [Out(Pointer(UINT), "pNumViewports"), Out(Array(D3D11_VIEWPORT, "*pNumViewports"), "pViewports")]),
- StdMethod(Void, "RSGetScissorRects", [Out(Pointer(UINT), "pNumRects"), Out(Array(D3D11_RECT, "*pNumRects"), "pRects")]),
+ StdMethod(Void, "RSGetViewports", [InOut(Pointer(UINT), "pNumViewports"), Out(Array(D3D11_VIEWPORT, "*pNumViewports"), "pViewports")], sideeffects=False),
+ StdMethod(Void, "RSGetScissorRects", [InOut(Pointer(UINT), "pNumRects"), Out(Array(D3D11_RECT, "*pNumRects"), "pRects")], sideeffects=False),
StdMethod(Void, "HSGetShaderResources", [(UINT, "StartSlot"), (UINT, "NumViews"), Out(Array(ObjPointer(ID3D11ShaderResourceView), "NumViews"), "ppShaderResourceViews")]),
- StdMethod(Void, "HSGetShader", [Out(Pointer(ObjPointer(ID3D11HullShader)), "ppHullShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), Out(Pointer(UINT), "pNumClassInstances")]),
+ StdMethod(Void, "HSGetShader", [Out(Pointer(ObjPointer(ID3D11HullShader)), "ppHullShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), InOut(Pointer(UINT), "pNumClassInstances")]),
StdMethod(Void, "HSGetSamplers", [(UINT, "StartSlot"), (UINT, "NumSamplers"), Out(Array(ObjPointer(ID3D11SamplerState), "NumSamplers"), "ppSamplers")]),
StdMethod(Void, "HSGetConstantBuffers", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers")]),
StdMethod(Void, "DSGetShaderResources", [(UINT, "StartSlot"), (UINT, "NumViews"), Out(Array(ObjPointer(ID3D11ShaderResourceView), "NumViews"), "ppShaderResourceViews")]),
- StdMethod(Void, "DSGetShader", [Out(Pointer(ObjPointer(ID3D11DomainShader)), "ppDomainShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), Out(Pointer(UINT), "pNumClassInstances")]),
+ StdMethod(Void, "DSGetShader", [Out(Pointer(ObjPointer(ID3D11DomainShader)), "ppDomainShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), InOut(Pointer(UINT), "pNumClassInstances")]),
StdMethod(Void, "DSGetSamplers", [(UINT, "StartSlot"), (UINT, "NumSamplers"), Out(Array(ObjPointer(ID3D11SamplerState), "NumSamplers"), "ppSamplers")]),
StdMethod(Void, "DSGetConstantBuffers", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers")]),
StdMethod(Void, "CSGetShaderResources", [(UINT, "StartSlot"), (UINT, "NumViews"), Out(Array(ObjPointer(ID3D11ShaderResourceView), "NumViews"), "ppShaderResourceViews")]),
StdMethod(Void, "CSGetUnorderedAccessViews", [(UINT, "StartSlot"), (UINT, "NumUAVs"), Out(Array(ObjPointer(ID3D11UnorderedAccessView), "NumUAVs"), "ppUnorderedAccessViews")]),
- StdMethod(Void, "CSGetShader", [Out(Pointer(ObjPointer(ID3D11ComputeShader)), "ppComputeShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), Out(Pointer(UINT), "pNumClassInstances")]),
+ StdMethod(Void, "CSGetShader", [Out(Pointer(ObjPointer(ID3D11ComputeShader)), "ppComputeShader"), Out(Array(ObjPointer(ID3D11ClassInstance), "*pNumClassInstances"), "ppClassInstances"), InOut(Pointer(UINT), "pNumClassInstances")]),
StdMethod(Void, "CSGetSamplers", [(UINT, "StartSlot"), (UINT, "NumSamplers"), Out(Array(ObjPointer(ID3D11SamplerState), "NumSamplers"), "ppSamplers")]),
StdMethod(Void, "CSGetConstantBuffers", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers")]),
StdMethod(Void, "ClearState", []),
@@ -1168,10 +1372,24 @@ D3D11_CREATE_DEVICE_FLAG = Flags(UINT, [
"D3D11_CREATE_DEVICE_SWITCH_TO_REF",
"D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS",
"D3D11_CREATE_DEVICE_BGRA_SUPPORT",
+ "D3D11_CREATE_DEVICE_DEBUGGABLE",
+ "D3D11_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY",
+ "D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT",
+ "D3D11_CREATE_DEVICE_VIDEO_SUPPORT",
+])
+
+D3D_FEATURE_LEVEL = Enum("D3D_FEATURE_LEVEL", [
+ "D3D_FEATURE_LEVEL_9_1",
+ "D3D_FEATURE_LEVEL_9_2",
+ "D3D_FEATURE_LEVEL_9_3",
+ "D3D_FEATURE_LEVEL_10_0",
+ "D3D_FEATURE_LEVEL_10_1",
+ "D3D_FEATURE_LEVEL_11_0",
+ "D3D_FEATURE_LEVEL_11_1",
])
ID3D11Device.methods += [
- StdMethod(HRESULT, "CreateBuffer", [(Pointer(Const(D3D11_BUFFER_DESC)), "pDesc"), (Array(Const(D3D11_SUBRESOURCE_DATA), "1"), "pInitialData"), Out(Pointer(ObjPointer(ID3D11Buffer)), "ppBuffer")]),
+ StdMethod(HRESULT, "CreateBuffer", [(Pointer(Const(D3D11_BUFFER_DESC)), "pDesc"), (Array(Const(D3D11_SUBRESOURCE_DATA), 1), "pInitialData"), Out(Pointer(ObjPointer(ID3D11Buffer)), "ppBuffer")]),
StdMethod(HRESULT, "CreateTexture1D", [(Pointer(Const(D3D11_TEXTURE1D_DESC)), "pDesc"), (Array(Const(D3D11_SUBRESOURCE_DATA), "_getNumSubResources(pDesc)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D11Texture1D)), "ppTexture1D")]),
StdMethod(HRESULT, "CreateTexture2D", [(Pointer(Const(D3D11_TEXTURE2D_DESC)), "pDesc"), (Array(Const(D3D11_SUBRESOURCE_DATA), "_getNumSubResources(pDesc)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D11Texture2D)), "ppTexture2D")]),
StdMethod(HRESULT, "CreateTexture3D", [(Pointer(Const(D3D11_TEXTURE3D_DESC)), "pDesc"), (Array(Const(D3D11_SUBRESOURCE_DATA), "_getNumSubResources(pDesc)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D11Texture3D)), "ppTexture3D")]),
@@ -1196,23 +1414,34 @@ ID3D11Device.methods += [
StdMethod(HRESULT, "CreatePredicate", [(Pointer(Const(D3D11_QUERY_DESC)), "pPredicateDesc"), Out(Pointer(ObjPointer(ID3D11Predicate)), "ppPredicate")]),
StdMethod(HRESULT, "CreateCounter", [(Pointer(Const(D3D11_COUNTER_DESC)), "pCounterDesc"), Out(Pointer(ObjPointer(ID3D11Counter)), "ppCounter")]),
StdMethod(HRESULT, "CreateDeferredContext", [(UINT, "ContextFlags"), Out(Pointer(ObjPointer(ID3D11DeviceContext)), "ppDeferredContext")]),
- StdMethod(HRESULT, "OpenSharedResource", [(HANDLE, "hResource"), (REFIID, "ReturnedInterface"), Out(Pointer(ObjPointer(Void)), "ppResource")]),
+ StdMethod(HRESULT, "OpenSharedResource", [(RAW_HANDLE, "hResource"), (REFIID, "ReturnedInterface"), Out(Pointer(ObjPointer(Void)), "ppResource")]),
StdMethod(HRESULT, "CheckFormatSupport", [(DXGI_FORMAT, "Format"), Out(Pointer(D3D11_FORMAT_SUPPORT), "pFormatSupport")], sideeffects=False),
StdMethod(HRESULT, "CheckMultisampleQualityLevels", [(DXGI_FORMAT, "Format"), (UINT, "SampleCount"), Out(Pointer(UINT), "pNumQualityLevels")], sideeffects=False),
StdMethod(Void, "CheckCounterInfo", [Out(Pointer(D3D11_COUNTER_INFO), "pCounterInfo")], sideeffects=False),
StdMethod(HRESULT, "CheckCounter", [(Pointer(Const(D3D11_COUNTER_DESC)), "pDesc"), Out(Pointer(D3D11_COUNTER_TYPE), "pType"), Out(Pointer(UINT), "pActiveCounters"), Out(LPSTR, "szName"), Out(Pointer(UINT), "pNameLength"), Out(LPSTR, "szUnits"), Out(Pointer(UINT), "pUnitsLength"), Out(LPSTR, "szDescription"), Out(Pointer(UINT), "pDescriptionLength")], sideeffects=False),
StdMethod(HRESULT, "CheckFeatureSupport", [(D3D11_FEATURE, "Feature"), Out(D3D11_FEATURE_DATA, "pFeatureSupportData"), (UINT, "FeatureSupportDataSize")], sideeffects=False),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "guid"), Out(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
- StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "guid"), (UINT, "DataSize"), (OpaqueBlob(Const(Void), "DataSize"), "pData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "guid"), InOut(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
+ StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "guid"), (UINT, "DataSize"), (OpaqueBlob(Const(Void), "DataSize"), "pData")]),
StdMethod(HRESULT, "SetPrivateDataInterface", [(REFGUID, "guid"), (OpaquePointer(Const(IUnknown)), "pData")], sideeffects=False),
StdMethod(D3D_FEATURE_LEVEL, "GetFeatureLevel", [], sideeffects=False),
StdMethod(D3D11_CREATE_DEVICE_FLAG, "GetCreationFlags", [], sideeffects=False),
StdMethod(HRESULT, "GetDeviceRemovedReason", [], sideeffects=False),
StdMethod(Void, "GetImmediateContext", [Out(Pointer(ObjPointer(ID3D11DeviceContext)), "ppImmediateContext")]),
StdMethod(HRESULT, "SetExceptionMode", [(D3D11_RAISE_FLAG, "RaiseFlags")]),
- StdMethod(UINT, "GetExceptionMode", [], sideeffects=False),
+ StdMethod(D3D11_RAISE_FLAG, "GetExceptionMode", [], sideeffects=False),
]
+
+D3D_DRIVER_TYPE = Enum("D3D_DRIVER_TYPE", [
+ "D3D_DRIVER_TYPE_UNKNOWN",
+ "D3D_DRIVER_TYPE_HARDWARE",
+ "D3D_DRIVER_TYPE_REFERENCE",
+ "D3D_DRIVER_TYPE_NULL",
+ "D3D_DRIVER_TYPE_SOFTWARE",
+ "D3D_DRIVER_TYPE_WARP",
+])
+
+
d3d11 = Module("d3d11")
d3d11.addFunctions([
@@ -1221,11 +1450,1203 @@ d3d11.addFunctions([
])
d3d11.addInterfaces([
- IDXGIFactory1,
- IDXGIAdapter1,
- IDXGIDevice1,
- IDXGIResource,
ID3D11Debug,
ID3D11InfoQueue,
ID3D11SwitchToRef,
])
+
+
+#
+# D3D11 Video
+#
+
+D3D11_VIDEO_DECODER_DESC = Struct("D3D11_VIDEO_DECODER_DESC", [
+ (GUID, "Guid"),
+ (UINT, "SampleWidth"),
+ (UINT, "SampleHeight"),
+ (DXGI_FORMAT, "OutputFormat"),
+])
+
+D3D11_VIDEO_DECODER_CONFIG = Struct("D3D11_VIDEO_DECODER_CONFIG", [
+ (GUID, "guidConfigBitstreamEncryption"),
+ (GUID, "guidConfigMBcontrolEncryption"),
+ (GUID, "guidConfigResidDiffEncryption"),
+ (UINT, "ConfigBitstreamRaw"),
+ (UINT, "ConfigMBcontrolRasterOrder"),
+ (UINT, "ConfigResidDiffHost"),
+ (UINT, "ConfigSpatialResid8"),
+ (UINT, "ConfigResid8Subtraction"),
+ (UINT, "ConfigSpatialHost8or9Clipping"),
+ (UINT, "ConfigSpatialResidInterleaved"),
+ (UINT, "ConfigIntraResidUnsigned"),
+ (UINT, "ConfigResidDiffAccelerator"),
+ (UINT, "ConfigHostInverseScan"),
+ (UINT, "ConfigSpecificIDCT"),
+ (UINT, "Config4GroupedCoefs"),
+ (USHORT, "ConfigMinRenderTargetBuffCount"),
+ (USHORT, "ConfigDecoderSpecific"),
+])
+
+D3D11_VIDEO_DECODER_BUFFER_TYPE = Enum("D3D11_VIDEO_DECODER_BUFFER_TYPE", [
+ "D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS",
+ "D3D11_VIDEO_DECODER_BUFFER_MACROBLOCK_CONTROL",
+ "D3D11_VIDEO_DECODER_BUFFER_RESIDUAL_DIFFERENCE",
+ "D3D11_VIDEO_DECODER_BUFFER_DEBLOCKING_CONTROL",
+ "D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX",
+ "D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL",
+ "D3D11_VIDEO_DECODER_BUFFER_BITSTREAM",
+ "D3D11_VIDEO_DECODER_BUFFER_MOTION_VECTOR",
+ "D3D11_VIDEO_DECODER_BUFFER_FILM_GRAIN",
+])
+
+D3D11_AES_CTR_IV = Struct("D3D11_AES_CTR_IV", [
+ (UINT64, "IV"),
+ (UINT64, "Count"),
+])
+
+D3D11_ENCRYPTED_BLOCK_INFO = Struct("D3D11_ENCRYPTED_BLOCK_INFO", [
+ (UINT, "NumEncryptedBytesAtBeginning"),
+ (UINT, "NumBytesInSkipPattern"),
+ (UINT, "NumBytesInEncryptPattern"),
+])
+
+D3D11_VIDEO_DECODER_BUFFER_DESC = Struct("D3D11_VIDEO_DECODER_BUFFER_DESC", [
+ (D3D11_VIDEO_DECODER_BUFFER_TYPE, "BufferType"),
+ (UINT, "BufferIndex"),
+ (UINT, "DataOffset"),
+ (UINT, "DataSize"),
+ (UINT, "FirstMBaddress"),
+ (UINT, "NumMBsInBuffer"),
+ (UINT, "Width"),
+ (UINT, "Height"),
+ (UINT, "Stride"),
+ (UINT, "ReservedBits"),
+ (Blob(Void, "{self}.IVSize"), "pIV"),
+ (UINT, "IVSize"),
+ (BOOL, "PartialEncryption"),
+ (D3D11_ENCRYPTED_BLOCK_INFO, "EncryptedBlockInfo"),
+])
+
+D3D11_VIDEO_DECODER_EXTENSION = Struct("D3D11_VIDEO_DECODER_EXTENSION", [
+ (UINT, "Function"),
+ (Blob(Void, "{self}.PrivateInputDataSize"), "pPrivateInputData"),
+ (UINT, "PrivateInputDataSize"),
+ (Blob(Void, "{self}.PrivateOutputDataSize"), "pPrivateOutputData"),
+ (UINT, "PrivateOutputDataSize"),
+ (UINT, "ResourceCount"),
+ (Array(ObjPointer(ID3D11Resource), "{self}.ResourceCount"), "ppResourceList"),
+])
+
+ID3D11VideoDecoder = Interface("ID3D11VideoDecoder", ID3D11DeviceChild)
+ID3D11VideoDecoder.methods += [
+ StdMethod(HRESULT, "GetCreationParameters", [Out(Pointer(D3D11_VIDEO_DECODER_DESC), "pVideoDesc"), Out(Pointer(D3D11_VIDEO_DECODER_CONFIG), "pConfig")], sideeffects=False),
+ StdMethod(HRESULT, "GetDriverHandle", [Out(Pointer(HANDLE), "pDriverHandle")]),
+]
+
+D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT = Flags(UINT, [
+ "D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT",
+ "D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT",
+])
+
+D3D11_VIDEO_PROCESSOR_DEVICE_CAPS = Flags(UINT, [
+ "D3D11_VIDEO_PROCESSOR_DEVICE_CAPS_LINEAR_SPACE",
+ "D3D11_VIDEO_PROCESSOR_DEVICE_CAPS_xvYCC",
+ "D3D11_VIDEO_PROCESSOR_DEVICE_CAPS_RGB_RANGE_CONVERSION",
+ "D3D11_VIDEO_PROCESSOR_DEVICE_CAPS_YCbCr_MATRIX_CONVERSION",
+ "D3D11_VIDEO_PROCESSOR_DEVICE_CAPS_NOMINAL_RANGE",
+])
+
+D3D11_VIDEO_PROCESSOR_FEATURE_CAPS = Flags(UINT, [
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_ALPHA_FILL",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_CONSTRICTION",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_LUMA_KEY",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_ALPHA_PALETTE",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_LEGACY",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_STEREO",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_ROTATION",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_ALPHA_STREAM",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_PIXEL_ASPECT_RATIO",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_MIRROR",
+ "D3D11_VIDEO_PROCESSOR_FEATURE_CAPS_SHADER_USAGE",
+])
+
+D3D11_VIDEO_PROCESSOR_FILTER_CAPS = Flags(UINT, [
+ "D3D11_VIDEO_PROCESSOR_FILTER_CAPS_BRIGHTNESS",
+ "D3D11_VIDEO_PROCESSOR_FILTER_CAPS_CONTRAST",
+ "D3D11_VIDEO_PROCESSOR_FILTER_CAPS_HUE",
+ "D3D11_VIDEO_PROCESSOR_FILTER_CAPS_SATURATION",
+ "D3D11_VIDEO_PROCESSOR_FILTER_CAPS_NOISE_REDUCTION",
+ "D3D11_VIDEO_PROCESSOR_FILTER_CAPS_EDGE_ENHANCEMENT",
+ "D3D11_VIDEO_PROCESSOR_FILTER_CAPS_ANAMORPHIC_SCALING",
+ "D3D11_VIDEO_PROCESSOR_FILTER_CAPS_STEREO_ADJUSTMENT",
+])
+
+D3D11_VIDEO_PROCESSOR_FORMAT_CAPS = Flags(UINT, [
+ "D3D11_VIDEO_PROCESSOR_FORMAT_CAPS_RGB_INTERLACED",
+ "D3D11_VIDEO_PROCESSOR_FORMAT_CAPS_RGB_PROCAMP",
+ "D3D11_VIDEO_PROCESSOR_FORMAT_CAPS_RGB_LUMA_KEY",
+ "D3D11_VIDEO_PROCESSOR_FORMAT_CAPS_PALETTE_INTERLACED",
+])
+
+D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS = Flags(UINT, [
+ "D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS_DENOISE",
+ "D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS_DERINGING",
+ "D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS_EDGE_ENHANCEMENT",
+ "D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS_COLOR_CORRECTION",
+ "D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS_FLESH_TONE_MAPPING",
+ "D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS_IMAGE_STABILIZATION",
+ "D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS_SUPER_RESOLUTION",
+ "D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS_ANAMORPHIC_SCALING",
+])
+
+D3D11_VIDEO_PROCESSOR_STEREO_CAPS = Flags(UINT, [
+ "D3D11_VIDEO_PROCESSOR_STEREO_CAPS_MONO_OFFSET",
+ "D3D11_VIDEO_PROCESSOR_STEREO_CAPS_ROW_INTERLEAVED",
+ "D3D11_VIDEO_PROCESSOR_STEREO_CAPS_COLUMN_INTERLEAVED",
+ "D3D11_VIDEO_PROCESSOR_STEREO_CAPS_CHECKERBOARD",
+ "D3D11_VIDEO_PROCESSOR_STEREO_CAPS_FLIP_MODE",
+])
+
+D3D11_VIDEO_PROCESSOR_CAPS = Struct("D3D11_VIDEO_PROCESSOR_CAPS", [
+ (D3D11_VIDEO_PROCESSOR_DEVICE_CAPS, "DeviceCaps"),
+ (D3D11_VIDEO_PROCESSOR_FEATURE_CAPS, "FeatureCaps"),
+ (D3D11_VIDEO_PROCESSOR_FILTER_CAPS, "FilterCaps"),
+ (D3D11_VIDEO_PROCESSOR_FORMAT_CAPS, "InputFormatCaps"),
+ (D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS, "AutoStreamCaps"),
+ (D3D11_VIDEO_PROCESSOR_STEREO_CAPS, "StereoCaps"),
+ (UINT, "RateConversionCapsCount"),
+ (UINT, "MaxInputStreams"),
+ (UINT, "MaxStreamStates"),
+])
+
+D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS = Flags(UINT, [
+ "D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BLEND",
+ "D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BOB",
+ "D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_ADAPTIVE",
+ "D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_MOTION_COMPENSATION",
+ "D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_INVERSE_TELECINE",
+ "D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_FRAME_RATE_CONVERSION",
+])
+
+D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS = Flags(UINT, [
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_32",
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_22",
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_2224",
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_2332",
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_32322",
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_55",
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_64",
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_87",
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_222222222223",
+ "D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS_OTHER",
+])
+
+D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS = Struct("D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS", [
+ (UINT, "PastFrames"),
+ (UINT, "FutureFrames"),
+ (D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS, "ProcessorCaps"),
+ (D3D11_VIDEO_PROCESSOR_ITELECINE_CAPS, "ITelecineCaps"),
+ (UINT, "CustomRateCount"),
+])
+
+D3D11_CONTENT_PROTECTION_CAPS = Flags(UINT, [
+ "D3D11_CONTENT_PROTECTION_CAPS_SOFTWARE",
+ "D3D11_CONTENT_PROTECTION_CAPS_HARDWARE",
+ "D3D11_CONTENT_PROTECTION_CAPS_PROTECTION_ALWAYS_ON",
+ "D3D11_CONTENT_PROTECTION_CAPS_PARTIAL_DECRYPTION",
+ "D3D11_CONTENT_PROTECTION_CAPS_CONTENT_KEY",
+ "D3D11_CONTENT_PROTECTION_CAPS_FRESHEN_SESSION_KEY",
+ "D3D11_CONTENT_PROTECTION_CAPS_ENCRYPTED_READ_BACK",
+ "D3D11_CONTENT_PROTECTION_CAPS_ENCRYPTED_READ_BACK_KEY",
+ "D3D11_CONTENT_PROTECTION_CAPS_SEQUENTIAL_CTR_IV",
+ "D3D11_CONTENT_PROTECTION_CAPS_ENCRYPT_SLICEDATA_ONLY",
+ "D3D11_CONTENT_PROTECTION_CAPS_DECRYPTION_BLT",
+ "D3D11_CONTENT_PROTECTION_CAPS_HARDWARE_PROTECT_UNCOMPRESSED",
+ "D3D11_CONTENT_PROTECTION_CAPS_HARDWARE_PROTECTED_MEMORY_PAGEABLE",
+ "D3D11_CONTENT_PROTECTION_CAPS_HARDWARE_TEARDOWN",
+ "D3D11_CONTENT_PROTECTION_CAPS_HARDWARE_DRM_COMMUNICATION",
+])
+
+D3D11_VIDEO_CONTENT_PROTECTION_CAPS = Struct("D3D11_VIDEO_CONTENT_PROTECTION_CAPS", [
+ (D3D11_CONTENT_PROTECTION_CAPS, "Caps"),
+ (UINT, "KeyExchangeTypeCount"),
+ (UINT, "BlockAlignmentSize"),
+ (ULONGLONG, "ProtectedMemorySize"),
+])
+
+D3D11_VIDEO_PROCESSOR_CUSTOM_RATE = Struct("D3D11_VIDEO_PROCESSOR_CUSTOM_RATE", [
+ (DXGI_RATIONAL, "CustomRate"),
+ (UINT, "OutputFrames"),
+ (BOOL, "InputInterlaced"),
+ (UINT, "InputFramesOrFields"),
+])
+
+D3D11_VIDEO_PROCESSOR_FILTER = Enum("D3D11_VIDEO_PROCESSOR_FILTER", [
+ "D3D11_VIDEO_PROCESSOR_FILTER_BRIGHTNESS",
+ "D3D11_VIDEO_PROCESSOR_FILTER_CONTRAST",
+ "D3D11_VIDEO_PROCESSOR_FILTER_HUE",
+ "D3D11_VIDEO_PROCESSOR_FILTER_SATURATION",
+ "D3D11_VIDEO_PROCESSOR_FILTER_NOISE_REDUCTION",
+ "D3D11_VIDEO_PROCESSOR_FILTER_EDGE_ENHANCEMENT",
+ "D3D11_VIDEO_PROCESSOR_FILTER_ANAMORPHIC_SCALING",
+ "D3D11_VIDEO_PROCESSOR_FILTER_STEREO_ADJUSTMENT",
+])
+
+D3D11_VIDEO_PROCESSOR_FILTER_RANGE = Struct("D3D11_VIDEO_PROCESSOR_FILTER_RANGE", [
+ (Int, "Minimum"),
+ (Int, "Maximum"),
+ (Int, "Default"),
+ (Float, "Multiplier"),
+])
+
+D3D11_VIDEO_FRAME_FORMAT = Enum("D3D11_VIDEO_FRAME_FORMAT", [
+ "D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE",
+ "D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST",
+ "D3D11_VIDEO_FRAME_FORMAT_INTERLACED_BOTTOM_FIELD_FIRST",
+])
+
+D3D11_VIDEO_USAGE = Enum("D3D11_VIDEO_USAGE", [
+ "D3D11_VIDEO_USAGE_PLAYBACK_NORMAL",
+ "D3D11_VIDEO_USAGE_OPTIMAL_SPEED",
+ "D3D11_VIDEO_USAGE_OPTIMAL_QUALITY",
+])
+
+D3D11_VIDEO_PROCESSOR_CONTENT_DESC = Struct("D3D11_VIDEO_PROCESSOR_CONTENT_DESC", [
+ (D3D11_VIDEO_FRAME_FORMAT, "InputFrameFormat"),
+ (DXGI_RATIONAL, "InputFrameRate"),
+ (UINT, "InputWidth"),
+ (UINT, "InputHeight"),
+ (DXGI_RATIONAL, "OutputFrameRate"),
+ (UINT, "OutputWidth"),
+ (UINT, "OutputHeight"),
+ (D3D11_VIDEO_USAGE, "Usage"),
+])
+
+ID3D11VideoProcessorEnumerator = Interface("ID3D11VideoProcessorEnumerator", ID3D11DeviceChild)
+ID3D11VideoProcessorEnumerator.methods += [
+ StdMethod(HRESULT, "GetVideoProcessorContentDesc", [Out(Pointer(D3D11_VIDEO_PROCESSOR_CONTENT_DESC), "pContentDesc")], sideeffects=False),
+ StdMethod(HRESULT, "CheckVideoProcessorFormat", [(DXGI_FORMAT, "Format"), Out(Pointer(D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT), "pFlags")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoProcessorCaps", [Out(Pointer(D3D11_VIDEO_PROCESSOR_CAPS), "pCaps")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoProcessorRateConversionCaps", [(UINT, "TypeIndex"), Out(Pointer(D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS), "pCaps")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoProcessorCustomRate", [(UINT, "TypeIndex"), (UINT, "CustomRateIndex"), Out(Pointer(D3D11_VIDEO_PROCESSOR_CUSTOM_RATE), "pRate")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoProcessorFilterRange", [(D3D11_VIDEO_PROCESSOR_FILTER, "Filter"), Out(Pointer(D3D11_VIDEO_PROCESSOR_FILTER_RANGE), "pRange")], sideeffects=False),
+]
+
+D3D11_VIDEO_COLOR_RGBA = Struct("D3D11_VIDEO_COLOR_RGBA", [
+ (Float, "R"),
+ (Float, "G"),
+ (Float, "B"),
+ (Float, "A"),
+])
+
+D3D11_VIDEO_COLOR_YCbCrA = Struct("D3D11_VIDEO_COLOR_YCbCrA", [
+ (Float, "Y"),
+ (Float, "Cb"),
+ (Float, "Cr"),
+ (Float, "A"),
+])
+
+D3D11_VIDEO_COLOR = Struct("D3D11_VIDEO_COLOR", [
+ (D3D11_VIDEO_COLOR_YCbCrA, "YCbCr"),
+ #(D3D11_VIDEO_COLOR_RGBA, "RGBA"),
+])
+
+D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE = FakeEnum(UINT, [
+ "D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_UNDEFINED",
+ "D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_16_235",
+ "D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255",
+])
+
+D3D11_VIDEO_PROCESSOR_COLOR_SPACE = Struct("D3D11_VIDEO_PROCESSOR_COLOR_SPACE", [
+ (UINT, "Usage"),
+ (UINT, "RGB_Range"),
+ (UINT, "YCbCr_Matrix"),
+ (UINT, "YCbCr_xvYCC"),
+ (D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE, "Nominal_Range"),
+ (UINT, "Reserved"),
+])
+
+D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE = Enum("D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE", [
+ "D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE_OPAQUE",
+ "D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE_BACKGROUND",
+ "D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE_DESTINATION",
+ "D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE_SOURCE_STREAM",
+])
+
+D3D11_VIDEO_PROCESSOR_OUTPUT_RATE = Enum("D3D11_VIDEO_PROCESSOR_OUTPUT_RATE", [
+ "D3D11_VIDEO_PROCESSOR_OUTPUT_RATE_NORMAL",
+ "D3D11_VIDEO_PROCESSOR_OUTPUT_RATE_HALF",
+ "D3D11_VIDEO_PROCESSOR_OUTPUT_RATE_CUSTOM",
+])
+
+D3D11_VIDEO_PROCESSOR_STEREO_FORMAT = Enum("D3D11_VIDEO_PROCESSOR_STEREO_FORMAT", [
+ "D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_MONO",
+ "D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_HORIZONTAL",
+ "D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_VERTICAL",
+ "D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_SEPARATE",
+ "D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_MONO_OFFSET",
+ "D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_ROW_INTERLEAVED",
+ "D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_COLUMN_INTERLEAVED",
+ "D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_CHECKERBOARD",
+])
+
+D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE = Enum("D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE", [
+ "D3D11_VIDEO_PROCESSOR_STEREO_FLIP_NONE",
+ "D3D11_VIDEO_PROCESSOR_STEREO_FLIP_FRAME0",
+ "D3D11_VIDEO_PROCESSOR_STEREO_FLIP_FRAME1",
+])
+
+D3D11_VIDEO_PROCESSOR_ROTATION = Enum("D3D11_VIDEO_PROCESSOR_ROTATION", [
+ "D3D11_VIDEO_PROCESSOR_ROTATION_IDENTITY",
+ "D3D11_VIDEO_PROCESSOR_ROTATION_90",
+ "D3D11_VIDEO_PROCESSOR_ROTATION_180",
+ "D3D11_VIDEO_PROCESSOR_ROTATION_270",
+])
+
+ID3D11VideoProcessorInputView = Interface("ID3D11VideoProcessorInputView", ID3D11View)
+
+D3D11_VIDEO_PROCESSOR_STREAM = Struct("D3D11_VIDEO_PROCESSOR_STREAM", [
+ (BOOL, "Enable"),
+ (UINT, "OutputIndex"),
+ (UINT, "InputFrameOrField"),
+ (UINT, "PastFrames"),
+ (UINT, "FutureFrames"),
+ (Array(ObjPointer(ID3D11VideoProcessorInputView), "{self}.PastFrames"), "ppPastSurfaces"),
+ (ObjPointer(ID3D11VideoProcessorInputView), "pInputSurface"),
+ (Array(ObjPointer(ID3D11VideoProcessorInputView), "{self}.FutureFrames"), "ppFutureSurfaces"),
+ (Array(ObjPointer(ID3D11VideoProcessorInputView), "{self}.PastFrames"), "ppPastSurfacesRight"),
+ (ObjPointer(ID3D11VideoProcessorInputView), "pInputSurfaceRight"),
+ (Array(ObjPointer(ID3D11VideoProcessorInputView), "{self}.FutureFrames"), "ppFutureSurfacesRight"),
+])
+
+ID3D11VideoProcessor = Interface("ID3D11VideoProcessor", ID3D11DeviceChild)
+ID3D11VideoProcessor.methods += [
+ StdMethod(Void, "GetContentDesc", [Out(Pointer(D3D11_VIDEO_PROCESSOR_CONTENT_DESC), "pDesc")], sideeffects=False),
+ StdMethod(Void, "GetRateConversionCaps", [Out(Pointer(D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS), "pCaps")], sideeffects=False),
+]
+
+D3D11_OMAC = Struct("D3D11_OMAC", [
+ (Array(BYTE, 16), "Omac"),
+])
+
+D3D11_AUTHENTICATED_CHANNEL_TYPE = Enum("D3D11_AUTHENTICATED_CHANNEL_TYPE", [
+ "D3D11_AUTHENTICATED_CHANNEL_D3D11",
+ "D3D11_AUTHENTICATED_CHANNEL_DRIVER_SOFTWARE",
+ "D3D11_AUTHENTICATED_CHANNEL_DRIVER_HARDWARE",
+])
+
+ID3D11AuthenticatedChannel = Interface("ID3D11AuthenticatedChannel", ID3D11DeviceChild)
+ID3D11AuthenticatedChannel.methods += [
+ StdMethod(HRESULT, "GetCertificateSize", [Out(Pointer(UINT), "pCertificateSize")], sideeffects=False),
+ StdMethod(HRESULT, "GetCertificate", [(UINT, "CertificateSize"), Out(Array(BYTE, "CertificateSize"), "pCertificate")], sideeffects=False),
+ StdMethod(Void, "GetChannelHandle", [Out(Pointer(HANDLE), "pChannelHandle")]),
+]
+
+D3D11_AUTHENTICATED_QUERY_INPUT = Struct("D3D11_AUTHENTICATED_QUERY_INPUT", [
+ (GUID, "QueryType"),
+ (HANDLE, "hChannel"),
+ (UINT, "SequenceNumber"),
+])
+
+D3D11_AUTHENTICATED_QUERY_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_OUTPUT", [
+ (D3D11_OMAC, "omac"),
+ (GUID, "QueryType"),
+ (HANDLE, "hChannel"),
+ (UINT, "SequenceNumber"),
+ (HRESULT, "ReturnCode"),
+])
+
+D3D11_AUTHENTICATED_PROTECTION_FLAGS = Struct("D3D11_AUTHENTICATED_PROTECTION_FLAGS", [
+ (UINT, "ProtectionEnabled"),
+ (UINT, "OverlayOrFullscreenRequired"),
+ (UINT, "Reserved"),
+])
+
+D3D11_AUTHENTICATED_QUERY_PROTECTION_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_PROTECTION_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (D3D11_AUTHENTICATED_PROTECTION_FLAGS, "ProtectionFlags"),
+])
+
+D3D11_AUTHENTICATED_QUERY_CHANNEL_TYPE_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_CHANNEL_TYPE_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (D3D11_AUTHENTICATED_CHANNEL_TYPE, "ChannelType"),
+])
+
+D3D11_AUTHENTICATED_QUERY_DEVICE_HANDLE_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_DEVICE_HANDLE_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (HANDLE, "DeviceHandle"),
+])
+
+D3D11_AUTHENTICATED_QUERY_CRYPTO_SESSION_INPUT = Struct("D3D11_AUTHENTICATED_QUERY_CRYPTO_SESSION_INPUT", [
+ (D3D11_AUTHENTICATED_QUERY_INPUT, "Input"),
+ (HANDLE, "DecoderHandle"),
+])
+
+D3D11_AUTHENTICATED_QUERY_CRYPTO_SESSION_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_CRYPTO_SESSION_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (HANDLE, "DecoderHandle"),
+ (HANDLE, "CryptoSessionHandle"),
+ (HANDLE, "DeviceHandle"),
+])
+
+D3D11_AUTHENTICATED_QUERY_RESTRICTED_SHARED_RESOURCE_PROCESS_COUNT_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_RESTRICTED_SHARED_RESOURCE_PROCESS_COUNT_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (UINT, "RestrictedSharedResourceProcessCount"),
+])
+
+D3D11_AUTHENTICATED_QUERY_RESTRICTED_SHARED_RESOURCE_PROCESS_INPUT = Struct("D3D11_AUTHENTICATED_QUERY_RESTRICTED_SHARED_RESOURCE_PROCESS_INPUT", [
+ (D3D11_AUTHENTICATED_QUERY_INPUT, "Input"),
+ (UINT, "ProcessIndex"),
+])
+
+D3D11_AUTHENTICATED_PROCESS_IDENTIFIER_TYPE = Enum("D3D11_AUTHENTICATED_PROCESS_IDENTIFIER_TYPE", [
+ "D3D11_PROCESSIDTYPE_UNKNOWN",
+ "D3D11_PROCESSIDTYPE_DWM",
+ "D3D11_PROCESSIDTYPE_HANDLE",
+])
+
+D3D11_AUTHENTICATED_QUERY_RESTRICTED_SHARED_RESOURCE_PROCESS_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_RESTRICTED_SHARED_RESOURCE_PROCESS_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (UINT, "ProcessIndex"),
+ (D3D11_AUTHENTICATED_PROCESS_IDENTIFIER_TYPE, "ProcessIdentifier"),
+ (HANDLE, "ProcessHandle"),
+])
+
+D3D11_AUTHENTICATED_QUERY_UNRESTRICTED_PROTECTED_SHARED_RESOURCE_COUNT_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_UNRESTRICTED_PROTECTED_SHARED_RESOURCE_COUNT_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (UINT, "UnrestrictedProtectedSharedResourceCount"),
+])
+
+D3D11_AUTHENTICATED_QUERY_OUTPUT_ID_COUNT_INPUT = Struct("D3D11_AUTHENTICATED_QUERY_OUTPUT_ID_COUNT_INPUT", [
+ (D3D11_AUTHENTICATED_QUERY_INPUT, "Input"),
+ (HANDLE, "DeviceHandle"),
+ (HANDLE, "CryptoSessionHandle"),
+])
+
+D3D11_AUTHENTICATED_QUERY_OUTPUT_ID_COUNT_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_OUTPUT_ID_COUNT_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (HANDLE, "DeviceHandle"),
+ (HANDLE, "CryptoSessionHandle"),
+ (UINT, "OutputIDCount"),
+])
+
+D3D11_AUTHENTICATED_QUERY_OUTPUT_ID_INPUT = Struct("D3D11_AUTHENTICATED_QUERY_OUTPUT_ID_INPUT", [
+ (D3D11_AUTHENTICATED_QUERY_INPUT, "Input"),
+ (HANDLE, "DeviceHandle"),
+ (HANDLE, "CryptoSessionHandle"),
+ (UINT, "OutputIDIndex"),
+])
+
+D3D11_AUTHENTICATED_QUERY_OUTPUT_ID_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_OUTPUT_ID_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (HANDLE, "DeviceHandle"),
+ (HANDLE, "CryptoSessionHandle"),
+ (UINT, "OutputIDIndex"),
+ (UINT64, "OutputID"),
+])
+
+D3D11_BUS_TYPE = Enum("D3D11_BUS_TYPE", [
+ "D3D11_BUS_TYPE_OTHER",
+ "D3D11_BUS_TYPE_PCI",
+ "D3D11_BUS_TYPE_PCIX",
+ "D3D11_BUS_TYPE_AGP",
+ "D3D11_BUS_TYPE_PCIEXPRESS",
+ # XXX: Flags
+ "D3D11_BUS_IMPL_MODIFIER_INSIDE_OF_CHIPSET",
+ "D3D11_BUS_IMPL_MODIFIER_TRACKS_ON_MOTHER_BOARD_TO_CHIP",
+ "D3D11_BUS_IMPL_MODIFIER_TRACKS_ON_MOTHER_BOARD_TO_SOCKET",
+ "D3D11_BUS_IMPL_MODIFIER_DAUGHTER_BOARD_CONNECTOR",
+ "D3D11_BUS_IMPL_MODIFIER_DAUGHTER_BOARD_CONNECTOR_INSIDE_OF_NUAE",
+ "D3D11_BUS_IMPL_MODIFIER_NON_STANDARD",
+])
+
+D3D11_AUTHENTICATED_QUERY_ACESSIBILITY_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_ACESSIBILITY_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (D3D11_BUS_TYPE, "BusType"),
+ (BOOL, "AccessibleInContiguousBlocks"),
+ (BOOL, "AccessibleInNonContiguousBlocks"),
+])
+
+D3D11_AUTHENTICATED_QUERY_ACCESSIBILITY_ENCRYPTION_GUID_COUNT_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_ACCESSIBILITY_ENCRYPTION_GUID_COUNT_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (UINT, "EncryptionGuidCount"),
+])
+
+D3D11_AUTHENTICATED_QUERY_ACCESSIBILITY_ENCRYPTION_GUID_INPUT = Struct("D3D11_AUTHENTICATED_QUERY_ACCESSIBILITY_ENCRYPTION_GUID_INPUT", [
+ (D3D11_AUTHENTICATED_QUERY_INPUT, "Input"),
+ (UINT, "EncryptionGuidIndex"),
+])
+
+D3D11_AUTHENTICATED_QUERY_ACCESSIBILITY_ENCRYPTION_GUID_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_ACCESSIBILITY_ENCRYPTION_GUID_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (UINT, "EncryptionGuidIndex"),
+ (GUID, "EncryptionGuid"),
+])
+
+D3D11_AUTHENTICATED_QUERY_CURRENT_ACCESSIBILITY_ENCRYPTION_OUTPUT = Struct("D3D11_AUTHENTICATED_QUERY_CURRENT_ACCESSIBILITY_ENCRYPTION_OUTPUT", [
+ (D3D11_AUTHENTICATED_QUERY_OUTPUT, "Output"),
+ (GUID, "EncryptionGuid"),
+])
+
+D3D11_AUTHENTICATED_CONFIGURE_INPUT = Struct("D3D11_AUTHENTICATED_CONFIGURE_INPUT", [
+ (D3D11_OMAC, "omac"),
+ (GUID, "ConfigureType"),
+ (HANDLE, "hChannel"),
+ (UINT, "SequenceNumber"),
+])
+
+D3D11_AUTHENTICATED_CONFIGURE_OUTPUT = Struct("D3D11_AUTHENTICATED_CONFIGURE_OUTPUT", [
+ (D3D11_OMAC, "omac"),
+ (GUID, "ConfigureType"),
+ (HANDLE, "hChannel"),
+ (UINT, "SequenceNumber"),
+ (HRESULT, "ReturnCode"),
+])
+
+D3D11_AUTHENTICATED_CONFIGURE_INITIALIZE_INPUT = Struct("D3D11_AUTHENTICATED_CONFIGURE_INITIALIZE_INPUT", [
+ (D3D11_AUTHENTICATED_CONFIGURE_INPUT, "Parameters"),
+ (UINT, "StartSequenceQuery"),
+ (UINT, "StartSequenceConfigure"),
+])
+
+D3D11_AUTHENTICATED_CONFIGURE_PROTECTION_INPUT = Struct("D3D11_AUTHENTICATED_CONFIGURE_PROTECTION_INPUT", [
+ (D3D11_AUTHENTICATED_CONFIGURE_INPUT, "Parameters"),
+ (D3D11_AUTHENTICATED_PROTECTION_FLAGS, "Protections"),
+])
+
+D3D11_AUTHENTICATED_CONFIGURE_CRYPTO_SESSION_INPUT = Struct("D3D11_AUTHENTICATED_CONFIGURE_CRYPTO_SESSION_INPUT", [
+ (D3D11_AUTHENTICATED_CONFIGURE_INPUT, "Parameters"),
+ (HANDLE, "DecoderHandle"),
+ (HANDLE, "CryptoSessionHandle"),
+ (HANDLE, "DeviceHandle"),
+])
+
+D3D11_AUTHENTICATED_CONFIGURE_SHARED_RESOURCE_INPUT = Struct("D3D11_AUTHENTICATED_CONFIGURE_SHARED_RESOURCE_INPUT", [
+ (D3D11_AUTHENTICATED_CONFIGURE_INPUT, "Parameters"),
+ (D3D11_AUTHENTICATED_PROCESS_IDENTIFIER_TYPE, "ProcessType"),
+ (HANDLE, "ProcessHandle"),
+ (BOOL, "AllowAccess"),
+])
+
+D3D11_AUTHENTICATED_CONFIGURE_ACCESSIBLE_ENCRYPTION_INPUT = Struct("D3D11_AUTHENTICATED_CONFIGURE_ACCESSIBLE_ENCRYPTION_INPUT", [
+ (D3D11_AUTHENTICATED_CONFIGURE_INPUT, "Parameters"),
+ (GUID, "EncryptionGuid"),
+])
+
+ID3D11CryptoSession = Interface("ID3D11CryptoSession", ID3D11DeviceChild)
+ID3D11CryptoSession.methods += [
+ StdMethod(Void, "GetCryptoType", [Out(Pointer(GUID), "pCryptoType")], sideeffects=False),
+ StdMethod(Void, "GetDecoderProfile", [Out(Pointer(GUID), "pDecoderProfile")], sideeffects=False),
+ StdMethod(HRESULT, "GetCertificateSize", [Out(Pointer(UINT), "pCertificateSize")], sideeffects=False),
+ StdMethod(HRESULT, "GetCertificate", [(UINT, "CertificateSize"), Out(Pointer(BYTE), "pCertificate")], sideeffects=False),
+ StdMethod(Void, "GetCryptoSessionHandle", [Out(Pointer(HANDLE), "pCryptoSessionHandle")]),
+]
+
+D3D11_VDOV_DIMENSION = Enum("D3D11_VDOV_DIMENSION", [
+ "D3D11_VDOV_DIMENSION_UNKNOWN",
+ "D3D11_VDOV_DIMENSION_TEXTURE2D",
+])
+
+D3D11_TEX2D_VDOV = Struct("D3D11_TEX2D_VDOV", [
+ (UINT, "ArraySlice"),
+])
+
+D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC = Struct("D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC", [
+ (GUID, "DecodeProfile"),
+ (D3D11_VDOV_DIMENSION, "ViewDimension"),
+ (Union("{self}.ViewDimension", [
+ ("D3D11_VDOV_DIMENSION_TEXTURE2D", D3D11_TEX2D_VDOV, "Texture2D"),
+ ]), None),
+])
+
+ID3D11VideoDecoderOutputView = Interface("ID3D11VideoDecoderOutputView", ID3D11View)
+ID3D11VideoDecoderOutputView.methods += [
+ StdMethod(Void, "GetDesc", [Out(Pointer(D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC), "pDesc")], sideeffects=None),
+]
+
+D3D11_VPIV_DIMENSION = Enum("D3D11_VPIV_DIMENSION", [
+ "D3D11_VPIV_DIMENSION_UNKNOWN",
+ "D3D11_VPIV_DIMENSION_TEXTURE2D",
+])
+
+D3D11_TEX2D_VPIV = Struct("D3D11_TEX2D_VPIV", [
+ (UINT, "MipSlice"),
+ (UINT, "ArraySlice"),
+])
+
+D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC = Struct("D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC", [
+ (UINT, "FourCC"),
+ (D3D11_VPIV_DIMENSION, "ViewDimension"),
+ (Union("{self}.ViewDimension", [
+ ("D3D11_VPIV_DIMENSION_TEXTURE2D", D3D11_TEX2D_VPIV, "Texture2D"),
+ ]), None),
+])
+
+ID3D11VideoProcessorInputView.methods += [
+ StdMethod(Void, "GetDesc", [Out(Pointer(D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC), "pDesc")], sideeffects=None),
+]
+
+D3D11_VPOV_DIMENSION = Enum("D3D11_VPOV_DIMENSION", [
+ "D3D11_VPOV_DIMENSION_UNKNOWN",
+ "D3D11_VPOV_DIMENSION_TEXTURE2D",
+ "D3D11_VPOV_DIMENSION_TEXTURE2DARRAY",
+])
+
+D3D11_TEX2D_VPOV = Struct("D3D11_TEX2D_VPOV", [
+ (UINT, "MipSlice"),
+])
+
+D3D11_TEX2D_ARRAY_VPOV = Struct("D3D11_TEX2D_ARRAY_VPOV", [
+ (UINT, "MipSlice"),
+ (UINT, "FirstArraySlice"),
+ (UINT, "ArraySize"),
+])
+
+D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC = Struct("D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC", [
+ (D3D11_VPOV_DIMENSION, "ViewDimension"),
+ (Union("{self}.ViewDimension", [
+ ("D3D11_VPOV_DIMENSION_TEXTURE2D", D3D11_TEX2D_VPOV, "Texture2D"),
+ ("D3D11_VPOV_DIMENSION_TEXTURE2DARRAY", D3D11_TEX2D_ARRAY_VPOV, "Texture2DArray"),
+ ]), None),
+])
+
+ID3D11VideoProcessorOutputView = Interface("ID3D11VideoProcessorOutputView", ID3D11View)
+ID3D11VideoProcessorOutputView.methods += [
+ StdMethod(Void, "GetDesc", [Out(Pointer(D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC), "pDesc")], sideeffects=None),
+]
+
+ID3D11VideoContext = Interface("ID3D11VideoContext", ID3D11DeviceChild)
+ID3D11VideoContext.methods += [
+ StdMethod(HRESULT, "GetDecoderBuffer", [(ObjPointer(ID3D11VideoDecoder), "pDecoder"), (D3D11_VIDEO_DECODER_BUFFER_TYPE, "Type"), Out(Pointer(UINT), "pBufferSize"), Out(Pointer(OpaqueBlob(Void, "*pBufferSize")), "ppBuffer")]),
+ StdMethod(HRESULT, "ReleaseDecoderBuffer", [(ObjPointer(ID3D11VideoDecoder), "pDecoder"), (D3D11_VIDEO_DECODER_BUFFER_TYPE, "Type")]),
+ StdMethod(HRESULT, "DecoderBeginFrame", [(ObjPointer(ID3D11VideoDecoder), "pDecoder"), (ObjPointer(ID3D11VideoDecoderOutputView), "pView"), (UINT, "ContentKeySize"), (Blob(Const(Void), "ContentKeySize"), "pContentKey")]),
+ StdMethod(HRESULT, "DecoderEndFrame", [(ObjPointer(ID3D11VideoDecoder), "pDecoder")]),
+ StdMethod(HRESULT, "SubmitDecoderBuffers", [(ObjPointer(ID3D11VideoDecoder), "pDecoder"), (UINT, "NumBuffers"), (Pointer(Const(D3D11_VIDEO_DECODER_BUFFER_DESC)), "pBufferDesc")]),
+ StdMethod(HRESULT, "DecoderExtension", [(ObjPointer(ID3D11VideoDecoder), "pDecoder"), (Pointer(Const(D3D11_VIDEO_DECODER_EXTENSION)), "pExtensionData")]),
+ StdMethod(Void, "VideoProcessorSetOutputTargetRect", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (BOOL, "Enable"), (Pointer(Const(RECT)), "pRect")]),
+ StdMethod(Void, "VideoProcessorSetOutputBackgroundColor", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (BOOL, "YCbCr"), (Pointer(Const(D3D11_VIDEO_COLOR)), "pColor")]),
+ StdMethod(Void, "VideoProcessorSetOutputColorSpace", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (Pointer(Const(D3D11_VIDEO_PROCESSOR_COLOR_SPACE)), "pColorSpace")]),
+ StdMethod(Void, "VideoProcessorSetOutputAlphaFillMode", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE, "AlphaFillMode"), (UINT, "StreamIndex")]),
+ StdMethod(Void, "VideoProcessorSetOutputConstriction", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (BOOL, "Enable"), (SIZE, "Size")]),
+ StdMethod(Void, "VideoProcessorSetOutputStereoMode", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (BOOL, "Enable")]),
+ StdMethod(HRESULT, "VideoProcessorSetOutputExtension", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (Pointer(Const(GUID)), "pExtensionGuid"), (UINT, "DataSize"), (Blob(Void, "DataSize"), "pData")]),
+ StdMethod(Void, "VideoProcessorGetOutputTargetRect", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), Out(Pointer(BOOL), "Enabled"), Out(Pointer(RECT), "pRect")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetOutputBackgroundColor", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), Out(Pointer(BOOL), "pYCbCr"), Out(Pointer(D3D11_VIDEO_COLOR), "pColor")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetOutputColorSpace", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), Out(Pointer(D3D11_VIDEO_PROCESSOR_COLOR_SPACE), "pColorSpace")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetOutputAlphaFillMode", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), Out(Pointer(D3D11_VIDEO_PROCESSOR_ALPHA_FILL_MODE), "pAlphaFillMode"), Out(Pointer(UINT), "pStreamIndex")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetOutputConstriction", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), Out(Pointer(BOOL), "pEnabled"), Out(Pointer(SIZE), "pSize")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetOutputStereoMode", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), Out(Pointer(BOOL), "pEnabled")], sideeffects=False),
+ StdMethod(HRESULT, "VideoProcessorGetOutputExtension", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (Pointer(Const(GUID)), "pExtensionGuid"), (UINT, "DataSize"), Out(OpaqueBlob(Void, "DataSize"), "pData")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorSetStreamFrameFormat", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (D3D11_VIDEO_FRAME_FORMAT, "FrameFormat")]),
+ StdMethod(Void, "VideoProcessorSetStreamColorSpace", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (Pointer(Const(D3D11_VIDEO_PROCESSOR_COLOR_SPACE)), "pColorSpace")]),
+ StdMethod(Void, "VideoProcessorSetStreamOutputRate", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (D3D11_VIDEO_PROCESSOR_OUTPUT_RATE, "OutputRate"), (BOOL, "RepeatFrame"), (Pointer(Const(DXGI_RATIONAL)), "pCustomRate")]),
+ StdMethod(Void, "VideoProcessorSetStreamSourceRect", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (BOOL, "Enable"), (Pointer(Const(RECT)), "pRect")]),
+ StdMethod(Void, "VideoProcessorSetStreamDestRect", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (BOOL, "Enable"), (Pointer(Const(RECT)), "pRect")]),
+ StdMethod(Void, "VideoProcessorSetStreamAlpha", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (BOOL, "Enable"), (FLOAT, "Alpha")]),
+ StdMethod(Void, "VideoProcessorSetStreamPalette", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (UINT, "Count"), (Pointer(Const(UINT)), "pEntries")]),
+ StdMethod(Void, "VideoProcessorSetStreamPixelAspectRatio", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (BOOL, "Enable"), (Pointer(Const(DXGI_RATIONAL)), "pSourceAspectRatio"), (Pointer(Const(DXGI_RATIONAL)), "pDestinationAspectRatio")]),
+ StdMethod(Void, "VideoProcessorSetStreamLumaKey", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (BOOL, "Enable"), (FLOAT, "Lower"), (FLOAT, "Upper")]),
+ StdMethod(Void, "VideoProcessorSetStreamStereoFormat", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (BOOL, "Enable"), (D3D11_VIDEO_PROCESSOR_STEREO_FORMAT, "Format"), (BOOL, "LeftViewFrame0"), (BOOL, "BaseViewFrame0"), (D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE, "FlipMode"), (Int, "MonoOffset")]),
+ StdMethod(Void, "VideoProcessorSetStreamAutoProcessingMode", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (BOOL, "Enable")]),
+ StdMethod(Void, "VideoProcessorSetStreamFilter", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (D3D11_VIDEO_PROCESSOR_FILTER, "Filter"), (BOOL, "Enable"), (Int, "Level")]),
+ StdMethod(HRESULT, "VideoProcessorSetStreamExtension", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (Pointer(Const(GUID)), "pExtensionGuid"), (UINT, "DataSize"), (Blob(Void, "DataSize"), "pData")]),
+ StdMethod(Void, "VideoProcessorGetStreamFrameFormat", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(D3D11_VIDEO_FRAME_FORMAT), "pFrameFormat")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamColorSpace", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(D3D11_VIDEO_PROCESSOR_COLOR_SPACE), "pColorSpace")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamOutputRate", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(D3D11_VIDEO_PROCESSOR_OUTPUT_RATE), "pOutputRate"), Out(Pointer(BOOL), "pRepeatFrame"), Out(Pointer(DXGI_RATIONAL), "pCustomRate")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamSourceRect", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(BOOL), "pEnabled"), Out(Pointer(RECT), "pRect")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamDestRect", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(BOOL), "pEnabled"), Out(Pointer(RECT), "pRect")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamAlpha", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(BOOL), "pEnabled"), Out(Pointer(FLOAT), "pAlpha")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamPalette", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (UINT, "Count"), Out(Array(UINT, "Count"), "pEntries")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamPixelAspectRatio", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(BOOL), "pEnabled"), Out(Pointer(DXGI_RATIONAL), "pSourceAspectRatio"), Out(Pointer(DXGI_RATIONAL), "pDestinationAspectRatio")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamLumaKey", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(BOOL), "pEnabled"), Out(Pointer(FLOAT), "pLower"), Out(Pointer(FLOAT), "pUpper")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamStereoFormat", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(BOOL), "pEnable"), Out(Pointer(D3D11_VIDEO_PROCESSOR_STEREO_FORMAT), "pFormat"), Out(Pointer(BOOL), "pLeftViewFrame0"), Out(Pointer(BOOL), "pBaseViewFrame0"), Out(Pointer(D3D11_VIDEO_PROCESSOR_STEREO_FLIP_MODE), "pFlipMode"), Out(Pointer(Int), "MonoOffset")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamAutoProcessingMode", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(BOOL), "pEnabled")], sideeffects=False),
+ StdMethod(Void, "VideoProcessorGetStreamFilter", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (D3D11_VIDEO_PROCESSOR_FILTER, "Filter"), Out(Pointer(BOOL), "pEnabled"), Out(Pointer(Int), "pLevel")], sideeffects=False),
+ StdMethod(HRESULT, "VideoProcessorGetStreamExtension", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (Pointer(Const(GUID)), "pExtensionGuid"), (UINT, "DataSize"), Out(OpaqueBlob(Void, "DataSize"), "pData")], sideeffects=False), # FIXME
+ StdMethod(HRESULT, "VideoProcessorBlt", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (ObjPointer(ID3D11VideoProcessorOutputView), "pView"), (UINT, "OutputFrame"), (UINT, "StreamCount"), (Array(Const(D3D11_VIDEO_PROCESSOR_STREAM), "StreamCount"), "pStreams")]),
+ StdMethod(HRESULT, "NegotiateCryptoSessionKeyExchange", [(ObjPointer(ID3D11CryptoSession), "pCryptoSession"), (UINT, "DataSize"), Out(OpaqueBlob(Void, "DataSize"), "pData")], sideeffects=False), # FIXME
+ StdMethod(Void, "EncryptionBlt", [(ObjPointer(ID3D11CryptoSession), "pCryptoSession"), (ObjPointer(ID3D11Texture2D), "pSrcSurface"), (ObjPointer(ID3D11Texture2D), "pDstSurface"), (UINT, "IVSize"), Out(OpaqueBlob(Void, "IVSize"), "pIV")], sideeffects=False), # FIXME
+ StdMethod(Void, "DecryptionBlt", [(ObjPointer(ID3D11CryptoSession), "pCryptoSession"), (ObjPointer(ID3D11Texture2D), "pSrcSurface"), (ObjPointer(ID3D11Texture2D), "pDstSurface"), (Pointer(D3D11_ENCRYPTED_BLOCK_INFO), "pEncryptedBlockInfo"), (UINT, "ContentKeySize"), (Blob(Const(Void), "ContentKeySize"), "pContentKey"), (UINT, "IVSize"), Out(OpaqueBlob(Void, "IVSize"), "pIV")], sideeffects=False), # FIXME
+ StdMethod(Void, "StartSessionKeyRefresh", [(ObjPointer(ID3D11CryptoSession), "pCryptoSession"), (UINT, "RandomNumberSize"), Out(OpaqueBlob(Void, "RandomNumberSize"), "pRandomNumber")], sideeffects=False), # FIXME
+ StdMethod(Void, "FinishSessionKeyRefresh", [(ObjPointer(ID3D11CryptoSession), "pCryptoSession")]),
+ StdMethod(HRESULT, "GetEncryptionBltKey", [(ObjPointer(ID3D11CryptoSession), "pCryptoSession"), (UINT, "KeySize"), Out(OpaqueBlob(Void, "KeySize"), "pReadbackKey")], sideeffects=False), # FIXME
+ StdMethod(HRESULT, "NegotiateAuthenticatedChannelKeyExchange", [(ObjPointer(ID3D11AuthenticatedChannel), "pChannel"), (UINT, "DataSize"), Out(OpaqueBlob(Void, "DataSize"), "pData")], sideeffects=False), # FIXME
+ StdMethod(HRESULT, "QueryAuthenticatedChannel", [(ObjPointer(ID3D11AuthenticatedChannel), "pChannel"), (UINT, "InputSize"), (Blob(Const(Void), "InputSize"), "pInput"), (UINT, "OutputSize"), Out(OpaqueBlob(Void, "OutputSize"), "pOutput")], sideeffects=False), # FIXME
+ StdMethod(HRESULT, "ConfigureAuthenticatedChannel", [(ObjPointer(ID3D11AuthenticatedChannel), "pChannel"), (UINT, "InputSize"), (Blob(Const(Void), "InputSize"), "pInput"), Out(Pointer(D3D11_AUTHENTICATED_CONFIGURE_OUTPUT), "pOutput")]),
+ StdMethod(Void, "VideoProcessorSetStreamRotation", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), (BOOL, "Enable"), (D3D11_VIDEO_PROCESSOR_ROTATION, "Rotation")]),
+ StdMethod(Void, "VideoProcessorGetStreamRotation", [(ObjPointer(ID3D11VideoProcessor), "pVideoProcessor"), (UINT, "StreamIndex"), Out(Pointer(BOOL), "pEnable"), Out(Pointer(D3D11_VIDEO_PROCESSOR_ROTATION), "pRotation")], sideeffects=False),
+]
+
+ID3D11VideoDevice = Interface("ID3D11VideoDevice", IUnknown)
+ID3D11VideoDevice.methods += [
+ StdMethod(HRESULT, "CreateVideoDecoder", [(Pointer(Const(D3D11_VIDEO_DECODER_DESC)), "pVideoDesc"), (Pointer(Const(D3D11_VIDEO_DECODER_CONFIG)), "pConfig"), Out(Pointer(ObjPointer(ID3D11VideoDecoder)), "ppDecoder")]),
+ StdMethod(HRESULT, "CreateVideoProcessor", [(ObjPointer(ID3D11VideoProcessorEnumerator), "pEnum"), (UINT, "RateConversionIndex"), Out(Pointer(ObjPointer(ID3D11VideoProcessor)), "ppVideoProcessor")]),
+ StdMethod(HRESULT, "CreateAuthenticatedChannel", [(D3D11_AUTHENTICATED_CHANNEL_TYPE, "ChannelType"), Out(Pointer(ObjPointer(ID3D11AuthenticatedChannel)), "ppAuthenticatedChannel")]),
+ StdMethod(HRESULT, "CreateCryptoSession", [(Pointer(Const(GUID)), "pCryptoType"), (Pointer(Const(GUID)), "pDecoderProfile"), (Pointer(Const(GUID)), "pKeyExchangeType"), (Pointer(ObjPointer(ID3D11CryptoSession)), "ppCryptoSession")]),
+ StdMethod(HRESULT, "CreateVideoDecoderOutputView", [(ObjPointer(ID3D11Resource), "pResource"), (Pointer(Const(D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC)), "pDesc"), Out(Pointer(ObjPointer(ID3D11VideoDecoderOutputView)), "ppVDOVView")]),
+ StdMethod(HRESULT, "CreateVideoProcessorInputView", [(ObjPointer(ID3D11Resource), "pResource"), (ObjPointer(ID3D11VideoProcessorEnumerator), "pEnum"), (Pointer(Const(D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC)), "pDesc"), Out(Pointer(ObjPointer(ID3D11VideoProcessorInputView)), "ppVPIView")]),
+ StdMethod(HRESULT, "CreateVideoProcessorOutputView", [(ObjPointer(ID3D11Resource), "pResource"), (ObjPointer(ID3D11VideoProcessorEnumerator), "pEnum"), (Pointer(Const(D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC)), "pDesc"), Out(Pointer(ObjPointer(ID3D11VideoProcessorOutputView)), "ppVPOView")]),
+ StdMethod(HRESULT, "CreateVideoProcessorEnumerator", [(Pointer(Const(D3D11_VIDEO_PROCESSOR_CONTENT_DESC)), "pDesc"), Out(Pointer(ObjPointer(ID3D11VideoProcessorEnumerator)), "ppEnum")]),
+ StdMethod(UINT, "GetVideoDecoderProfileCount", [], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoDecoderProfile", [(UINT, "Index"), Out(Pointer(GUID), "pDecoderProfile")], sideeffects=False),
+ StdMethod(HRESULT, "CheckVideoDecoderFormat", [(Pointer(Const(GUID)), "pDecoderProfile"), (DXGI_FORMAT, "Format"), Out(Pointer(BOOL), "pSupported")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoDecoderConfigCount", [(Pointer(Const(D3D11_VIDEO_DECODER_DESC)), "pDesc"), Out(Pointer(UINT), "pCount")]),
+ StdMethod(HRESULT, "GetVideoDecoderConfig", [(Pointer(Const(D3D11_VIDEO_DECODER_DESC)), "pDesc"), (UINT, "Index"), Out(Pointer(D3D11_VIDEO_DECODER_CONFIG), "pConfig")], sideeffects=False),
+ StdMethod(HRESULT, "GetContentProtectionCaps", [(Pointer(Const(GUID)), "pCryptoType"), (Pointer(Const(GUID)), "pDecoderProfile"), Out(Pointer(D3D11_VIDEO_CONTENT_PROTECTION_CAPS), "pCaps")], sideeffects=False),
+ StdMethod(HRESULT, "CheckCryptoKeyExchange", [(Pointer(Const(GUID)), "pCryptoType"), (Pointer(Const(GUID)), "pDecoderProfile"), (UINT, "Index"), Out(Pointer(GUID), "pKeyExchangeType")]),
+ StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "guid"), (UINT, "DataSize"), (OpaqueBlob(Const(Void), "DataSize"), "pData")]),
+ StdMethod(HRESULT, "SetPrivateDataInterface", [(REFGUID, "guid"), (OpaquePointer(Const(IUnknown)), "pData")], sideeffects=False),
+]
+
+d3d11.addInterfaces([
+ ID3D11VideoContext,
+ ID3D11VideoDevice,
+])
+
+
+
+#
+# D3D11.1
+#
+
+D3D_MIN_PRECISION = Enum("D3D_MIN_PRECISION", [
+ "D3D_MIN_PRECISION_DEFAULT",
+ "D3D_MIN_PRECISION_FLOAT_16",
+ "D3D_MIN_PRECISION_FLOAT_2_8",
+ "D3D_MIN_PRECISION_RESERVED",
+ "D3D_MIN_PRECISION_SINT_16",
+ "D3D_MIN_PRECISION_UINT_16",
+ "D3D_MIN_PRECISION_ANY_16",
+ "D3D_MIN_PRECISION_ANY_10",
+])
+
+ID3D11BlendState1 = Interface("ID3D11BlendState1", ID3D11BlendState)
+ID3D11RasterizerState1 = Interface("ID3D11RasterizerState1", ID3D11RasterizerState)
+ID3DDeviceContextState = Interface("ID3DDeviceContextState", ID3D11DeviceChild)
+ID3D11DeviceContext1 = Interface("ID3D11DeviceContext1", ID3D11DeviceContext)
+ID3D11Device1 = Interface("ID3D11Device1", ID3D11Device)
+ID3DUserDefinedAnnotation = Interface("ID3DUserDefinedAnnotation", IUnknown)
+
+
+D3D11_COPY_FLAGS = Flags(UINT, [
+ "D3D11_COPY_NO_OVERWRITE",
+ "D3D11_COPY_DISCARD",
+])
+
+D3D11_LOGIC_OP = Enum("D3D11_LOGIC_OP", [
+ "D3D11_LOGIC_OP_CLEAR",
+ "D3D11_LOGIC_OP_SET",
+ "D3D11_LOGIC_OP_COPY",
+ "D3D11_LOGIC_OP_COPY_INVERTED",
+ "D3D11_LOGIC_OP_NOOP",
+ "D3D11_LOGIC_OP_INVERT",
+ "D3D11_LOGIC_OP_AND",
+ "D3D11_LOGIC_OP_NAND",
+ "D3D11_LOGIC_OP_OR",
+ "D3D11_LOGIC_OP_NOR",
+ "D3D11_LOGIC_OP_XOR",
+ "D3D11_LOGIC_OP_EQUIV",
+ "D3D11_LOGIC_OP_AND_REVERSE",
+ "D3D11_LOGIC_OP_AND_INVERTED",
+ "D3D11_LOGIC_OP_OR_REVERSE",
+ "D3D11_LOGIC_OP_OR_INVERTED",
+])
+
+D3D11_RENDER_TARGET_BLEND_DESC1 = Struct("D3D11_RENDER_TARGET_BLEND_DESC1", [
+ (BOOL, "BlendEnable"),
+ (BOOL, "LogicOpEnable"),
+ (D3D11_BLEND, "SrcBlend"),
+ (D3D11_BLEND, "DestBlend"),
+ (D3D11_BLEND_OP, "BlendOp"),
+ (D3D11_BLEND, "SrcBlendAlpha"),
+ (D3D11_BLEND, "DestBlendAlpha"),
+ (D3D11_BLEND_OP, "BlendOpAlpha"),
+ (D3D11_LOGIC_OP, "LogicOp"),
+ (UINT8, "RenderTargetWriteMask"),
+])
+
+D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT = 8
+
+D3D11_BLEND_DESC1 = Struct("D3D11_BLEND_DESC1", [
+ (BOOL, "AlphaToCoverageEnable"),
+ (BOOL, "IndependentBlendEnable"),
+ (Array(D3D11_RENDER_TARGET_BLEND_DESC1, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT), "RenderTarget"),
+])
+
+ID3D11BlendState1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_BLEND_DESC1), "pDesc")], sideeffects=False),
+]
+
+D3D11_RASTERIZER_DESC1 = Struct("D3D11_RASTERIZER_DESC1", [
+ (D3D11_FILL_MODE, "FillMode"),
+ (D3D11_CULL_MODE, "CullMode"),
+ (BOOL, "FrontCounterClockwise"),
+ (INT, "DepthBias"),
+ (FLOAT, "DepthBiasClamp"),
+ (FLOAT, "SlopeScaledDepthBias"),
+ (BOOL, "DepthClipEnable"),
+ (BOOL, "ScissorEnable"),
+ (BOOL, "MultisampleEnable"),
+ (BOOL, "AntialiasedLineEnable"),
+ (UINT, "ForcedSampleCount"),
+])
+
+ID3D11RasterizerState1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_RASTERIZER_DESC1), "pDesc")], sideeffects=False),
+]
+
+D3D11_1_CREATE_DEVICE_CONTEXT_STATE_FLAG = Flags(UINT, [
+ "D3D11_1_CREATE_DEVICE_CONTEXT_STATE_SINGLETHREADED",
+])
+
+ID3D11DeviceContext1.methods += [
+ StdMethod(Void, "CopySubresourceRegion1", [(ObjPointer(ID3D11Resource), "pDstResource"), (UINT, "DstSubresource"), (UINT, "DstX"), (UINT, "DstY"), (UINT, "DstZ"), (ObjPointer(ID3D11Resource), "pSrcResource"), (UINT, "SrcSubresource"), (Pointer(Const(D3D11_BOX)), "pSrcBox"), (D3D11_COPY_FLAGS, "CopyFlags")]),
+ StdMethod(Void, "UpdateSubresource1", [(ObjPointer(ID3D11Resource), "pDstResource"), (UINT, "DstSubresource"), (Pointer(Const(D3D11_BOX)), "pDstBox"), (Blob(Const(Void), "_calcSubresourceSize(pDstResource, DstSubresource, pDstBox, SrcRowPitch, SrcDepthPitch)"), "pSrcData"), (UINT, "SrcRowPitch"), (UINT, "SrcDepthPitch"), (D3D11_COPY_FLAGS, "CopyFlags")]),
+ StdMethod(Void, "DiscardResource", [(ObjPointer(ID3D11Resource), "pResource")]),
+ StdMethod(Void, "DiscardView", [(ObjPointer(ID3D11View), "pResourceView")]),
+ StdMethod(Void, "DiscardView1", [(ObjPointer(ID3D11View), "pResourceView"), (Array(Const(D3D11_RECT), "NumRects"), "pRect"), (UINT, "NumRects")]),
+ StdMethod(Void, "VSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "HSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "DSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "GSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "PSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "CSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "VSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "HSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "DSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "GSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "PSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "CSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
+ StdMethod(Void, "SwapDeviceContextState", [(ObjPointer(ID3DDeviceContextState), "pState"), Out(Pointer(ObjPointer(ID3DDeviceContextState)), "ppPreviousState")]),
+ StdMethod(Void, "ClearView", [(ObjPointer(ID3D11View), "pView"), (Array(Const(FLOAT), 4), "Color"), (Array(Const(D3D11_RECT), "NumRects"), "pRect"), (UINT, "NumRects")]),
+]
+
+
+ID3D11Device1.methods += [
+ StdMethod(Void, "GetImmediateContext1", [Out(Pointer(ObjPointer(ID3D11DeviceContext1)), "ppImmediateContext")]),
+ StdMethod(HRESULT, "CreateDeferredContext1", [(UINT, "ContextFlags"), Out(Pointer(ObjPointer(ID3D11DeviceContext1)), "ppDeferredContext")]),
+ StdMethod(HRESULT, "CreateBlendState1", [(Pointer(Const(D3D11_BLEND_DESC1)), "pBlendStateDesc"), Out(Pointer(ObjPointer(ID3D11BlendState1)), "ppBlendState")]),
+ StdMethod(HRESULT, "CreateRasterizerState1", [(Pointer(Const(D3D11_RASTERIZER_DESC1)), "pRasterizerDesc"), Out(Pointer(ObjPointer(ID3D11RasterizerState1)), "ppRasterizerState")]),
+ StdMethod(HRESULT, "CreateDeviceContextState", [(D3D11_1_CREATE_DEVICE_CONTEXT_STATE_FLAG, "Flags"), (Array(Const(D3D_FEATURE_LEVEL), "FeatureLevels"), "pFeatureLevels"), (UINT, "FeatureLevels"), (UINT, "SDKVersion"), (REFIID, "EmulatedInterface"), Out(Pointer(D3D_FEATURE_LEVEL), "pChosenFeatureLevel"), Out(Pointer(ObjPointer(ID3DDeviceContextState)), "ppContextState")]),
+ StdMethod(HRESULT, "OpenSharedResource1", [(HANDLE, "hResource"), (REFIID, "ReturnedInterface"), Out(Pointer(ObjPointer(Void)), "ppResource")]),
+ StdMethod(HRESULT, "OpenSharedResourceByName", [(LPCWSTR, "lpName"), (DXGI_SHARED_RESOURCE_FLAG, "dwDesiredAccess"), (REFIID, "ReturnedInterface"), Out(Pointer(ObjPointer(Void)), "ppResource")]),
+]
+
+ID3DUserDefinedAnnotation.methods += [
+ StdMethod(INT, "BeginEvent", [(LPCWSTR, "Name")], sideeffects=False),
+ StdMethod(INT, "EndEvent", [], sideeffects=False),
+ StdMethod(Void, "SetMarker", [(LPCWSTR, "Name")], sideeffects=False),
+ StdMethod(BOOL, "GetStatus", [], sideeffects=False),
+]
+
+d3d11.addInterfaces([
+ ID3D11Device1,
+ ID3DUserDefinedAnnotation,
+])
+
+
+
+#
+# D3D11.2
+#
+
+D3D11_TILED_RESOURCE_COORDINATE = Struct("D3D11_TILED_RESOURCE_COORDINATE", [
+ (UINT, "X"),
+ (UINT, "Y"),
+ (UINT, "Z"),
+ (UINT, "Subresource"),
+])
+
+D3D11_TILE_REGION_SIZE = Struct("D3D11_TILE_REGION_SIZE", [
+ (UINT, "NumTiles"),
+ (BOOL, "bUseBox"),
+ (UINT, "Width"),
+ (UINT16, "Height"),
+ (UINT16, "Depth"),
+])
+
+D3D11_TILE_MAPPING_FLAG = Flags(UINT, [
+ "D3D11_TILE_MAPPING_NO_OVERWRITE",
+])
+
+D3D11_TILE_RANGE_FLAG = Flags(UINT, [
+ "D3D11_TILE_RANGE_NULL",
+ "D3D11_TILE_RANGE_SKIP",
+ "D3D11_TILE_RANGE_REUSE_SINGLE_TILE",
+])
+
+D3D11_SUBRESOURCE_TILING = Struct("D3D11_SUBRESOURCE_TILING", [
+ (UINT, "WidthInTiles"),
+ (UINT16, "HeightInTiles"),
+ (UINT16, "DepthInTiles"),
+ (FakeEnum(UINT, ["D3D11_PACKED_TILE"]), "StartTileIndexInOverallResource"),
+])
+
+D3D11_TILE_SHAPE = Struct("D3D11_TILE_SHAPE", [
+ (UINT, "WidthInTexels"),
+ (UINT, "HeightInTexels"),
+ (UINT, "DepthInTexels"),
+])
+
+D3D11_PACKED_MIP_DESC = Struct("D3D11_PACKED_MIP_DESC", [
+ (UINT8, "NumStandardMips"),
+ (UINT8, "NumPackedMips"),
+ (UINT, "NumTilesForPackedMips"),
+ (UINT, "StartTileIndexInOverallResource"),
+])
+
+D3D11_CHECK_MULTISAMPLE_QUALITY_LEVELS_FLAG = Flags(UINT, [
+ "D3D11_CHECK_MULTISAMPLE_QUALITY_LEVELS_TILED_RESOURCE",
+])
+
+D3D11_TILE_COPY_FLAG = Flags(UINT, [
+ "D3D11_TILE_COPY_NO_OVERWRITE",
+ "D3D11_TILE_COPY_LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE",
+ "D3D11_TILE_COPY_SWIZZLED_TILED_RESOURCE_TO_LINEAR_BUFFER",
+])
+
+ID3D11DeviceContext2 = Interface("ID3D11DeviceContext2", ID3D11DeviceContext1)
+ID3D11DeviceContext2.methods += [
+ StdMethod(HRESULT, "UpdateTileMappings", [(ObjPointer(ID3D11Resource), "pTiledResource"), (UINT, "NumTiledResourceRegions"), (Array(Const(D3D11_TILED_RESOURCE_COORDINATE), "NumTiledResourceRegions"), "pTiledResourceRegionStartCoordinates"), (Array(Const(D3D11_TILE_REGION_SIZE), "NumTiledResourceRegions"), "pTiledResourceRegionSizes"), (ObjPointer(ID3D11Buffer), "pTilePool"), (UINT, "NumRanges"), (Array(Const(D3D11_TILE_RANGE_FLAG), "NumRanges"), "pRangeFlags"), (Array(Const(UINT), "NumRanges"), "pTilePoolStartOffsets"), (Array(Const(UINT), "NumRanges"), "pRangeTileCounts"), (D3D11_TILE_MAPPING_FLAG, "Flags")]),
+ StdMethod(HRESULT, "CopyTileMappings", [(ObjPointer(ID3D11Resource), "pDestTiledResource"), (Pointer(Const(D3D11_TILED_RESOURCE_COORDINATE)), "pDestRegionStartCoordinate"), (ObjPointer(ID3D11Resource), "pSourceTiledResource"), (Pointer(Const(D3D11_TILED_RESOURCE_COORDINATE)), "pSourceRegionStartCoordinate"), (Pointer(Const(D3D11_TILE_REGION_SIZE)), "pTileRegionSize"), (D3D11_TILE_MAPPING_FLAG, "Flags")]),
+ StdMethod(Void, "CopyTiles", [(ObjPointer(ID3D11Resource), "pTiledResource"), (Pointer(Const(D3D11_TILED_RESOURCE_COORDINATE)), "pTileRegionStartCoordinate"), (Pointer(Const(D3D11_TILE_REGION_SIZE)), "pTileRegionSize"), (ObjPointer(ID3D11Buffer), "pBuffer"), (UINT64, "BufferStartOffsetInBytes"), (D3D11_TILE_COPY_FLAG, "Flags")]),
+ StdMethod(Void, "UpdateTiles", [(ObjPointer(ID3D11Resource), "pDestTiledResource"), (Pointer(Const(D3D11_TILED_RESOURCE_COORDINATE)), "pDestTileRegionStartCoordinate"), (Pointer(Const(D3D11_TILE_REGION_SIZE)), "pDestTileRegionSize"), (OpaquePointer(Const(Void)), "pSourceTileData"), (D3D11_TILE_COPY_FLAG, "Flags")]), # FIXME
+ StdMethod(HRESULT, "ResizeTilePool", [(ObjPointer(ID3D11Buffer), "pTilePool"), (UINT64, "NewSizeInBytes")]),
+ StdMethod(Void, "TiledResourceBarrier", [(ObjPointer(ID3D11DeviceChild), "pTiledResourceOrViewAccessBeforeBarrier"), (ObjPointer(ID3D11DeviceChild), "pTiledResourceOrViewAccessAfterBarrier")]),
+ StdMethod(BOOL, "IsAnnotationEnabled", [], sideeffects=False),
+ StdMethod(Void, "SetMarkerInt", [(LPCWSTR, "pLabel"), (INT, "Data")]),
+ StdMethod(Void, "BeginEventInt", [(LPCWSTR, "pLabel"), (INT, "Data")]),
+ StdMethod(Void, "EndEvent", []),
+]
+
+ID3D11Device2 = Interface("ID3D11Device2", ID3D11Device1)
+ID3D11Device2.methods += [
+ StdMethod(Void, "GetImmediateContext2", [Out(Pointer(ObjPointer(ID3D11DeviceContext2)), "ppImmediateContext")]),
+ StdMethod(HRESULT, "CreateDeferredContext2", [(UINT, "ContextFlags"), Out(Pointer(ObjPointer(ID3D11DeviceContext2)), "ppDeferredContext")]),
+ StdMethod(Void, "GetResourceTiling", [(ObjPointer(ID3D11Resource), "pTiledResource"), Out(Pointer(UINT), "pNumTilesForEntireResource"), Out(Pointer(D3D11_PACKED_MIP_DESC), "pPackedMipDesc"), Out(Pointer(D3D11_TILE_SHAPE), "pStandardTileShapeForNonPackedMips"), Out(Pointer(UINT), "pNumSubresourceTilings"), (UINT, "FirstSubresourceTilingToGet"), Out(Pointer(D3D11_SUBRESOURCE_TILING), "pSubresourceTilingsForNonPackedMips")]),
+ StdMethod(HRESULT, "CheckMultisampleQualityLevels1", [(DXGI_FORMAT, "Format"), (UINT, "SampleCount"), (D3D11_CHECK_MULTISAMPLE_QUALITY_LEVELS_FLAG, "Flags"), Out(Pointer(UINT), "pNumQualityLevels")], sideeffects=False),
+]
+
+d3d11.addInterfaces([
+ ID3D11Device2,
+ ID3D11DeviceContext2,
+])
+
+
+
+#
+# D3D11.3
+#
+
+D3D11_CONTEXT_TYPE = Enum("D3D11_CONTEXT_TYPE", [
+ "D3D11_CONTEXT_TYPE_ALL",
+ "D3D11_CONTEXT_TYPE_3D",
+ "D3D11_CONTEXT_TYPE_COMPUTE",
+ "D3D11_CONTEXT_TYPE_COPY",
+ "D3D11_CONTEXT_TYPE_VIDEO",
+])
+
+D3D11_TEXTURE_LAYOUT = Enum("D3D11_TEXTURE_LAYOUT", [
+ "D3D11_TEXTURE_LAYOUT_UNDEFINED",
+ "D3D11_TEXTURE_LAYOUT_ROW_MAJOR",
+ "D3D11_TEXTURE_LAYOUT_64K_STANDARD_SWIZZLE",
+])
+
+D3D11_TEXTURE2D_DESC1 = Struct("D3D11_TEXTURE2D_DESC1", [
+ (UINT, "Width"),
+ (UINT, "Height"),
+ (UINT, "MipLevels"),
+ (UINT, "ArraySize"),
+ (DXGI_FORMAT, "Format"),
+ (DXGI_SAMPLE_DESC, "SampleDesc"),
+ (D3D11_USAGE, "Usage"),
+ (UINT, "BindFlags"),
+ (UINT, "CPUAccessFlags"),
+ (UINT, "MiscFlags"),
+ (D3D11_TEXTURE_LAYOUT, "TextureLayout"),
+])
+
+ID3D11Texture2D1 = Interface("ID3D11Texture2D1", ID3D11Texture2D)
+ID3D11Texture2D1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_TEXTURE2D_DESC1), "pDesc")], sideeffects=False),
+]
+D3D11_TEXTURE3D_DESC1 = Struct("D3D11_TEXTURE3D_DESC1", [
+ (UINT, "Width"),
+ (UINT, "Height"),
+ (UINT, "Depth"),
+ (UINT, "MipLevels"),
+ (DXGI_FORMAT, "Format"),
+ (D3D11_USAGE, "Usage"),
+ (UINT, "BindFlags"),
+ (UINT, "CPUAccessFlags"),
+ (UINT, "MiscFlags"),
+ (D3D11_TEXTURE_LAYOUT, "TextureLayout"),
+])
+
+ID3D11Texture3D1 = Interface("ID3D11Texture3D1", ID3D11Texture3D)
+ID3D11Texture3D1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_TEXTURE3D_DESC1), "pDesc")], sideeffects=False),
+]
+
+D3D11_CONSERVATIVE_RASTERIZATION_MODE = Enum("D3D11_CONSERVATIVE_RASTERIZATION_MODE", [
+ "D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF",
+ "D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON",
+])
+
+D3D11_RASTERIZER_DESC2 = Struct("D3D11_RASTERIZER_DESC2", [
+ (D3D11_FILL_MODE, "FillMode"),
+ (D3D11_CULL_MODE, "CullMode"),
+ (BOOL, "FrontCounterClockwise"),
+ (INT, "DepthBias"),
+ (FLOAT, "DepthBiasClamp"),
+ (FLOAT, "SlopeScaledDepthBias"),
+ (BOOL, "DepthClipEnable"),
+ (BOOL, "ScissorEnable"),
+ (BOOL, "MultisampleEnable"),
+ (BOOL, "AntialiasedLineEnable"),
+ (UINT, "ForcedSampleCount"),
+ (D3D11_CONSERVATIVE_RASTERIZATION_MODE, "ConservativeRaster"),
+])
+
+ID3D11RasterizerState2 = Interface("ID3D11RasterizerState2", ID3D11RasterizerState1)
+ID3D11RasterizerState2.methods += [
+ StdMethod(Void, "GetDesc2", [Out(Pointer(D3D11_RASTERIZER_DESC2), "pDesc")], sideeffects=False),
+]
+
+D3D11_TEX2D_SRV1 = Struct("D3D11_TEX2D_SRV1", [
+ (UINT, "MostDetailedMip"),
+ (UINT, "MipLevels"),
+ (UINT, "PlaneSlice"),
+])
+
+D3D11_TEX2D_ARRAY_SRV1 = Struct("D3D11_TEX2D_ARRAY_SRV1", [
+ (UINT, "MostDetailedMip"),
+ (UINT, "MipLevels"),
+ (UINT, "FirstArraySlice"),
+ (UINT, "ArraySize"),
+ (UINT, "PlaneSlice"),
+])
+
+D3D11_SHADER_RESOURCE_VIEW_DESC1 = Struct("D3D11_SHADER_RESOURCE_VIEW_DESC1", [
+ (DXGI_FORMAT, "Format"),
+ (D3D11_SRV_DIMENSION, "ViewDimension"),
+ (Union("{self}.ViewDimension", [
+ ("D3D11_SRV_DIMENSION_BUFFER", D3D11_BUFFER_SRV, "Buffer"),
+ ("D3D11_SRV_DIMENSION_TEXTURE1D", D3D11_TEX1D_SRV, "Texture1D"),
+ ("D3D11_SRV_DIMENSION_TEXTURE1DARRAY", D3D11_TEX1D_ARRAY_SRV, "Texture1DArray"),
+ ("D3D11_SRV_DIMENSION_TEXTURE2D", D3D11_TEX2D_SRV1, "Texture2D"),
+ ("D3D11_SRV_DIMENSION_TEXTURE2DARRAY", D3D11_TEX2D_ARRAY_SRV1, "Texture2DArray"),
+ ("D3D11_SRV_DIMENSION_TEXTURE2DMS", D3D11_TEX2DMS_SRV, "Texture2DMS"),
+ ("D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY", D3D11_TEX2DMS_ARRAY_SRV, "Texture2DMSArray"),
+ ("D3D11_SRV_DIMENSION_TEXTURE3D", D3D11_TEX3D_SRV, "Texture3D"),
+ ("D3D11_SRV_DIMENSION_TEXTURECUBE", D3D11_TEXCUBE_SRV, "TextureCube"),
+ ("D3D11_SRV_DIMENSION_TEXTURECUBEARRAY", D3D11_TEXCUBE_ARRAY_SRV, "TextureCubeArray"),
+ ("D3D11_SRV_DIMENSION_BUFFEREX", D3D11_BUFFEREX_SRV, "BufferEx"),
+ ]), None),
+])
+
+
+ID3D11ShaderResourceView1 = Interface("ID3D11ShaderResourceView1", ID3D11ShaderResourceView)
+ID3D11ShaderResourceView1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_SHADER_RESOURCE_VIEW_DESC1), "pDesc1")], sideeffects=False),
+]
+
+D3D11_TEX2D_RTV1 = Struct("D3D11_TEX2D_RTV1", [
+ (UINT, "MipSlice"),
+ (UINT, "PlaneSlice"),
+])
+
+D3D11_TEX2D_ARRAY_RTV1 = Struct("D3D11_TEX2D_ARRAY_RTV1", [
+ (UINT, "MipSlice"),
+ (UINT, "FirstArraySlice"),
+ (UINT, "ArraySize"),
+ (UINT, "PlaneSlice"),
+])
+
+D3D11_RENDER_TARGET_VIEW_DESC1 = Struct("D3D11_RENDER_TARGET_VIEW_DESC1", [
+ (DXGI_FORMAT, "Format"),
+ (D3D11_RTV_DIMENSION, "ViewDimension"),
+ (Union("{self}.ViewDimension", [
+ ("D3D11_RTV_DIMENSION_BUFFER", D3D11_BUFFER_RTV, "Buffer"),
+ ("D3D11_RTV_DIMENSION_TEXTURE1D", D3D11_TEX1D_RTV, "Texture1D"),
+ ("D3D11_RTV_DIMENSION_TEXTURE1DARRAY", D3D11_TEX1D_ARRAY_RTV, "Texture1DArray"),
+ ("D3D11_RTV_DIMENSION_TEXTURE2D", D3D11_TEX2D_RTV1, "Texture2D"),
+ ("D3D11_RTV_DIMENSION_TEXTURE2DARRAY", D3D11_TEX2D_ARRAY_RTV1, "Texture2DArray"),
+ ("D3D11_RTV_DIMENSION_TEXTURE2DMS", D3D11_TEX2DMS_RTV, "Texture2DMS"),
+ ("D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY", D3D11_TEX2DMS_ARRAY_RTV, "Texture2DMSArray"),
+ ("D3D11_RTV_DIMENSION_TEXTURE3D", D3D11_TEX3D_RTV, "Texture3D"),
+ ]), None),
+])
+
+ID3D11RenderTargetView1 = Interface("ID3D11RenderTargetView1", ID3D11RenderTargetView)
+ID3D11RenderTargetView1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_RENDER_TARGET_VIEW_DESC1), "pDesc1")], sideeffects=False),
+]
+
+D3D11_TEX2D_UAV1 = Struct("D3D11_TEX2D_UAV1", [
+ (UINT, "MipSlice"),
+ (UINT, "PlaneSlice"),
+])
+
+D3D11_TEX2D_ARRAY_UAV1 = Struct("D3D11_TEX2D_ARRAY_UAV1", [
+ (UINT, "MipSlice"),
+ (UINT, "FirstArraySlice"),
+ (UINT, "ArraySize"),
+ (UINT, "PlaneSlice"),
+])
+
+D3D11_UNORDERED_ACCESS_VIEW_DESC1 = Struct("D3D11_UNORDERED_ACCESS_VIEW_DESC1", [
+ (DXGI_FORMAT, "Format"),
+ (D3D11_UAV_DIMENSION, "ViewDimension"),
+ (Union("{self}.ViewDimension", [
+ ("D3D11_UAV_DIMENSION_BUFFER", D3D11_BUFFER_UAV, "Buffer"),
+ ("D3D11_UAV_DIMENSION_TEXTURE1D", D3D11_TEX1D_UAV, "Texture1D"),
+ ("D3D11_UAV_DIMENSION_TEXTURE1DARRAY", D3D11_TEX1D_ARRAY_UAV, "Texture1DArray"),
+ ("D3D11_UAV_DIMENSION_TEXTURE2D", D3D11_TEX2D_UAV1, "Texture2D"),
+ ("D3D11_UAV_DIMENSION_TEXTURE2DARRAY", D3D11_TEX2D_ARRAY_UAV1, "Texture2DArray"),
+ ("D3D11_UAV_DIMENSION_TEXTURE3D", D3D11_TEX3D_UAV, "Texture3D"),
+ ]), None),
+])
+
+ID3D11UnorderedAccessView1 = Interface("ID3D11UnorderedAccessView1", ID3D11UnorderedAccessView)
+ID3D11UnorderedAccessView1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_UNORDERED_ACCESS_VIEW_DESC1), "pDesc1")], sideeffects=False),
+]
+
+D3D11_QUERY_DESC1 = Struct("D3D11_QUERY_DESC1", [
+ (D3D11_QUERY, "Query"),
+ (D3D11_QUERY_MISC_FLAG, "MiscFlags"),
+ (D3D11_CONTEXT_TYPE, "ContextType"),
+])
+
+ID3D11Query1 = Interface("ID3D11Query1", ID3D11Query)
+ID3D11Query1.methods += [
+ StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_QUERY_DESC1), "pDesc1")], sideeffects=False),
+]
+
+ID3D11DeviceContext3 = Interface("ID3D11DeviceContext3", ID3D11DeviceContext2)
+ID3D11DeviceContext3.methods += [
+ StdMethod(Void, "Flush1", [(D3D11_CONTEXT_TYPE, "ContextType"), (HANDLE, "hEvent")]),
+ StdMethod(Void, "SetHardwareProtectionState", [(BOOL, "HwProtectionEnable")]),
+ StdMethod(Void, "GetHardwareProtectionState", [Out(Pointer(BOOL), "pHwProtectionEnable")], sideeffects=False),
+]
+
+ID3D11Device3 = Interface("ID3D11Device3", ID3D11Device2)
+ID3D11Device3.methods += [
+ StdMethod(HRESULT, "CreateTexture2D1", [(Pointer(Const(D3D11_TEXTURE2D_DESC1)), "pDesc1"), (Array(Const(D3D11_SUBRESOURCE_DATA), "_getNumSubResources(pDesc1)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D11Texture2D1)), "ppTexture2D")]),
+ StdMethod(HRESULT, "CreateTexture3D1", [(Pointer(Const(D3D11_TEXTURE3D_DESC1)), "pDesc1"), (Array(Const(D3D11_SUBRESOURCE_DATA), "_getNumSubResources(pDesc1)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D11Texture3D1)), "ppTexture3D")]),
+ StdMethod(HRESULT, "CreateRasterizerState2", [(Pointer(Const(D3D11_RASTERIZER_DESC2)), "pRasterizerDesc"), Out(Pointer(ObjPointer(ID3D11RasterizerState2)), "ppRasterizerState")]),
+ StdMethod(HRESULT, "CreateShaderResourceView1", [(ObjPointer(ID3D11Resource), "pResource"), (Pointer(Const(D3D11_SHADER_RESOURCE_VIEW_DESC1)), "pDesc1"), Out(Pointer(ObjPointer(ID3D11ShaderResourceView1)), "ppSRView1")]),
+ StdMethod(HRESULT, "CreateUnorderedAccessView1", [(ObjPointer(ID3D11Resource), "pResource"), (Pointer(Const(D3D11_UNORDERED_ACCESS_VIEW_DESC1)), "pDesc1"), Out(Pointer(ObjPointer(ID3D11UnorderedAccessView1)), "ppUAView1")]),
+ StdMethod(HRESULT, "CreateRenderTargetView1", [(ObjPointer(ID3D11Resource), "pResource"), (Pointer(Const(D3D11_RENDER_TARGET_VIEW_DESC1)), "pDesc1"), Out(Pointer(ObjPointer(ID3D11RenderTargetView1)), "ppRTView1")]),
+ StdMethod(HRESULT, "CreateQuery1", [(Pointer(Const(D3D11_QUERY_DESC1)), "pQueryDesc1"), Out(Pointer(ObjPointer(ID3D11Query1)), "ppQuery1")]),
+ StdMethod(Void, "GetImmediateContext3", [Out(Pointer(ObjPointer(ID3D11DeviceContext3)), "ppImmediateContext")]),
+ StdMethod(HRESULT, "CreateDeferredContext3", [(UINT, "ContextFlags"), Out(Pointer(ObjPointer(ID3D11DeviceContext3)), "ppDeferredContext")]),
+ StdMethod(Void, "WriteToSubresource", [(ObjPointer(ID3D11Resource), "pDstResource"), (UINT, "DstSubresource"), (Pointer(Const(D3D11_BOX)), "pDstBox"), (OpaquePointer(Const(Void)), "pSrcData"), (UINT, "SrcRowPitch"), (UINT, "SrcDepthPitch")]), # FIXME
+ StdMethod(Void, "ReadFromSubresource", [Out(OpaquePointer(Void), "pDstData"), (UINT, "DstRowPitch"), (UINT, "DstDepthPitch"), (ObjPointer(ID3D11Resource), "pSrcResource"), (UINT, "SrcSubresource"), (Pointer(Const(D3D11_BOX)), "pSrcBox")], sideeffects=False), # FIXME
+]
+
+d3d11.addInterfaces([
+ ID3D11Device3,
+ ID3D11DeviceContext3,
+])
diff --git a/specs/d3d11_1.py b/specs/d3d11_1.py
deleted file mode 100644
index d163d8f0..00000000
--- a/specs/d3d11_1.py
+++ /dev/null
@@ -1,177 +0,0 @@
-##########################################################################
-#
-# Copyright 2012 Jose Fonseca
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-"""d3d11_1.h"""
-
-
-from winapi import *
-from d3d11sdklayers import *
-from d3d11 import *
-
-import dxgi1_2
-
-D3D_FEATURE_LEVEL.values += [
- "D3D_FEATURE_LEVEL_11_1",
-]
-
-D3D11_CREATE_DEVICE_FLAG.values += [
- "D3D11_CREATE_DEVICE_DEBUGGABLE",
- "D3D11_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY",
- "D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT",
- "D3D11_CREATE_DEVICE_VIDEO_SUPPORT",
-]
-
-D3D_MIN_PRECISION = Enum("D3D_MIN_PRECISION", [
- "D3D_MIN_PRECISION_DEFAULT",
- "D3D_MIN_PRECISION_FLOAT_16",
- "D3D_MIN_PRECISION_FLOAT_2_8",
- "D3D_MIN_PRECISION_RESERVED",
- "D3D_MIN_PRECISION_SINT_16",
- "D3D_MIN_PRECISION_UINT_16",
- "D3D_MIN_PRECISION_ANY_16",
- "D3D_MIN_PRECISION_ANY_10",
-])
-
-ID3D11BlendState1 = Interface("ID3D11BlendState1", ID3D11BlendState)
-ID3D11RasterizerState1 = Interface("ID3D11RasterizerState1", ID3D11RasterizerState)
-ID3DDeviceContextState = Interface("ID3DDeviceContextState", ID3D11DeviceChild)
-ID3D11DeviceContext1 = Interface("ID3D11DeviceContext1", ID3D11DeviceContext)
-ID3D11Device1 = Interface("ID3D11Device1", ID3D11Device)
-ID3DUserDefinedAnnotation = Interface("ID3DUserDefinedAnnotation", IUnknown)
-
-
-D3D11_COPY_FLAGS = Flags(UINT, [
- "D3D11_COPY_NO_OVERWRITE",
- "D3D11_COPY_DISCARD",
-])
-
-D3D11_LOGIC_OP = Enum("D3D11_LOGIC_OP", [
- "D3D11_LOGIC_OP_CLEAR",
- "D3D11_LOGIC_OP_SET",
- "D3D11_LOGIC_OP_COPY",
- "D3D11_LOGIC_OP_COPY_INVERTED",
- "D3D11_LOGIC_OP_NOOP",
- "D3D11_LOGIC_OP_INVERT",
- "D3D11_LOGIC_OP_AND",
- "D3D11_LOGIC_OP_NAND",
- "D3D11_LOGIC_OP_OR",
- "D3D11_LOGIC_OP_NOR",
- "D3D11_LOGIC_OP_XOR",
- "D3D11_LOGIC_OP_EQUIV",
- "D3D11_LOGIC_OP_AND_REVERSE",
- "D3D11_LOGIC_OP_AND_INVERTED",
- "D3D11_LOGIC_OP_OR_REVERSE",
- "D3D11_LOGIC_OP_OR_INVERTED",
-])
-
-D3D11_RENDER_TARGET_BLEND_DESC1 = Struct("D3D11_RENDER_TARGET_BLEND_DESC1", [
- (BOOL, "BlendEnable"),
- (BOOL, "LogicOpEnable"),
- (D3D11_BLEND, "SrcBlend"),
- (D3D11_BLEND, "DestBlend"),
- (D3D11_BLEND_OP, "BlendOp"),
- (D3D11_BLEND, "SrcBlendAlpha"),
- (D3D11_BLEND, "DestBlendAlpha"),
- (D3D11_BLEND_OP, "BlendOpAlpha"),
- (D3D11_LOGIC_OP, "LogicOp"),
- (UINT8, "RenderTargetWriteMask"),
-])
-
-D3D11_BLEND_DESC1 = Struct("D3D11_BLEND_DESC1", [
- (BOOL, "AlphaToCoverageEnable"),
- (BOOL, "IndependentBlendEnable"),
- (Array(D3D11_RENDER_TARGET_BLEND_DESC1, "D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT"), "RenderTarget"),
-])
-
-ID3D11BlendState1.methods += [
- StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_BLEND_DESC1), "pDesc")], sideeffects=False),
-]
-
-D3D11_RASTERIZER_DESC1 = Struct("D3D11_RASTERIZER_DESC1", [
- (D3D11_FILL_MODE, "FillMode"),
- (D3D11_CULL_MODE, "CullMode"),
- (BOOL, "FrontCounterClockwise"),
- (INT, "DepthBias"),
- (FLOAT, "DepthBiasClamp"),
- (FLOAT, "SlopeScaledDepthBias"),
- (BOOL, "DepthClipEnable"),
- (BOOL, "ScissorEnable"),
- (BOOL, "MultisampleEnable"),
- (BOOL, "AntialiasedLineEnable"),
- (UINT, "ForcedSampleCount"),
-])
-
-ID3D11RasterizerState1.methods += [
- StdMethod(Void, "GetDesc1", [Out(Pointer(D3D11_RASTERIZER_DESC1), "pDesc")], sideeffects=False),
-]
-
-D3D11_1_CREATE_DEVICE_CONTEXT_STATE_FLAG = Flags(UINT, [
- "D3D11_1_CREATE_DEVICE_CONTEXT_STATE_SINGLETHREADED",
-])
-
-ID3D11DeviceContext1.methods += [
- StdMethod(Void, "CopySubresourceRegion1", [(ObjPointer(ID3D11Resource), "pDstResource"), (UINT, "DstSubresource"), (UINT, "DstX"), (UINT, "DstY"), (UINT, "DstZ"), (ObjPointer(ID3D11Resource), "pSrcResource"), (UINT, "SrcSubresource"), (Pointer(Const(D3D11_BOX)), "pSrcBox"), (D3D11_COPY_FLAGS, "CopyFlags")]),
- StdMethod(Void, "UpdateSubresource1", [(ObjPointer(ID3D11Resource), "pDstResource"), (UINT, "DstSubresource"), (Pointer(Const(D3D11_BOX)), "pDstBox"), (Blob(Const(Void), "_calcSubresourceSize(pDstResource, DstSubresource, pDstBox, SrcRowPitch, SrcDepthPitch)"), "pSrcData"), (UINT, "SrcRowPitch"), (UINT, "SrcDepthPitch"), (D3D11_COPY_FLAGS, "CopyFlags")]),
- StdMethod(Void, "DiscardResource", [(ObjPointer(ID3D11Resource), "pResource")]),
- StdMethod(Void, "DiscardView", [(ObjPointer(ID3D11View), "pResourceView")]),
- StdMethod(Void, "DiscardView1", [(ObjPointer(ID3D11View), "pResourceView"), (Array(Const(D3D11_RECT), "NumRects"), "pRect"), (UINT, "NumRects")]),
- StdMethod(Void, "VSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "HSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "DSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "GSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "PSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "CSSetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), (Array(Const(ObjPointer(ID3D11Buffer)), "NumBuffers"), "ppConstantBuffers"), (Array(Const(UINT), "NumBuffers"), "pFirstConstant"), (Array(Const(UINT), "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "VSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "HSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "DSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "GSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "PSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "CSGetConstantBuffers1", [(UINT, "StartSlot"), (UINT, "NumBuffers"), Out(Array(ObjPointer(ID3D11Buffer), "NumBuffers"), "ppConstantBuffers"), Out(Array(UINT, "NumBuffers"), "pFirstConstant"), Out(Array(UINT, "NumBuffers"), "pNumConstants")]),
- StdMethod(Void, "SwapDeviceContextState", [(ObjPointer(ID3DDeviceContextState), "pState"), Out(Pointer(ObjPointer(ID3DDeviceContextState)), "ppPreviousState")]),
- StdMethod(Void, "ClearView", [(ObjPointer(ID3D11View), "pView"), (Array(Const(FLOAT), 4), "Color"), (Pointer(Const(D3D11_RECT)), "pRect"), (UINT, "NumRects")]),
-]
-
-
-ID3D11Device1.methods += [
- StdMethod(Void, "GetImmediateContext1", [Out(Pointer(ObjPointer(ID3D11DeviceContext1)), "ppImmediateContext")]),
- StdMethod(HRESULT, "CreateDeferredContext1", [(UINT, "ContextFlags"), Out(Pointer(ObjPointer(ID3D11DeviceContext1)), "ppDeferredContext")]),
- StdMethod(HRESULT, "CreateBlendState1", [(Pointer(Const(D3D11_BLEND_DESC1)), "pBlendStateDesc"), Out(Pointer(ObjPointer(ID3D11BlendState1)), "ppBlendState")]),
- StdMethod(HRESULT, "CreateRasterizerState1", [(Pointer(Const(D3D11_RASTERIZER_DESC1)), "pRasterizerDesc"), Out(Pointer(ObjPointer(ID3D11RasterizerState1)), "ppRasterizerState")]),
- StdMethod(HRESULT, "CreateDeviceContextState", [(D3D11_1_CREATE_DEVICE_CONTEXT_STATE_FLAG, "Flags"), (Array(Const(D3D_FEATURE_LEVEL), "FeatureLevels"), "pFeatureLevels"), (UINT, "FeatureLevels"), (UINT, "SDKVersion"), (REFIID, "EmulatedInterface"), Out(Pointer(D3D_FEATURE_LEVEL), "pChosenFeatureLevel"), Out(Pointer(ObjPointer(ID3DDeviceContextState)), "ppContextState")]),
- StdMethod(HRESULT, "OpenSharedResource1", [(HANDLE, "hResource"), (REFIID, "returnedInterface"), Out(Pointer(ObjPointer(Void)), "ppResource")]),
- StdMethod(HRESULT, "OpenSharedResourceByName", [(LPCWSTR, "lpName"), (DXGI_SHARED_RESOURCE_FLAG, "dwDesiredAccess"), (REFIID, "returnedInterface"), Out(Pointer(ObjPointer(Void)), "ppResource")]),
-]
-
-ID3DUserDefinedAnnotation.methods += [
- StdMethod(INT, "BeginEvent", [(LPCWSTR, "Name")], sideeffects=False),
- StdMethod(INT, "EndEvent", [], sideeffects=False),
- StdMethod(Void, "SetMarker", [(LPCWSTR, "Name")], sideeffects=False),
- StdMethod(BOOL, "GetStatus", [], sideeffects=False),
-]
-
-d3d11.addInterfaces([
- ID3D11Device1,
- ID3DUserDefinedAnnotation,
-])
diff --git a/specs/d3d11sdklayers.py b/specs/d3d11sdklayers.py
index ceecaa8a..907c4b09 100644
--- a/specs/d3d11sdklayers.py
+++ b/specs/d3d11sdklayers.py
@@ -831,17 +831,17 @@ D3D11_MESSAGE = Struct("D3D11_MESSAGE", [
(D3D11_MESSAGE_CATEGORY, "Category"),
(D3D11_MESSAGE_SEVERITY, "Severity"),
(D3D11_MESSAGE_ID, "ID"),
- (Pointer(Const(Int)), "pDescription"),
+ (ConstCString, "pDescription"),
(SIZE_T, "DescriptionByteLength"),
])
D3D11_INFO_QUEUE_FILTER_DESC = Struct("D3D11_INFO_QUEUE_FILTER_DESC", [
(UINT, "NumCategories"),
- (Pointer(D3D11_MESSAGE_CATEGORY), "pCategoryList"),
+ (Array(D3D11_MESSAGE_CATEGORY, "{self}.NumCategories"), "pCategoryList"),
(UINT, "NumSeverities"),
- (Pointer(D3D11_MESSAGE_SEVERITY), "pSeverityList"),
+ (Array(D3D11_MESSAGE_SEVERITY, "{self}.NumSeverities"), "pSeverityList"),
(UINT, "NumIDs"),
- (Pointer(D3D11_MESSAGE_ID), "pIDList"),
+ (Array(D3D11_MESSAGE_ID, "{self}.NumIDs"), "pIDList"),
])
D3D11_INFO_QUEUE_FILTER = Struct("D3D11_INFO_QUEUE_FILTER", [
diff --git a/specs/d3d11shader.py b/specs/d3d11shader.py
deleted file mode 100644
index 16bb5e44..00000000
--- a/specs/d3d11shader.py
+++ /dev/null
@@ -1,186 +0,0 @@
-##########################################################################
-#
-# Copyright 2012 Jose Fonseca
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-
-from d3dcommon import *
-
-
-ID3D11ShaderReflectionType = Interface("ID3D11ShaderReflectionType", IUnknown)
-ID3D11ShaderReflectionVariable = Interface("ID3D11ShaderReflectionVariable", IUnknown)
-ID3D11ShaderReflectionConstantBuffer = Interface("ID3D11ShaderReflectionConstantBuffer", IUnknown)
-ID3D11ShaderReflection = Interface("ID3D11ShaderReflection", IUnknown)
-
-
-D3D11_SHADER_VERSION_TYPE = Enum("D3D11_SHADER_VERSION_TYPE", [
- "D3D11_SHVER_PIXEL_SHADER",
- "D3D11_SHVER_VERTEX_SHADER",
- "D3D11_SHVER_GEOMETRY_SHADER",
- "D3D11_SHVER_HULL_SHADER",
- "D3D11_SHVER_DOMAIN_SHADER",
- "D3D11_SHVER_COMPUTE_SHADER",
-])
-
-D3D11_SIGNATURE_PARAMETER_DESC = Struct("D3D11_SIGNATURE_PARAMETER_DESC", [
- (LPCSTR, "SemanticName"),
- (UINT, "SemanticIndex"),
- (UINT, "Register"),
- (D3D_NAME, "SystemValueType"),
- (D3D_REGISTER_COMPONENT_TYPE, "ComponentType"),
- (BYTE, "Mask"),
- (BYTE, "ReadWriteMask"),
- (UINT, "Stream"),
-])
-
-D3D11_SHADER_BUFFER_DESC = Struct("D3D11_SHADER_BUFFER_DESC", [
- (LPCSTR, "Name"),
- (D3D_CBUFFER_TYPE, "Type"),
- (UINT, "Variables"),
- (UINT, "Size"),
- (UINT, "uFlags"),
-])
-
-D3D11_SHADER_VARIABLE_DESC = Struct("D3D11_SHADER_VARIABLE_DESC", [
- (LPCSTR, "Name"),
- (UINT, "StartOffset"),
- (UINT, "Size"),
- (UINT, "uFlags"),
- (LPVOID, "DefaultValue"),
- (UINT, "StartTexture"),
- (UINT, "TextureSize"),
- (UINT, "StartSampler"),
- (UINT, "SamplerSize"),
-])
-
-D3D11_SHADER_TYPE_DESC = Struct("D3D11_SHADER_TYPE_DESC", [
- (D3D_SHADER_VARIABLE_CLASS, "Class"),
- (D3D_SHADER_VARIABLE_TYPE, "Type"),
- (UINT, "Rows"),
- (UINT, "Columns"),
- (UINT, "Elements"),
- (UINT, "Members"),
- (UINT, "Offset"),
- (LPCSTR, "Name"),
-])
-
-D3D11_SHADER_DESC = Struct("D3D11_SHADER_DESC", [
- (UINT, "Version"),
- (LPCSTR, "Creator"),
- (UINT, "Flags"),
- (UINT, "ConstantBuffers"),
- (UINT, "BoundResources"),
- (UINT, "InputParameters"),
- (UINT, "OutputParameters"),
- (UINT, "InstructionCount"),
- (UINT, "TempRegisterCount"),
- (UINT, "TempArrayCount"),
- (UINT, "DefCount"),
- (UINT, "DclCount"),
- (UINT, "TextureNormalInstructions"),
- (UINT, "TextureLoadInstructions"),
- (UINT, "TextureCompInstructions"),
- (UINT, "TextureBiasInstructions"),
- (UINT, "TextureGradientInstructions"),
- (UINT, "FloatInstructionCount"),
- (UINT, "IntInstructionCount"),
- (UINT, "UintInstructionCount"),
- (UINT, "StaticFlowControlCount"),
- (UINT, "DynamicFlowControlCount"),
- (UINT, "MacroInstructionCount"),
- (UINT, "ArrayInstructionCount"),
- (UINT, "CutInstructionCount"),
- (UINT, "EmitInstructionCount"),
- (D3D_PRIMITIVE_TOPOLOGY, "GSOutputTopology"),
- (UINT, "GSMaxOutputVertexCount"),
- (D3D_PRIMITIVE, "InputPrimitive"),
- (UINT, "PatchConstantParameters"),
- (UINT, "cGSInstanceCount"),
- (UINT, "cControlPoints"),
- (D3D_TESSELLATOR_OUTPUT_PRIMITIVE, "HSOutputPrimitive"),
- (D3D_TESSELLATOR_PARTITIONING, "HSPartitioning"),
- (D3D_TESSELLATOR_DOMAIN, "TessellatorDomain"),
- (UINT, "cBarrierInstructions"),
- (UINT, "cInterlockedInstructions"),
- (UINT, "cTextureStoreInstructions"),
-])
-
-D3D11_SHADER_INPUT_BIND_DESC = Struct("D3D11_SHADER_INPUT_BIND_DESC", [
- (LPCSTR, "Name"),
- (D3D_SHADER_INPUT_TYPE, "Type"),
- (UINT, "BindPoint"),
- (UINT, "BindCount"),
- (UINT, "uFlags"),
- (D3D_RESOURCE_RETURN_TYPE, "ReturnType"),
- (D3D_SRV_DIMENSION, "Dimension"),
- (UINT, "NumSamples"),
-])
-
-ID3D11ShaderReflectionType.methods += [
- StdMethod(HRESULT, "GetDesc", [Out(Pointer(D3D11_SHADER_TYPE_DESC), "pDesc")], sideeffects=False),
- StdMethod(ObjPointer(ID3D11ShaderReflectionType), "GetMemberTypeByIndex", [(UINT, "Index")]),
- StdMethod(ObjPointer(ID3D11ShaderReflectionType), "GetMemberTypeByName", [(LPCSTR, "Name")]),
- StdMethod(LPCSTR, "GetMemberTypeName", [(UINT, "Index")], sideeffects=False),
- StdMethod(HRESULT, "IsEqual", [(ObjPointer(ID3D11ShaderReflectionType), "pType")], sideeffects=False),
- StdMethod(ObjPointer(ID3D11ShaderReflectionType), "GetSubType", []),
- StdMethod(ObjPointer(ID3D11ShaderReflectionType), "GetBaseClass", []),
- StdMethod(UINT, "GetNumInterfaces", [], sideeffects=False),
- StdMethod(ObjPointer(ID3D11ShaderReflectionType), "GetInterfaceByIndex", [(UINT, "uIndex")]),
- StdMethod(HRESULT, "IsOfType", [(ObjPointer(ID3D11ShaderReflectionType), "pType")], sideeffects=False),
- StdMethod(HRESULT, "ImplementsInterface", [(ObjPointer(ID3D11ShaderReflectionType), "pBase")], sideeffects=False),
-]
-
-ID3D11ShaderReflectionVariable.methods += [
- StdMethod(HRESULT, "GetDesc", [Out(Pointer(D3D11_SHADER_VARIABLE_DESC), "pDesc")], sideeffects=False),
- StdMethod(ObjPointer(ID3D11ShaderReflectionType), "GetType", []),
- StdMethod(ObjPointer(ID3D11ShaderReflectionConstantBuffer), "GetBuffer", []),
- StdMethod(UINT, "GetInterfaceSlot", [(UINT, "uArrayIndex")], sideeffects=False),
-]
-
-ID3D11ShaderReflectionConstantBuffer.methods += [
- StdMethod(HRESULT, "GetDesc", [Out(Pointer(D3D11_SHADER_BUFFER_DESC), "pDesc")], sideeffects=False),
- StdMethod(ObjPointer(ID3D11ShaderReflectionVariable), "GetVariableByIndex", [(UINT, "Index")]),
- StdMethod(ObjPointer(ID3D11ShaderReflectionVariable), "GetVariableByName", [(LPCSTR, "Name")]),
-]
-
-ID3D11ShaderReflection.methods += [
- StdMethod(HRESULT, "GetDesc", [Out(Pointer(D3D11_SHADER_DESC), "pDesc")]),
- StdMethod(ObjPointer(ID3D11ShaderReflectionConstantBuffer), "GetConstantBufferByIndex", [(UINT, "Index")]),
- StdMethod(ObjPointer(ID3D11ShaderReflectionConstantBuffer), "GetConstantBufferByName", [(LPCSTR, "Name")]),
- StdMethod(HRESULT, "GetResourceBindingDesc", [(UINT, "ResourceIndex"), Out(Pointer(D3D11_SHADER_INPUT_BIND_DESC), "pDesc")]),
- StdMethod(HRESULT, "GetInputParameterDesc", [(UINT, "ParameterIndex"), Out(Pointer(D3D11_SIGNATURE_PARAMETER_DESC), "pDesc")]),
- StdMethod(HRESULT, "GetOutputParameterDesc", [(UINT, "ParameterIndex"), Out(Pointer(D3D11_SIGNATURE_PARAMETER_DESC), "pDesc")]),
- StdMethod(HRESULT, "GetPatchConstantParameterDesc", [(UINT, "ParameterIndex"), Out(Pointer(D3D11_SIGNATURE_PARAMETER_DESC), "pDesc")]),
- StdMethod(ObjPointer(ID3D11ShaderReflectionVariable), "GetVariableByName", [(LPCSTR, "Name")]),
- StdMethod(HRESULT, "GetResourceBindingDescByName", [(LPCSTR, "Name"), Out(Pointer(D3D11_SHADER_INPUT_BIND_DESC), "pDesc")]),
- StdMethod(UINT, "GetMovInstructionCount", [], sideeffects=False),
- StdMethod(UINT, "GetMovcInstructionCount", [], sideeffects=False),
- StdMethod(UINT, "GetConversionInstructionCount", [], sideeffects=False),
- StdMethod(UINT, "GetBitwiseInstructionCount", [], sideeffects=False),
- StdMethod(D3D_PRIMITIVE, "GetGSInputPrimitive", [], sideeffects=False),
- StdMethod(BOOL, "IsSampleFrequencyShader", [], sideeffects=False),
- StdMethod(UINT, "GetNumInterfaceSlots", [], sideeffects=False),
- StdMethod(HRESULT, "GetMinFeatureLevel", [Out(Pointer(D3D_FEATURE_LEVEL), "pLevel")]),
- StdMethod(UINT, "GetThreadGroupSize", [Out(Pointer(UINT), "pSizeX"), Out(Pointer(UINT), "pSizeY"), Out(Pointer(UINT), "pSizeZ")], sideeffects=False),
-]
-
diff --git a/specs/d3d8.py b/specs/d3d8.py
index 1166ea49..2dbf1140 100644
--- a/specs/d3d8.py
+++ b/specs/d3d8.py
@@ -156,7 +156,7 @@ IDirect3DDevice8.methods += [
StdMethod(HRESULT, "GetDepthStencilSurface", [Out(Pointer(PDIRECT3DSURFACE8), "ppZStencilSurface")]),
StdMethod(HRESULT, "BeginScene", []),
StdMethod(HRESULT, "EndScene", []),
- StdMethod(HRESULT, "Clear", [(DWORD, "Count"), (ConstPointer(D3DRECT), "pRects"), (D3DCLEAR, "Flags"), (D3DCOLOR, "Color"), (Float, "Z"), (DWORD, "Stencil")]),
+ StdMethod(HRESULT, "Clear", [(DWORD, "Count"), (Array(Const(D3DRECT), "Count"), "pRects"), (D3DCLEAR, "Flags"), (D3DCOLOR, "Color"), (Float, "Z"), (DWORD, "Stencil")]),
StdMethod(HRESULT, "SetTransform", [(D3DTRANSFORMSTATETYPE, "State"), (ConstPointer(D3DMATRIX), "pMatrix")]),
StdMethod(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "State"), Out(Pointer(D3DMATRIX), "pMatrix")], sideeffects=False),
StdMethod(HRESULT, "MultiplyTransform", [(D3DTRANSFORMSTATETYPE, "State"), (ConstPointer(D3DMATRIX), "pMatrix")]),
@@ -168,8 +168,8 @@ IDirect3DDevice8.methods += [
StdMethod(HRESULT, "GetLight", [(DWORD, "Index"), Out(Pointer(D3DLIGHT8), "pLight")], sideeffects=False),
StdMethod(HRESULT, "LightEnable", [(DWORD, "Index"), (BOOL, "Enable")]),
StdMethod(HRESULT, "GetLightEnable", [(DWORD, "Index"), Out(Pointer(BOOL), "pEnable")], sideeffects=False),
- StdMethod(HRESULT, "SetClipPlane", [(DWORD, "Index"), (ConstPointer(Float), "pPlane")]),
- StdMethod(HRESULT, "GetClipPlane", [(DWORD, "Index"), Out(Pointer(Float), "pPlane")], sideeffects=False),
+ StdMethod(HRESULT, "SetClipPlane", [(DWORD, "Index"), (Array(Const(Float), 4), "pPlane")]),
+ StdMethod(HRESULT, "GetClipPlane", [(DWORD, "Index"), Out(Array(Float, 4), "pPlane")], sideeffects=False),
StdMethod(HRESULT, "SetRenderState", [(D3DRENDERSTATETYPE, "State"), (D3DRENDERSTATEVALUE, "Value")]),
StdMethod(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "State"), Out(Pointer(D3DRENDERSTATEVALUE), "pValue")], sideeffects=False),
StdMethod(HRESULT, "BeginStateBlock", []),
@@ -186,8 +186,8 @@ IDirect3DDevice8.methods += [
StdMethod(HRESULT, "SetTextureStageState", [(DWORD, "Stage"), (D3DTEXTURESTAGESTATETYPE, "Type"), (D3DTEXTURESTAGESTATEVALUE, "Value")]),
StdMethod(HRESULT, "ValidateDevice", [Out(Pointer(DWORD), "pNumPasses")]),
StdMethod(HRESULT, "GetInfo", [(D3DDEVINFOID, "DevInfoID"), Out(OpaqueBlob(Void, "DevInfoStructSize"), "pDevInfoStruct"), (DWORD, "DevInfoStructSize")], sideeffects=False),
- StdMethod(HRESULT, "SetPaletteEntries", [(UINT, "PaletteNumber"), (ConstPointer(PALETTEENTRY), "pEntries")]),
- StdMethod(HRESULT, "GetPaletteEntries", [(UINT, "PaletteNumber"), Out(Pointer(PALETTEENTRY), "pEntries")], sideeffects=False),
+ StdMethod(HRESULT, "SetPaletteEntries", [(UINT, "PaletteNumber"), (Array(Const(PALETTEENTRY), 256), "pEntries")]),
+ StdMethod(HRESULT, "GetPaletteEntries", [(UINT, "PaletteNumber"), Out(Array(PALETTEENTRY, 256), "pEntries")], sideeffects=False),
StdMethod(HRESULT, "SetCurrentTexturePalette", [(UINT, "PaletteNumber")]),
StdMethod(HRESULT, "GetCurrentTexturePalette", [Out(Pointer(UINT), "PaletteNumber")], sideeffects=False),
StdMethod(HRESULT, "DrawPrimitive", [(D3DPRIMITIVETYPE, "PrimitiveType"), (UINT, "StartVertex"), (UINT, "PrimitiveCount")]),
@@ -227,7 +227,7 @@ IDirect3DSwapChain8.methods += [
IDirect3DResource8.methods += [
StdMethod(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE8), "ppDevice")]),
StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "refguid"), (OpaqueBlob(Const(Void), "SizeOfData"), "pData"), (DWORD, "SizeOfData"), (D3DSPD, "Flags")], sideeffects=False),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), Out(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), InOut(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
StdMethod(HRESULT, "FreePrivateData", [(REFGUID, "refguid")], sideeffects=False),
StdMethod(DWORD, "SetPriority", [(DWORD, "PriorityNew")]),
StdMethod(DWORD, "GetPriority", [], sideeffects=False),
@@ -280,7 +280,7 @@ IDirect3DIndexBuffer8.methods += [
IDirect3DSurface8.methods += [
StdMethod(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE8), "ppDevice")]),
StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "refguid"), (OpaqueBlob(Const(Void), "SizeOfData"), "pData"), (DWORD, "SizeOfData"), (D3DSPD, "Flags")], sideeffects=False),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), Out(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), InOut(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
StdMethod(HRESULT, "FreePrivateData", [(REFGUID, "refguid")], sideeffects=False),
StdMethod(HRESULT, "GetContainer", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppContainer")]),
StdMethod(HRESULT, "GetDesc", [Out(Pointer(D3DSURFACE_DESC), "pDesc")], sideeffects=False),
@@ -291,7 +291,7 @@ IDirect3DSurface8.methods += [
IDirect3DVolume8.methods += [
StdMethod(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE8), "ppDevice")]),
StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "refguid"), (OpaqueBlob(Const(Void), "SizeOfData"), "pData"), (DWORD, "SizeOfData"), (D3DSPD, "Flags")], sideeffects=False),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), Out(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), InOut(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
StdMethod(HRESULT, "FreePrivateData", [(REFGUID, "refguid")], sideeffects=False),
StdMethod(HRESULT, "GetContainer", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppContainer")]),
StdMethod(HRESULT, "GetDesc", [Out(Pointer(D3DVOLUME_DESC), "pDesc")], sideeffects=False),
diff --git a/specs/d3d8types.py b/specs/d3d8types.py
index df90f710..fe58a0cd 100644
--- a/specs/d3d8types.py
+++ b/specs/d3d8types.py
@@ -50,7 +50,7 @@ D3DRECT = Struct("D3DRECT", [
])
D3DMATRIX = Struct("D3DMATRIX", [
- (Array(Array(Float, 4), "4"), "m"),
+ (Array(Array(Float, 4), 4), "m"),
])
D3DVIEWPORT8 = Struct("D3DVIEWPORT8", [
diff --git a/specs/d3d9.py b/specs/d3d9.py
index 5530ccb0..21015149 100644
--- a/specs/d3d9.py
+++ b/specs/d3d9.py
@@ -193,7 +193,7 @@ IDirect3DDevice9.methods += [
StdMethod(HRESULT, "GetDepthStencilSurface", [Out(Pointer(PDIRECT3DSURFACE9), "ppZStencilSurface")]),
StdMethod(HRESULT, "BeginScene", []),
StdMethod(HRESULT, "EndScene", []),
- StdMethod(HRESULT, "Clear", [(DWORD, "Count"), (ConstPointer(D3DRECT), "pRects"), (D3DCLEAR, "Flags"), (D3DCOLOR, "Color"), (Float, "Z"), (DWORD, "Stencil")]),
+ StdMethod(HRESULT, "Clear", [(DWORD, "Count"), (Array(Const(D3DRECT), "Count"), "pRects"), (D3DCLEAR, "Flags"), (D3DCOLOR, "Color"), (Float, "Z"), (DWORD, "Stencil")]),
StdMethod(HRESULT, "SetTransform", [(D3DTRANSFORMSTATETYPE, "State"), (ConstPointer(D3DMATRIX), "pMatrix")]),
StdMethod(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "State"), Out(Pointer(D3DMATRIX), "pMatrix")], sideeffects=False),
StdMethod(HRESULT, "MultiplyTransform", [(D3DTRANSFORMSTATETYPE, "State"), (ConstPointer(D3DMATRIX), "pMatrix")]),
@@ -205,8 +205,8 @@ IDirect3DDevice9.methods += [
StdMethod(HRESULT, "GetLight", [(DWORD, "Index"), Out(Pointer(D3DLIGHT9), "pLight")], sideeffects=False),
StdMethod(HRESULT, "LightEnable", [(DWORD, "Index"), (BOOL, "Enable")]),
StdMethod(HRESULT, "GetLightEnable", [(DWORD, "Index"), Out(Pointer(BOOL), "pEnable")], sideeffects=False),
- StdMethod(HRESULT, "SetClipPlane", [(DWORD, "Index"), (ConstPointer(Float), "pPlane")]),
- StdMethod(HRESULT, "GetClipPlane", [(DWORD, "Index"), Out(Pointer(Float), "pPlane")], sideeffects=False),
+ StdMethod(HRESULT, "SetClipPlane", [(DWORD, "Index"), (Array(Const(Float), 4), "pPlane")]),
+ StdMethod(HRESULT, "GetClipPlane", [(DWORD, "Index"), Out(Array(Float, 4), "pPlane")], sideeffects=False),
StdMethod(HRESULT, "SetRenderState", [(D3DRENDERSTATETYPE, "State"), (D3DRENDERSTATEVALUE, "Value")]),
StdMethod(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "State"), Out(Pointer(D3DRENDERSTATEVALUE), "pValue")], sideeffects=False),
StdMethod(HRESULT, "CreateStateBlock", [(D3DSTATEBLOCKTYPE, "Type"), Out(Pointer(PDIRECT3DSTATEBLOCK9), "ppSB")]),
@@ -221,8 +221,8 @@ IDirect3DDevice9.methods += [
StdMethod(HRESULT, "GetSamplerState", [(DWORD, "Sampler"), (D3DSAMPLERSTATETYPE, "Type"), Out(Pointer(D3DSAMPLERSTATEVALUE), "pValue")], sideeffects=False),
StdMethod(HRESULT, "SetSamplerState", [(DWORD, "Sampler"), (D3DSAMPLERSTATETYPE, "Type"), (D3DSAMPLERSTATEVALUE, "Value")]),
StdMethod(HRESULT, "ValidateDevice", [Out(Pointer(DWORD), "pNumPasses")]),
- StdMethod(HRESULT, "SetPaletteEntries", [(UINT, "PaletteNumber"), (ConstPointer(PALETTEENTRY), "pEntries")]),
- StdMethod(HRESULT, "GetPaletteEntries", [(UINT, "PaletteNumber"), Out(Pointer(PALETTEENTRY), "pEntries")], sideeffects=False),
+ StdMethod(HRESULT, "SetPaletteEntries", [(UINT, "PaletteNumber"), (Array(Const(PALETTEENTRY), 256), "pEntries")]),
+ StdMethod(HRESULT, "GetPaletteEntries", [(UINT, "PaletteNumber"), Out(Array(PALETTEENTRY, 256), "pEntries")], sideeffects=False),
StdMethod(HRESULT, "SetCurrentTexturePalette", [(UINT, "PaletteNumber")]),
StdMethod(HRESULT, "GetCurrentTexturePalette", [Out(Pointer(UINT), "PaletteNumber")], sideeffects=False),
StdMethod(HRESULT, "SetScissorRect", [(ConstPointer(RECT), "pRect")]),
@@ -290,7 +290,7 @@ IDirect3DSwapChain9.methods += [
IDirect3DResource9.methods += [
StdMethod(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "refguid"), (OpaqueBlob(Const(Void), "SizeOfData"), "pData"), (DWORD, "SizeOfData"), (D3DSPD, "Flags")], sideeffects=False),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), Out(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), InOut(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
StdMethod(HRESULT, "FreePrivateData", [(REFGUID, "refguid")], sideeffects=False),
StdMethod(D3D9_RESOURCE_PRIORITY, "SetPriority", [(D3D9_RESOURCE_PRIORITY, "PriorityNew")]),
StdMethod(D3D9_RESOURCE_PRIORITY, "GetPriority", [], sideeffects=False),
@@ -300,7 +300,7 @@ IDirect3DResource9.methods += [
IDirect3DVertexDeclaration9.methods += [
StdMethod(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
- StdMethod(HRESULT, "GetDeclaration", [Out(Array(D3DVERTEXELEMENT9, "*pNumElements"), "pElement"), Out(Pointer(UINT), "pNumElements")], sideeffects=False),
+ StdMethod(HRESULT, "GetDeclaration", [Out(Array(D3DVERTEXELEMENT9, "*pNumElements"), "pElement"), InOut(Pointer(UINT), "pNumElements")], sideeffects=False),
]
IDirect3DVertexShader9.methods += [
@@ -363,14 +363,14 @@ IDirect3DSurface9.methods += [
StdMethod(HRESULT, "GetDesc", [Out(Pointer(D3DSURFACE_DESC), "pDesc")], sideeffects=False),
StdMethod(HRESULT, "LockRect", [Out(Pointer(D3DLOCKED_RECT), "pLockedRect"), (ConstPointer(RECT), "pRect"), (D3DLOCK, "Flags")]),
StdMethod(HRESULT, "UnlockRect", []),
- StdMethod(HRESULT, "GetDC", [Out(Pointer(HDC), "phdc")]),
- StdMethod(HRESULT, "ReleaseDC", [(HDC, "hdc")]),
+ StdMethod(HRESULT, "GetDC", [Out(Pointer(HDC), "phdc")], sideeffects=False),
+ StdMethod(HRESULT, "ReleaseDC", [(HDC, "hdc")], sideeffects=False),
]
IDirect3DVolume9.methods += [
StdMethod(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "refguid"), (OpaqueBlob(Const(Void), "SizeOfData"), "pData"), (DWORD, "SizeOfData"), (D3DSPD, "Flags")], sideeffects=False),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), Out(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaqueBlob(Void, "*pSizeOfData"), "pData"), InOut(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
StdMethod(HRESULT, "FreePrivateData", [(REFGUID, "refguid")], sideeffects=False),
StdMethod(HRESULT, "GetContainer", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppContainer")]),
StdMethod(HRESULT, "GetDesc", [Out(Pointer(D3DVOLUME_DESC), "pDesc")], sideeffects=False),
@@ -422,6 +422,16 @@ d3d9 = Module("d3d9")
d3d9.addFunctions([
StdFunction(PDIRECT3D9, "Direct3DCreate9", [(UINT, "SDKVersion")], fail='NULL'),
StdFunction(HRESULT, "Direct3DCreate9Ex", [(UINT, "SDKVersion"), Out(Pointer(PDIRECT3D9EX), "ppD3D")], fail='D3DERR_NOTAVAILABLE'),
+])
+d3d9.addInterfaces([
+ IDirect3DSwapChain9Ex,
+])
+
+# D3DPERF_* functions can also be used by D3D10 applications, so keep them in a
+# separate module to be merged as necessary
+# See http://web.archive.org/web/20110510070258/http://msdn.microsoft.com/en-us/library/ee417071%28v=VS.85%29.aspx
+d3dperf = Module("d3d9")
+d3dperf.addFunctions([
StdFunction(Int, "D3DPERF_BeginEvent", [(D3DCOLOR, "col"), (LPCWSTR, "wszName")], fail='-1', sideeffects=False),
StdFunction(Int, "D3DPERF_EndEvent", [], fail='-1', sideeffects=False),
StdFunction(Void, "D3DPERF_SetMarker", [(D3DCOLOR, "col"), (LPCWSTR, "wszName")], sideeffects=False),
@@ -430,6 +440,3 @@ d3d9.addFunctions([
StdFunction(Void, "D3DPERF_SetOptions", [(DWORD, "dwOptions")], sideeffects=False),
StdFunction(DWORD, "D3DPERF_GetStatus", [], fail='0', sideeffects=False),
])
-d3d9.addInterfaces([
- IDirect3DSwapChain9Ex,
-])
diff --git a/specs/d3d9dxva2.py b/specs/d3d9dxva2.py
deleted file mode 100644
index 5c52f98d..00000000
--- a/specs/d3d9dxva2.py
+++ /dev/null
@@ -1,382 +0,0 @@
-##########################################################################
-#
-# Copyright 2012 VMware, Inc.
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-
-from d3d9 import *
-
-REFERENCE_TIME = Alias("REFERENCE_TIME", LONGLONG)
-
-DXVA2_ProcAmp = Flags(UINT, [
- "DXVA2_ProcAmp_None",
- "DXVA2_ProcAmp_Brightness",
- "DXVA2_ProcAmp_Contrast",
- "DXVA2_ProcAmp_Hue",
- "DXVA2_ProcAmp_Saturation",
-])
-
-HRESULT = FakeEnum(HRESULT, [
- "DXVA2_E_NOT_INITIALIZED",
- "DXVA2_E_NEW_VIDEO_DEVICE",
- "DXVA2_E_VIDEO_DEVICE_LOCKED",
- "DXVA2_E_NOT_AVAILABLE",
-])
-
-DXVA2_SampleFormat = Enum("DXVA2_SampleFormat", [
- "DXVA2_SampleFormatMask",
- "DXVA2_SampleUnknown",
- "DXVA2_SampleProgressiveFrame",
- "DXVA2_SampleFieldInterleavedEvenFirst",
- "DXVA2_SampleFieldInterleavedOddFirst",
- "DXVA2_SampleFieldSingleEven",
- "DXVA2_SampleFieldSingleOdd",
- "DXVA2_SampleSubStream",
-])
-
-DXVA2_VideoChromaSubSampling = Enum("DXVA2_VideoChromaSubSampling", [
- "DXVA2_VideoChromaSubsamplingMask",
- "DXVA2_VideoChromaSubsampling_Unknown",
- "DXVA2_VideoChromaSubsampling_ProgressiveChroma",
- "DXVA2_VideoChromaSubsampling_Horizontally_Cosited",
- "DXVA2_VideoChromaSubsampling_Vertically_Cosited",
- "DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes",
- "DXVA2_VideoChromaSubsampling_MPEG2",
- "DXVA2_VideoChromaSubsampling_MPEG1",
- "DXVA2_VideoChromaSubsampling_DV_PAL",
- "DXVA2_VideoChromaSubsampling_Cosited",
-])
-
-DXVA2_NominalRange = Enum("DXVA2_NominalRange", [
- "DXVA2_NominalRangeMask",
- "DXVA2_NominalRange_Unknown",
- "DXVA2_NominalRange_Normal",
- "DXVA2_NominalRange_Wide",
- "DXVA2_NominalRange_0_255",
- "DXVA2_NominalRange_16_235",
- "DXVA2_NominalRange_48_208",
-])
-
-DXVA2_VideoLighting = Enum("DXVA2_VideoLighting", [
- "DXVA2_VideoLightingMask",
- "DXVA2_VideoLighting_Unknown",
- "DXVA2_VideoLighting_bright",
- "DXVA2_VideoLighting_office",
- "DXVA2_VideoLighting_dim",
- "DXVA2_VideoLighting_dark",
-])
-
-DXVA2_VideoPrimaries = Enum("DXVA2_VideoPrimaries", [
- "DXVA2_VideoPrimariesMask",
- "DXVA2_VideoPrimaries_Unknown",
- "DXVA2_VideoPrimaries_reserved",
- "DXVA2_VideoPrimaries_BT709",
- "DXVA2_VideoPrimaries_BT470_2_SysM",
- "DXVA2_VideoPrimaries_BT470_2_SysBG",
- "DXVA2_VideoPrimaries_SMPTE170M",
- "DXVA2_VideoPrimaries_SMPTE240M",
- "DXVA2_VideoPrimaries_EBU3213",
- "DXVA2_VideoPrimaries_SMPTE_C",
-])
-
-DXVA2_VideoTransferFunction = Enum("DXVA2_VideoTransferFunction", [
- "DXVA2_VideoTransFuncMask",
- "DXVA2_VideoTransFunc_Unknown",
- "DXVA2_VideoTransFunc_10",
- "DXVA2_VideoTransFunc_18",
- "DXVA2_VideoTransFunc_20",
- "DXVA2_VideoTransFunc_22",
- "DXVA2_VideoTransFunc_709",
- "DXVA2_VideoTransFunc_240M",
- "DXVA2_VideoTransFunc_sRGB",
- "DXVA2_VideoTransFunc_28",
-])
-
-DXVA2_SurfaceType = FakeEnum(DWORD, [
- "DXVA2_SurfaceType_DecoderRenderTarget",
- "DXVA2_SurfaceType_ProcessorRenderTarget",
- "DXVA2_SurfaceType_D3DRenderTargetTexture",
-])
-
-DXVA2_VideoTransferMatrix = Enum("DXVA2_VideoTransferMatrix", [
- "DXVA2_VideoTransferMatrixMask",
- "DXVA2_VideoTransferMatrix_Unknown",
- "DXVA2_VideoTransferMatrix_BT709",
- "DXVA2_VideoTransferMatrix_BT601",
- "DXVA2_VideoTransferMatrix_SMPTE240M",
-])
-
-DXVA2_AYUVSample16 = Struct("DXVA2_AYUVSample16", [
- (USHORT, "Cr"),
- (USHORT, "Cb"),
- (USHORT, "Y"),
- (USHORT, "Alpha"),
-])
-
-DXVA2_AYUVSample8 = Struct("DXVA2_AYUVSample8", [
- (UCHAR, "Cr"),
- (UCHAR, "Cb"),
- (UCHAR, "Y"),
- (UCHAR, "Alpha"),
-])
-
-DXVA2_ConfigPictureDecode = Struct("DXVA2_ConfigPictureDecode", [
- (GUID, "guidConfigBitstreamEncryption"),
- (GUID, "guidConfigMBcontrolEncryption"),
- (GUID, "guidConfigResidDiffEncryption"),
- (UINT, "ConfigBitstreamRaw"),
- (UINT, "ConfigMBcontrolRasterOrder"),
- (UINT, "ConfigResidDiffHost"),
- (UINT, "ConfigSpatialResid8"),
- (UINT, "ConfigResid8Subtraction"),
- (UINT, "ConfigSpatialHost8or9Clipping"),
- (UINT, "ConfigSpatialResidInterleaved"),
- (UINT, "ConfigIntraResidUnsigned"),
- (UINT, "ConfigResidDiffAccelerator"),
- (UINT, "ConfigHostInverseScan"),
- (UINT, "ConfigSpecificIDCT"),
- (UINT, "Config4GroupedCoefs"),
- (USHORT, "ConfigMinRenderTargetBuffCount"),
- (USHORT, "ConfigDecoderSpecific"),
-])
-
-DXVA2_DecodeBufferDesc = Struct("DXVA2_DecodeBufferDesc", [
- (DWORD, "CompressedBufferType"),
- (UINT, "BufferIndex"),
- (UINT, "DataOffset"),
- (UINT, "DataSize"),
- (UINT, "FirstMBaddress"),
- (UINT, "NumMBsInBuffer"),
- (UINT, "Width"),
- (UINT, "Height"),
- (UINT, "Stride"),
- (UINT, "ReservedBits"),
- (PVOID, "pvPVPState"),
-])
-
-DXVA2_DecodeExtensionData = Struct("DXVA2_DecodeExtensionData", [
- (UINT, "Function"),
- (PVOID, "pPrivateInputData"),
- (UINT, "PrivateInputDataSize"),
- (PVOID, "pPrivateOutputData"),
- (UINT, "PrivateOutputDataSize"),
-])
-
-DXVA2_DecodeExecuteParams = Struct("DXVA2_DecodeExecuteParams", [
- (UINT, "NumCompBuffers"),
- (Array(DXVA2_DecodeBufferDesc, "{self}.NumCompBuffers"), "pCompressedBuffers"),
- (Pointer(DXVA2_DecodeExtensionData), "pExtensionData"),
-])
-
-DXVA2_ExtendedFormat = Struct("DXVA2_ExtendedFormat", [
- (UINT, "value"),
-])
-
-DXVA2_Fixed32 = Struct("DXVA2_Fixed32", [
- (USHORT, "Fraction"),
- (SHORT, "Value"),
-])
-
-DXVA2_FilterValues = Struct("DXVA2_FilterValues", [
- (DXVA2_Fixed32, "Level"),
- (DXVA2_Fixed32, "Threshold"),
- (DXVA2_Fixed32, "Radius"),
-])
-
-DXVA2_Frequency = Struct("DXVA2_Frequency", [
- (UINT, "Numerator"),
- (UINT, "Denominator"),
-])
-
-DXVA2_ProcAmpValues = Struct("DXVA2_ProcAmpValues", [
- (DXVA2_Fixed32, "Brightness"),
- (DXVA2_Fixed32, "Contrast"),
- (DXVA2_Fixed32, "Hue"),
- (DXVA2_Fixed32, "Saturation"),
-])
-
-DXVA2_ValueRange = Struct("DXVA2_ValueRange", [
- (DXVA2_Fixed32, "MinValue"),
- (DXVA2_Fixed32, "MaxValue"),
- (DXVA2_Fixed32, "DefaultValue"),
- (DXVA2_Fixed32, "StepSize"),
-])
-
-DXVA2_VideoDesc = Struct("DXVA2_VideoDesc", [
- (UINT, "SampleWidth"),
- (UINT, "SampleHeight"),
- (DXVA2_ExtendedFormat, "SampleFormat"),
- (D3DFORMAT, "Format"),
- (DXVA2_Frequency, "InputSampleFreq"),
- (DXVA2_Frequency, "OutputFrameFreq"),
- (UINT, "UABProtectionLevel"),
- (UINT, "Reserved"),
-])
-
-DXVA2_VideoProcessBltParams = Struct("DXVA2_VideoProcessBltParams", [
- (REFERENCE_TIME, "TargetFrame"),
- (RECT, "TargetRect"),
- (SIZE, "ConstrictionSize"),
- (UINT, "StreamingFlags"),
- (DXVA2_AYUVSample16, "BackgroundColor"),
- (DXVA2_ExtendedFormat, "DestFormat"),
- (DXVA2_ProcAmpValues, "ProcAmpValues"),
- (DXVA2_Fixed32, "Alpha"),
- (DXVA2_FilterValues, "NoiseFilterLuma"),
- (DXVA2_FilterValues, "NoiseFilterChroma"),
- (DXVA2_FilterValues, "DetailFilterLuma"),
- (DXVA2_FilterValues, "DetailFilterChroma"),
- (DWORD, "DestData"),
-])
-
-DXVA2_VideoProcessorCaps = Struct("DXVA2_VideoProcessorCaps", [
- (UINT, "DeviceCaps"),
- (D3DPOOL, "InputPool"),
- (UINT, "NumForwardRefSamples"),
- (UINT, "NumBackwardRefSamples"),
- (UINT, "Reserved"),
- (UINT, "DeinterlaceTechnology"),
- (UINT, "ProcAmpControlCaps"),
- (UINT, "VideoProcessorOperations"),
- (UINT, "NoiseFilterTechnology"),
- (UINT, "DetailFilterTechnology"),
-])
-
-
-# See also DXVADDI_PVP_KEY128
-DXVA2_PVP_KEY128 = Struct('DXVA2_PVP_KEY128', [
- (Array(BYTE, 16), 'Data'),
-])
-
-# See also DXVADDI_PVP_SETKEY
-DXVA2_PVP_SETKEY = Struct('DXVA2_PVP_SETKEY', [
- (DXVA2_PVP_KEY128, 'ContentKey'),
-])
-
-DXVA2_DECODEBUFFERDESC = Struct("DXVA2_DECODEBUFFERDESC", [
- (ObjPointer(IDirect3DSurface9), "pRenderTarget"),
- (DWORD, "CompressedBufferType"),
- (DWORD, "BufferIndex"),
- (DWORD, "DataOffset"),
- (DWORD, "DataSize"),
- (DWORD, "FirstMBaddress"),
- (DWORD, "NumMBsInBuffer"),
- (DWORD, "Width"),
- (DWORD, "Height"),
- (DWORD, "Stride"),
- (DWORD, "ReservedBits"),
- (PVOID, "pCipherCounter"),
-])
-
-DXVA2_DECODEEXECUTE = Struct("DXVA2_DECODEEXECUTE", [
- (UINT, "NumCompBuffers"),
- (Array(DXVA2_DECODEBUFFERDESC, "{self}.NumCompBuffers"), "pCompressedBuffers"),
-])
-
-DXVA2_VIDEOSAMPLE = Struct("DXVA2_VIDEOSAMPLE", [
- (REFERENCE_TIME, "Start"),
- (REFERENCE_TIME, "End"),
- (DXVA2_ExtendedFormat, "SampleFormat"),
- (DWORD, "SampleFlags"),
- (ObjPointer(IDirect3DSurface9), "SrcSurface"),
- (RECT, "SrcRect"),
- (RECT, "DstRect"),
- #(Array(DXVA2_AYUVSample8, 16), "Pal"),
- (DXVA2_Fixed32, "PlanarAlpha"),
-])
-
-DXVA2_VIDEOPROCESSBLT = Struct("DXVA2_VIDEOPROCESSBLT", [
- (REFERENCE_TIME, "TargetFrame"),
- (RECT, "TargetRect"),
- (SIZE, "ConstrictionSize"),
- (DWORD, "StreamingFlags"),
- (DXVA2_AYUVSample16, "BackgroundColor"),
- (DXVA2_ExtendedFormat, "DestFormat"),
- (DWORD, "DestFlags"),
- (DXVA2_ProcAmpValues, "ProcAmpValues"),
- (DXVA2_Fixed32, "Alpha"),
- (DXVA2_FilterValues, "NoiseFilterLuma"),
- (DXVA2_FilterValues, "NoiseFilterChroma"),
- (DXVA2_FilterValues, "DetailFilterLuma"),
- (DXVA2_FilterValues, "DetailFilterChroma"),
- (Array(DXVA2_VIDEOSAMPLE, "{self}.NumSrcSurfaces"), "pSrcSurfaces"),
- (UINT, "NumSrcSurfaces"),
-])
-
-DXVA2_EXTENSIONEXECUTE = Opaque('DXVA2_EXTENSIONEXECUTE')
-DXVA2_DECODEBUFFERINFO = Opaque('DXVA2_DECODEBUFFERINFO')
-
-
-IDirect3DDecodeDevice9 = Interface("IDirect3DDecodeDevice9", IUnknown)
-IDirect3DDecodeDevice9.methods += [
- StdMethod(HRESULT, "DecodeBeginFrame", [(Pointer(DXVA2_PVP_SETKEY), "pPVPSetKey")]),
- StdMethod(HRESULT, "DecodeEndFrame", [(Pointer(HANDLE), "pHandleComplete")]),
- StdMethod(HRESULT, "DecodeSetRenderTarget", [(ObjPointer(IDirect3DSurface9), "pRenderTarget")]),
- StdMethod(HRESULT, "DecodeExecute", [(Pointer(DXVA2_DECODEEXECUTE), "pExecuteParams")]),
-]
-
-IDirect3DVideoProcessDevice9 = Interface("IDirect3DVideoProcessDevice9", IUnknown)
-IDirect3DVideoProcessDevice9.methods += [
- StdMethod(HRESULT, "VideoProcessBeginFrame", []),
- StdMethod(HRESULT, "VideoProcessEndFrame", [(Pointer(HANDLE), "pHandleComplete")]),
- StdMethod(HRESULT, "VideoProcessSetRenderTarget", [(ObjPointer(IDirect3DSurface9), "pRenderTarget")]),
- StdMethod(HRESULT, "VideoProcessBlt", [(Pointer(DXVA2_VIDEOPROCESSBLT), "pData")]),
-]
-
-IDirect3DDXVAExtensionDevice9 = Interface("IDirect3DDXVAExtensionDevice9", IUnknown)
-IDirect3DDXVAExtensionDevice9.methods += [
- StdMethod(HRESULT, "ExtensionExecute", [(OpaquePointer(DXVA2_EXTENSIONEXECUTE), "pData")]),
-]
-
-IDirect3DDxva2Container9 = Interface("IDirect3DDxva2Container9", IUnknown)
-IDirect3DDxva2Container9.methods += [
- StdMethod(HRESULT, "CreateSurface", [(UINT, "Width"), (UINT, "Height"), (UINT, "BackBuffers"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), (DWORD, "Usage"), (DXVA2_SurfaceType, "DxvaType"), Out(Array(ObjPointer(IDirect3DSurface9), "1 + BackBuffers"), "ppSurface"), (Pointer(HANDLE), "pSharedHandle")]),
- StdMethod(HRESULT, "VidToSysBlt", [(ObjPointer(IDirect3DSurface9), "pSourceSurface"), (Pointer(RECT), "pSourceRect"), (ObjPointer(IDirect3DSurface9), "pDestSurface"), (Pointer(RECT), "pDestRect")]),
- StdMethod(HRESULT, "GetDecodeGuidCount", [Out(Pointer(UINT), "pCount")], sideeffects=False),
- StdMethod(HRESULT, "GetDecodeGuids", [(UINT, "Count"), Out(Array(GUID, "Count"), "pGuids")], sideeffects=False),
- StdMethod(HRESULT, "GetDecodeRenderTargetFormatCount", [(REFGUID, "Guid"), Out(Pointer(UINT), "pCount")], sideeffects=False),
- StdMethod(HRESULT, "GetDecodeRenderTargets", [(REFGUID, "Guid"), (UINT, "Count"), Out(Array(D3DFORMAT, "Count"), "pFormats")], sideeffects=False),
- StdMethod(HRESULT, "GetDecodeCompressedBufferCount", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), Out(Pointer(UINT), "pCount")], sideeffects=False),
- StdMethod(HRESULT, "GetDecodeCompressedBuffers", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (UINT, "Count"), Out(OpaquePointer(DXVA2_DECODEBUFFERINFO), "pBufferInfo")], sideeffects=False),
- StdMethod(HRESULT, "GetDecodeConfigurationCount", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), Out(Pointer(UINT), "pCount")], sideeffects=False),
- StdMethod(HRESULT, "GetDecodeConfigurations", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (UINT, "Count"), Out(Array(DXVA2_ConfigPictureDecode, "Count"), "pConfigs")], sideeffects=False),
- StdMethod(HRESULT, "CreateDecodeDevice", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (Pointer(Const(DXVA2_ConfigPictureDecode)), "pConfig"), (Array(ObjPointer(IDirect3DSurface9), "NumSurfaces"), "ppDecoderRenderTargets"), (UINT, "NumSurfaces"), Out(Pointer(ObjPointer(IDirect3DDecodeDevice9)), "ppDecode")]),
- StdMethod(HRESULT, "GetVideoProcessorDeviceGuidCount", [(Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), Out(Pointer(UINT), "pCount")], sideeffects=False),
- StdMethod(HRESULT, "GetVideoProcessorDeviceGuids", [(Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (UINT, "Count"), Out(Pointer(GUID), "pGuids")], sideeffects=False),
- StdMethod(HRESULT, "GetVideoProcessorCaps", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "Format"), Out(Pointer(DXVA2_VideoProcessorCaps), "pCaps")], sideeffects=False),
- StdMethod(HRESULT, "GetProcAmpRange", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "Format"), (UINT, "ProcAmpCap"), Out(Pointer(DXVA2_ValueRange), "pRange")]),
- StdMethod(HRESULT, "GetFilterPropertyRange", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "Format"), (UINT, "FilterSetting"), Out(Pointer(DXVA2_ValueRange), "pRange")], sideeffects=False),
- StdMethod(HRESULT, "GetVideoProcessorRenderTargetCount", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), Out(Pointer(UINT), "pCount")], sideeffects=False),
- StdMethod(HRESULT, "GetVideoProcessorRenderTargets", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (UINT, "Count"), Out(Array(D3DFORMAT, "Count"), "pFormats")], sideeffects=False),
- StdMethod(HRESULT, "GetVideoProcessorSubStreamFormatCount", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "Format"), Out(Pointer(UINT), "pCount")], sideeffects=False),
- StdMethod(HRESULT, "GetVideoProcessorSubStreamFormats", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "Format"), (UINT, "Count"), Out(Array(D3DFORMAT, "Count"), "pFormats")], sideeffects=False),
- StdMethod(HRESULT, "CreateVideoProcessDevice", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "Format"), (UINT, "MaxSubStreams"), Out(Pointer(ObjPointer(IDirect3DVideoProcessDevice9)), "ppVideoProcessDevice")]),
- StdMethod(HRESULT, "GetExtensionGuidCount", [(DWORD, "Extension"), Out(Pointer(UINT), "pCount")], sideeffects=False),
- StdMethod(HRESULT, "GetExtensionGuids", [(DWORD, "Extension"), (UINT, "Count"), Out(Array(GUID, "Count"), "pGuids")], sideeffects=False),
- StdMethod(HRESULT, "GetExtensionCaps", [(REFGUID, "Guid"), (UINT, "arg2"), (OpaquePointer(Void), "arg3"), (UINT, "arg4"), (OpaquePointer(Void), "arg5"), (UINT, "arg6")], sideeffects=False),
- StdMethod(HRESULT, "CreateExtensionDevice", [(REFGUID, "Guid"), (OpaquePointer(Void), "arg2"), (UINT, "arg3"), Out(Pointer(ObjPointer(IDirect3DDXVAExtensionDevice9)), "ppExtension")]),
-]
-
-d3d9.addInterfaces([
- IDirect3DDxva2Container9,
-])
diff --git a/specs/d3d9types.py b/specs/d3d9types.py
index a9aefffd..2545a767 100644
--- a/specs/d3d9types.py
+++ b/specs/d3d9types.py
@@ -51,7 +51,7 @@ D3DRECT = Struct("D3DRECT", [
])
D3DMATRIX = Struct("D3DMATRIX", [
- (Array(Array(Float, 4), "4"), "m"),
+ (Array(Array(Float, 4), 4), "m"),
])
D3DVIEWPORT9 = Struct("D3DVIEWPORT9", [
diff --git a/specs/d3dcommon.py b/specs/d3dcommon.py
deleted file mode 100644
index 9486ba87..00000000
--- a/specs/d3dcommon.py
+++ /dev/null
@@ -1,701 +0,0 @@
-##########################################################################
-#
-# Copyright 2012 Jose Fonseca
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-
-from winapi import *
-
-
-D3D_DRIVER_TYPE = Enum('D3D_DRIVER_TYPE', [
- 'D3D_DRIVER_TYPE_UNKNOWN',
- 'D3D_DRIVER_TYPE_HARDWARE',
- 'D3D_DRIVER_TYPE_REFERENCE',
- 'D3D_DRIVER_TYPE_NULL',
- 'D3D_DRIVER_TYPE_SOFTWARE',
- 'D3D_DRIVER_TYPE_WARP',
-])
-
-D3D_FEATURE_LEVEL = Enum('D3D_FEATURE_LEVEL', [
- 'D3D_FEATURE_LEVEL_9_1',
- 'D3D_FEATURE_LEVEL_9_2',
- 'D3D_FEATURE_LEVEL_9_3',
- 'D3D_FEATURE_LEVEL_10_0',
- 'D3D_FEATURE_LEVEL_10_1',
- 'D3D_FEATURE_LEVEL_11_0',
-])
-
-D3D_PRIMITIVE_TOPOLOGY = Enum('D3D_PRIMITIVE_TOPOLOGY', [
- 'D3D_PRIMITIVE_TOPOLOGY_UNDEFINED',
- 'D3D_PRIMITIVE_TOPOLOGY_POINTLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_LINELIST',
- 'D3D_PRIMITIVE_TOPOLOGY_LINESTRIP',
- 'D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST',
- 'D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP',
- 'D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ',
- 'D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ',
- 'D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ',
- 'D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ',
- 'D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST',
- 'D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST',
-])
-
-D3D10_PRIMITIVE_TOPOLOGY = Enum('D3D10_PRIMITIVE_TOPOLOGY', [
- 'D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED',
- 'D3D10_PRIMITIVE_TOPOLOGY_POINTLIST',
- 'D3D10_PRIMITIVE_TOPOLOGY_LINELIST',
- 'D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP',
- 'D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST',
- 'D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP',
- 'D3D10_PRIMITIVE_TOPOLOGY_LINELIST_ADJ',
- 'D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ',
- 'D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ',
- 'D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ',
-])
-
-D3D11_PRIMITIVE_TOPOLOGY = Enum('D3D11_PRIMITIVE_TOPOLOGY', [
- 'D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED',
- 'D3D11_PRIMITIVE_TOPOLOGY_POINTLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_LINELIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP',
- 'D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP',
- 'D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ',
- 'D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ',
- 'D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ',
- 'D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ',
- 'D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST',
- 'D3D11_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST',
-])
-
-D3D_PRIMITIVE = Enum('D3D_PRIMITIVE', [
- 'D3D_PRIMITIVE_UNDEFINED',
- 'D3D_PRIMITIVE_POINT',
- 'D3D_PRIMITIVE_LINE',
- 'D3D_PRIMITIVE_TRIANGLE',
- 'D3D_PRIMITIVE_LINE_ADJ',
- 'D3D_PRIMITIVE_TRIANGLE_ADJ',
- 'D3D_PRIMITIVE_1_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_2_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_3_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_4_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_5_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_6_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_7_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_8_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_9_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_10_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_11_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_12_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_13_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_14_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_15_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_16_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_17_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_18_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_19_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_20_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_21_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_22_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_23_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_24_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_25_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_26_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_27_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_28_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_29_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_30_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_31_CONTROL_POINT_PATCH',
- 'D3D_PRIMITIVE_32_CONTROL_POINT_PATCH',
-])
-
-D3D10_PRIMITIVE = Enum('D3D10_PRIMITIVE', [
- 'D3D10_PRIMITIVE_UNDEFINED',
- 'D3D10_PRIMITIVE_POINT',
- 'D3D10_PRIMITIVE_LINE',
- 'D3D10_PRIMITIVE_TRIANGLE',
- 'D3D10_PRIMITIVE_LINE_ADJ',
- 'D3D10_PRIMITIVE_TRIANGLE_ADJ',
-])
-
-D3D11_PRIMITIVE = Enum('D3D11_PRIMITIVE', [
- 'D3D11_PRIMITIVE_UNDEFINED',
- 'D3D11_PRIMITIVE_POINT',
- 'D3D11_PRIMITIVE_LINE',
- 'D3D11_PRIMITIVE_TRIANGLE',
- 'D3D11_PRIMITIVE_LINE_ADJ',
- 'D3D11_PRIMITIVE_TRIANGLE_ADJ',
- 'D3D11_PRIMITIVE_1_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_2_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_3_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_4_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_5_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_6_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_7_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_8_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_9_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_10_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_11_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_12_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_13_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_14_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_15_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_16_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_17_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_18_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_19_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_20_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_21_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_22_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_23_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_24_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_25_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_26_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_27_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_28_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_29_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_30_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_31_CONTROL_POINT_PATCH',
- 'D3D11_PRIMITIVE_32_CONTROL_POINT_PATCH',
-])
-
-D3D_SRV_DIMENSION = Enum('D3D_SRV_DIMENSION', [
- 'D3D_SRV_DIMENSION_UNKNOWN',
- 'D3D_SRV_DIMENSION_BUFFER',
- 'D3D_SRV_DIMENSION_TEXTURE1D',
- 'D3D_SRV_DIMENSION_TEXTURE1DARRAY',
- 'D3D_SRV_DIMENSION_TEXTURE2D',
- 'D3D_SRV_DIMENSION_TEXTURE2DARRAY',
- 'D3D_SRV_DIMENSION_TEXTURE2DMS',
- 'D3D_SRV_DIMENSION_TEXTURE2DMSARRAY',
- 'D3D_SRV_DIMENSION_TEXTURE3D',
- 'D3D_SRV_DIMENSION_TEXTURECUBE',
- 'D3D_SRV_DIMENSION_TEXTURECUBEARRAY',
- 'D3D_SRV_DIMENSION_BUFFEREX',
-])
-
-D3D10_SRV_DIMENSION = Enum('D3D10_SRV_DIMENSION', [
- 'D3D10_SRV_DIMENSION_UNKNOWN',
- 'D3D10_SRV_DIMENSION_BUFFER',
- 'D3D10_SRV_DIMENSION_TEXTURE1D',
- 'D3D10_SRV_DIMENSION_TEXTURE1DARRAY',
- 'D3D10_SRV_DIMENSION_TEXTURE2D',
- 'D3D10_SRV_DIMENSION_TEXTURE2DARRAY',
- 'D3D10_SRV_DIMENSION_TEXTURE2DMS',
- 'D3D10_SRV_DIMENSION_TEXTURE2DMSARRAY',
- 'D3D10_SRV_DIMENSION_TEXTURE3D',
- 'D3D10_SRV_DIMENSION_TEXTURECUBE',
-])
-
-D3D10_SRV_DIMENSION1 = Enum('D3D10_SRV_DIMENSION1', [
- 'D3D10_1_SRV_DIMENSION_UNKNOWN',
- 'D3D10_1_SRV_DIMENSION_BUFFER',
- 'D3D10_1_SRV_DIMENSION_TEXTURE1D',
- 'D3D10_1_SRV_DIMENSION_TEXTURE1DARRAY',
- 'D3D10_1_SRV_DIMENSION_TEXTURE2D',
- 'D3D10_1_SRV_DIMENSION_TEXTURE2DARRAY',
- 'D3D10_1_SRV_DIMENSION_TEXTURE2DMS',
- 'D3D10_1_SRV_DIMENSION_TEXTURE2DMSARRAY',
- 'D3D10_1_SRV_DIMENSION_TEXTURE3D',
- 'D3D10_1_SRV_DIMENSION_TEXTURECUBE',
- 'D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY',
-])
-
-D3D11_SRV_DIMENSION = Enum('D3D11_SRV_DIMENSION', [
- 'D3D11_SRV_DIMENSION_UNKNOWN',
- 'D3D11_SRV_DIMENSION_BUFFER',
- 'D3D11_SRV_DIMENSION_TEXTURE1D',
- 'D3D11_SRV_DIMENSION_TEXTURE1DARRAY',
- 'D3D11_SRV_DIMENSION_TEXTURE2D',
- 'D3D11_SRV_DIMENSION_TEXTURE2DARRAY',
- 'D3D11_SRV_DIMENSION_TEXTURE2DMS',
- 'D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY',
- 'D3D11_SRV_DIMENSION_TEXTURE3D',
- 'D3D11_SRV_DIMENSION_TEXTURECUBE',
- 'D3D11_SRV_DIMENSION_TEXTURECUBEARRAY',
- 'D3D11_SRV_DIMENSION_BUFFEREX',
-])
-
-D3D10_SHADER_MACRO = Struct('D3D10_SHADER_MACRO', [
- (LPCSTR, 'Name'),
- (LPCSTR, 'Definition'),
-])
-
-ID3D10Blob = Interface('ID3D10Blob', IUnknown)
-ID3D10Blob.methods += [
- StdMethod(LPVOID, 'GetBufferPointer', [], sideeffects=False),
- StdMethod(SIZE_T, 'GetBufferSize', [], sideeffects=False),
-]
-LPD3D10BLOB = ObjPointer(ID3D10Blob)
-
-D3D_INCLUDE_TYPE = Enum('D3D_INCLUDE_TYPE', [
- 'D3D_INCLUDE_LOCAL',
- 'D3D_INCLUDE_SYSTEM',
-])
-
-D3D10_INCLUDE_TYPE = Enum('D3D10_INCLUDE_TYPE', [
- 'D3D10_INCLUDE_LOCAL',
- 'D3D10_INCLUDE_SYSTEM',
-])
-
-ID3D10Include = Interface("ID3D10Include", IUnknown)
-ID3D10Include.methods += [
- StdMethod(HRESULT, "Open", [(D3D10_INCLUDE_TYPE, "IncludeType"), (LPCSTR, "pFileName"), (LPCVOID, "pParentData"), Out(Pointer(LPCVOID), "ppData"), Out(Pointer(UINT), "pBytes")]),
- StdMethod(HRESULT, "Close", [(LPCVOID, "pData")]),
-]
-# It is implemented by applications, not D3D runtime, so treat as opaque for
-# now.
-LPD3D10INCLUDE = OpaquePointer(ID3D10Include)
-
-D3D_SHADER_VARIABLE_CLASS = Enum('D3D_SHADER_VARIABLE_CLASS', [
- 'D3D_SVC_SCALAR',
- 'D3D_SVC_VECTOR',
- 'D3D_SVC_MATRIX_ROWS',
- 'D3D_SVC_MATRIX_COLUMNS',
- 'D3D_SVC_OBJECT',
- 'D3D_SVC_STRUCT',
- 'D3D_SVC_INTERFACE_CLASS',
- 'D3D_SVC_INTERFACE_POINTER',
-])
-
-D3D10_SHADER_VARIABLE_CLASS = Enum('D3D_SHADER_VARIABLE_CLASS', [
- 'D3D10_SVC_SCALAR',
- 'D3D10_SVC_VECTOR',
- 'D3D10_SVC_MATRIX_ROWS',
- 'D3D10_SVC_MATRIX_COLUMNS',
- 'D3D10_SVC_OBJECT',
- 'D3D10_SVC_STRUCT',
-])
-
-D3D11_SHADER_VARIABLE_CLASS = Enum('D3D_SHADER_VARIABLE_CLASS', [
- 'D3D11_SVC_INTERFACE_CLASS',
- 'D3D11_SVC_INTERFACE_POINTER',
-])
-
-D3D10_SHADER_VARIABLE_FLAGS = Enum('D3D10_SHADER_VARIABLE_FLAGS', [
- 'D3D_SVF_USERPACKED',
- 'D3D_SVF_USED',
- 'D3D_SVF_INTERFACE_POINTER',
- 'D3D_SVF_INTERFACE_PARAMETER',
-])
-
-D3D11_SHADER_VARIABLE_FLAGS = Enum('D3D11_SHADER_VARIABLE_FLAGS', [
- 'D3D10_SVF_USERPACKED',
- 'D3D10_SVF_USED',
- 'D3D11_SVF_INTERFACE_POINTER',
- 'D3D11_SVF_INTERFACE_PARAMETER',
-])
-
-D3D_SHADER_VARIABLE_TYPE = Enum('D3D_SHADER_VARIABLE_TYPE', [
- 'D3D_SVT_VOID',
- 'D3D_SVT_BOOL',
- 'D3D_SVT_INT',
- 'D3D_SVT_FLOAT',
- 'D3D_SVT_STRING',
- 'D3D_SVT_TEXTURE',
- 'D3D_SVT_TEXTURE1D',
- 'D3D_SVT_TEXTURE2D',
- 'D3D_SVT_TEXTURE3D',
- 'D3D_SVT_TEXTURECUBE',
- 'D3D_SVT_SAMPLER',
- 'D3D_SVT_SAMPLER1D',
- 'D3D_SVT_SAMPLER2D',
- 'D3D_SVT_SAMPLER3D',
- 'D3D_SVT_SAMPLERCUBE',
- 'D3D_SVT_PIXELSHADER',
- 'D3D_SVT_VERTEXSHADER',
- 'D3D_SVT_PIXELFRAGMENT',
- 'D3D_SVT_VERTEXFRAGMENT',
- 'D3D_SVT_UINT',
- 'D3D_SVT_UINT8',
- 'D3D_SVT_GEOMETRYSHADER',
- 'D3D_SVT_RASTERIZER',
- 'D3D_SVT_DEPTHSTENCIL',
- 'D3D_SVT_BLEND',
- 'D3D_SVT_BUFFER',
- 'D3D_SVT_CBUFFER',
- 'D3D_SVT_TBUFFER',
- 'D3D_SVT_TEXTURE1DARRAY',
- 'D3D_SVT_TEXTURE2DARRAY',
- 'D3D_SVT_RENDERTARGETVIEW',
- 'D3D_SVT_DEPTHSTENCILVIEW',
- 'D3D_SVT_TEXTURE2DMS',
- 'D3D_SVT_TEXTURE2DMSARRAY',
- 'D3D_SVT_TEXTURECUBEARRAY',
- 'D3D_SVT_HULLSHADER',
- 'D3D_SVT_DOMAINSHADER',
- 'D3D_SVT_INTERFACE_POINTER',
- 'D3D_SVT_COMPUTESHADER',
- 'D3D_SVT_DOUBLE',
- 'D3D_SVT_RWTEXTURE1D',
- 'D3D_SVT_RWTEXTURE1DARRAY',
- 'D3D_SVT_RWTEXTURE2D',
- 'D3D_SVT_RWTEXTURE2DARRAY',
- 'D3D_SVT_RWTEXTURE3D',
- 'D3D_SVT_RWBUFFER',
- 'D3D_SVT_BYTEADDRESS_BUFFER',
- 'D3D_SVT_RWBYTEADDRESS_BUFFER',
- 'D3D_SVT_STRUCTURED_BUFFER',
- 'D3D_SVT_RWSTRUCTURED_BUFFER',
- 'D3D_SVT_APPEND_STRUCTURED_BUFFER',
- 'D3D_SVT_CONSUME_STRUCTURED_BUFFER',
-])
-
-D3D10_SHADER_VARIABLE_TYPE = Enum('D3D10_SHADER_VARIABLE_TYPE', [
- 'D3D10_SVT_VOID',
- 'D3D10_SVT_BOOL',
- 'D3D10_SVT_INT',
- 'D3D10_SVT_FLOAT',
- 'D3D10_SVT_STRING',
- 'D3D10_SVT_TEXTURE',
- 'D3D10_SVT_TEXTURE1D',
- 'D3D10_SVT_TEXTURE2D',
- 'D3D10_SVT_TEXTURE3D',
- 'D3D10_SVT_TEXTURECUBE',
- 'D3D10_SVT_SAMPLER',
- 'D3D10_SVT_SAMPLER1D',
- 'D3D10_SVT_SAMPLER2D',
- 'D3D10_SVT_SAMPLER3D',
- 'D3D10_SVT_SAMPLERCUBE',
- 'D3D10_SVT_PIXELSHADER',
- 'D3D10_SVT_VERTEXSHADER',
- 'D3D10_SVT_PIXELFRAGMENT',
- 'D3D10_SVT_VERTEXFRAGMENT',
- 'D3D10_SVT_UINT',
- 'D3D10_SVT_UINT8',
- 'D3D10_SVT_GEOMETRYSHADER',
- 'D3D10_SVT_RASTERIZER',
- 'D3D10_SVT_DEPTHSTENCIL',
- 'D3D10_SVT_BLEND',
- 'D3D10_SVT_BUFFER',
- 'D3D10_SVT_CBUFFER',
- 'D3D10_SVT_TBUFFER',
- 'D3D10_SVT_TEXTURE1DARRAY',
- 'D3D10_SVT_TEXTURE2DARRAY',
- 'D3D10_SVT_RENDERTARGETVIEW',
- 'D3D10_SVT_DEPTHSTENCILVIEW',
- 'D3D10_SVT_TEXTURE2DMS',
- 'D3D10_SVT_TEXTURE2DMSARRAY',
- 'D3D10_SVT_TEXTURECUBEARRAY',
-])
-
-D3D11_SHADER_VARIABLE_TYPE = Enum('D3D11_SHADER_VARIABLE_TYPE', [
- 'D3D11_SVT_HULLSHADER',
- 'D3D11_SVT_DOMAINSHADER',
- 'D3D11_SVT_INTERFACE_POINTER',
- 'D3D11_SVT_COMPUTESHADER',
- 'D3D11_SVT_DOUBLE',
- 'D3D11_SVT_RWTEXTURE1D',
- 'D3D11_SVT_RWTEXTURE1DARRAY',
- 'D3D11_SVT_RWTEXTURE2D',
- 'D3D11_SVT_RWTEXTURE2DARRAY',
- 'D3D11_SVT_RWTEXTURE3D',
- 'D3D11_SVT_RWBUFFER',
- 'D3D11_SVT_BYTEADDRESS_BUFFER',
- 'D3D11_SVT_RWBYTEADDRESS_BUFFER',
- 'D3D11_SVT_STRUCTURED_BUFFER',
- 'D3D11_SVT_RWSTRUCTURED_BUFFER',
- 'D3D11_SVT_APPEND_STRUCTURED_BUFFER',
- 'D3D11_SVT_CONSUME_STRUCTURED_BUFFER',
-])
-
-D3D_SHADER_INPUT_FLAGS = Enum('D3D_SHADER_INPUT_FLAGS', [
- 'D3D_SIF_USERPACKED',
- 'D3D_SIF_COMPARISON_SAMPLER',
- 'D3D_SIF_TEXTURE_COMPONENT_0',
- 'D3D_SIF_TEXTURE_COMPONENT_1',
- 'D3D_SIF_TEXTURE_COMPONENTS',
-])
-
-D3D10_SHADER_INPUT_FLAGS = Enum('D3D10_SHADER_INPUT_FLAGS', [
- 'D3D10_SIF_USERPACKED',
- 'D3D10_SIF_COMPARISON_SAMPLER',
- 'D3D10_SIF_TEXTURE_COMPONENT_0',
- 'D3D10_SIF_TEXTURE_COMPONENT_1',
- 'D3D10_SIF_TEXTURE_COMPONENTS',
-])
-
-D3D_SHADER_INPUT_TYPE = Enum('D3D_SHADER_INPUT_TYPE', [
- 'D3D_SIT_CBUFFER',
- 'D3D_SIT_TBUFFER',
- 'D3D_SIT_TEXTURE',
- 'D3D_SIT_SAMPLER',
- 'D3D_SIT_UAV_RWTYPED',
- 'D3D_SIT_STRUCTURED',
- 'D3D_SIT_UAV_RWSTRUCTURED',
- 'D3D_SIT_BYTEADDRESS',
- 'D3D_SIT_UAV_RWBYTEADDRESS',
- 'D3D_SIT_UAV_APPEND_STRUCTURED',
- 'D3D_SIT_UAV_CONSUME_STRUCTURED',
- 'D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER',
-])
-
-D3D10_SHADER_INPUT_TYPE = Enum('D3D10_SHADER_INPUT_TYPE', [
- 'D3D10_SIT_CBUFFER',
- 'D3D10_SIT_TBUFFER',
- 'D3D10_SIT_TEXTURE',
- 'D3D10_SIT_SAMPLER',
-])
-
-D3D11_SHADER_INPUT_TYPE = Enum('D3D11_SHADER_INPUT_TYPE', [
- 'D3D11_SIT_UAV_RWTYPED',
- 'D3D11_SIT_STRUCTURED',
- 'D3D11_SIT_UAV_RWSTRUCTURED',
- 'D3D11_SIT_BYTEADDRESS',
- 'D3D11_SIT_UAV_RWBYTEADDRESS',
- 'D3D11_SIT_UAV_APPEND_STRUCTURED',
- 'D3D11_SIT_UAV_CONSUME_STRUCTURED',
- 'D3D11_SIT_UAV_RWSTRUCTURED_WITH_COUNTER',
-])
-
-D3D_SHADER_CBUFFER_FLAGS = Enum('D3D_SHADER_CBUFFER_FLAGS', [
- 'D3D_CBF_USERPACKED',
-])
-
-D3D10_SHADER_CBUFFER_FLAGS = Enum('D3D10_SHADER_CBUFFER_FLAGS', [
- 'D3D10_CBF_USERPACKED',
-])
-
-D3D_CBUFFER_TYPE = Enum('D3D_CBUFFER_TYPE', [
- 'D3D_CT_CBUFFER',
- 'D3D_CT_TBUFFER',
- 'D3D_CT_INTERFACE_POINTERS',
- 'D3D_CT_RESOURCE_BIND_INFO',
-])
-
-D3D10_CBUFFER_TYPE = Enum('D3D10_CBUFFER_TYPE', [
- 'D3D10_CT_CBUFFER',
- 'D3D10_CT_TBUFFER',
-])
-
-D3D11_CBUFFER_TYPE = Enum('D3D11_CBUFFER_TYPE', [
- 'D3D11_CT_CBUFFER',
- 'D3D11_CT_TBUFFER',
- 'D3D11_CT_INTERFACE_POINTERS',
- 'D3D11_CT_RESOURCE_BIND_INFO',
-])
-
-D3D_NAME = Enum('D3D_NAME', [
- 'D3D_NAME_UNDEFINED',
- 'D3D_NAME_POSITION',
- 'D3D_NAME_CLIP_DISTANCE',
- 'D3D_NAME_CULL_DISTANCE',
- 'D3D_NAME_RENDER_TARGET_ARRAY_INDEX',
- 'D3D_NAME_VIEWPORT_ARRAY_INDEX',
- 'D3D_NAME_VERTEX_ID',
- 'D3D_NAME_PRIMITIVE_ID',
- 'D3D_NAME_INSTANCE_ID',
- 'D3D_NAME_IS_FRONT_FACE',
- 'D3D_NAME_SAMPLE_INDEX',
- 'D3D_NAME_FINAL_QUAD_EDGE_TESSFACTOR',
- 'D3D_NAME_FINAL_QUAD_INSIDE_TESSFACTOR',
- 'D3D_NAME_FINAL_TRI_EDGE_TESSFACTOR',
- 'D3D_NAME_FINAL_TRI_INSIDE_TESSFACTOR',
- 'D3D_NAME_FINAL_LINE_DETAIL_TESSFACTOR',
- 'D3D_NAME_FINAL_LINE_DENSITY_TESSFACTOR',
- 'D3D_NAME_TARGET',
- 'D3D_NAME_DEPTH',
- 'D3D_NAME_COVERAGE',
- 'D3D_NAME_DEPTH_GREATER_EQUAL',
- 'D3D_NAME_DEPTH_LESS_EQUAL',
-])
-
-D3D10_NAME = Enum('D3D10_NAME', [
- 'D3D10_NAME_UNDEFINED',
- 'D3D10_NAME_POSITION',
- 'D3D10_NAME_CLIP_DISTANCE',
- 'D3D10_NAME_CULL_DISTANCE',
- 'D3D10_NAME_RENDER_TARGET_ARRAY_INDEX',
- 'D3D10_NAME_VIEWPORT_ARRAY_INDEX',
- 'D3D10_NAME_VERTEX_ID',
- 'D3D10_NAME_PRIMITIVE_ID',
- 'D3D10_NAME_INSTANCE_ID',
- 'D3D10_NAME_IS_FRONT_FACE',
- 'D3D10_NAME_SAMPLE_INDEX',
- 'D3D10_NAME_TARGET',
- 'D3D10_NAME_DEPTH',
- 'D3D10_NAME_COVERAGE',
-])
-
-D3D11_NAME = Enum('D3D11_NAME', [
- 'D3D11_NAME_FINAL_QUAD_EDGE_TESSFACTOR',
- 'D3D11_NAME_FINAL_QUAD_INSIDE_TESSFACTOR',
- 'D3D11_NAME_FINAL_TRI_EDGE_TESSFACTOR',
- 'D3D11_NAME_FINAL_TRI_INSIDE_TESSFACTOR',
- 'D3D11_NAME_FINAL_LINE_DETAIL_TESSFACTOR',
- 'D3D11_NAME_FINAL_LINE_DENSITY_TESSFACTOR',
- 'D3D11_NAME_DEPTH_GREATER_EQUAL',
- 'D3D11_NAME_DEPTH_LESS_EQUAL',
-])
-
-D3D_RESOURCE_RETURN_TYPE = Enum('D3D_RESOURCE_RETURN_TYPE', [
- 'D3D_RETURN_TYPE_UNORM',
- 'D3D_RETURN_TYPE_SNORM',
- 'D3D_RETURN_TYPE_SINT',
- 'D3D_RETURN_TYPE_UINT',
- 'D3D_RETURN_TYPE_FLOAT',
- 'D3D_RETURN_TYPE_MIXED',
- 'D3D_RETURN_TYPE_DOUBLE',
- 'D3D_RETURN_TYPE_CONTINUED',
-])
-
-D3D10_RESOURCE_RETURN_TYPE = Enum('D3D10_RESOURCE_RETURN_TYPE', [
- 'D3D10_RETURN_TYPE_UNORM',
- 'D3D10_RETURN_TYPE_SNORM',
- 'D3D10_RETURN_TYPE_SINT',
- 'D3D10_RETURN_TYPE_UINT',
- 'D3D10_RETURN_TYPE_FLOAT',
- 'D3D10_RETURN_TYPE_MIXED',
-])
-
-D3D11_RESOURCE_RETURN_TYPE = Enum('D3D11_RESOURCE_RETURN_TYPE', [
- 'D3D11_RETURN_TYPE_UNORM',
- 'D3D11_RETURN_TYPE_SNORM',
- 'D3D11_RETURN_TYPE_SINT',
- 'D3D11_RETURN_TYPE_UINT',
- 'D3D11_RETURN_TYPE_FLOAT',
- 'D3D11_RETURN_TYPE_MIXED',
- 'D3D11_RETURN_TYPE_DOUBLE',
- 'D3D11_RETURN_TYPE_CONTINUED',
-])
-
-D3D_REGISTER_COMPONENT_TYPE = Enum('D3D_REGISTER_COMPONENT_TYPE', [
- 'D3D_REGISTER_COMPONENT_UNKNOWN',
- 'D3D_REGISTER_COMPONENT_UINT32',
- 'D3D_REGISTER_COMPONENT_SINT32',
- 'D3D_REGISTER_COMPONENT_FLOAT32',
-])
-
-D3D10_REGISTER_COMPONENT_TYPE = Enum('D3D10_REGISTER_COMPONENT_TYPE', [
- 'D3D10_REGISTER_COMPONENT_UNKNOWN',
- 'D3D10_REGISTER_COMPONENT_UINT32',
- 'D3D10_REGISTER_COMPONENT_SINT32',
- 'D3D10_REGISTER_COMPONENT_FLOAT32',
-])
-
-D3D_TESSELLATOR_DOMAIN = Enum('D3D_TESSELLATOR_DOMAIN', [
- 'D3D_TESSELLATOR_DOMAIN_UNDEFINED',
- 'D3D_TESSELLATOR_DOMAIN_ISOLINE',
- 'D3D_TESSELLATOR_DOMAIN_TRI',
- 'D3D_TESSELLATOR_DOMAIN_QUAD',
-])
-
-D3D11_TESSELLATOR_DOMAIN = Enum('D3D11_TESSELLATOR_DOMAIN', [
- 'D3D11_TESSELLATOR_DOMAIN_UNDEFINED',
- 'D3D11_TESSELLATOR_DOMAIN_ISOLINE',
- 'D3D11_TESSELLATOR_DOMAIN_TRI',
- 'D3D11_TESSELLATOR_DOMAIN_QUAD',
-])
-
-D3D_TESSELLATOR_PARTITIONING = Enum('D3D_TESSELLATOR_PARTITIONING', [
- 'D3D_TESSELLATOR_PARTITIONING_UNDEFINED',
- 'D3D_TESSELLATOR_PARTITIONING_INTEGER',
- 'D3D_TESSELLATOR_PARTITIONING_POW2',
- 'D3D_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD',
- 'D3D_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN',
-])
-
-D3D11_TESSELLATOR_PARTITIONING = Enum('D3D11_TESSELLATOR_PARTITIONING', [
- 'D3D11_TESSELLATOR_PARTITIONING_UNDEFINED',
- 'D3D11_TESSELLATOR_PARTITIONING_INTEGER',
- 'D3D11_TESSELLATOR_PARTITIONING_POW2',
- 'D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD',
- 'D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN',
-])
-
-D3D_TESSELLATOR_OUTPUT_PRIMITIVE = Enum('D3D_TESSELLATOR_OUTPUT_PRIMITIVE', [
- 'D3D_TESSELLATOR_OUTPUT_UNDEFINED',
- 'D3D_TESSELLATOR_OUTPUT_POINT',
- 'D3D_TESSELLATOR_OUTPUT_LINE',
- 'D3D_TESSELLATOR_OUTPUT_TRIANGLE_CW',
- 'D3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW',
-])
-
-D3D11_TESSELLATOR_OUTPUT_PRIMITIVE = Enum('D3D11_TESSELLATOR_OUTPUT_PRIMITIVE', [
- 'D3D11_TESSELLATOR_OUTPUT_UNDEFINED',
- 'D3D11_TESSELLATOR_OUTPUT_POINT',
- 'D3D11_TESSELLATOR_OUTPUT_LINE',
- 'D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW',
- 'D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CCW',
-])
-
diff --git a/specs/d3dtypes.py b/specs/d3dtypes.py
index 1137143f..e1507975 100644
--- a/specs/d3dtypes.py
+++ b/specs/d3dtypes.py
@@ -329,13 +329,11 @@ D3DLIGHTDATA = Struct("D3DLIGHTDATA", [
])
LPD3DLIGHTDATA = Pointer(D3DLIGHTDATA)
-D3DCOLOR = Flags(DWORD, [
+D3DCOLORMODEL = FakeEnum(DWORD, [
"D3DCOLOR_MONO",
"D3DCOLOR_RGB",
])
-D3DCOLORMODEL = DWORD
-
D3DCLEAR = Flags(DWORD, [
"D3DCLEAR_TARGET",
"D3DCLEAR_ZBUFFER",
diff --git a/specs/ddraw.py b/specs/ddraw.py
index 1b224763..99f542fe 100644
--- a/specs/ddraw.py
+++ b/specs/ddraw.py
@@ -131,26 +131,113 @@ DDBLTFX = Struct("DDBLTFX", [
])
LPDDBLTFX = Pointer(DDBLTFX)
+DirectDrawCapsFlags = Flags(DWORD, [
+ "DDSCAPS_RESERVED1",
+ "DDSCAPS_ALPHA",
+ "DDSCAPS_BACKBUFFER",
+ "DDSCAPS_COMPLEX",
+ "DDSCAPS_FLIP",
+ "DDSCAPS_FRONTBUFFER",
+ "DDSCAPS_OFFSCREENPLAIN",
+ "DDSCAPS_OVERLAY",
+ "DDSCAPS_PALETTE",
+ "DDSCAPS_PRIMARYSURFACE",
+ "DDSCAPS_RESERVED3", # was DDSCAPS_PRIMARYSURFACELEFT
+ "DDSCAPS_SYSTEMMEMORY",
+ "DDSCAPS_TEXTURE",
+ "DDSCAPS_3DDEVICE",
+ "DDSCAPS_VIDEOMEMORY",
+ "DDSCAPS_VISIBLE",
+ "DDSCAPS_WRITEONLY",
+ "DDSCAPS_ZBUFFER",
+ "DDSCAPS_OWNDC",
+ "DDSCAPS_LIVEVIDEO",
+ "DDSCAPS_HWCODEC",
+ "DDSCAPS_MODEX",
+ "DDSCAPS_MIPMAP",
+ "DDSCAPS_RESERVED2",
+ "DDSCAPS_ALLOCONLOAD",
+ "DDSCAPS_VIDEOPORT",
+ "DDSCAPS_LOCALVIDMEM",
+ "DDSCAPS_NONLOCALVIDMEM",
+ "DDSCAPS_STANDARDVGAMODE",
+ "DDSCAPS_OPTIMIZED",
+])
+
+DirectDrawCapabilityFlags2 = Flags(DWORD, [
+ "DDSCAPS2_RESERVED4", # was DDSCAPS2_HARDWAREDEINTERLACE
+ "DDSCAPS2_HINTDYNAMIC",
+ "DDSCAPS2_HINTSTATIC",
+ "DDSCAPS2_TEXTUREMANAGE",
+ "DDSCAPS2_RESERVED1",
+ "DDSCAPS2_RESERVED2",
+ "DDSCAPS2_OPAQUE",
+ "DDSCAPS2_HINTANTIALIASING",
+ "DDSCAPS2_CUBEMAP",
+ "DDSCAPS2_CUBEMAP_ALLFACES",
+ "DDSCAPS2_CUBEMAP_POSITIVEX",
+ "DDSCAPS2_CUBEMAP_NEGATIVEX",
+ "DDSCAPS2_CUBEMAP_POSITIVEY",
+ "DDSCAPS2_CUBEMAP_NEGATIVEY",
+ "DDSCAPS2_CUBEMAP_POSITIVEZ",
+ "DDSCAPS2_CUBEMAP_NEGATIVEZ",
+ "DDSCAPS2_MIPMAPSUBLEVEL",
+ "DDSCAPS2_D3DTEXTUREMANAGE",
+ "DDSCAPS2_DONOTPERSIST",
+ "DDSCAPS2_STEREOSURFACELEFT",
+ "DDSCAPS2_VOLUME",
+ "DDSCAPS2_NOTUSERLOCKABLE",
+ "DDSCAPS2_POINTS",
+ "DDSCAPS2_RTPATCHES",
+ "DDSCAPS2_NPATCHES",
+ "DDSCAPS2_RESERVED3",
+ "DDSCAPS2_DISCARDBACKBUFFER",
+ "DDSCAPS2_ENABLEALPHACHANNEL",
+ "DDSCAPS2_EXTENDEDFORMATPRIMARY",
+ "DDSCAPS2_ADDITIONALPRIMARY",
+])
+DirectDrawCapabilityFlags3 = Flags(DWORD, [
+ "DDSCAPS3_MULTISAMPLE_MASK",
+ "DDSCAPS3_MULTISAMPLE_QUALITY_MASK",
+ "DDSCAPS3_MULTISAMPLE_QUALITY_SHIFT",
+ "DDSCAPS3_RESERVED1",
+ "DDSCAPS3_RESERVED2",
+ "DDSCAPS3_LIGHTWEIGHTMIPMAP",
+ "DDSCAPS3_AUTOGENMIPMAP",
+ "DDSCAPS3_DMAP",
+ "DDSCAPS3_CREATESHAREDRESOURCE",
+ "DDSCAPS3_READONLYRESOURCE",
+ "DDSCAPS3_OPENSHAREDRESOURCE",
+])
+
DDSCAPS = Struct("DDSCAPS", [
- (DWORD, "dwCaps"),
+ (DirectDrawCapsFlags, "dwCaps"),
])
LPDDSCAPS = Pointer(DDSCAPS)
+DDOSDCAPSFlags = Flags(DWORD, [
+ "DDOSDCAPS_OPTCOMPRESSED",
+ "DDOSDCAPS_OPTREORDERED",
+ "DDOSDCAPS_MONOLITHICMIPMAP",
+ "DDOSDCAPS_VALIDSCAPS",
+ "DDOSDCAPS_VALIDOSCAPS",
+])
+
DDOSCAPS = Struct("DDOSCAPS", [
- (DWORD, "dwCaps"),
+ (DDOSDCAPSFlags, "dwCaps"),
])
LPDDOSCAPS = Pointer(DDOSCAPS)
DDSCAPSEX = Struct("DDSCAPSEX", [
- (DWORD, "dwCaps2"),
- (DWORD, "dwCaps3"),
+ (DirectDrawCapabilityFlags2, "dwCaps2"),
+ (DirectDrawCapabilityFlags3, "dwCaps3"),
(DWORD, "dwCaps4"),
])
DDSCAPS2 = Struct("DDSCAPS2", [
- (DWORD, "dwCaps"),
- (DWORD, "dwCaps2"),
- (DWORD, "dwCaps3"),
+ (DirectDrawCapsFlags, "dwCaps"),
+ (DirectDrawCapabilityFlags2, "dwCaps2"),
+ (DirectDrawCapabilityFlags3, "dwCaps3"),
(DWORD, "dwCaps4"),
])
LPDDSCAPS2 = Pointer(DDSCAPS2)
@@ -434,9 +521,31 @@ LPDDCAPS_DX7 = Pointer(DDCAPS_DX7)
DDCAPS = DDCAPS_DX7
LPDDCAPS = Pointer(DDCAPS)
+DirectDrawPixelFormatFlags = Flags(DWORD, [
+ "DDPF_ALPHAPIXELS",
+ "DDPF_ALPHA",
+ "DDPF_FOURCC",
+ "DDPF_PALETTEINDEXED4",
+ "DDPF_PALETTEINDEXEDTO8",
+ "DDPF_PALETTEINDEXED8",
+ "DDPF_RGB",
+ "DDPF_COMPRESSED",
+ "DDPF_RGBTOYUV",
+ "DDPF_YUV",
+ "DDPF_ZBUFFER",
+ "DDPF_PALETTEINDEXED1",
+ "DDPF_PALETTEINDEXED2",
+ "DDPF_ZPIXELS",
+ "DDPF_STENCILBUFFER",
+ "DDPF_ALPHAPREMULT",
+ "DDPF_LUMINANCE",
+ "DDPF_BUMPLUMINANCE",
+ "DDPF_BUMPDUDV",
+])
+
DDPIXELFORMAT = Struct("DDPIXELFORMAT", [
(DWORD, "dwSize"),
- (DWORD, "dwFlags"),
+ (DirectDrawPixelFormatFlags, "dwFlags"),
(DWORD, "dwFourCC"),
(DWORD, "dwRGBBitCount"),
(DWORD, "dwYUVBitCount"),
@@ -533,9 +642,33 @@ LPDDDEVICEIDENTIFIER2 = Pointer(DDDEVICEIDENTIFIER2)
LPCLIPPERCALLBACK = FunctionPointer(DWORD, "LPCLIPPERCALLBACK", [(LPDIRECTDRAWCLIPPER, "lpDDClipper"), (HWND, "hWnd"), (DWORD, "code"), (LPVOID, "lpContext")])
LPSURFACESTREAMINGCALLBACK = FunctionPointer(DWORD, "LPSURFACESTREAMINGCALLBACK", [DWORD])
+DirectDrawSurfaceDescFlags = Flags(DWORD, [
+ "DDSD_CAPS",
+ "DDSD_HEIGHT",
+ "DDSD_WIDTH",
+ "DDSD_PITCH",
+ "DDSD_BACKBUFFERCOUNT",
+ "DDSD_ZBUFFERBITDEPTH",
+ "DDSD_ALPHABITDEPTH",
+ "DDSD_LPSURFACE",
+ "DDSD_PIXELFORMAT",
+ "DDSD_CKDESTOVERLAY",
+ "DDSD_CKDESTBLT",
+ "DDSD_CKSRCOVERLAY",
+ "DDSD_CKSRCBLT",
+ "DDSD_MIPMAPCOUNT",
+ "DDSD_REFRESHRATE",
+ "DDSD_LINEARSIZE",
+ "DDSD_TEXTURESTAGE",
+ "DDSD_FVF",
+ "DDSD_SRCVBHANDLE",
+ "DDSD_DEPTH",
+ "DDSD_ALL",
+])
+
DDSURFACEDESC = Struct("DDSURFACEDESC", [
(DWORD, "dwSize"),
- (DWORD, "dwFlags"),
+ (DirectDrawSurfaceDescFlags, "dwFlags"),
(DWORD, "dwHeight"),
(DWORD, "dwWidth"),
(LONG, "lPitch"),
@@ -546,7 +679,7 @@ DDSURFACEDESC = Struct("DDSURFACEDESC", [
(DWORD, "dwRefreshRate"),
(DWORD, "dwAlphaBitDepth"),
(DWORD, "dwReserved"),
- (LPVOID, "lpSurface"),
+ (IntPointer("LPVOID"), "lpSurface"),
(DDCOLORKEY, "ddckCKDestOverlay"),
(DDCOLORKEY, "ddckCKDestBlt"),
(DDCOLORKEY, "ddckCKSrcOverlay"),
@@ -558,7 +691,7 @@ LPDDSURFACEDESC = Pointer(DDSURFACEDESC)
DDSURFACEDESC2 = Struct("DDSURFACEDESC2", [
(DWORD, "dwSize"),
- (DWORD, "dwFlags"),
+ (DirectDrawSurfaceDescFlags, "dwFlags"),
(DWORD, "dwHeight"),
(DWORD, "dwWidth"),
(LONG, "lPitch"),
@@ -570,7 +703,7 @@ DDSURFACEDESC2 = Struct("DDSURFACEDESC2", [
(DWORD, "dwSrcVBHandle"),
(DWORD, "dwAlphaBitDepth"),
(DWORD, "dwReserved"),
- (LPVOID, "lpSurface"),
+ (IntPointer("LPVOID"), "lpSurface"),
(DDCOLORKEY, "ddckCKDestOverlay"),
(DWORD, "dwEmptyFaceColor"),
(DDCOLORKEY, "ddckCKDestBlt"),
@@ -583,55 +716,23 @@ DDSURFACEDESC2 = Struct("DDSURFACEDESC2", [
])
LPDDSURFACEDESC2 = Pointer(DDSURFACEDESC2)
-DirectDrawSurfaceDescFlags = Flags(DWORD, [
- "DDSD_CAPS",
- "DDSD_HEIGHT",
- "DDSD_WIDTH",
- "DDSD_PITCH",
- "DDSD_BACKBUFFERCOUNT",
- "DDSD_ZBUFFERBITDEPTH",
- "DDSD_ALPHABITDEPTH",
- "DDSD_LPSURFACE",
- "DDSD_PIXELFORMAT",
- "DDSD_CKDESTOVERLAY",
- "DDSD_CKDESTBLT",
- "DDSD_CKSRCOVERLAY",
- "DDSD_CKSRCBLT",
- "DDSD_MIPMAPCOUNT",
- "DDSD_REFRESHRATE",
- "DDSD_LINEARSIZE",
- "DDSD_TEXTURESTAGE",
- "DDSD_FVF",
- "DDSD_SRCVBHANDLE",
- "DDSD_DEPTH",
- "DDSD_ALL",
+DDOSD = Flags(DWORD, [
+ "DDOSD_GUID",
+ "DDOSD_COMPRESSION_RATIO",
+ "DDOSD_SCAPS",
+ "DDOSD_OSCAPS",
+ "DDOSD_ALL",
])
DDOPTSURFACEDESC = Struct("DDOPTSURFACEDESC", [
(DWORD, "dwSize"),
- (DWORD, "dwFlags"),
+ (DDOSD, "dwFlags"),
(DDSCAPS2, "ddSCaps"),
(DDOSCAPS, "ddOSCaps"),
(GUID, "guid"),
(DWORD, "dwCompressionRatio"),
])
-DDSD = Flags(DWORD, [
- "DDOSD_GUID",
- "DDOSD_COMPRESSION_RATIO",
- "DDOSD_SCAPS",
- "DDOSD_OSCAPS",
- "DDOSD_ALL",
-])
-
-DDOSDCAPS = Flags(DWORD, [
- "DDOSDCAPS_OPTCOMPRESSED",
- "DDOSDCAPS_OPTREORDERED",
- "DDOSDCAPS_MONOLITHICMIPMAP",
- "DDOSDCAPS_VALIDSCAPS",
- "DDOSDCAPS_VALIDOSCAPS",
-])
-
DDCOLORCONTROL = Struct("DDCOLORCONTROL", [
(DWORD, "dwSize"),
(DWORD, "dwFlags"),
@@ -646,17 +747,23 @@ DDCOLORCONTROL = Struct("DDCOLORCONTROL", [
])
LPDDCOLORCONTROL = Pointer(DDCOLORCONTROL)
-DirectDrawEnumerateExFlags = Flags(DWORD, [
+DDENUM = Flags(DWORD, [
"DDENUM_ATTACHEDSECONDARYDEVICES",
"DDENUM_DETACHEDSECONDARYDEVICES",
"DDENUM_NONDISPLAYDEVICES",
])
-DirectDrawCreateFlags = FakeEnum(DWORD, [
+DDCREATE = FakeEnum(DWORD, [
"DDCREATE_HARDWAREONLY",
"DDCREATE_EMULATIONONLY",
])
+DDCREATE_LPGUID = Polymorphic("reinterpret_cast<uintptr_t>(lpGUID)", [
+ ("DDCREATE_HARDWAREONLY", IntPointer("LPGUID")),
+ ("DDCREATE_EMULATIONONLY", IntPointer("LPGUID")),
+], LPGUID)
+
+
DirectDrawColorControlFlags = Flags(DWORD, [
"DDCOLOR_BRIGHTNESS",
"DDCOLOR_CONTRAST",
@@ -667,87 +774,6 @@ DirectDrawColorControlFlags = Flags(DWORD, [
"DDCOLOR_COLORENABLE",
])
-DirectDrawCapsFlags = Flags(DWORD, [
- "DDSCAPS_RESERVED1",
- "DDSCAPS_ALPHA",
- "DDSCAPS_BACKBUFFER",
- "DDSCAPS_COMPLEX",
- "DDSCAPS_FLIP",
- "DDSCAPS_FRONTBUFFER",
- "DDSCAPS_OFFSCREENPLAIN",
- "DDSCAPS_OVERLAY",
- "DDSCAPS_PALETTE",
- "DDSCAPS_PRIMARYSURFACE",
- "DDSCAPS_RESERVED3",
- "DDSCAPS_PRIMARYSURFACELEFT",
- "DDSCAPS_SYSTEMMEMORY",
- "DDSCAPS_TEXTURE",
- "DDSCAPS_3DDEVICE",
- "DDSCAPS_VIDEOMEMORY",
- "DDSCAPS_VISIBLE",
- "DDSCAPS_WRITEONLY",
- "DDSCAPS_ZBUFFER",
- "DDSCAPS_OWNDC",
- "DDSCAPS_LIVEVIDEO",
- "DDSCAPS_HWCODEC",
- "DDSCAPS_MODEX",
- "DDSCAPS_MIPMAP",
- "DDSCAPS_RESERVED2",
- "DDSCAPS_ALLOCONLOAD",
- "DDSCAPS_VIDEOPORT",
- "DDSCAPS_LOCALVIDMEM",
- "DDSCAPS_NONLOCALVIDMEM",
- "DDSCAPS_STANDARDVGAMODE",
- "DDSCAPS_OPTIMIZED",
-])
-
-DirectDrawCapabilityFlags2 = Flags(DWORD, [
- "DDSCAPS2_RESERVED4",
- "DDSCAPS2_HARDWAREDEINTERLACE",
- "DDSCAPS2_HINTDYNAMIC",
- "DDSCAPS2_HINTSTATIC",
- "DDSCAPS2_TEXTUREMANAGE",
- "DDSCAPS2_RESERVED1",
- "DDSCAPS2_RESERVED2",
- "DDSCAPS2_OPAQUE",
- "DDSCAPS2_HINTANTIALIASING",
- "DDSCAPS2_CUBEMAP",
- "DDSCAPS2_CUBEMAP_ALLFACES",
- "DDSCAPS2_CUBEMAP_POSITIVEX",
- "DDSCAPS2_CUBEMAP_NEGATIVEX",
- "DDSCAPS2_CUBEMAP_POSITIVEY",
- "DDSCAPS2_CUBEMAP_NEGATIVEY",
- "DDSCAPS2_CUBEMAP_POSITIVEZ",
- "DDSCAPS2_CUBEMAP_NEGATIVEZ",
- "DDSCAPS2_MIPMAPSUBLEVEL",
- "DDSCAPS2_D3DTEXTUREMANAGE",
- "DDSCAPS2_DONOTPERSIST",
- "DDSCAPS2_STEREOSURFACELEFT",
- "DDSCAPS2_VOLUME",
- "DDSCAPS2_NOTUSERLOCKABLE",
- "DDSCAPS2_POINTS",
- "DDSCAPS2_RTPATCHES",
- "DDSCAPS2_NPATCHES",
- "DDSCAPS2_RESERVED3",
- "DDSCAPS2_DISCARDBACKBUFFER",
- "DDSCAPS2_ENABLEALPHACHANNEL",
- "DDSCAPS2_EXTENDEDFORMATPRIMARY",
- "DDSCAPS2_ADDITIONALPRIMARY",
-])
-DDSCAPS3 = Flags(DWORD, [
- "DDSCAPS3_MULTISAMPLE_MASK",
- "DDSCAPS3_MULTISAMPLE_QUALITY_MASK",
- "DDSCAPS3_MULTISAMPLE_QUALITY_SHIFT",
- "DDSCAPS3_RESERVED1",
- "DDSCAPS3_RESERVED2",
- "DDSCAPS3_LIGHTWEIGHTMIPMAP",
- "DDSCAPS3_AUTOGENMIPMAP",
- "DDSCAPS3_DMAP",
- "DDSCAPS3_CREATESHAREDRESOURCE",
- "DDSCAPS3_READONLYRESOURCE",
- "DDSCAPS3_OPENSHAREDRESOURCE",
-])
-
DirectDrawDriverCapsFlags = Flags(DWORD, [
"DDCAPS_3D",
"DDCAPS_ALIGNBOUNDARYDEST",
@@ -930,28 +956,6 @@ DirectDrawColorKeyCapsFlags = Flags(DWORD, [
"DDCKEYCAPS_NOCOSTOVERLAY",
])
-DirectDrawPixelFormatFlags = Flags(DWORD, [
- "DDPF_ALPHAPIXELS",
- "DDPF_ALPHA",
- "DDPF_FOURCC",
- "DDPF_PALETTEINDEXED4",
- "DDPF_PALETTEINDEXEDTO8",
- "DDPF_PALETTEINDEXED8",
- "DDPF_RGB",
- "DDPF_COMPRESSED",
- "DDPF_RGBTOYUV",
- "DDPF_YUV",
- "DDPF_ZBUFFER",
- "DDPF_PALETTEINDEXED1",
- "DDPF_PALETTEINDEXED2",
- "DDPF_ZPIXELS",
- "DDPF_STENCILBUFFER",
- "DDPF_ALPHAPREMULT",
- "DDPF_LUMINANCE",
- "DDPF_BUMPLUMINANCE",
- "DDPF_BUMPDUDV",
-])
-
DirectDrawEnumSurfacesFlags = Flags(DWORD, [
"DDENUMSURFACES_ALL",
"DDENUMSURFACES_MATCH",
@@ -1283,16 +1287,16 @@ IDirectDraw.methods += [
StdMethod(DDRESULT, "CreatePalette", [(DirectDrawPaletteCapsFlags, "dwFlags"), (LPPALETTEENTRY, "lpDDColorArray"), Out(Pointer(LPDIRECTDRAWPALETTE), "lplpDDPalette"), (ObjPointer(IUnknown), "pUnkOuter")]),
StdMethod(DDRESULT, "CreateSurface", [(LPDDSURFACEDESC, "lpDDSurfaceDesc"), Out(Pointer(LPDIRECTDRAWSURFACE), "lplpDDSurface"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(DDRESULT, "DuplicateSurface", [(LPDIRECTDRAWSURFACE, "lpDDSurface"), Out(Pointer(LPDIRECTDRAWSURFACE), "lplpDupDDSurface")]),
- StdMethod(DDRESULT, "EnumDisplayModes", [(DirectDrawEnumDisplayModesFlags, "dwFlags"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMMODESCALLBACK, "lpEnumModesCallback")]),
- StdMethod(DDRESULT, "EnumSurfaces", [(DirectDrawEnumSurfacesFlags, "dwFlags"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")]),
+ StdMethod(DDRESULT, "EnumDisplayModes", [(DirectDrawEnumDisplayModesFlags, "dwFlags"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMMODESCALLBACK, "lpEnumModesCallback")], sideeffects=False),
+ StdMethod(DDRESULT, "EnumSurfaces", [(DirectDrawEnumSurfacesFlags, "dwFlags"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")], sideeffects=False),
StdMethod(DDRESULT, "FlipToGDISurface", []),
- StdMethod(DDRESULT, "GetCaps", [Out(LPDDCAPS, "lpDDDriverCaps"), Out(LPDDCAPS, "lpDDHELCaps")]),
- StdMethod(DDRESULT, "GetDisplayMode", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")]),
- StdMethod(DDRESULT, "GetFourCCCodes", [Out(LPDWORD, "lpNumCodes"), Out(LPDWORD, "lpCodes")]),
+ StdMethod(DDRESULT, "GetCaps", [Out(LPDDCAPS, "lpDDDriverCaps"), Out(LPDDCAPS, "lpDDHELCaps")], sideeffects=False),
+ StdMethod(DDRESULT, "GetDisplayMode", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")], sideeffects=False),
+ StdMethod(DDRESULT, "GetFourCCCodes", [Out(LPDWORD, "lpNumCodes"), Out(LPDWORD, "lpCodes")], sideeffects=False),
StdMethod(DDRESULT, "GetGDISurface", [Out(Pointer(LPDIRECTDRAWSURFACE), "lplpGDIDDSSurface")]),
- StdMethod(DDRESULT, "GetMonitorFrequency", [Out(LPDWORD, "lpdwFrequency")]),
- StdMethod(DDRESULT, "GetScanLine", [Out(LPDWORD, "lpdwScanLine")]),
- StdMethod(DDRESULT, "GetVerticalBlankStatus", [Out(LPBOOL, "lpbIsInVB")]),
+ StdMethod(DDRESULT, "GetMonitorFrequency", [Out(LPDWORD, "lpdwFrequency")], sideeffects=False),
+ StdMethod(DDRESULT, "GetScanLine", [Out(LPDWORD, "lpdwScanLine")], sideeffects=False),
+ StdMethod(DDRESULT, "GetVerticalBlankStatus", [Out(LPBOOL, "lpbIsInVB")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(Pointer(GUID), "lpGUID")]),
StdMethod(DDRESULT, "RestoreDisplayMode", []),
StdMethod(DDRESULT, "SetCooperativeLevel", [(HWND, "hWnd"), (DirectDrawSetCooperativeLevelFlags, "dwFlags")]),
@@ -1306,22 +1310,22 @@ IDirectDraw2.methods += [
StdMethod(DDRESULT, "CreatePalette", [(DirectDrawPaletteCapsFlags, "dwFlags"), (LPPALETTEENTRY, "lpDDColorArray"), Out(Pointer(LPDIRECTDRAWPALETTE), "lplpDDPalette"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(DDRESULT, "CreateSurface", [(LPDDSURFACEDESC, "lpDDSurfaceDesc"), Out(Pointer(LPDIRECTDRAWSURFACE), "lplpDDSurface"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(DDRESULT, "DuplicateSurface", [(LPDIRECTDRAWSURFACE, "lpDDSurface"), Out(Pointer(LPDIRECTDRAWSURFACE), "lplpDupDDSurface")]),
- StdMethod(DDRESULT, "EnumDisplayModes", [(DirectDrawEnumDisplayModesFlags, "dwFlags"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMMODESCALLBACK, "lpEnumModesCallback")]),
- StdMethod(DDRESULT, "EnumSurfaces", [(DirectDrawEnumSurfacesFlags, "dwFlags"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")]),
+ StdMethod(DDRESULT, "EnumDisplayModes", [(DirectDrawEnumDisplayModesFlags, "dwFlags"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMMODESCALLBACK, "lpEnumModesCallback")], sideeffects=False),
+ StdMethod(DDRESULT, "EnumSurfaces", [(DirectDrawEnumSurfacesFlags, "dwFlags"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")], sideeffects=False),
StdMethod(DDRESULT, "FlipToGDISurface", []),
- StdMethod(DDRESULT, "GetCaps", [Out(LPDDCAPS, "lpDDDriverCaps"), Out(LPDDCAPS, "lpDDHELCaps")]),
- StdMethod(DDRESULT, "GetDisplayMode", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")]),
- StdMethod(DDRESULT, "GetFourCCCodes", [Out(LPDWORD, "lpNumCodes"), Out(LPDWORD, "lpCodes")]),
+ StdMethod(DDRESULT, "GetCaps", [Out(LPDDCAPS, "lpDDDriverCaps"), Out(LPDDCAPS, "lpDDHELCaps")], sideeffects=False),
+ StdMethod(DDRESULT, "GetDisplayMode", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")], sideeffects=False),
+ StdMethod(DDRESULT, "GetFourCCCodes", [Out(LPDWORD, "lpNumCodes"), Out(LPDWORD, "lpCodes")], sideeffects=False),
StdMethod(DDRESULT, "GetGDISurface", [Out(Pointer(LPDIRECTDRAWSURFACE), "lplpGDIDDSSurface")]),
- StdMethod(DDRESULT, "GetMonitorFrequency", [Out(LPDWORD, "lpdwFrequency")]),
- StdMethod(DDRESULT, "GetScanLine", [Out(LPDWORD, "lpdwScanLine")]),
- StdMethod(DDRESULT, "GetVerticalBlankStatus", [Out(LPBOOL, "lpbIsInVB")]),
+ StdMethod(DDRESULT, "GetMonitorFrequency", [Out(LPDWORD, "lpdwFrequency")], sideeffects=False),
+ StdMethod(DDRESULT, "GetScanLine", [Out(LPDWORD, "lpdwScanLine")], sideeffects=False),
+ StdMethod(DDRESULT, "GetVerticalBlankStatus", [Out(LPBOOL, "lpbIsInVB")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(Pointer(GUID), "lpGUID")]),
StdMethod(DDRESULT, "RestoreDisplayMode", []),
StdMethod(DDRESULT, "SetCooperativeLevel", [(HWND, "hWnd"), (DirectDrawSetCooperativeLevelFlags, "dwFlags")]),
StdMethod(DDRESULT, "SetDisplayMode", [(DWORD, "dwWidth"), (DWORD, "dwHeight"), (DWORD, "dwBPP"), (DWORD, "dwRefreshRate"), (DirectDrawSetDisplayModeFlags, "dwFlags")]),
StdMethod(DDRESULT, "WaitForVerticalBlank", [(DirectDrawWaitForVerticalBlankFlags, "dwFlags"), (HANDLE, "hEvent")]),
- StdMethod(DDRESULT, "GetAvailableVidMem", [(LPDDSCAPS, "lpDDSCaps"), Out(LPDWORD, "lpdwTotal"), Out(LPDWORD, "lpdwFree")]),
+ StdMethod(DDRESULT, "GetAvailableVidMem", [(LPDDSCAPS, "lpDDSCaps"), Out(LPDWORD, "lpdwTotal"), Out(LPDWORD, "lpdwFree")], sideeffects=False),
]
IDirectDraw4.methods += [
@@ -1330,26 +1334,26 @@ IDirectDraw4.methods += [
StdMethod(DDRESULT, "CreatePalette", [(DirectDrawPaletteCapsFlags, "dwFlags"), (LPPALETTEENTRY, "lpDDColorArray"), Out(Pointer(LPDIRECTDRAWPALETTE), "lplpDDPalette"), (ObjPointer(IUnknown), "pUnkOuter")]),
StdMethod(DDRESULT, "CreateSurface", [(LPDDSURFACEDESC2, "lpDDSurfaceDesc"), Out(Pointer(LPDIRECTDRAWSURFACE4), "lplpDDSurface"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(DDRESULT, "DuplicateSurface", [(LPDIRECTDRAWSURFACE4, "lpDDSurface"), Out(Pointer(LPDIRECTDRAWSURFACE4), "lplpDupDDSurface")]),
- StdMethod(DDRESULT, "EnumDisplayModes", [(DirectDrawEnumDisplayModesFlags, "dwFlags"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMMODESCALLBACK2, "lpEnumModesCallback")]),
- StdMethod(DDRESULT, "EnumSurfaces", [(DirectDrawEnumSurfacesFlags, "dwFlags"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK2, "lpEnumSurfacesCallback")]),
+ StdMethod(DDRESULT, "EnumDisplayModes", [(DirectDrawEnumDisplayModesFlags, "dwFlags"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMMODESCALLBACK2, "lpEnumModesCallback")], sideeffects=False),
+ StdMethod(DDRESULT, "EnumSurfaces", [(DirectDrawEnumSurfacesFlags, "dwFlags"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK2, "lpEnumSurfacesCallback")], sideeffects=False),
StdMethod(DDRESULT, "FlipToGDISurface", []),
- StdMethod(DDRESULT, "GetCaps", [Out(LPDDCAPS, "lpDDDriverCaps"), Out(LPDDCAPS, "lpDDHELCaps")]),
- StdMethod(DDRESULT, "GetDisplayMode", [Out(LPDDSURFACEDESC2, "lpDDSurfaceDesc")]),
- StdMethod(DDRESULT, "GetFourCCCodes", [Out(LPDWORD, "lpNumCodes"), Out(LPDWORD, "lpCodes")]),
+ StdMethod(DDRESULT, "GetCaps", [Out(LPDDCAPS, "lpDDDriverCaps"), Out(LPDDCAPS, "lpDDHELCaps")], sideeffects=False),
+ StdMethod(DDRESULT, "GetDisplayMode", [Out(LPDDSURFACEDESC2, "lpDDSurfaceDesc")], sideeffects=False),
+ StdMethod(DDRESULT, "GetFourCCCodes", [Out(LPDWORD, "lpNumCodes"), Out(LPDWORD, "lpCodes")], sideeffects=False),
StdMethod(DDRESULT, "GetGDISurface", [Out(Pointer(LPDIRECTDRAWSURFACE4), "lplpGDIDDSSurface")]),
- StdMethod(DDRESULT, "GetMonitorFrequency", [Out(LPDWORD, "lpdwFrequency")]),
- StdMethod(DDRESULT, "GetScanLine", [Out(LPDWORD, "lpdwScanLine")]),
- StdMethod(DDRESULT, "GetVerticalBlankStatus", [Out(LPBOOL, "lpbIsInVB")]),
+ StdMethod(DDRESULT, "GetMonitorFrequency", [Out(LPDWORD, "lpdwFrequency")], sideeffects=False),
+ StdMethod(DDRESULT, "GetScanLine", [Out(LPDWORD, "lpdwScanLine")], sideeffects=False),
+ StdMethod(DDRESULT, "GetVerticalBlankStatus", [Out(LPBOOL, "lpbIsInVB")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(Pointer(GUID), "lpGUID")]),
StdMethod(DDRESULT, "RestoreDisplayMode", []),
StdMethod(DDRESULT, "SetCooperativeLevel", [(HWND, "hWnd"), (DirectDrawSetCooperativeLevelFlags, "dwFlags")]),
StdMethod(DDRESULT, "SetDisplayMode", [(DWORD, "dwWidth"), (DWORD, "dwHeight"), (DWORD, "dwBPP"), (DWORD, "dwRefreshRate"), (DirectDrawSetDisplayModeFlags, "dwFlags")]),
StdMethod(DDRESULT, "WaitForVerticalBlank", [(DirectDrawWaitForVerticalBlankFlags, "dwFlags"), (HANDLE, "hEvent")]),
- StdMethod(DDRESULT, "GetAvailableVidMem", [(LPDDSCAPS2, "lpDDSCaps"), Out(LPDWORD, "lpdwTotal"), Out(LPDWORD, "lpdwFree")]),
+ StdMethod(DDRESULT, "GetAvailableVidMem", [(LPDDSCAPS2, "lpDDSCaps"), Out(LPDWORD, "lpdwTotal"), Out(LPDWORD, "lpdwFree")], sideeffects=False),
StdMethod(DDRESULT, "GetSurfaceFromDC", [(HDC, "hdc"), Out(Pointer(LPDIRECTDRAWSURFACE4), "lpDDSurface")]),
StdMethod(DDRESULT, "RestoreAllSurfaces", []),
StdMethod(DDRESULT, "TestCooperativeLevel", []),
- StdMethod(DDRESULT, "GetDeviceIdentifier", [Out(LPDDDEVICEIDENTIFIER, "lpDDDI"), (DirectDrawGetDeviceIdentifierFlags, "dwFlags")]),
+ StdMethod(DDRESULT, "GetDeviceIdentifier", [Out(LPDDDEVICEIDENTIFIER, "lpDDDI"), (DirectDrawGetDeviceIdentifierFlags, "dwFlags")], sideeffects=False),
]
IDirectDraw7.methods += [
@@ -1358,40 +1362,40 @@ IDirectDraw7.methods += [
StdMethod(DDRESULT, "CreatePalette", [(DirectDrawPaletteCapsFlags, "dwFlags"), (LPPALETTEENTRY, "lpDDColorArray"), Out(Pointer(LPDIRECTDRAWPALETTE), "lplpDDPalette"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(DDRESULT, "CreateSurface", [(LPDDSURFACEDESC2, "lpDDSurfaceDesc"), Out(Pointer(LPDIRECTDRAWSURFACE7), "lplpDDSurface"), (LPUNKNOWN, "pUnkOuter")]),
StdMethod(DDRESULT, "DuplicateSurface", [(LPDIRECTDRAWSURFACE7, "lpDDSurface"), Out(Pointer(LPDIRECTDRAWSURFACE7), "lplpDupDDSurface")]),
- StdMethod(DDRESULT, "EnumDisplayModes", [(DirectDrawEnumDisplayModesFlags, "dwFlags"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMMODESCALLBACK2, "lpEnumModesCallback")]),
- StdMethod(DDRESULT, "EnumSurfaces", [(DirectDrawEnumSurfacesFlags, "dwFlags"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK7, "lpEnumSurfacesCallback")]),
+ StdMethod(DDRESULT, "EnumDisplayModes", [(DirectDrawEnumDisplayModesFlags, "dwFlags"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMMODESCALLBACK2, "lpEnumModesCallback")], sideeffects=False),
+ StdMethod(DDRESULT, "EnumSurfaces", [(DirectDrawEnumSurfacesFlags, "dwFlags"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK7, "lpEnumSurfacesCallback")], sideeffects=False),
StdMethod(DDRESULT, "FlipToGDISurface", []),
- StdMethod(DDRESULT, "GetCaps", [Out(LPDDCAPS, "lpDDDriverCaps"), Out(LPDDCAPS, "lpDDHELCaps")]),
- StdMethod(DDRESULT, "GetDisplayMode", [Out(LPDDSURFACEDESC2, "lpDDSurfaceDesc")]),
- StdMethod(DDRESULT, "GetFourCCCodes", [Out(LPDWORD, "lpNumCodes"), Out(LPDWORD, "lpCodes")]),
+ StdMethod(DDRESULT, "GetCaps", [Out(LPDDCAPS, "lpDDDriverCaps"), Out(LPDDCAPS, "lpDDHELCaps")], sideeffects=False),
+ StdMethod(DDRESULT, "GetDisplayMode", [Out(LPDDSURFACEDESC2, "lpDDSurfaceDesc")], sideeffects=False),
+ StdMethod(DDRESULT, "GetFourCCCodes", [Out(LPDWORD, "lpNumCodes"), Out(LPDWORD, "lpCodes")], sideeffects=False),
StdMethod(DDRESULT, "GetGDISurface", [Out(Pointer(LPDIRECTDRAWSURFACE7), "lplpGDIDDSSurface")]),
- StdMethod(DDRESULT, "GetMonitorFrequency", [Out(LPDWORD, "lpdwFrequency")]),
- StdMethod(DDRESULT, "GetScanLine", [Out(LPDWORD, "lpdwScanLine")]),
- StdMethod(DDRESULT, "GetVerticalBlankStatus", [Out(LPBOOL, "lpbIsInVB")]),
+ StdMethod(DDRESULT, "GetMonitorFrequency", [Out(LPDWORD, "lpdwFrequency")], sideeffects=False),
+ StdMethod(DDRESULT, "GetScanLine", [Out(LPDWORD, "lpdwScanLine")], sideeffects=False),
+ StdMethod(DDRESULT, "GetVerticalBlankStatus", [Out(LPBOOL, "lpbIsInVB")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(Pointer(GUID), "lpGUID")]),
StdMethod(DDRESULT, "RestoreDisplayMode", []),
StdMethod(DDRESULT, "SetCooperativeLevel", [(HWND, "hWnd"), (DirectDrawSetCooperativeLevelFlags, "dwFlags")]),
StdMethod(DDRESULT, "SetDisplayMode", [(DWORD, "dwWidth"), (DWORD, "dwHeight"), (DWORD, "dwBPP"), (DWORD, "dwRefreshRate"), (DirectDrawSetDisplayModeFlags, "dwFlags")]),
StdMethod(DDRESULT, "WaitForVerticalBlank", [(DirectDrawWaitForVerticalBlankFlags, "dwFlags"), (HANDLE, "hEvent")]),
- StdMethod(DDRESULT, "GetAvailableVidMem", [(LPDDSCAPS2, "lpDDSCaps"), Out(LPDWORD, "lpdwTotal"), Out(LPDWORD, "lpdwFree")]),
+ StdMethod(DDRESULT, "GetAvailableVidMem", [(LPDDSCAPS2, "lpDDSCaps"), Out(LPDWORD, "lpdwTotal"), Out(LPDWORD, "lpdwFree")], sideeffects=False),
StdMethod(DDRESULT, "GetSurfaceFromDC", [(HDC, "hdc"), Out(Pointer(LPDIRECTDRAWSURFACE7), "lpDDSurface")]),
StdMethod(DDRESULT, "RestoreAllSurfaces", []),
StdMethod(DDRESULT, "TestCooperativeLevel", []),
- StdMethod(DDRESULT, "GetDeviceIdentifier", [Out(LPDDDEVICEIDENTIFIER2, "lpDDDI"), (DirectDrawGetDeviceIdentifierFlags, "dwFlags")]),
+ StdMethod(DDRESULT, "GetDeviceIdentifier", [Out(LPDDDEVICEIDENTIFIER2, "lpDDDI"), (DirectDrawGetDeviceIdentifierFlags, "dwFlags")], sideeffects=False),
StdMethod(DDRESULT, "StartModeTest", [(LPSIZE, "lpModesToTest"), (DWORD, "dwNumEntries"), (DirectDrawStartModeTestFlags, "dwFlags")]),
StdMethod(DDRESULT, "EvaluateMode", [(DirectDrawEvaluateModeFlags, "dwFlags"), Out(Pointer(DWORD), "pSecondsUntilTimeout")]),
]
IDirectDrawPalette.methods += [
- StdMethod(DDRESULT, "GetCaps", [Out(Pointer(DirectDrawPaletteCapsFlags), "lpdwCaps")]),
- StdMethod(DDRESULT, "GetEntries", [(DWORD, "dwFlags"), (DWORD, "dwBase"), (DWORD, "dwNumEntries"), Out(LPPALETTEENTRY, "lpEntries")]),
+ StdMethod(DDRESULT, "GetCaps", [Out(Pointer(DirectDrawPaletteCapsFlags), "lpdwCaps")], sideeffects=False),
+ StdMethod(DDRESULT, "GetEntries", [(DWORD, "dwFlags"), (DWORD, "dwBase"), (DWORD, "dwNumEntries"), Out(Array(PALETTEENTRY, "dwNumEntries"), "lpEntries")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(LPDIRECTDRAW, "lpDD"), (DWORD, "dwFlags"), (LPPALETTEENTRY, "lpDDColorTable")]),
- StdMethod(DDRESULT, "SetEntries", [(DWORD, "dwFlags"), (DWORD, "dwStartingEntry"), (DWORD, "dwCount"), (LPPALETTEENTRY, "lpEntries")]),
+ StdMethod(DDRESULT, "SetEntries", [(DWORD, "dwFlags"), (DWORD, "dwStartingEntry"), (DWORD, "dwCount"), (Array(PALETTEENTRY, "dwCount"), "lpEntries")]),
]
IDirectDrawClipper.methods += [
- StdMethod(DDRESULT, "GetClipList", [(LPRECT, "lpRect"), (LPRGNDATA, "lpClipList"), Out(LPDWORD, "lpdwSize")]),
- StdMethod(DDRESULT, "GetHWnd", [Out(Pointer(HWND), "hWnd")]),
+ StdMethod(DDRESULT, "GetClipList", [(LPRECT, "lpRect"), (LPRGNDATA, "lpClipList"), Out(LPDWORD, "lpdwSize")], sideeffects=False),
+ StdMethod(DDRESULT, "GetHWnd", [Out(Pointer(HWND), "hWnd")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(LPDIRECTDRAW, "lpDD"), (DWORD, "dwFlags")]),
StdMethod(DDRESULT, "IsClipListChanged", [Out(Pointer(BOOL), "lpbChanged")]),
StdMethod(DDRESULT, "SetClipList", [(LPRGNDATA, "lpClipList"), (DWORD, "dwFlags")]),
@@ -1406,24 +1410,24 @@ IDirectDrawSurface.methods += [
StdMethod(DDRESULT, "BltBatch", [(LPDDBLTBATCH, "lpDDBltBatch"), (DWORD, "dwCount"), (DWORD, "dwFlags")]),
StdMethod(DDRESULT, "BltFast", [(DWORD, "dwX"), (DWORD, "dwY"), (LPDIRECTDRAWSURFACE, "lpDDSrcSurface"), (LPRECT, "lpSrcRect"), (DWORD, "dwTrans")]),
StdMethod(DDRESULT, "DeleteAttachedSurface", [(DWORD, "dwFlags"), (LPDIRECTDRAWSURFACE, "lpDDSurface")]),
- StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")]),
- StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpfnCallback")]),
+ StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")], sideeffects=False),
+ StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpfnCallback")], sideeffects=False),
StdMethod(DDRESULT, "Flip", [(LPDIRECTDRAWSURFACE, "lpDDSurfaceTargetOverride"), (DirectDrawFlipFlags, "dwFlags")]),
StdMethod(DDRESULT, "GetAttachedSurface", [(LPDDSCAPS, "lpDDSCaps"), Out(Pointer(LPDIRECTDRAWSURFACE), "lplpDDAttachedSurface")]),
StdMethod(DDRESULT, "GetBltStatus", [(DirectDrawGetBltStatusFlags, "dwFlags")]),
- StdMethod(DDRESULT, "GetCaps", [Out(LPDDSCAPS, "lpDDSCaps")]),
+ StdMethod(DDRESULT, "GetCaps", [Out(LPDDSCAPS, "lpDDSCaps")], sideeffects=False),
StdMethod(DDRESULT, "GetClipper", [Out(Pointer(LPDIRECTDRAWCLIPPER), "lplpDDClipper")]),
- StdMethod(DDRESULT, "GetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
- StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")]),
- StdMethod(DDRESULT, "GetFlipStatus", [(DWORD, "dwFlags")]),
- StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")]),
+ StdMethod(DDRESULT, "GetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")], sideeffects=False),
+ StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")], sideeffects=False),
+ StdMethod(DDRESULT, "GetFlipStatus", [(DWORD, "dwFlags")], sideeffects=False),
+ StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")], sideeffects=False),
StdMethod(DDRESULT, "GetPalette", [Out(Pointer(LPDIRECTDRAWPALETTE), "lplpDDPalette")]),
- StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")]),
- StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")]),
+ StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")], sideeffects=False),
+ StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(LPDIRECTDRAW, "lpDD"), (LPDDSURFACEDESC, "lpDDSurfaceDesc")]),
StdMethod(DDRESULT, "IsLost", []),
- StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
- StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")]),
+ StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), InOut(LPDDSURFACEDESC, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
+ StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")], sideeffects=False),
StdMethod(DDRESULT, "Restore", []),
StdMethod(DDRESULT, "SetClipper", [(LPDIRECTDRAWCLIPPER, "lpDDClipper")]),
StdMethod(DDRESULT, "SetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
@@ -1442,24 +1446,24 @@ IDirectDrawSurface2.methods += [
StdMethod(DDRESULT, "BltBatch", [(LPDDBLTBATCH, "lpDDBltBatch"), (DWORD, "dwCount"), (DWORD, "dwFlags")]),
StdMethod(DDRESULT, "BltFast", [(DWORD, "dwX"), (DWORD, "dwY"), (LPDIRECTDRAWSURFACE2, "lpDDSrcSurface"), (LPRECT, "lpSrcRect"), (DWORD, "dwTrans")]),
StdMethod(DDRESULT, "DeleteAttachedSurface", [(DWORD, "dwFlags"), (LPDIRECTDRAWSURFACE2, "lpDDSurface")]),
- StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")]),
- StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpfnCallback")]),
+ StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")], sideeffects=False),
+ StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpfnCallback")], sideeffects=False),
StdMethod(DDRESULT, "Flip", [(LPDIRECTDRAWSURFACE2, "lpDDSurfaceTargetOverride"), (DirectDrawFlipFlags, "dwFlags")]),
StdMethod(DDRESULT, "GetAttachedSurface", [(LPDDSCAPS, "lpDDSCaps"), Out(Pointer(LPDIRECTDRAWSURFACE2), "lplpDDAttachedSurface")]),
- StdMethod(DDRESULT, "GetBltStatus", [(DirectDrawGetBltStatusFlags, "dwFlags")]),
- StdMethod(DDRESULT, "GetCaps", [Out(LPDDSCAPS, "lpDDSCaps")]),
+ StdMethod(DDRESULT, "GetBltStatus", [(DirectDrawGetBltStatusFlags, "dwFlags")], sideeffects=False),
+ StdMethod(DDRESULT, "GetCaps", [Out(LPDDSCAPS, "lpDDSCaps")], sideeffects=False),
StdMethod(DDRESULT, "GetClipper", [Out(Pointer(LPDIRECTDRAWCLIPPER), "lplpDDClipper")]),
- StdMethod(DDRESULT, "GetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
- StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")]),
- StdMethod(DDRESULT, "GetFlipStatus", [(DWORD, "dwFlags")]),
- StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")]),
+ StdMethod(DDRESULT, "GetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")], sideeffects=False),
+ StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")], sideeffects=False),
+ StdMethod(DDRESULT, "GetFlipStatus", [(DWORD, "dwFlags")], sideeffects=False),
+ StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")], sideeffects=False),
StdMethod(DDRESULT, "GetPalette", [Out(Pointer(LPDIRECTDRAWPALETTE), "lplpDDPalette")]),
- StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")]),
- StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")]),
+ StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")], sideeffects=False),
+ StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(LPDIRECTDRAW, "lpDD"), (LPDDSURFACEDESC, "lpDDSurfaceDesc")]),
StdMethod(DDRESULT, "IsLost", []),
- StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
- StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")]),
+ StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), InOut(LPDDSURFACEDESC, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
+ StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")], sideeffects=False),
StdMethod(DDRESULT, "Restore", []),
StdMethod(DDRESULT, "SetClipper", [(LPDIRECTDRAWCLIPPER, "lpDDClipper")]),
StdMethod(DDRESULT, "SetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
@@ -1469,7 +1473,7 @@ IDirectDrawSurface2.methods += [
StdMethod(DDRESULT, "UpdateOverlay", [(LPRECT, "lpSrcRect"), (LPDIRECTDRAWSURFACE2, "lpDDDestSurface"), (LPRECT, "lpDestRect"), (DirectDrawSurfaceOverlayFlags, "dwFlags"), (LPDDOVERLAYFX, "lpDDOverlayFx")]),
StdMethod(DDRESULT, "UpdateOverlayDisplay", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "UpdateOverlayZOrder", [(DirectDrawUpdateOverlayZOrderFlags, "dwFlags"), (LPDIRECTDRAWSURFACE2, "lpDDSReference")]),
- StdMethod(DDRESULT, "GetDDInterface", [Out(LPUNKNOWN, "lplpDD")]),
+ StdMethod(DDRESULT, "GetDDInterface", [Out(Pointer(ObjPointer(VOID)), "lplpDD")]),
StdMethod(DDRESULT, "PageLock", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "PageUnlock", [(DWORD, "dwFlags")]),
]
@@ -1481,24 +1485,24 @@ IDirectDrawSurface3.methods += [
StdMethod(DDRESULT, "BltBatch", [(LPDDBLTBATCH, "lpDDBltBatch"), (DWORD, "dwCount"), (DWORD, "dwFlags")]),
StdMethod(DDRESULT, "BltFast", [(DWORD, "dwX"), (DWORD, "dwY"), (LPDIRECTDRAWSURFACE3, "lpDDSrcSurface"), (LPRECT, "lpSrcRect"), (DWORD, "dwTrans")]),
StdMethod(DDRESULT, "DeleteAttachedSurface", [(DWORD, "dwFlags"), (LPDIRECTDRAWSURFACE3, "lpDDSurface")]),
- StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")]),
- StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpfnCallback")]),
+ StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpEnumSurfacesCallback")], sideeffects=False),
+ StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK, "lpfnCallback")], sideeffects=False),
StdMethod(DDRESULT, "Flip", [(LPDIRECTDRAWSURFACE3, "lpDDSurfaceTargetOverride"), (DirectDrawFlipFlags, "dwFlags")]),
StdMethod(DDRESULT, "GetAttachedSurface", [(LPDDSCAPS, "lpDDSCaps"), Out(Pointer(LPDIRECTDRAWSURFACE3), "lplpDDAttachedSurface")]),
- StdMethod(DDRESULT, "GetBltStatus", [(DirectDrawGetBltStatusFlags, "dwFlags")]),
- StdMethod(DDRESULT, "GetCaps", [Out(LPDDSCAPS, "lpDDSCaps")]),
+ StdMethod(DDRESULT, "GetBltStatus", [(DirectDrawGetBltStatusFlags, "dwFlags")], sideeffects=False),
+ StdMethod(DDRESULT, "GetCaps", [Out(LPDDSCAPS, "lpDDSCaps")], sideeffects=False),
StdMethod(DDRESULT, "GetClipper", [Out(Pointer(LPDIRECTDRAWCLIPPER), "lplpDDClipper")]),
- StdMethod(DDRESULT, "GetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
- StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")]),
- StdMethod(DDRESULT, "GetFlipStatus", [(DWORD, "dwFlags")]),
- StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")]),
+ StdMethod(DDRESULT, "GetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")], sideeffects=False),
+ StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")], sideeffects=False),
+ StdMethod(DDRESULT, "GetFlipStatus", [(DWORD, "dwFlags")], sideeffects=False),
+ StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")], sideeffects=False),
StdMethod(DDRESULT, "GetPalette", [Out(Pointer(LPDIRECTDRAWPALETTE), "lplpDDPalette")]),
- StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")]),
- StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")]),
+ StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")], sideeffects=False),
+ StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC, "lpDDSurfaceDesc")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(LPDIRECTDRAW, "lpDD"), (LPDDSURFACEDESC, "lpDDSurfaceDesc")]),
StdMethod(DDRESULT, "IsLost", []),
- StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), (LPDDSURFACEDESC, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
- StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")]),
+ StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), InOut(LPDDSURFACEDESC, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
+ StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")], sideeffects=False),
StdMethod(DDRESULT, "Restore", []),
StdMethod(DDRESULT, "SetClipper", [(LPDIRECTDRAWCLIPPER, "lpDDClipper")]),
StdMethod(DDRESULT, "SetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
@@ -1508,7 +1512,7 @@ IDirectDrawSurface3.methods += [
StdMethod(DDRESULT, "UpdateOverlay", [(LPRECT, "lpSrcRect"), (LPDIRECTDRAWSURFACE3, "lpDDDestSurface"), (LPRECT, "lpDestRect"), (DirectDrawSurfaceOverlayFlags, "dwFlags"), (LPDDOVERLAYFX, "lpDDOverlayFx")]),
StdMethod(DDRESULT, "UpdateOverlayDisplay", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "UpdateOverlayZOrder", [(DirectDrawUpdateOverlayZOrderFlags, "dwFlags"), (LPDIRECTDRAWSURFACE3, "lpDDSReference")]),
- StdMethod(DDRESULT, "GetDDInterface", [Out(LPUNKNOWN, "lplpDD")]),
+ StdMethod(DDRESULT, "GetDDInterface", [Out(Pointer(ObjPointer(VOID)), "lplpDD")]),
StdMethod(DDRESULT, "PageLock", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "PageUnlock", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "SetSurfaceDesc", [(LPDDSURFACEDESC, "lpDDSD"), (DWORD, "dwFlags")]),
@@ -1521,24 +1525,24 @@ IDirectDrawSurface4.methods += [
StdMethod(DDRESULT, "BltBatch", [(LPDDBLTBATCH, "lpDDBltBatch"), (DWORD, "dwCount"), (DWORD, "dwFlags")]),
StdMethod(DDRESULT, "BltFast", [(DWORD, "dwX"), (DWORD, "dwY"), (LPDIRECTDRAWSURFACE4, "lpDDSrcSurface"), (LPRECT, "lpSrcRect"), (DWORD, "dwTrans")]),
StdMethod(DDRESULT, "DeleteAttachedSurface", [(DWORD, "dwFlags"), (LPDIRECTDRAWSURFACE4, "lpDDSurface")]),
- StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK2, "lpEnumSurfacesCallback")]),
- StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK2, "lpfnCallback")]),
+ StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK2, "lpEnumSurfacesCallback")], sideeffects=False),
+ StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK2, "lpfnCallback")], sideeffects=False),
StdMethod(DDRESULT, "Flip", [(LPDIRECTDRAWSURFACE4, "lpDDSurfaceTargetOverride"), (DirectDrawFlipFlags, "dwFlags")]),
StdMethod(DDRESULT, "GetAttachedSurface", [(LPDDSCAPS2, "lpDDSCaps"), Out(Pointer(LPDIRECTDRAWSURFACE4), "lplpDDAttachedSurface")]),
- StdMethod(DDRESULT, "GetBltStatus", [(DirectDrawGetBltStatusFlags, "dwFlags")]),
- StdMethod(DDRESULT, "GetCaps", [Out(LPDDSCAPS2, "lpDDSCaps")]),
+ StdMethod(DDRESULT, "GetBltStatus", [(DirectDrawGetBltStatusFlags, "dwFlags")], sideeffects=False),
+ StdMethod(DDRESULT, "GetCaps", [Out(LPDDSCAPS2, "lpDDSCaps")], sideeffects=False),
StdMethod(DDRESULT, "GetClipper", [Out(Pointer(LPDIRECTDRAWCLIPPER), "lplpDDClipper")]),
- StdMethod(DDRESULT, "GetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
- StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")]),
- StdMethod(DDRESULT, "GetFlipStatus", [(DWORD, "dwFlags")]),
- StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")]),
+ StdMethod(DDRESULT, "GetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")], sideeffects=False),
+ StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")], sideeffects=False),
+ StdMethod(DDRESULT, "GetFlipStatus", [(DWORD, "dwFlags")], sideeffects=False),
+ StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")], sideeffects=False),
StdMethod(DDRESULT, "GetPalette", [Out(Pointer(LPDIRECTDRAWPALETTE), "lplpDDPalette")]),
- StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")]),
- StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC2, "lpDDSurfaceDesc")]),
+ StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")], sideeffects=False),
+ StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC2, "lpDDSurfaceDesc")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(LPDIRECTDRAW, "lpDD"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc")]),
StdMethod(DDRESULT, "IsLost", []),
- StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
- StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")]),
+ StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), InOut(LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
+ StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")], sideeffects=False),
StdMethod(DDRESULT, "Restore", []),
StdMethod(DDRESULT, "SetClipper", [(LPDIRECTDRAWCLIPPER, "lpDDClipper")]),
StdMethod(DDRESULT, "SetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
@@ -1548,13 +1552,13 @@ IDirectDrawSurface4.methods += [
StdMethod(DDRESULT, "UpdateOverlay", [(LPRECT, "lpSrcRect"), (LPDIRECTDRAWSURFACE4, "lpDDDestSurface"), (LPRECT, "lpDestRect"), (DirectDrawSurfaceOverlayFlags, "dwFlags"), (LPDDOVERLAYFX, "lpDDOverlayFx")]),
StdMethod(DDRESULT, "UpdateOverlayDisplay", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "UpdateOverlayZOrder", [(DirectDrawUpdateOverlayZOrderFlags, "dwFlags"), (LPDIRECTDRAWSURFACE4, "lpDDSReference")]),
- StdMethod(DDRESULT, "GetDDInterface", [Out(Pointer(LPVOID), "lplpDD")]),
+ StdMethod(DDRESULT, "GetDDInterface", [Out(Pointer(ObjPointer(VOID)), "lplpDD")]),
StdMethod(DDRESULT, "PageLock", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "PageUnlock", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "SetSurfaceDesc", [(LPDDSURFACEDESC2, "lpDDSD"), (DWORD, "dwFlags")]),
- StdMethod(DDRESULT, "SetPrivateData", [(REFGUID, "guidTag"), (LPVOID, "lpData"), (DWORD, "cbSize"), (DWORD, "dwFlags")]),
- StdMethod(DDRESULT, "GetPrivateData", [(REFGUID, "guidTag"), (LPVOID, "lpData"), Out(LPDWORD, "lpcbBufferSize")]),
- StdMethod(DDRESULT, "FreePrivateData", [(REFGUID, "guidTag")]),
+ StdMethod(DDRESULT, "SetPrivateData", [(REFGUID, "guidTag"), (LPVOID, "lpData"), (DWORD, "cbSize"), (DWORD, "dwFlags")], sideeffects=False),
+ StdMethod(DDRESULT, "GetPrivateData", [(REFGUID, "guidTag"), (LPVOID, "lpData"), InOut(LPDWORD, "lpcbBufferSize")], sideeffects=False),
+ StdMethod(DDRESULT, "FreePrivateData", [(REFGUID, "guidTag")], sideeffects=False),
StdMethod(DDRESULT, "GetUniquenessValue", [Out(LPDWORD, "lpValue")]),
StdMethod(DDRESULT, "ChangeUniquenessValue", []),
]
@@ -1566,24 +1570,24 @@ IDirectDrawSurface7.methods += [
StdMethod(DDRESULT, "BltBatch", [(LPDDBLTBATCH, "lpDDBltBatch"), (DWORD, "dwCount"), (DWORD, "dwFlags")]),
StdMethod(DDRESULT, "BltFast", [(DWORD, "dwX"), (DWORD, "dwY"), (LPDIRECTDRAWSURFACE7, "lpDDSrcSurface"), (LPRECT, "lpSrcRect"), (DWORD, "dwTrans")]),
StdMethod(DDRESULT, "DeleteAttachedSurface", [(DWORD, "dwFlags"), (LPDIRECTDRAWSURFACE7, "lpDDSurface")]),
- StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK7, "lpEnumSurfacesCallback")]),
- StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK7, "lpfnCallback")]),
+ StdMethod(DDRESULT, "EnumAttachedSurfaces", [(LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK7, "lpEnumSurfacesCallback")], sideeffects=False),
+ StdMethod(DDRESULT, "EnumOverlayZOrders", [(DirectDrawEnumOverlayZOrderFlags, "dwFlags"), (LPVOID, "lpContext"), (LPDDENUMSURFACESCALLBACK7, "lpfnCallback")], sideeffects=False),
StdMethod(DDRESULT, "Flip", [(LPDIRECTDRAWSURFACE7, "lpDDSurfaceTargetOverride"), (DirectDrawFlipFlags, "dwFlags")]),
StdMethod(DDRESULT, "GetAttachedSurface", [(LPDDSCAPS2, "lpDDSCaps"), Out(Pointer(LPDIRECTDRAWSURFACE7), "lplpDDAttachedSurface")]),
StdMethod(DDRESULT, "GetBltStatus", [(DirectDrawGetBltStatusFlags, "dwFlags")]),
StdMethod(DDRESULT, "GetCaps", [Out(LPDDSCAPS2, "lpDDSCaps")]),
StdMethod(DDRESULT, "GetClipper", [Out(Pointer(LPDIRECTDRAWCLIPPER), "lplpDDClipper")]),
StdMethod(DDRESULT, "GetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
- StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")]),
+ StdMethod(DDRESULT, "GetDC", [Out(Pointer(HDC), "phDC")], sideeffects=False),
StdMethod(DDRESULT, "GetFlipStatus", [(DWORD, "dwFlags")]),
- StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")]),
+ StdMethod(DDRESULT, "GetOverlayPosition", [Out(LPLONG, "lplX"), Out(LPLONG, "lplY")], sideeffects=False),
StdMethod(DDRESULT, "GetPalette", [Out(Pointer(LPDIRECTDRAWPALETTE), "lplpDDPalette")]),
- StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")]),
- StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC2, "lpDDSurfaceDesc")]),
+ StdMethod(DDRESULT, "GetPixelFormat", [Out(LPDDPIXELFORMAT, "lpDDPixelFormat")], sideeffects=False),
+ StdMethod(DDRESULT, "GetSurfaceDesc", [Out(LPDDSURFACEDESC2, "lpDDSurfaceDesc")], sideeffects=False),
StdMethod(DDRESULT, "Initialize", [(LPDIRECTDRAW, "lpDD"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc")]),
- StdMethod(DDRESULT, "IsLost", []),
- StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), (LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
- StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")]),
+ StdMethod(DDRESULT, "IsLost", [], sideeffects=False),
+ StdMethod(DDRESULT, "Lock", [(LPRECT, "lpDestRect"), InOut(LPDDSURFACEDESC2, "lpDDSurfaceDesc"), (DirectDrawSurfaceLockFlags, "dwFlags"), (HANDLE, "hEvent")]),
+ StdMethod(DDRESULT, "ReleaseDC", [(HDC, "hDC")], sideeffects=False),
StdMethod(DDRESULT, "Restore", []),
StdMethod(DDRESULT, "SetClipper", [(LPDIRECTDRAWCLIPPER, "lpDDClipper")]),
StdMethod(DDRESULT, "SetColorKey", [(DirectDrawSurfaceSetGetColorKeyFlags, "dwFlags"), Out(LPDDCOLORKEY, "lpDDColorKey")]),
@@ -1593,19 +1597,19 @@ IDirectDrawSurface7.methods += [
StdMethod(DDRESULT, "UpdateOverlay", [(LPRECT, "lpSrcRect"), (LPDIRECTDRAWSURFACE7, "lpDDDestSurface"), (LPRECT, "lpDestRect"), (DirectDrawSurfaceOverlayFlags, "dwFlags"), (LPDDOVERLAYFX, "lpDDOverlayFx")]),
StdMethod(DDRESULT, "UpdateOverlayDisplay", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "UpdateOverlayZOrder", [(DirectDrawUpdateOverlayZOrderFlags, "dwFlags"), (LPDIRECTDRAWSURFACE7, "lpDDSReference")]),
- StdMethod(DDRESULT, "GetDDInterface", [Out(Pointer(LPVOID), "lplpDD")]),
+ StdMethod(DDRESULT, "GetDDInterface", [Out(Pointer(ObjPointer(VOID)), "lplpDD")]),
StdMethod(DDRESULT, "PageLock", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "PageUnlock", [(DWORD, "dwFlags")]),
StdMethod(DDRESULT, "SetSurfaceDesc", [(LPDDSURFACEDESC2, "lpDDSD"), (DWORD, "dwFlags")]),
- StdMethod(DDRESULT, "SetPrivateData", [(REFGUID, "guidTag"), (LPVOID, "lpData"), (DWORD, "cbSize"), (DWORD, "dwFlags")]),
- StdMethod(DDRESULT, "GetPrivateData", [(REFGUID, "guidTag"), (LPVOID, "lpData"), Out(LPDWORD, "lpcbBufferSize")]),
- StdMethod(DDRESULT, "FreePrivateData", [(REFGUID, "guidTag")]),
- StdMethod(DDRESULT, "GetUniquenessValue", [Out(LPDWORD, "lpValue")]),
+ StdMethod(DDRESULT, "SetPrivateData", [(REFGUID, "guidTag"), (LPVOID, "lpData"), (DWORD, "cbSize"), (DWORD, "dwFlags")], sideeffects=False),
+ StdMethod(DDRESULT, "GetPrivateData", [(REFGUID, "guidTag"), (LPVOID, "lpData"), InOut(LPDWORD, "lpcbBufferSize")], sideeffects=False),
+ StdMethod(DDRESULT, "FreePrivateData", [(REFGUID, "guidTag")], sideeffects=False),
+ StdMethod(DDRESULT, "GetUniquenessValue", [Out(LPDWORD, "lpValue")], sideeffects=False),
StdMethod(DDRESULT, "ChangeUniquenessValue", []),
StdMethod(DDRESULT, "SetPriority", [(DWORD, "dwPriority")]),
- StdMethod(DDRESULT, "GetPriority", [Out(LPDWORD, "lpdwPriority")]),
+ StdMethod(DDRESULT, "GetPriority", [Out(LPDWORD, "lpdwPriority")], sideeffects=False),
StdMethod(DDRESULT, "SetLOD", [(DWORD, "dwMaxLOD")]),
- StdMethod(DDRESULT, "GetLOD", [Out(LPDWORD, "lpdwMaxLOD")]),
+ StdMethod(DDRESULT, "GetLOD", [Out(LPDWORD, "lpdwMaxLOD")], sideeffects=False),
]
IDirectDrawColorControl.methods += [
@@ -1623,43 +1627,39 @@ LPDDENUMCALLBACKW = FunctionPointer(BOOL, "LPDDENUMCALLBACKW", [Pointer(GUID),
LPDDENUMCALLBACKEXA = FunctionPointer(BOOL, "LPDDENUMCALLBACKEXA", [Pointer(GUID), LPSTR, LPSTR, LPVOID, HMONITOR])
LPDDENUMCALLBACKEXW = FunctionPointer(BOOL, "LPDDENUMCALLBACKEXW", [Pointer(GUID), LPWSTR, LPWSTR, LPVOID, HMONITOR])
-DDENUM = Flags(DWORD, [
- "DDENUM_ATTACHEDSECONDARYDEVICES",
- "DDENUM_DETACHEDSECONDARYDEVICES",
- "DDENUM_NONDISPLAYDEVICES",
-])
-
-DDCREATE = Flags(DWORD, [
- "DDCREATE_HARDWAREONLY",
- "DDCREATE_EMULATIONONLY",
-])
-
ddraw = Module("ddraw")
ddraw.addFunctions([
- StdFunction(HRESULT, "DirectDrawEnumerateW", [(LPDDENUMCALLBACKW, "lpCallback"), (LPVOID, "lpContext")]),
- StdFunction(HRESULT, "DirectDrawEnumerateA", [(LPDDENUMCALLBACKA, "lpCallback"), (LPVOID, "lpContext")]),
- StdFunction(HRESULT, "DirectDrawEnumerateExW", [(LPDDENUMCALLBACKEXW, "lpCallback"), (LPVOID, "lpContext"), (DDENUM, "dwFlags")]),
- StdFunction(HRESULT, "DirectDrawEnumerateExA", [(LPDDENUMCALLBACKEXA, "lpCallback"), (LPVOID, "lpContext"), (DDENUM, "dwFlags")]),
- StdFunction(HRESULT, "DirectDrawCreate", [(Pointer(GUID), "lpGUID"), Out(Pointer(LPDIRECTDRAW), "lplpDD"), (LPUNKNOWN, "pUnkOuter")]),
- StdFunction(HRESULT, "DirectDrawCreateEx", [(Pointer(GUID), "lpGuid"), Out(Pointer(ObjPointer(Void)), "lplpDD"), (REFIID, "iid"), (LPUNKNOWN, "pUnkOuter")]),
+ StdFunction(HRESULT, "DirectDrawEnumerateW", [(LPDDENUMCALLBACKW, "lpCallback"), (LPVOID, "lpContext")], sideeffects=False),
+ StdFunction(HRESULT, "DirectDrawEnumerateA", [(LPDDENUMCALLBACKA, "lpCallback"), (LPVOID, "lpContext")], sideeffects=False),
+ StdFunction(HRESULT, "DirectDrawEnumerateExW", [(LPDDENUMCALLBACKEXW, "lpCallback"), (LPVOID, "lpContext"), (DDENUM, "dwFlags")], sideeffects=False),
+ StdFunction(HRESULT, "DirectDrawEnumerateExA", [(LPDDENUMCALLBACKEXA, "lpCallback"), (LPVOID, "lpContext"), (DDENUM, "dwFlags")], sideeffects=False),
+ StdFunction(HRESULT, "DirectDrawCreate", [(DDCREATE_LPGUID, "lpGUID"), Out(Pointer(LPDIRECTDRAW), "lplpDD"), (LPUNKNOWN, "pUnkOuter")]),
+ StdFunction(HRESULT, "DirectDrawCreateEx", [(DDCREATE_LPGUID, "lpGUID"), Out(Pointer(ObjPointer(Void)), "lplpDD"), (REFIID, "iid"), (LPUNKNOWN, "pUnkOuter")]),
StdFunction(HRESULT, "DirectDrawCreateClipper", [(DWORD, "dwFlags"), Out(Pointer(LPDIRECTDRAWCLIPPER), "lplpDDClipper"), (LPUNKNOWN, "pUnkOuter")]),
StdFunction(Void, "AcquireDDThreadLock", [], internal=True),
StdFunction(Void, "ReleaseDDThreadLock", [], internal=True),
- StdFunction(DWORD, "D3DParseUnknownCommand", [(LPVOID, "lpCmd"), Out(Pointer(LPVOID), "lpRetCmd")]),
- StdFunction(HRESULT, "DllCanUnloadNow", []),
- StdFunction(HRESULT, "DllGetClassObject", [(REFCLSID, "rclsid"), (REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppv")]),
+ StdFunction(DWORD, "D3DParseUnknownCommand", [(LPVOID, "lpCmd"), Out(Pointer(LPVOID), "lpRetCmd")], internal=True),
+ StdFunction(HRESULT, "DllCanUnloadNow", [], internal=True),
+ StdFunction(HRESULT, "DllGetClassObject", [(REFCLSID, "rclsid"), (REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppv")], sideeffects=False),
# XXX
- StdFunction(HRESULT, "CompleteCreateSysmemSurface", [Int, Int]),
- StdFunction(HRESULT, "GetSurfaceFromDC", [Int, Int, Int]),
- StdFunction(HRESULT, "DDInternalLock", [Int, Int]),
- StdFunction(HRESULT, "DDInternalUnlock", [Int]),
- StdFunction(HRESULT, "DSoundHelp", [HWND, Int, Int]),
- StdFunction(HRESULT, "GetDDSurfaceLocal", [Int, Int, Int]),
- StdFunction(HANDLE, "GetOLEThunkData", [Int]),
- StdFunction(HRESULT, "RegisterSpecialCase", [Int, Int, Int, Int]),
- StdFunction(HRESULT, "DDGetAttachedSurfaceLcl", [Int, Int, Int]),
+ StdFunction(HRESULT, "CompleteCreateSysmemSurface", [Int, Int], internal=True),
+ #StdFunction(HRESULT, "GetSurfaceFromDC", [Int, Int, Int], internal=True),
+ StdFunction(HRESULT, "DDInternalLock", [Int, Int], internal=True),
+ StdFunction(HRESULT, "DDInternalUnlock", [Int], internal=True),
+ StdFunction(HRESULT, "DSoundHelp", [HWND, Int, Int], internal=True),
+ StdFunction(HRESULT, "GetDDSurfaceLocal", [Int, Int, Int], internal=True),
+ StdFunction(HANDLE, "GetOLEThunkData", [Int], internal=True),
+ StdFunction(HRESULT, "RegisterSpecialCase", [Int, Int, Int, Int], internal=True),
+ StdFunction(HRESULT, "DDGetAttachedSurfaceLcl", [Int, Int, Int], internal=True),
# TODO: SetAppCompatData
])
+# Add otherwise unreferenced interfaces
+ddraw.addInterfaces([
+ IDirectDrawSurface2,
+ IDirectDrawSurface3,
+ IDirectDrawColorControl,
+ IDirectDrawGammaControl,
+])
diff --git a/specs/dwrite.py b/specs/dwrite.py
index 1a8aae0e..60e5034c 100644
--- a/specs/dwrite.py
+++ b/specs/dwrite.py
@@ -267,7 +267,7 @@ IDWriteFontFileEnumerator.methods += [
IDWriteLocalizedStrings.methods += [
StdMethod(UINT32, "GetCount", []),
- StdMethod(HRESULT, "FindLocaleName", [(Pointer(Const(WCHAR)), "localeName"), Out(Pointer(UINT32), "index"), Out(Pointer(BOOL), "exists")]),
+ StdMethod(HRESULT, "FindLocaleName", [(PCWSTR, "localeName"), Out(Pointer(UINT32), "index"), Out(Pointer(BOOL), "exists")]),
StdMethod(HRESULT, "GetLocaleNameLength", [(UINT32, "index"), Out(Pointer(UINT32), "length")]),
StdMethod(HRESULT, "GetLocaleName", [(UINT32, "index"), Out(Pointer(WCHAR), "localeName"), (UINT32, "size")]),
StdMethod(HRESULT, "GetStringLength", [(UINT32, "index"), Out(Pointer(UINT32), "length")]),
@@ -277,7 +277,7 @@ IDWriteLocalizedStrings.methods += [
IDWriteFontCollection.methods += [
StdMethod(UINT32, "GetFontFamilyCount", []),
StdMethod(HRESULT, "GetFontFamily", [(UINT32, "index"), Out(Pointer(ObjPointer(IDWriteFontFamily)), "fontFamily")]),
- StdMethod(HRESULT, "FindFamilyName", [(Pointer(Const(WCHAR)), "familyName"), Out(Pointer(UINT32), "index"), Out(Pointer(BOOL), "exists")]),
+ StdMethod(HRESULT, "FindFamilyName", [(PCWSTR, "familyName"), Out(Pointer(UINT32), "index"), Out(Pointer(BOOL), "exists")]),
StdMethod(HRESULT, "GetFontFromFontFace", [(ObjPointer(IDWriteFontFace), "fontFace"), Out(Pointer(ObjPointer(IDWriteFont)), "font")]),
]
@@ -550,9 +550,9 @@ IDWriteTextAnalyzer.methods += [
StdMethod(HRESULT, "AnalyzeBidi", [(ObjPointer(IDWriteTextAnalysisSource), "analysisSource"), (UINT32, "textPosition"), (UINT32, "textLength"), (ObjPointer(IDWriteTextAnalysisSink), "analysisSink")]),
StdMethod(HRESULT, "AnalyzeNumberSubstitution", [(ObjPointer(IDWriteTextAnalysisSource), "analysisSource"), (UINT32, "textPosition"), (UINT32, "textLength"), (ObjPointer(IDWriteTextAnalysisSink), "analysisSink")]),
StdMethod(HRESULT, "AnalyzeLineBreakpoints", [(ObjPointer(IDWriteTextAnalysisSource), "analysisSource"), (UINT32, "textPosition"), (UINT32, "textLength"), (ObjPointer(IDWriteTextAnalysisSink), "analysisSink")]),
- StdMethod(HRESULT, "GetGlyphs", [(Pointer(Const(WCHAR)), "textString"), (UINT32, "textLength"), (ObjPointer(IDWriteFontFace), "fontFace"), (BOOL, "isSideways"), (BOOL, "isRightToLeft"), (Pointer(Const(DWRITE_SCRIPT_ANALYSIS)), "scriptAnalysis"), (Pointer(Const(WCHAR)), "localeName"), (ObjPointer(IDWriteNumberSubstitution), "numberSubstitution"), (OpaquePointer(Pointer(Const(DWRITE_TYPOGRAPHIC_FEATURES))), "features"), (Pointer(Const(UINT32)), "featureRangeLengths"), (UINT32, "featureRanges"), (UINT32, "maxGlyphCount"), Out(Pointer(UINT16), "clusterMap"), Out(Pointer(DWRITE_SHAPING_TEXT_PROPERTIES), "textProps"), Out(Pointer(UINT16), "glyphIndices"), Out(Pointer(DWRITE_SHAPING_GLYPH_PROPERTIES), "glyphProps"), Out(Pointer(UINT32), "actualGlyphCount")]),
- StdMethod(HRESULT, "GetGlyphPlacements", [(Array(Const(WCHAR), "textLength"), "textString"), (Array(Const(UINT16), "textLength"), "clusterMap"), (Array(DWRITE_SHAPING_TEXT_PROPERTIES, "textLength"), "textProps"), (UINT32, "textLength"), (Array(Const(UINT16), "glyphCount"), "glyphIndices"), (Array(Const(DWRITE_SHAPING_GLYPH_PROPERTIES), "glyphCount"), "glyphProps"), (UINT32, "glyphCount"), (ObjPointer(IDWriteFontFace), "fontFace"), (FLOAT, "fontEmSize"), (BOOL, "isSideways"), (BOOL, "isRightToLeft"), (Pointer(Const(DWRITE_SCRIPT_ANALYSIS)), "scriptAnalysis"), (LPCWSTR, "localeName"), (Array(Pointer(Const(DWRITE_TYPOGRAPHIC_FEATURES)), "featureRanges"), "features"), (Array(Const(UINT32), "featureRanges"), "featureRangeLengths"), (UINT32, "featureRanges"), Out(Array(FLOAT, "glyphCount"), "glyphAdvances"), Out(Array(DWRITE_GLYPH_OFFSET, "glyphCount"), "glyphOffsets")]),
- StdMethod(HRESULT, "GetGdiCompatibleGlyphPlacements", [(Array(Const(WCHAR), "textLength"), "textString"), (Array(Const(UINT16), "textLength"), "clusterMap"), (Array(DWRITE_SHAPING_TEXT_PROPERTIES, "textLength"), "textProps"), (UINT32, "textLength"), (Array(Const(UINT16), "glyphCount"), "glyphIndices"), (Array(Const(DWRITE_SHAPING_GLYPH_PROPERTIES), "glyphCount"), "glyphProps"), (UINT32, "glyphCount"), (ObjPointer(IDWriteFontFace), "fontFace"), (FLOAT, "fontEmSize"), (FLOAT, "pixelsPerDip"), (Pointer(Const(DWRITE_MATRIX)), "transform"), (BOOL, "useGdiNatural"), (BOOL, "isSideways"), (BOOL, "isRightToLeft"), (Pointer(Const(DWRITE_SCRIPT_ANALYSIS)), "scriptAnalysis"), (LPCWSTR, "localeName"), (Array(Pointer(Const(DWRITE_TYPOGRAPHIC_FEATURES)), "featureRanges"), "features"), (Array(Const(UINT32), "featureRanges"), "featureRangeLengths"), (UINT32, "featureRanges"), Out(Array(FLOAT, "glyphCount"), "glyphAdvances"), Out(Array(DWRITE_GLYPH_OFFSET, "glyphCount"), "glyphOffsets")]),
+ StdMethod(HRESULT, "GetGlyphs", [(String(Const(WCHAR), "textLength", wide=True), "textString"), (UINT32, "textLength"), (ObjPointer(IDWriteFontFace), "fontFace"), (BOOL, "isSideways"), (BOOL, "isRightToLeft"), (Pointer(Const(DWRITE_SCRIPT_ANALYSIS)), "scriptAnalysis"), (PCWSTR, "localeName"), (ObjPointer(IDWriteNumberSubstitution), "numberSubstitution"), (OpaquePointer(Pointer(Const(DWRITE_TYPOGRAPHIC_FEATURES))), "features"), (Pointer(Const(UINT32)), "featureRangeLengths"), (UINT32, "featureRanges"), (UINT32, "maxGlyphCount"), Out(Pointer(UINT16), "clusterMap"), Out(Pointer(DWRITE_SHAPING_TEXT_PROPERTIES), "textProps"), Out(Pointer(UINT16), "glyphIndices"), Out(Pointer(DWRITE_SHAPING_GLYPH_PROPERTIES), "glyphProps"), Out(Pointer(UINT32), "actualGlyphCount")]),
+ StdMethod(HRESULT, "GetGlyphPlacements", [(String(Const(WCHAR), "textLength", wide=True), "textString"), (Array(Const(UINT16), "textLength"), "clusterMap"), (Array(DWRITE_SHAPING_TEXT_PROPERTIES, "textLength"), "textProps"), (UINT32, "textLength"), (Array(Const(UINT16), "glyphCount"), "glyphIndices"), (Array(Const(DWRITE_SHAPING_GLYPH_PROPERTIES), "glyphCount"), "glyphProps"), (UINT32, "glyphCount"), (ObjPointer(IDWriteFontFace), "fontFace"), (FLOAT, "fontEmSize"), (BOOL, "isSideways"), (BOOL, "isRightToLeft"), (Pointer(Const(DWRITE_SCRIPT_ANALYSIS)), "scriptAnalysis"), (LPCWSTR, "localeName"), (Array(Pointer(Const(DWRITE_TYPOGRAPHIC_FEATURES)), "featureRanges"), "features"), (Array(Const(UINT32), "featureRanges"), "featureRangeLengths"), (UINT32, "featureRanges"), Out(Array(FLOAT, "glyphCount"), "glyphAdvances"), Out(Array(DWRITE_GLYPH_OFFSET, "glyphCount"), "glyphOffsets")]),
+ StdMethod(HRESULT, "GetGdiCompatibleGlyphPlacements", [(String(Const(WCHAR), "textLength", wide=True), "textString"), (Array(Const(UINT16), "textLength"), "clusterMap"), (Array(DWRITE_SHAPING_TEXT_PROPERTIES, "textLength"), "textProps"), (UINT32, "textLength"), (Array(Const(UINT16), "glyphCount"), "glyphIndices"), (Array(Const(DWRITE_SHAPING_GLYPH_PROPERTIES), "glyphCount"), "glyphProps"), (UINT32, "glyphCount"), (ObjPointer(IDWriteFontFace), "fontFace"), (FLOAT, "fontEmSize"), (FLOAT, "pixelsPerDip"), (Pointer(Const(DWRITE_MATRIX)), "transform"), (BOOL, "useGdiNatural"), (BOOL, "isSideways"), (BOOL, "isRightToLeft"), (Pointer(Const(DWRITE_SCRIPT_ANALYSIS)), "scriptAnalysis"), (LPCWSTR, "localeName"), (Array(Pointer(Const(DWRITE_TYPOGRAPHIC_FEATURES)), "featureRanges"), "features"), (Array(Const(UINT32), "featureRanges"), "featureRangeLengths"), (UINT32, "featureRanges"), Out(Array(FLOAT, "glyphCount"), "glyphAdvances"), Out(Array(DWRITE_GLYPH_OFFSET, "glyphCount"), "glyphOffsets")]),
]
DWRITE_GLYPH_RUN = Struct("DWRITE_GLYPH_RUN", [
@@ -567,8 +567,8 @@ DWRITE_GLYPH_RUN = Struct("DWRITE_GLYPH_RUN", [
])
DWRITE_GLYPH_RUN_DESCRIPTION = Struct("DWRITE_GLYPH_RUN_DESCRIPTION", [
- (Pointer(Const(WCHAR)), "localeName"),
- (Pointer(Const(WCHAR)), "string"),
+ (PCWSTR, "localeName"),
+ (String(Const(WCHAR), "{self}.stringLength", wide=True), "string"),
(UINT32, "stringLength"),
(Pointer(Const(UINT16)), "clusterMap"),
(UINT32, "textPosition"),
@@ -581,7 +581,7 @@ DWRITE_UNDERLINE = Struct("DWRITE_UNDERLINE", [
(FLOAT, "runHeight"),
(DWRITE_READING_DIRECTION, "readingDirection"),
(DWRITE_FLOW_DIRECTION, "flowDirection"),
- (Pointer(Const(WCHAR)), "localeName"),
+ (PCWSTR, "localeName"),
(DWRITE_MEASURING_MODE, "measuringMode"),
])
@@ -591,7 +591,7 @@ DWRITE_STRIKETHROUGH = Struct("DWRITE_STRIKETHROUGH", [
(FLOAT, "offset"),
(DWRITE_READING_DIRECTION, "readingDirection"),
(DWRITE_FLOW_DIRECTION, "flowDirection"),
- (Pointer(Const(WCHAR)), "localeName"),
+ (PCWSTR, "localeName"),
(DWRITE_MEASURING_MODE, "measuringMode"),
])
@@ -670,14 +670,14 @@ IDWriteTextRenderer.methods += [
StdMethod(HRESULT, "DrawGlyphRun", [(OpaquePointer(Void), "clientDrawingContext"), (FLOAT, "baselineOriginX"), (FLOAT, "baselineOriginY"), (DWRITE_MEASURING_MODE, "measuringMode"), (Pointer(Const(DWRITE_GLYPH_RUN)), "glyphRun"), (Pointer(Const(DWRITE_GLYPH_RUN_DESCRIPTION)), "glyphRunDescription"), (ObjPointer(IUnknown), "clientDrawingEffect")]),
StdMethod(HRESULT, "DrawUnderline", [(OpaquePointer(Void), "clientDrawingContext"), (FLOAT, "baselineOriginX"), (FLOAT, "baselineOriginY"), (Pointer(Const(DWRITE_UNDERLINE)), "underline"), (ObjPointer(IUnknown), "clientDrawingEffect")]),
StdMethod(HRESULT, "DrawStrikethrough", [(OpaquePointer(Void), "clientDrawingContext"), (FLOAT, "baselineOriginX"), (FLOAT, "baselineOriginY"), (Pointer(Const(DWRITE_STRIKETHROUGH)), "strikethrough"), (ObjPointer(IUnknown), "clientDrawingEffect")]),
- StdMethod(HRESULT, "DrawInlineObject", [(OpaquePointer(Void), "clientDrawingContext"), (FLOAT, "originX"), (FLOAT, "originY"), (ObjPointer(IDWriteInlineObject), "inlineObject"), (BOOL, "isSideways"), (BOOL, "isRightToLeft"), (ObjPointer(IUnknown), "clientDrawingEffect")]),
+ StdMethod(HRESULT, "DrawInlineObject", [(OpaquePointer(Void), "clientDrawingContext"), (FLOAT, "originX"), (FLOAT, "originY"), (OpaquePointer(IDWriteInlineObject), "inlineObject"), (BOOL, "isSideways"), (BOOL, "isRightToLeft"), (ObjPointer(IUnknown), "clientDrawingEffect")]),
]
IDWriteTextLayout.methods += [
StdMethod(HRESULT, "SetMaxWidth", [(FLOAT, "maxWidth")]),
StdMethod(HRESULT, "SetMaxHeight", [(FLOAT, "maxHeight")]),
StdMethod(HRESULT, "SetFontCollection", [(ObjPointer(IDWriteFontCollection), "fontCollection"), (DWRITE_TEXT_RANGE, "textRange")]),
- StdMethod(HRESULT, "SetFontFamilyName", [(Pointer(Const(WCHAR)), "fontFamilyName"), (DWRITE_TEXT_RANGE, "textRange")]),
+ StdMethod(HRESULT, "SetFontFamilyName", [(PCWSTR, "fontFamilyName"), (DWRITE_TEXT_RANGE, "textRange")]),
StdMethod(HRESULT, "SetFontWeight", [(DWRITE_FONT_WEIGHT, "fontWeight"), (DWRITE_TEXT_RANGE, "textRange")]),
StdMethod(HRESULT, "SetFontStyle", [(DWRITE_FONT_STYLE, "fontStyle"), (DWRITE_TEXT_RANGE, "textRange")]),
StdMethod(HRESULT, "SetFontStretch", [(DWRITE_FONT_STRETCH, "fontStretch"), (DWRITE_TEXT_RANGE, "textRange")]),
@@ -685,9 +685,9 @@ IDWriteTextLayout.methods += [
StdMethod(HRESULT, "SetUnderline", [(BOOL, "hasUnderline"), (DWRITE_TEXT_RANGE, "textRange")]),
StdMethod(HRESULT, "SetStrikethrough", [(BOOL, "hasStrikethrough"), (DWRITE_TEXT_RANGE, "textRange")]),
StdMethod(HRESULT, "SetDrawingEffect", [(ObjPointer(IUnknown), "drawingEffect"), (DWRITE_TEXT_RANGE, "textRange")]),
- StdMethod(HRESULT, "SetInlineObject", [(ObjPointer(IDWriteInlineObject), "inlineObject"), (DWRITE_TEXT_RANGE, "textRange")]),
+ StdMethod(HRESULT, "SetInlineObject", [(OpaquePointer(IDWriteInlineObject), "inlineObject"), (DWRITE_TEXT_RANGE, "textRange")]),
StdMethod(HRESULT, "SetTypography", [(ObjPointer(IDWriteTypography), "typography"), (DWRITE_TEXT_RANGE, "textRange")]),
- StdMethod(HRESULT, "SetLocaleName", [(Pointer(Const(WCHAR)), "localeName"), (DWRITE_TEXT_RANGE, "textRange")]),
+ StdMethod(HRESULT, "SetLocaleName", [(PCWSTR, "localeName"), (DWRITE_TEXT_RANGE, "textRange")]),
StdMethod(FLOAT, "GetMaxWidth", []),
StdMethod(FLOAT, "GetMaxHeight", []),
StdMethod(HRESULT, "GetFontCollection", [(UINT32, "currentPosition"), Out(Pointer(ObjPointer(IDWriteFontCollection)), "fontCollection"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
@@ -700,7 +700,7 @@ IDWriteTextLayout.methods += [
StdMethod(HRESULT, "GetUnderline", [(UINT32, "currentPosition"), Out(Pointer(BOOL), "hasUnderline"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
StdMethod(HRESULT, "GetStrikethrough", [(UINT32, "currentPosition"), Out(Pointer(BOOL), "hasStrikethrough"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
StdMethod(HRESULT, "GetDrawingEffect", [(UINT32, "currentPosition"), Out(Pointer(ObjPointer(IUnknown)), "drawingEffect"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
- StdMethod(HRESULT, "GetInlineObject", [(UINT32, "currentPosition"), Out(Pointer(ObjPointer(IDWriteInlineObject)), "inlineObject"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
+ StdMethod(HRESULT, "GetInlineObject", [(UINT32, "currentPosition"), Out(Pointer(OpaquePointer(IDWriteInlineObject)), "inlineObject"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
StdMethod(HRESULT, "GetTypography", [(UINT32, "currentPosition"), Out(Pointer(ObjPointer(IDWriteTypography)), "typography"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
StdMethod(HRESULT, "GetLocaleNameLength", [(UINT32, "currentPosition"), Out(Pointer(UINT32), "nameLength"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
StdMethod(HRESULT, "GetLocaleName", [(UINT32, "currentPosition"), Out(Pointer(WCHAR), "localeName"), (UINT32, "nameSize"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
@@ -750,7 +750,7 @@ IDWriteFactory.methods += [
StdMethod(HRESULT, "CreateCustomFontCollection", [(ObjPointer(IDWriteFontCollectionLoader), "collectionLoader"), (OpaquePointer(Const(Void)), "collectionKey"), (UINT32, "collectionKeySize"), Out(Pointer(ObjPointer(IDWriteFontCollection)), "fontCollection")]),
StdMethod(HRESULT, "RegisterFontCollectionLoader", [(ObjPointer(IDWriteFontCollectionLoader), "fontCollectionLoader")]),
StdMethod(HRESULT, "UnregisterFontCollectionLoader", [(ObjPointer(IDWriteFontCollectionLoader), "fontCollectionLoader")]),
- StdMethod(HRESULT, "CreateFontFileReference", [(Pointer(Const(WCHAR)), "filePath"), (Pointer(Const(FILETIME)), "lastWriteTime"), Out(Pointer(ObjPointer(IDWriteFontFile)), "fontFile")]),
+ StdMethod(HRESULT, "CreateFontFileReference", [(PCWSTR, "filePath"), (Pointer(Const(FILETIME)), "lastWriteTime"), Out(Pointer(ObjPointer(IDWriteFontFile)), "fontFile")]),
StdMethod(HRESULT, "CreateCustomFontFileReference", [(OpaquePointer(Const(Void)), "fontFileReferenceKey"), (UINT32, "fontFileReferenceKeySize"), (ObjPointer(IDWriteFontFileLoader), "fontFileLoader"), Out(Pointer(ObjPointer(IDWriteFontFile)), "fontFile")]),
StdMethod(HRESULT, "CreateFontFace", [(DWRITE_FONT_FACE_TYPE, "fontFaceType"), (UINT32, "numberOfFiles"), (Array(Const(ObjPointer(IDWriteFontFile)), "numberOfFiles"), "fontFiles"), (UINT32, "faceIndex"), (DWRITE_FONT_SIMULATIONS, "fontFaceSimulationFlags"), Out(Pointer(ObjPointer(IDWriteFontFace)), "fontFace")]),
StdMethod(HRESULT, "CreateRenderingParams", [Out(Pointer(ObjPointer(IDWriteRenderingParams)), "renderingParams")]),
@@ -758,14 +758,14 @@ IDWriteFactory.methods += [
StdMethod(HRESULT, "CreateCustomRenderingParams", [(FLOAT, "gamma"), (FLOAT, "enhancedContrast"), (FLOAT, "clearTypeLevel"), (DWRITE_PIXEL_GEOMETRY, "pixelGeometry"), (DWRITE_RENDERING_MODE, "renderingMode"), Out(Pointer(ObjPointer(IDWriteRenderingParams)), "renderingParams")]),
StdMethod(HRESULT, "RegisterFontFileLoader", [(ObjPointer(IDWriteFontFileLoader), "fontFileLoader")]),
StdMethod(HRESULT, "UnregisterFontFileLoader", [(ObjPointer(IDWriteFontFileLoader), "fontFileLoader")]),
- StdMethod(HRESULT, "CreateTextFormat", [(Pointer(Const(WCHAR)), "fontFamilyName"), (ObjPointer(IDWriteFontCollection), "fontCollection"), (DWRITE_FONT_WEIGHT, "fontWeight"), (DWRITE_FONT_STYLE, "fontStyle"), (DWRITE_FONT_STRETCH, "fontStretch"), (FLOAT, "fontSize"), (Pointer(Const(WCHAR)), "localeName"), Out(Pointer(ObjPointer(IDWriteTextFormat)), "textFormat")]),
+ StdMethod(HRESULT, "CreateTextFormat", [(PCWSTR, "fontFamilyName"), (ObjPointer(IDWriteFontCollection), "fontCollection"), (DWRITE_FONT_WEIGHT, "fontWeight"), (DWRITE_FONT_STYLE, "fontStyle"), (DWRITE_FONT_STRETCH, "fontStretch"), (FLOAT, "fontSize"), (PCWSTR, "localeName"), Out(Pointer(ObjPointer(IDWriteTextFormat)), "textFormat")]),
StdMethod(HRESULT, "CreateTypography", [Out(Pointer(ObjPointer(IDWriteTypography)), "typography")]),
StdMethod(HRESULT, "GetGdiInterop", [Out(Pointer(ObjPointer(IDWriteGdiInterop)), "gdiInterop")]),
- StdMethod(HRESULT, "CreateTextLayout", [(Pointer(Const(WCHAR)), "string"), (UINT32, "stringLength"), (ObjPointer(IDWriteTextFormat), "textFormat"), (FLOAT, "maxWidth"), (FLOAT, "maxHeight"), Out(Pointer(ObjPointer(IDWriteTextLayout)), "textLayout")]),
- StdMethod(HRESULT, "CreateGdiCompatibleTextLayout", [(Pointer(Const(WCHAR)), "string"), (UINT32, "stringLength"), (ObjPointer(IDWriteTextFormat), "textFormat"), (FLOAT, "layoutWidth"), (FLOAT, "layoutHeight"), (FLOAT, "pixelsPerDip"), (Pointer(Const(DWRITE_MATRIX)), "transform"), (BOOL, "useGdiNatural"), Out(Pointer(ObjPointer(IDWriteTextLayout)), "textLayout")]),
- StdMethod(HRESULT, "CreateEllipsisTrimmingSign", [(ObjPointer(IDWriteTextFormat), "textFormat"), Out(Pointer(ObjPointer(IDWriteInlineObject)), "trimmingSign")]),
+ StdMethod(HRESULT, "CreateTextLayout", [(String(Const(WCHAR), "stringLength", wide=True), "string"), (UINT32, "stringLength"), (ObjPointer(IDWriteTextFormat), "textFormat"), (FLOAT, "maxWidth"), (FLOAT, "maxHeight"), Out(Pointer(ObjPointer(IDWriteTextLayout)), "textLayout")]),
+ StdMethod(HRESULT, "CreateGdiCompatibleTextLayout", [(String(Const(WCHAR), "stringLength", wide=True), "string"), (UINT32, "stringLength"), (ObjPointer(IDWriteTextFormat), "textFormat"), (FLOAT, "layoutWidth"), (FLOAT, "layoutHeight"), (FLOAT, "pixelsPerDip"), (Pointer(Const(DWRITE_MATRIX)), "transform"), (BOOL, "useGdiNatural"), Out(Pointer(ObjPointer(IDWriteTextLayout)), "textLayout")]),
+ StdMethod(HRESULT, "CreateEllipsisTrimmingSign", [(ObjPointer(IDWriteTextFormat), "textFormat"), Out(Pointer(OpaquePointer(IDWriteInlineObject)), "trimmingSign")]),
StdMethod(HRESULT, "CreateTextAnalyzer", [Out(Pointer(ObjPointer(IDWriteTextAnalyzer)), "textAnalyzer")]),
- StdMethod(HRESULT, "CreateNumberSubstitution", [(DWRITE_NUMBER_SUBSTITUTION_METHOD, "substitutionMethod"), (Pointer(Const(WCHAR)), "localeName"), (BOOL, "ignoreUserOverride"), Out(Pointer(ObjPointer(IDWriteNumberSubstitution)), "numberSubstitution")]),
+ StdMethod(HRESULT, "CreateNumberSubstitution", [(DWRITE_NUMBER_SUBSTITUTION_METHOD, "substitutionMethod"), (PCWSTR, "localeName"), (BOOL, "ignoreUserOverride"), Out(Pointer(ObjPointer(IDWriteNumberSubstitution)), "numberSubstitution")]),
StdMethod(HRESULT, "CreateGlyphRunAnalysis", [(Pointer(Const(DWRITE_GLYPH_RUN)), "glyphRun"), (FLOAT, "pixelsPerDip"), (Pointer(Const(DWRITE_MATRIX)), "transform"), (DWRITE_RENDERING_MODE, "renderingMode"), (DWRITE_MEASURING_MODE, "measuringMode"), (FLOAT, "baselineOriginX"), (FLOAT, "baselineOriginY"), Out(Pointer(ObjPointer(IDWriteGlyphRunAnalysis)), "glyphRunAnalysis")]),
]
@@ -776,3 +776,594 @@ dwrite.addInterfaces([
dwrite.addFunctions([
StdFunction(HRESULT, "DWriteCreateFactory", [(DWRITE_FACTORY_TYPE, "factoryType"), (REFIID, "iid"), Out(Pointer(ObjPointer(IUnknown)), "factory")]),
])
+
+
+#
+# dwrite_1
+#
+
+
+DWRITE_PANOSE_FAMILY = Enum("DWRITE_PANOSE_FAMILY", [
+ "DWRITE_PANOSE_FAMILY_ANY",
+ "DWRITE_PANOSE_FAMILY_NO_FIT",
+ "DWRITE_PANOSE_FAMILY_TEXT_DISPLAY",
+ "DWRITE_PANOSE_FAMILY_SCRIPT",
+ "DWRITE_PANOSE_FAMILY_DECORATIVE",
+ "DWRITE_PANOSE_FAMILY_SYMBOL",
+ "DWRITE_PANOSE_FAMILY_PICTORIAL",
+])
+
+DWRITE_PANOSE_SERIF_STYLE = Enum("DWRITE_PANOSE_SERIF_STYLE", [
+ "DWRITE_PANOSE_SERIF_STYLE_ANY",
+ "DWRITE_PANOSE_SERIF_STYLE_NO_FIT",
+ "DWRITE_PANOSE_SERIF_STYLE_COVE",
+ "DWRITE_PANOSE_SERIF_STYLE_OBTUSE_COVE",
+ "DWRITE_PANOSE_SERIF_STYLE_SQUARE_COVE",
+ "DWRITE_PANOSE_SERIF_STYLE_OBTUSE_SQUARE_COVE",
+ "DWRITE_PANOSE_SERIF_STYLE_SQUARE",
+ "DWRITE_PANOSE_SERIF_STYLE_THIN",
+ "DWRITE_PANOSE_SERIF_STYLE_OVAL",
+ "DWRITE_PANOSE_SERIF_STYLE_EXAGGERATED",
+ "DWRITE_PANOSE_SERIF_STYLE_TRIANGLE",
+ "DWRITE_PANOSE_SERIF_STYLE_NORMAL_SANS",
+ "DWRITE_PANOSE_SERIF_STYLE_OBTUSE_SANS",
+ "DWRITE_PANOSE_SERIF_STYLE_PERPENDICULAR_SANS",
+ "DWRITE_PANOSE_SERIF_STYLE_FLARED",
+ "DWRITE_PANOSE_SERIF_STYLE_ROUNDED",
+ "DWRITE_PANOSE_SERIF_STYLE_SCRIPT",
+ "DWRITE_PANOSE_SERIF_STYLE_PERP_SANS",
+ "DWRITE_PANOSE_SERIF_STYLE_BONE",
+])
+
+DWRITE_PANOSE_WEIGHT = Enum("DWRITE_PANOSE_WEIGHT", [
+ "DWRITE_PANOSE_WEIGHT_ANY",
+ "DWRITE_PANOSE_WEIGHT_NO_FIT",
+ "DWRITE_PANOSE_WEIGHT_VERY_LIGHT",
+ "DWRITE_PANOSE_WEIGHT_LIGHT",
+ "DWRITE_PANOSE_WEIGHT_THIN",
+ "DWRITE_PANOSE_WEIGHT_BOOK",
+ "DWRITE_PANOSE_WEIGHT_MEDIUM",
+ "DWRITE_PANOSE_WEIGHT_DEMI",
+ "DWRITE_PANOSE_WEIGHT_BOLD",
+ "DWRITE_PANOSE_WEIGHT_HEAVY",
+ "DWRITE_PANOSE_WEIGHT_BLACK",
+ "DWRITE_PANOSE_WEIGHT_EXTRA_BLACK",
+ "DWRITE_PANOSE_WEIGHT_NORD",
+])
+
+DWRITE_PANOSE_PROPORTION = Enum("DWRITE_PANOSE_PROPORTION", [
+ "DWRITE_PANOSE_PROPORTION_ANY",
+ "DWRITE_PANOSE_PROPORTION_NO_FIT",
+ "DWRITE_PANOSE_PROPORTION_OLD_STYLE",
+ "DWRITE_PANOSE_PROPORTION_MODERN",
+ "DWRITE_PANOSE_PROPORTION_EVEN_WIDTH",
+ "DWRITE_PANOSE_PROPORTION_EXPANDED",
+ "DWRITE_PANOSE_PROPORTION_CONDENSED",
+ "DWRITE_PANOSE_PROPORTION_VERY_EXPANDED",
+ "DWRITE_PANOSE_PROPORTION_VERY_CONDENSED",
+ "DWRITE_PANOSE_PROPORTION_MONOSPACED",
+])
+
+DWRITE_PANOSE_CONTRAST = Enum("DWRITE_PANOSE_CONTRAST", [
+ "DWRITE_PANOSE_CONTRAST_ANY",
+ "DWRITE_PANOSE_CONTRAST_NO_FIT",
+ "DWRITE_PANOSE_CONTRAST_NONE",
+ "DWRITE_PANOSE_CONTRAST_VERY_LOW",
+ "DWRITE_PANOSE_CONTRAST_LOW",
+ "DWRITE_PANOSE_CONTRAST_MEDIUM_LOW",
+ "DWRITE_PANOSE_CONTRAST_MEDIUM",
+ "DWRITE_PANOSE_CONTRAST_MEDIUM_HIGH",
+ "DWRITE_PANOSE_CONTRAST_HIGH",
+ "DWRITE_PANOSE_CONTRAST_VERY_HIGH",
+ "DWRITE_PANOSE_CONTRAST_HORIZONTAL_LOW",
+ "DWRITE_PANOSE_CONTRAST_HORIZONTAL_MEDIUM",
+ "DWRITE_PANOSE_CONTRAST_HORIZONTAL_HIGH",
+ "DWRITE_PANOSE_CONTRAST_BROKEN",
+])
+
+DWRITE_PANOSE_STROKE_VARIATION = Enum("DWRITE_PANOSE_STROKE_VARIATION", [
+ "DWRITE_PANOSE_STROKE_VARIATION_ANY",
+ "DWRITE_PANOSE_STROKE_VARIATION_NO_FIT",
+ "DWRITE_PANOSE_STROKE_VARIATION_NO_VARIATION",
+ "DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_DIAGONAL",
+ "DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_TRANSITIONAL",
+ "DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_VERTICAL",
+ "DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_HORIZONTAL",
+ "DWRITE_PANOSE_STROKE_VARIATION_RAPID_VERTICAL",
+ "DWRITE_PANOSE_STROKE_VARIATION_RAPID_HORIZONTAL",
+ "DWRITE_PANOSE_STROKE_VARIATION_INSTANT_VERTICAL",
+ "DWRITE_PANOSE_STROKE_VARIATION_INSTANT_HORIZONTAL",
+])
+
+DWRITE_PANOSE_ARM_STYLE = Enum("DWRITE_PANOSE_ARM_STYLE", [
+ "DWRITE_PANOSE_ARM_STYLE_ANY",
+ "DWRITE_PANOSE_ARM_STYLE_NO_FIT",
+ "DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_HORIZONTAL",
+ "DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_WEDGE",
+ "DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_VERTICAL",
+ "DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_SINGLE_SERIF",
+ "DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_DOUBLE_SERIF",
+ "DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_HORIZONTAL",
+ "DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_WEDGE",
+ "DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_VERTICAL",
+ "DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_SINGLE_SERIF",
+ "DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_DOUBLE_SERIF",
+ "DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_HORZ",
+ "DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_VERT",
+ "DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_HORZ",
+ "DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_WEDGE",
+ "DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_VERT",
+ "DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_SINGLE_SERIF",
+ "DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_DOUBLE_SERIF",
+])
+
+DWRITE_PANOSE_LETTERFORM = Enum("DWRITE_PANOSE_LETTERFORM", [
+ "DWRITE_PANOSE_LETTERFORM_ANY",
+ "DWRITE_PANOSE_LETTERFORM_NO_FIT",
+ "DWRITE_PANOSE_LETTERFORM_NORMAL_CONTACT",
+ "DWRITE_PANOSE_LETTERFORM_NORMAL_WEIGHTED",
+ "DWRITE_PANOSE_LETTERFORM_NORMAL_BOXED",
+ "DWRITE_PANOSE_LETTERFORM_NORMAL_FLATTENED",
+ "DWRITE_PANOSE_LETTERFORM_NORMAL_ROUNDED",
+ "DWRITE_PANOSE_LETTERFORM_NORMAL_OFF_CENTER",
+ "DWRITE_PANOSE_LETTERFORM_NORMAL_SQUARE",
+ "DWRITE_PANOSE_LETTERFORM_OBLIQUE_CONTACT",
+ "DWRITE_PANOSE_LETTERFORM_OBLIQUE_WEIGHTED",
+ "DWRITE_PANOSE_LETTERFORM_OBLIQUE_BOXED",
+ "DWRITE_PANOSE_LETTERFORM_OBLIQUE_FLATTENED",
+ "DWRITE_PANOSE_LETTERFORM_OBLIQUE_ROUNDED",
+ "DWRITE_PANOSE_LETTERFORM_OBLIQUE_OFF_CENTER",
+ "DWRITE_PANOSE_LETTERFORM_OBLIQUE_SQUARE",
+])
+
+DWRITE_PANOSE_MIDLINE = Enum("DWRITE_PANOSE_MIDLINE", [
+ "DWRITE_PANOSE_MIDLINE_ANY",
+ "DWRITE_PANOSE_MIDLINE_NO_FIT",
+ "DWRITE_PANOSE_MIDLINE_STANDARD_TRIMMED",
+ "DWRITE_PANOSE_MIDLINE_STANDARD_POINTED",
+ "DWRITE_PANOSE_MIDLINE_STANDARD_SERIFED",
+ "DWRITE_PANOSE_MIDLINE_HIGH_TRIMMED",
+ "DWRITE_PANOSE_MIDLINE_HIGH_POINTED",
+ "DWRITE_PANOSE_MIDLINE_HIGH_SERIFED",
+ "DWRITE_PANOSE_MIDLINE_CONSTANT_TRIMMED",
+ "DWRITE_PANOSE_MIDLINE_CONSTANT_POINTED",
+ "DWRITE_PANOSE_MIDLINE_CONSTANT_SERIFED",
+ "DWRITE_PANOSE_MIDLINE_LOW_TRIMMED",
+ "DWRITE_PANOSE_MIDLINE_LOW_POINTED",
+ "DWRITE_PANOSE_MIDLINE_LOW_SERIFED",
+])
+
+DWRITE_PANOSE_XHEIGHT = Enum("DWRITE_PANOSE_XHEIGHT", [
+ "DWRITE_PANOSE_XHEIGHT_ANY",
+ "DWRITE_PANOSE_XHEIGHT_NO_FIT",
+ "DWRITE_PANOSE_XHEIGHT_CONSTANT_SMALL",
+ "DWRITE_PANOSE_XHEIGHT_CONSTANT_STANDARD",
+ "DWRITE_PANOSE_XHEIGHT_CONSTANT_LARGE",
+ "DWRITE_PANOSE_XHEIGHT_DUCKING_SMALL",
+ "DWRITE_PANOSE_XHEIGHT_DUCKING_STANDARD",
+ "DWRITE_PANOSE_XHEIGHT_DUCKING_LARGE",
+ "DWRITE_PANOSE_XHEIGHT_CONSTANT_STD",
+ "DWRITE_PANOSE_XHEIGHT_DUCKING_STD",
+])
+
+DWRITE_PANOSE_TOOL_KIND = Enum("DWRITE_PANOSE_TOOL_KIND", [
+ "DWRITE_PANOSE_TOOL_KIND_ANY",
+ "DWRITE_PANOSE_TOOL_KIND_NO_FIT",
+ "DWRITE_PANOSE_TOOL_KIND_FLAT_NIB",
+ "DWRITE_PANOSE_TOOL_KIND_PRESSURE_POINT",
+ "DWRITE_PANOSE_TOOL_KIND_ENGRAVED",
+ "DWRITE_PANOSE_TOOL_KIND_BALL",
+ "DWRITE_PANOSE_TOOL_KIND_BRUSH",
+ "DWRITE_PANOSE_TOOL_KIND_ROUGH",
+ "DWRITE_PANOSE_TOOL_KIND_FELT_PEN_BRUSH_TIP",
+ "DWRITE_PANOSE_TOOL_KIND_WILD_BRUSH",
+])
+
+DWRITE_PANOSE_SPACING = Enum("DWRITE_PANOSE_SPACING", [
+ "DWRITE_PANOSE_SPACING_ANY",
+ "DWRITE_PANOSE_SPACING_NO_FIT",
+ "DWRITE_PANOSE_SPACING_PROPORTIONAL_SPACED",
+ "DWRITE_PANOSE_SPACING_MONOSPACED",
+])
+
+DWRITE_PANOSE_ASPECT_RATIO = Enum("DWRITE_PANOSE_ASPECT_RATIO", [
+ "DWRITE_PANOSE_ASPECT_RATIO_ANY",
+ "DWRITE_PANOSE_ASPECT_RATIO_NO_FIT",
+ "DWRITE_PANOSE_ASPECT_RATIO_VERY_CONDENSED",
+ "DWRITE_PANOSE_ASPECT_RATIO_CONDENSED",
+ "DWRITE_PANOSE_ASPECT_RATIO_NORMAL",
+ "DWRITE_PANOSE_ASPECT_RATIO_EXPANDED",
+ "DWRITE_PANOSE_ASPECT_RATIO_VERY_EXPANDED",
+])
+
+DWRITE_PANOSE_SCRIPT_TOPOLOGY = Enum("DWRITE_PANOSE_SCRIPT_TOPOLOGY", [
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_ANY",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_NO_FIT",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_ROMAN_DISCONNECTED",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_ROMAN_TRAILING",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_ROMAN_CONNECTED",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_CURSIVE_DISCONNECTED",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_CURSIVE_TRAILING",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_CURSIVE_CONNECTED",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_BLACKLETTER_DISCONNECTED",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_BLACKLETTER_TRAILING",
+ "DWRITE_PANOSE_SCRIPT_TOPOLOGY_BLACKLETTER_CONNECTED",
+])
+
+DWRITE_PANOSE_SCRIPT_FORM = Enum("DWRITE_PANOSE_SCRIPT_FORM", [
+ "DWRITE_PANOSE_SCRIPT_FORM_ANY",
+ "DWRITE_PANOSE_SCRIPT_FORM_NO_FIT",
+ "DWRITE_PANOSE_SCRIPT_FORM_UPRIGHT_NO_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_UPRIGHT_SOME_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_UPRIGHT_MORE_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_UPRIGHT_EXTREME_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_OBLIQUE_NO_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_OBLIQUE_SOME_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_OBLIQUE_MORE_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_OBLIQUE_EXTREME_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_EXAGGERATED_NO_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_EXAGGERATED_SOME_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_EXAGGERATED_MORE_WRAPPING",
+ "DWRITE_PANOSE_SCRIPT_FORM_EXAGGERATED_EXTREME_WRAPPING",
+])
+
+DWRITE_PANOSE_FINIALS = Enum("DWRITE_PANOSE_FINIALS", [
+ "DWRITE_PANOSE_FINIALS_ANY",
+ "DWRITE_PANOSE_FINIALS_NO_FIT",
+ "DWRITE_PANOSE_FINIALS_NONE_NO_LOOPS",
+ "DWRITE_PANOSE_FINIALS_NONE_CLOSED_LOOPS",
+ "DWRITE_PANOSE_FINIALS_NONE_OPEN_LOOPS",
+ "DWRITE_PANOSE_FINIALS_SHARP_NO_LOOPS",
+ "DWRITE_PANOSE_FINIALS_SHARP_CLOSED_LOOPS",
+ "DWRITE_PANOSE_FINIALS_SHARP_OPEN_LOOPS",
+ "DWRITE_PANOSE_FINIALS_TAPERED_NO_LOOPS",
+ "DWRITE_PANOSE_FINIALS_TAPERED_CLOSED_LOOPS",
+ "DWRITE_PANOSE_FINIALS_TAPERED_OPEN_LOOPS",
+ "DWRITE_PANOSE_FINIALS_ROUND_NO_LOOPS",
+ "DWRITE_PANOSE_FINIALS_ROUND_CLOSED_LOOPS",
+ "DWRITE_PANOSE_FINIALS_ROUND_OPEN_LOOPS",
+])
+
+DWRITE_PANOSE_XASCENT = Enum("DWRITE_PANOSE_XASCENT", [
+ "DWRITE_PANOSE_XASCENT_ANY",
+ "DWRITE_PANOSE_XASCENT_NO_FIT",
+ "DWRITE_PANOSE_XASCENT_VERY_LOW",
+ "DWRITE_PANOSE_XASCENT_LOW",
+ "DWRITE_PANOSE_XASCENT_MEDIUM",
+ "DWRITE_PANOSE_XASCENT_HIGH",
+ "DWRITE_PANOSE_XASCENT_VERY_HIGH",
+])
+
+DWRITE_PANOSE_DECORATIVE_CLASS = Enum("DWRITE_PANOSE_DECORATIVE_CLASS", [
+ "DWRITE_PANOSE_DECORATIVE_CLASS_ANY",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_NO_FIT",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_DERIVATIVE",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_NONSTANDARD_TOPOLOGY",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_NONSTANDARD_ELEMENTS",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_NONSTANDARD_ASPECT",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_INITIALS",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_CARTOON",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_PICTURE_STEMS",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_ORNAMENTED",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_TEXT_AND_BACKGROUND",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_COLLAGE",
+ "DWRITE_PANOSE_DECORATIVE_CLASS_MONTAGE",
+])
+
+DWRITE_PANOSE_ASPECT = Enum("DWRITE_PANOSE_ASPECT", [
+ "DWRITE_PANOSE_ASPECT_ANY",
+ "DWRITE_PANOSE_ASPECT_NO_FIT",
+ "DWRITE_PANOSE_ASPECT_SUPER_CONDENSED",
+ "DWRITE_PANOSE_ASPECT_VERY_CONDENSED",
+ "DWRITE_PANOSE_ASPECT_CONDENSED",
+ "DWRITE_PANOSE_ASPECT_NORMAL",
+ "DWRITE_PANOSE_ASPECT_EXTENDED",
+ "DWRITE_PANOSE_ASPECT_VERY_EXTENDED",
+ "DWRITE_PANOSE_ASPECT_SUPER_EXTENDED",
+ "DWRITE_PANOSE_ASPECT_MONOSPACED",
+])
+
+DWRITE_PANOSE_FILL = Enum("DWRITE_PANOSE_FILL", [
+ "DWRITE_PANOSE_FILL_ANY",
+ "DWRITE_PANOSE_FILL_NO_FIT",
+ "DWRITE_PANOSE_FILL_STANDARD_SOLID_FILL",
+ "DWRITE_PANOSE_FILL_NO_FILL",
+ "DWRITE_PANOSE_FILL_PATTERNED_FILL",
+ "DWRITE_PANOSE_FILL_COMPLEX_FILL",
+ "DWRITE_PANOSE_FILL_SHAPED_FILL",
+ "DWRITE_PANOSE_FILL_DRAWN_DISTRESSED",
+])
+
+DWRITE_PANOSE_LINING = Enum("DWRITE_PANOSE_LINING", [
+ "DWRITE_PANOSE_LINING_ANY",
+ "DWRITE_PANOSE_LINING_NO_FIT",
+ "DWRITE_PANOSE_LINING_NONE",
+ "DWRITE_PANOSE_LINING_INLINE",
+ "DWRITE_PANOSE_LINING_OUTLINE",
+ "DWRITE_PANOSE_LINING_ENGRAVED",
+ "DWRITE_PANOSE_LINING_SHADOW",
+ "DWRITE_PANOSE_LINING_RELIEF",
+ "DWRITE_PANOSE_LINING_BACKDROP",
+])
+
+DWRITE_PANOSE_DECORATIVE_TOPOLOGY = Enum("DWRITE_PANOSE_DECORATIVE_TOPOLOGY", [
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_ANY",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_NO_FIT",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_STANDARD",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_SQUARE",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_MULTIPLE_SEGMENT",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_ART_DECO",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_UNEVEN_WEIGHTING",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_DIVERSE_ARMS",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_DIVERSE_FORMS",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_LOMBARDIC_FORMS",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_UPPER_CASE_IN_LOWER_CASE",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_IMPLIED_TOPOLOGY",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_HORSESHOE_E_AND_A",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_CURSIVE",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_BLACKLETTER",
+ "DWRITE_PANOSE_DECORATIVE_TOPOLOGY_SWASH_VARIANCE",
+])
+
+DWRITE_PANOSE_CHARACTER_RANGES = Enum("DWRITE_PANOSE_CHARACTER_RANGES", [
+ "DWRITE_PANOSE_CHARACTER_RANGES_ANY",
+ "DWRITE_PANOSE_CHARACTER_RANGES_NO_FIT",
+ "DWRITE_PANOSE_CHARACTER_RANGES_EXTENDED_COLLECTION",
+ "DWRITE_PANOSE_CHARACTER_RANGES_LITERALS",
+ "DWRITE_PANOSE_CHARACTER_RANGES_NO_LOWER_CASE",
+ "DWRITE_PANOSE_CHARACTER_RANGES_SMALL_CAPS",
+])
+
+DWRITE_PANOSE_SYMBOL_KIND = Enum("DWRITE_PANOSE_SYMBOL_KIND", [
+ "DWRITE_PANOSE_SYMBOL_KIND_ANY",
+ "DWRITE_PANOSE_SYMBOL_KIND_NO_FIT",
+ "DWRITE_PANOSE_SYMBOL_KIND_MONTAGES",
+ "DWRITE_PANOSE_SYMBOL_KIND_PICTURES",
+ "DWRITE_PANOSE_SYMBOL_KIND_SHAPES",
+ "DWRITE_PANOSE_SYMBOL_KIND_SCIENTIFIC",
+ "DWRITE_PANOSE_SYMBOL_KIND_MUSIC",
+ "DWRITE_PANOSE_SYMBOL_KIND_EXPERT",
+ "DWRITE_PANOSE_SYMBOL_KIND_PATTERNS",
+ "DWRITE_PANOSE_SYMBOL_KIND_BOARDERS",
+ "DWRITE_PANOSE_SYMBOL_KIND_ICONS",
+ "DWRITE_PANOSE_SYMBOL_KIND_LOGOS",
+ "DWRITE_PANOSE_SYMBOL_KIND_INDUSTRY_SPECIFIC",
+])
+
+DWRITE_PANOSE_SYMBOL_ASPECT_RATIO = Enum("DWRITE_PANOSE_SYMBOL_ASPECT_RATIO", [
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_ANY",
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_NO_FIT",
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_NO_WIDTH",
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_EXCEPTIONALLY_WIDE",
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_SUPER_WIDE",
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_VERY_WIDE",
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_WIDE",
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_NORMAL",
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_NARROW",
+ "DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_VERY_NARROW",
+])
+
+DWRITE_OUTLINE_THRESHOLD = Enum("DWRITE_OUTLINE_THRESHOLD", [
+ "DWRITE_OUTLINE_THRESHOLD_ANTIALIASED",
+ "DWRITE_OUTLINE_THRESHOLD_ALIASED",
+])
+
+DWRITE_BASELINE = Enum("DWRITE_BASELINE", [
+ "DWRITE_BASELINE_DEFAULT",
+ "DWRITE_BASELINE_ROMAN",
+ "DWRITE_BASELINE_CENTRAL",
+ "DWRITE_BASELINE_MATH",
+ "DWRITE_BASELINE_HANGING",
+ "DWRITE_BASELINE_IDEOGRAPHIC_BOTTOM",
+ "DWRITE_BASELINE_IDEOGRAPHIC_TOP",
+ "DWRITE_BASELINE_MINIMUM",
+ "DWRITE_BASELINE_MAXIMUM",
+])
+
+DWRITE_VERTICAL_GLYPH_ORIENTATION = Enum("DWRITE_VERTICAL_GLYPH_ORIENTATION", [
+ "DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT",
+ "DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED",
+])
+
+DWRITE_GLYPH_ORIENTATION_ANGLE = Enum("DWRITE_GLYPH_ORIENTATION_ANGLE", [
+ "DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES",
+ "DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES",
+ "DWRITE_GLYPH_ORIENTATION_ANGLE_180_DEGREES",
+ "DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES",
+])
+
+DWRITE_FONT_METRICS1 = Struct("DWRITE_FONT_METRICS1", [
+ (INT16, "glyphBoxLeft"),
+ (INT16, "glyphBoxTop"),
+ (INT16, "glyphBoxRight"),
+ (INT16, "glyphBoxBottom"),
+ (INT16, "subscriptPositionX"),
+ (INT16, "subscriptPositionY"),
+ (INT16, "subscriptSizeX"),
+ (INT16, "subscriptSizeY"),
+ (INT16, "superscriptPositionX"),
+ (INT16, "superscriptPositionY"),
+ (INT16, "superscriptSizeX"),
+ (INT16, "superscriptSizeY"),
+ (BOOL, "hasTypographicMetrics"),
+])
+
+DWRITE_CARET_METRICS = Struct("DWRITE_CARET_METRICS", [
+ (INT16, "slopeRise"),
+ (INT16, "slopeRun"),
+ (INT16, "offset"),
+])
+
+DWRITE_UNICODE_RANGE = Struct("DWRITE_UNICODE_RANGE", [
+ (UINT32, "first"),
+ (UINT32, "last"),
+])
+
+DWRITE_SCRIPT_PROPERTIES = Struct("DWRITE_SCRIPT_PROPERTIES", [
+ (UINT32, "isoScriptCode"),
+ (UINT32, "isoScriptNumber"),
+ (UINT32, "clusterLookahead"),
+ (UINT32, "justificationCharacter"),
+ (UINT32, "restrictCaretToClusters"),
+ (UINT32, "usesWordDividers"),
+ (UINT32, "isDiscreteWriting"),
+ (UINT32, "isBlockWriting"),
+ (UINT32, "isDistributedWithinCluster"),
+ (UINT32, "isConnectedWriting"),
+ (UINT32, "isCursiveWriting"),
+ (UINT32, "reserved"),
+])
+
+DWRITE_JUSTIFICATION_OPPORTUNITY = Struct("DWRITE_JUSTIFICATION_OPPORTUNITY", [
+ (FLOAT, "expansionMinimum"),
+ (FLOAT, "expansionMaximum"),
+ (FLOAT, "compressionMaximum"),
+ (UINT32, "expansionPriority"),
+ (UINT32, "compressionPriority"),
+ (UINT32, "allowResidualExpansion"),
+ (UINT32, "allowResidualCompression"),
+ (UINT32, "applyToLeadingEdge"),
+ (UINT32, "applyToTrailingEdge"),
+ (UINT32, "reserved"),
+])
+
+IDWriteFactory1 = Interface("IDWriteFactory1", IDWriteFactory)
+IDWriteFontFace1 = Interface("IDWriteFontFace1", IDWriteFontFace)
+IDWriteFont1 = Interface("IDWriteFont1", IDWriteFont)
+IDWriteRenderingParams1 = Interface("IDWriteRenderingParams1", IDWriteRenderingParams)
+IDWriteTextAnalyzer1 = Interface("IDWriteTextAnalyzer1", IDWriteTextAnalyzer)
+IDWriteTextAnalysisSource1 = Interface("IDWriteTextAnalysisSource1", IDWriteTextAnalysisSource)
+IDWriteTextAnalysisSink1 = Interface("IDWriteTextAnalysisSink1", IDWriteTextAnalysisSink)
+IDWriteTextLayout1 = Interface("IDWriteTextLayout1", IDWriteTextLayout)
+IDWriteBitmapRenderTarget1 = Interface("IDWriteBitmapRenderTarget1", IDWriteBitmapRenderTarget)
+
+IDWriteFactory1.methods += [
+ StdMethod(HRESULT, "GetEudcFontCollection", [(Pointer(ObjPointer(IDWriteFontCollection)), "fontCollection"), (BOOL, "checkForUpdates")]),
+ StdMethod(HRESULT, "CreateCustomRenderingParams", [(FLOAT, "gamma"), (FLOAT, "enhancedContrast"), (FLOAT, "enhancedContrastGrayscale"), (FLOAT, "clearTypeLevel"), (DWRITE_PIXEL_GEOMETRY, "pixelGeometry"), (DWRITE_RENDERING_MODE, "renderingMode"), Out(Pointer(ObjPointer(IDWriteRenderingParams1)), "renderingParams")]),
+]
+
+IDWriteFontFace1.methods += [
+ StdMethod(Void, "GetMetrics", [Out(Pointer(DWRITE_FONT_METRICS1), "fontMetrics")]),
+ StdMethod(HRESULT, "GetGdiCompatibleMetrics", [(FLOAT, "emSize"), (FLOAT, "pixelsPerDip"), (Pointer(Const(DWRITE_MATRIX)), "transform"), Out(Pointer(DWRITE_FONT_METRICS1), "fontMetrics")]),
+ StdMethod(Void, "GetCaretMetrics", [Out(Pointer(DWRITE_CARET_METRICS), "caretMetrics")]),
+ StdMethod(HRESULT, "GetUnicodeRanges", [(UINT32, "maxRangeCount"), Out(Pointer(DWRITE_UNICODE_RANGE), "unicodeRanges"), Out(Pointer(UINT32), "actualRangeCount")]),
+ StdMethod(BOOL, "IsMonospacedFont", []),
+ StdMethod(HRESULT, "GetDesignGlyphAdvances", [(UINT32, "glyphCount"), (Pointer(Const(UINT16)), "glyphIndices"), Out(ObjPointer(INT32), "glyphAdvances"), (BOOL, "isSideways")]),
+ StdMethod(HRESULT, "GetGdiCompatibleGlyphAdvances", [(FLOAT, "emSize"), (FLOAT, "pixelsPerDip"), (Pointer(Const(DWRITE_MATRIX)), "transform"), (BOOL, "useGdiNatural"), (BOOL, "isSideways"), (UINT32, "glyphCount"), (Pointer(Const(UINT16)), "glyphIndices"), Out(ObjPointer(INT32), "glyphAdvances")]),
+ StdMethod(HRESULT, "GetKerningPairAdjustments", [(UINT32, "glyphCount"), (Pointer(Const(UINT16)), "glyphIndices"), Out(ObjPointer(INT32), "glyphAdvanceAdjustments")]),
+ StdMethod(BOOL, "HasKerningPairs", []),
+ StdMethod(HRESULT, "GetRecommendedRenderingMode", [(FLOAT, "fontEmSize"), (FLOAT, "dpiX"), (FLOAT, "dpiY"), (Pointer(Const(DWRITE_MATRIX)), "transform"), (BOOL, "isSideways"), (DWRITE_OUTLINE_THRESHOLD, "outlineThreshold"), (DWRITE_MEASURING_MODE, "measuringMode"), Out(Pointer(DWRITE_RENDERING_MODE), "renderingMode")]),
+ StdMethod(HRESULT, "GetVerticalGlyphVariants", [(UINT32, "glyphCount"), (Pointer(Const(UINT16)), "nominalGlyphIndices"), Out(Pointer(UINT16), "verticalGlyphIndices")]),
+ StdMethod(BOOL, "HasVerticalGlyphVariants", []),
+]
+
+
+DWRITE_PANOSE_TEXT = Struct("DWRITE_PANOSE_TEXT", [
+ (UINT8, "familyKind"),
+ (UINT8, "serifStyle"),
+ (UINT8, "weight"),
+ (UINT8, "proportion"),
+ (UINT8, "contrast"),
+ (UINT8, "strokeVariation"),
+ (UINT8, "armStyle"),
+ (UINT8, "letterform"),
+ (UINT8, "midline"),
+ (UINT8, "xHeight"),
+])
+
+DWRITE_PANOSE_SCRIPT = Struct("DWRITE_PANOSE_SCRIPT", [
+ (UINT8, "familyKind"),
+ (UINT8, "toolKind"),
+ (UINT8, "weight"),
+ (UINT8, "spacing"),
+ (UINT8, "aspectRatio"),
+ (UINT8, "contrast"),
+ (UINT8, "scriptTopology"),
+ (UINT8, "scriptForm"),
+ (UINT8, "finials"),
+ (UINT8, "xAscent"),
+])
+
+DWRITE_PANOSE_DECORATIVE = Struct("DWRITE_PANOSE_DECORATIVE", [
+ (UINT8, "familyKind"),
+ (UINT8, "decorativeClass"),
+ (UINT8, "weight"),
+ (UINT8, "aspect"),
+ (UINT8, "contrast"),
+ (UINT8, "serifVariant"),
+ (UINT8, "fill"),
+ (UINT8, "lining"),
+ (UINT8, "decorativeTopology"),
+ (UINT8, "characterRange"),
+])
+
+DWRITE_PANOSE_SYMBOL = Struct("DWRITE_PANOSE_SYMBOL", [
+ (UINT8, "familyKind"),
+ (UINT8, "symbolKind"),
+ (UINT8, "weight"),
+ (UINT8, "spacing"),
+ (UINT8, "aspectRatioAndContrast"),
+ (UINT8, "aspectRatio94"),
+ (UINT8, "aspectRatio119"),
+ (UINT8, "aspectRatio157"),
+ (UINT8, "aspectRatio163"),
+ (UINT8, "aspectRatio211"),
+])
+
+DWRITE_PANOSE = Struct("DWRITE_PANOSE", [
+ (UINT8, "familyKind"),
+ # FIXME
+])
+
+
+IDWriteFont1.methods += [
+ StdMethod(Void, "GetMetrics", [Out(Pointer(DWRITE_FONT_METRICS1), "fontMetrics")]),
+ StdMethod(Void, "GetPanose", [Out(OpaquePointer(DWRITE_PANOSE), "panose")]),
+ StdMethod(HRESULT, "GetUnicodeRanges", [(UINT32, "maxRangeCount"), Out(Pointer(DWRITE_UNICODE_RANGE), "unicodeRanges"), Out(Pointer(UINT32), "actualRangeCount")]),
+ StdMethod(BOOL, "IsMonospacedFont", []),
+]
+
+IDWriteRenderingParams1.methods += [
+ StdMethod(FLOAT, "GetGrayscaleEnhancedContrast", []),
+]
+
+IDWriteTextAnalyzer1.methods += [
+ StdMethod(HRESULT, "ApplyCharacterSpacing", [(FLOAT, "leadingSpacing"), (FLOAT, "trailingSpacing"), (FLOAT, "minimumAdvanceWidth"), (UINT32, "textLength"), (UINT32, "glyphCount"), (Pointer(Const(UINT16)), "clusterMap"), (Pointer(Const(FLOAT)), "glyphAdvances"), (Pointer(Const(DWRITE_GLYPH_OFFSET)), "glyphOffsets"), (Pointer(Const(DWRITE_SHAPING_GLYPH_PROPERTIES)), "glyphProperties"), Out(Pointer(FLOAT), "modifiedGlyphAdvances"), Out(Pointer(DWRITE_GLYPH_OFFSET), "modifiedGlyphOffsets")]),
+ StdMethod(HRESULT, "GetBaseline", [(ObjPointer(IDWriteFontFace), "fontFace"), (DWRITE_BASELINE, "baseline"), (BOOL, "isVertical"), (BOOL, "isSimulationAllowed"), (DWRITE_SCRIPT_ANALYSIS, "scriptAnalysis"), (PCWSTR, "localeName"), Out(ObjPointer(INT32), "baselineCoordinate"), Out(Pointer(BOOL), "exists")]),
+ StdMethod(HRESULT, "AnalyzeVerticalGlyphOrientation", [(ObjPointer(IDWriteTextAnalysisSource1), "analysisSource"), (UINT32, "textPosition"), (UINT32, "textLength"), (ObjPointer(IDWriteTextAnalysisSink1), "analysisSink")]),
+ StdMethod(HRESULT, "GetGlyphOrientationTransform", [(DWRITE_GLYPH_ORIENTATION_ANGLE, "glyphOrientationAngle"), (BOOL, "isSideways"), Out(Pointer(DWRITE_MATRIX), "transform")]),
+ StdMethod(HRESULT, "GetScriptProperties", [(DWRITE_SCRIPT_ANALYSIS, "scriptAnalysis"), Out(Pointer(DWRITE_SCRIPT_PROPERTIES), "scriptProperties")]),
+ StdMethod(HRESULT, "GetTextComplexity", [(String(Const(WCHAR), "textLength", wide=True), "textString"), (UINT32, "textLength"), (ObjPointer(IDWriteFontFace), "fontFace"), Out(Pointer(BOOL), "isTextSimple"), Out(Pointer(UINT32), "textLengthRead"), Out(Pointer(UINT16), "glyphIndices")]),
+ StdMethod(HRESULT, "GetJustificationOpportunities", [(ObjPointer(IDWriteFontFace), "fontFace"), (FLOAT, "fontEmSize"), (DWRITE_SCRIPT_ANALYSIS, "scriptAnalysis"), (UINT32, "textLength"), (UINT32, "glyphCount"), (String(Const(WCHAR), "textLength", wide=True), "textString"), (Pointer(Const(UINT16)), "clusterMap"), (Pointer(Const(DWRITE_SHAPING_GLYPH_PROPERTIES)), "glyphProperties"), Out(Pointer(DWRITE_JUSTIFICATION_OPPORTUNITY), "justificationOpportunities")]),
+ StdMethod(HRESULT, "JustifyGlyphAdvances", [(FLOAT, "lineWidth"), (UINT32, "glyphCount"), (Pointer(Const(DWRITE_JUSTIFICATION_OPPORTUNITY)), "justificationOpportunities"), (Pointer(Const(FLOAT)), "glyphAdvances"), (Pointer(Const(DWRITE_GLYPH_OFFSET)), "glyphOffsets"), Out(Pointer(FLOAT), "justifiedGlyphAdvances"), Out(Pointer(DWRITE_GLYPH_OFFSET), "justifiedGlyphOffsets")]),
+ StdMethod(HRESULT, "GetJustifiedGlyphs", [(ObjPointer(IDWriteFontFace), "fontFace"), (FLOAT, "fontEmSize"), (DWRITE_SCRIPT_ANALYSIS, "scriptAnalysis"), (UINT32, "textLength"), (UINT32, "glyphCount"), (UINT32, "maxGlyphCount"), (Pointer(Const(UINT16)), "clusterMap"), (Pointer(Const(UINT16)), "glyphIndices"), (Pointer(Const(FLOAT)), "glyphAdvances"), (Pointer(Const(FLOAT)), "justifiedGlyphAdvances"), (Pointer(Const(DWRITE_GLYPH_OFFSET)), "justifiedGlyphOffsets"), (Pointer(Const(DWRITE_SHAPING_GLYPH_PROPERTIES)), "glyphProperties"), Out(Pointer(UINT32), "actualGlyphCount"), Out(Pointer(UINT16), "modifiedClusterMap"), Out(Pointer(UINT16), "modifiedGlyphIndices"), Out(Pointer(FLOAT), "modifiedGlyphAdvances"), Out(Pointer(DWRITE_GLYPH_OFFSET), "modifiedGlyphOffsets")]),
+]
+
+IDWriteTextAnalysisSource1.methods += [
+ StdMethod(HRESULT, "GetVerticalGlyphOrientation", [(UINT32, "textPosition"), Out(Pointer(UINT32), "textLength"), Out(Pointer(DWRITE_VERTICAL_GLYPH_ORIENTATION), "glyphOrientation"), Out(Pointer(UINT8), "bidiLevel")]),
+]
+
+IDWriteTextAnalysisSink1.methods += [
+ StdMethod(HRESULT, "SetGlyphOrientation", [(UINT32, "textPosition"), (UINT32, "textLength"), (DWRITE_GLYPH_ORIENTATION_ANGLE, "glyphOrientationAngle"), (UINT8, "adjustedBidiLevel"), (BOOL, "isSideways"), (BOOL, "isRightToLeft")]),
+]
+
+IDWriteTextLayout1.methods += [
+ StdMethod(HRESULT, "SetPairKerning", [(BOOL, "isPairKerningEnabled"), (DWRITE_TEXT_RANGE, "textRange")]),
+ StdMethod(HRESULT, "GetPairKerning", [(UINT32, "currentPosition"), Out(Pointer(BOOL), "isPairKerningEnabled"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
+ StdMethod(HRESULT, "SetCharacterSpacing", [(FLOAT, "leadingSpacing"), (FLOAT, "trailingSpacing"), (FLOAT, "minimumAdvanceWidth"), (DWRITE_TEXT_RANGE, "textRange")]),
+ StdMethod(HRESULT, "GetCharacterSpacing", [(UINT32, "currentPosition"), Out(Pointer(FLOAT), "leadingSpacing"), Out(Pointer(FLOAT), "trailingSpacing"), Out(Pointer(FLOAT), "minimumAdvanceWidth"), Out(Pointer(DWRITE_TEXT_RANGE), "textRange")]),
+]
+
+DWRITE_TEXT_ANTIALIAS_MODE = Enum("DWRITE_TEXT_ANTIALIAS_MODE", [
+ "DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE",
+ "DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE",
+])
+
+IDWriteBitmapRenderTarget1.methods += [
+ StdMethod(DWRITE_TEXT_ANTIALIAS_MODE, "GetTextAntialiasMode", []),
+ StdMethod(HRESULT, "SetTextAntialiasMode", [(DWRITE_TEXT_ANTIALIAS_MODE, "antialiasMode")]),
+]
+
+dwrite.addInterfaces([
+ IDWriteFactory1
+])
diff --git a/specs/dxgi.py b/specs/dxgi.py
index 303dfc20..0e880548 100644
--- a/specs/dxgi.py
+++ b/specs/dxgi.py
@@ -1,5 +1,6 @@
##########################################################################
#
+# Copyright 2014 VMware, Inc
# Copyright 2011 Jose Fonseca
# All Rights Reserved.
#
@@ -24,7 +25,224 @@
##########################################################################/
-from dxgitype import *
+from winapi import *
+
+
+DXGI_FORMAT = Enum("DXGI_FORMAT", [
+ "DXGI_FORMAT_UNKNOWN",
+ "DXGI_FORMAT_R32G32B32A32_TYPELESS",
+ "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "DXGI_FORMAT_R32G32B32A32_UINT",
+ "DXGI_FORMAT_R32G32B32A32_SINT",
+ "DXGI_FORMAT_R32G32B32_TYPELESS",
+ "DXGI_FORMAT_R32G32B32_FLOAT",
+ "DXGI_FORMAT_R32G32B32_UINT",
+ "DXGI_FORMAT_R32G32B32_SINT",
+ "DXGI_FORMAT_R16G16B16A16_TYPELESS",
+ "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "DXGI_FORMAT_R16G16B16A16_UINT",
+ "DXGI_FORMAT_R16G16B16A16_SNORM",
+ "DXGI_FORMAT_R16G16B16A16_SINT",
+ "DXGI_FORMAT_R32G32_TYPELESS",
+ "DXGI_FORMAT_R32G32_FLOAT",
+ "DXGI_FORMAT_R32G32_UINT",
+ "DXGI_FORMAT_R32G32_SINT",
+ "DXGI_FORMAT_R32G8X24_TYPELESS",
+ "DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
+ "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
+ "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT",
+ "DXGI_FORMAT_R10G10B10A2_TYPELESS",
+ "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "DXGI_FORMAT_R10G10B10A2_UINT",
+ "DXGI_FORMAT_R11G11B10_FLOAT",
+ "DXGI_FORMAT_R8G8B8A8_TYPELESS",
+ "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "DXGI_FORMAT_R8G8B8A8_UINT",
+ "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "DXGI_FORMAT_R8G8B8A8_SINT",
+ "DXGI_FORMAT_R16G16_TYPELESS",
+ "DXGI_FORMAT_R16G16_FLOAT",
+ "DXGI_FORMAT_R16G16_UNORM",
+ "DXGI_FORMAT_R16G16_UINT",
+ "DXGI_FORMAT_R16G16_SNORM",
+ "DXGI_FORMAT_R16G16_SINT",
+ "DXGI_FORMAT_R32_TYPELESS",
+ "DXGI_FORMAT_D32_FLOAT",
+ "DXGI_FORMAT_R32_FLOAT",
+ "DXGI_FORMAT_R32_UINT",
+ "DXGI_FORMAT_R32_SINT",
+ "DXGI_FORMAT_R24G8_TYPELESS",
+ "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
+ "DXGI_FORMAT_X24_TYPELESS_G8_UINT",
+ "DXGI_FORMAT_R8G8_TYPELESS",
+ "DXGI_FORMAT_R8G8_UNORM",
+ "DXGI_FORMAT_R8G8_UINT",
+ "DXGI_FORMAT_R8G8_SNORM",
+ "DXGI_FORMAT_R8G8_SINT",
+ "DXGI_FORMAT_R16_TYPELESS",
+ "DXGI_FORMAT_R16_FLOAT",
+ "DXGI_FORMAT_D16_UNORM",
+ "DXGI_FORMAT_R16_UNORM",
+ "DXGI_FORMAT_R16_UINT",
+ "DXGI_FORMAT_R16_SNORM",
+ "DXGI_FORMAT_R16_SINT",
+ "DXGI_FORMAT_R8_TYPELESS",
+ "DXGI_FORMAT_R8_UNORM",
+ "DXGI_FORMAT_R8_UINT",
+ "DXGI_FORMAT_R8_SNORM",
+ "DXGI_FORMAT_R8_SINT",
+ "DXGI_FORMAT_A8_UNORM",
+ "DXGI_FORMAT_R1_UNORM",
+ "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "DXGI_FORMAT_R8G8_B8G8_UNORM",
+ "DXGI_FORMAT_G8R8_G8B8_UNORM",
+ "DXGI_FORMAT_BC1_TYPELESS",
+ "DXGI_FORMAT_BC1_UNORM",
+ "DXGI_FORMAT_BC1_UNORM_SRGB",
+ "DXGI_FORMAT_BC2_TYPELESS",
+ "DXGI_FORMAT_BC2_UNORM",
+ "DXGI_FORMAT_BC2_UNORM_SRGB",
+ "DXGI_FORMAT_BC3_TYPELESS",
+ "DXGI_FORMAT_BC3_UNORM",
+ "DXGI_FORMAT_BC3_UNORM_SRGB",
+ "DXGI_FORMAT_BC4_TYPELESS",
+ "DXGI_FORMAT_BC4_UNORM",
+ "DXGI_FORMAT_BC4_SNORM",
+ "DXGI_FORMAT_BC5_TYPELESS",
+ "DXGI_FORMAT_BC5_UNORM",
+ "DXGI_FORMAT_BC5_SNORM",
+ "DXGI_FORMAT_B5G6R5_UNORM",
+ "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "DXGI_FORMAT_B8G8R8X8_UNORM",
+ "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM",
+ "DXGI_FORMAT_B8G8R8A8_TYPELESS",
+ "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB",
+ "DXGI_FORMAT_B8G8R8X8_TYPELESS",
+ "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB",
+ "DXGI_FORMAT_BC6H_TYPELESS",
+ "DXGI_FORMAT_BC6H_UF16",
+ "DXGI_FORMAT_BC6H_SF16",
+ "DXGI_FORMAT_BC7_TYPELESS",
+ "DXGI_FORMAT_BC7_UNORM",
+ "DXGI_FORMAT_BC7_UNORM_SRGB",
+ "DXGI_FORMAT_AYUV",
+ "DXGI_FORMAT_Y410",
+ "DXGI_FORMAT_Y416",
+ "DXGI_FORMAT_NV12",
+ "DXGI_FORMAT_P010",
+ "DXGI_FORMAT_P016",
+ "DXGI_FORMAT_420_OPAQUE",
+ "DXGI_FORMAT_YUY2",
+ "DXGI_FORMAT_Y210",
+ "DXGI_FORMAT_Y216",
+ "DXGI_FORMAT_NV11",
+ "DXGI_FORMAT_AI44",
+ "DXGI_FORMAT_IA44",
+ "DXGI_FORMAT_P8",
+ "DXGI_FORMAT_A8P8",
+ "DXGI_FORMAT_B4G4R4A4_UNORM",
+])
+
+
+HRESULT = MAKE_HRESULT([
+ "DXGI_STATUS_OCCLUDED",
+ "DXGI_STATUS_CLIPPED",
+ "DXGI_STATUS_NO_REDIRECTION",
+ "DXGI_STATUS_NO_DESKTOP_ACCESS",
+ "DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE",
+ "DXGI_STATUS_MODE_CHANGED",
+ "DXGI_STATUS_MODE_CHANGE_IN_PROGRESS",
+ "DXGI_ERROR_INVALID_CALL",
+ "DXGI_ERROR_NOT_FOUND",
+ "DXGI_ERROR_MORE_DATA",
+ "DXGI_ERROR_UNSUPPORTED",
+ "DXGI_ERROR_DEVICE_REMOVED",
+ "DXGI_ERROR_DEVICE_HUNG",
+ "DXGI_ERROR_DEVICE_RESET",
+ "DXGI_ERROR_WAS_STILL_DRAWING",
+ "DXGI_ERROR_FRAME_STATISTICS_DISJOINT",
+ "DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE",
+ "DXGI_ERROR_DRIVER_INTERNAL_ERROR",
+ "DXGI_ERROR_NONEXCLUSIVE",
+ "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE",
+ "DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED",
+ "DXGI_ERROR_REMOTE_OUTOFMEMORY",
+ # IDXGIKeyedMutex::AcquireSync
+ "WAIT_ABANDONED",
+ "WAIT_TIMEOUT",
+])
+
+
+DXGI_RGB = Struct("DXGI_RGB", [
+ (Float, "Red"),
+ (Float, "Green"),
+ (Float, "Blue"),
+])
+
+DXGI_GAMMA_CONTROL = Struct("DXGI_GAMMA_CONTROL", [
+ (DXGI_RGB, "Scale"),
+ (DXGI_RGB, "Offset"),
+ (Array(DXGI_RGB, 1025), "GammaCurve"),
+])
+
+DXGI_GAMMA_CONTROL_CAPABILITIES = Struct("DXGI_GAMMA_CONTROL_CAPABILITIES", [
+ (BOOL, "ScaleAndOffsetSupported"),
+ (Float, "MaxConvertedValue"),
+ (Float, "MinConvertedValue"),
+ (UINT, "NumGammaControlPoints"),
+ (Array(Float, "{self}.NumGammaControlPoints"), "ControlPointPositions"),
+])
+
+DXGI_RATIONAL = Struct("DXGI_RATIONAL", [
+ (UINT, "Numerator"),
+ (UINT, "Denominator"),
+])
+
+DXGI_MODE_SCANLINE_ORDER = Enum("DXGI_MODE_SCANLINE_ORDER", [
+ "DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED",
+ "DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE",
+ "DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST",
+ "DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST",
+])
+
+DXGI_MODE_SCALING = Enum("DXGI_MODE_SCALING", [
+ "DXGI_MODE_SCALING_UNSPECIFIED",
+ "DXGI_MODE_SCALING_CENTERED",
+ "DXGI_MODE_SCALING_STRETCHED",
+])
+
+DXGI_MODE_ROTATION = Enum("DXGI_MODE_ROTATION", [
+ "DXGI_MODE_ROTATION_UNSPECIFIED",
+ "DXGI_MODE_ROTATION_IDENTITY",
+ "DXGI_MODE_ROTATION_ROTATE90",
+ "DXGI_MODE_ROTATION_ROTATE180",
+ "DXGI_MODE_ROTATION_ROTATE270",
+])
+
+DXGI_MODE_DESC = Struct("DXGI_MODE_DESC", [
+ (UINT, "Width"),
+ (UINT, "Height"),
+ (DXGI_RATIONAL, "RefreshRate"),
+ (DXGI_FORMAT, "Format"),
+ (DXGI_MODE_SCANLINE_ORDER, "ScanlineOrdering"),
+ (DXGI_MODE_SCALING, "Scaling"),
+])
+
+DXGI_SAMPLE_DESC = Struct("DXGI_SAMPLE_DESC", [
+ (UINT, "Count"),
+ (UINT, "Quality"),
+])
+
+DXGI_RGBA = Struct("DXGI_RGBA", [
+ (Float, "r"),
+ (Float, "g"),
+ (Float, "b"),
+ (Float, "a"),
+])
IDXGIObject = Interface("IDXGIObject", IUnknown)
@@ -118,12 +336,20 @@ DXGI_SURFACE_DESC = Struct("DXGI_SURFACE_DESC", [
DXGI_SWAP_EFFECT = Enum("DXGI_SWAP_EFFECT", [
"DXGI_SWAP_EFFECT_DISCARD",
"DXGI_SWAP_EFFECT_SEQUENTIAL",
+ "DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL",
])
DXGI_SWAP_CHAIN_FLAG = Flags(UINT, [
"DXGI_SWAP_CHAIN_FLAG_NONPREROTATED",
"DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH",
"DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE",
+ "DXGI_SWAP_CHAIN_FLAG_RESTRICTED_CONTENT",
+ "DXGI_SWAP_CHAIN_FLAG_RESTRICT_SHARED_RESOURCE_DRIVER",
+ "DXGI_SWAP_CHAIN_FLAG_DISPLAY_ONLY",
+ "DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT",
+ "DXGI_SWAP_CHAIN_FLAG_FOREGROUND_LAYER",
+ "DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO",
+ "DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO",
])
DXGI_SWAP_CHAIN_DESC = Struct("DXGI_SWAP_CHAIN_DESC", [
@@ -137,10 +363,11 @@ DXGI_SWAP_CHAIN_DESC = Struct("DXGI_SWAP_CHAIN_DESC", [
(DXGI_SWAP_CHAIN_FLAG, "Flags"),
])
+
IDXGIObject.methods += [
StdMethod(HRESULT, "SetPrivateData", [(REFGUID, "Name"), (UINT, "DataSize"), (OpaqueBlob(Const(Void), "DataSize"), "pData")], sideeffects=False),
StdMethod(HRESULT, "SetPrivateDataInterface", [(REFGUID, "Name"), (OpaquePointer(Const(IUnknown)), "pUnknown")], sideeffects=False),
- StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "Name"), Out(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
+ StdMethod(HRESULT, "GetPrivateData", [(REFGUID, "Name"), InOut(Pointer(UINT), "pDataSize"), Out(OpaquePointer(Void), "pData")], sideeffects=False),
StdMethod(HRESULT, "GetParent", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppParent")]),
]
@@ -148,21 +375,21 @@ IDXGIDeviceSubObject.methods += [
StdMethod(HRESULT, "GetDevice", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppDevice")]),
]
+SHARED_HANDLE = Handle("shared_handle", RAW_HANDLE)
+
IDXGIResource.methods += [
- StdMethod(HRESULT, "GetSharedHandle", [Out(Pointer(HANDLE), "pSharedHandle")]),
+ StdMethod(HRESULT, "GetSharedHandle", [Out(Pointer(SHARED_HANDLE), "pSharedHandle")]),
StdMethod(HRESULT, "GetUsage", [Out(Pointer(DXGI_USAGE), "pUsage")], sideeffects=False),
StdMethod(HRESULT, "SetEvictionPriority", [(DXGI_RESOURCE_PRIORITY, "EvictionPriority")]),
StdMethod(HRESULT, "GetEvictionPriority", [Out(Pointer(DXGI_RESOURCE_PRIORITY), "pEvictionPriority")], sideeffects=False),
]
-DXGI_SHARED_RESOURCE_FLAG = Flags(DWORD, [
- "DXGI_SHARED_RESOURCE_READ",
- "DXGI_SHARED_RESOURCE_WRITE",
+DWORD_TIMEOUT = FakeEnum(DWORD, [
+ "INFINITE",
])
-
IDXGIKeyedMutex.methods += [
- StdMethod(HRESULT, "AcquireSync", [(UINT64, "Key"), (DWORD, "dwMilliseconds")]),
+ StdMethod(HRESULT, "AcquireSync", [(UINT64, "Key"), (DWORD_TIMEOUT, "dwMilliseconds")]),
StdMethod(HRESULT, "ReleaseSync", [(UINT64, "Key")]),
]
@@ -192,16 +419,18 @@ IDXGIAdapter.methods += [
DXGI_ENUM_MODES = Flags(UINT, [
"DXGI_ENUM_MODES_INTERLACED",
"DXGI_ENUM_MODES_SCALING",
+ "DXGI_ENUM_MODES_STEREO",
+ "DXGI_ENUM_MODES_DISABLED_STEREO",
])
IDXGIOutput.methods += [
StdMethod(HRESULT, "GetDesc", [Out(Pointer(DXGI_OUTPUT_DESC), "pDesc")], sideeffects=False),
- StdMethod(HRESULT, "GetDisplayModeList", [(DXGI_FORMAT, "EnumFormat"), (DXGI_ENUM_MODES, "Flags"), Out(Pointer(UINT), "pNumModes"), Out(Array(DXGI_MODE_DESC, "*pNumModes"), "pDesc")], sideeffects=False),
- StdMethod(HRESULT, "FindClosestMatchingMode", [(Pointer(Const(DXGI_MODE_DESC)), "pModeToMatch"), Out(Pointer(DXGI_MODE_DESC), "pClosestMatch"), (ObjPointer(IUnknown), "pConcernedDevice")]),
+ StdMethod(HRESULT, "GetDisplayModeList", [(DXGI_FORMAT, "EnumFormat"), (DXGI_ENUM_MODES, "Flags"), InOut(Pointer(UINT), "pNumModes"), Out(Array(DXGI_MODE_DESC, "*pNumModes"), "pDesc")], sideeffects=False),
+ StdMethod(HRESULT, "FindClosestMatchingMode", [(Pointer(Const(DXGI_MODE_DESC)), "pModeToMatch"), Out(Pointer(DXGI_MODE_DESC), "pClosestMatch"), (ObjPointer(IUnknown), "pConcernedDevice")], sideeffects=False),
StdMethod(HRESULT, "WaitForVBlank", []),
StdMethod(HRESULT, "TakeOwnership", [(ObjPointer(IUnknown), "pDevice"), (BOOL, "Exclusive")]),
StdMethod(Void, "ReleaseOwnership", []),
- StdMethod(HRESULT, "GetGammaControlCapabilities", [Out(Pointer(DXGI_GAMMA_CONTROL_CAPABILITIES), "pGammaCaps")]),
+ StdMethod(HRESULT, "GetGammaControlCapabilities", [Out(Pointer(DXGI_GAMMA_CONTROL_CAPABILITIES), "pGammaCaps")], sideeffects=False),
StdMethod(HRESULT, "SetGammaControl", [(Pointer(Const(DXGI_GAMMA_CONTROL)), "pArray")]),
StdMethod(HRESULT, "GetGammaControl", [Out(Pointer(DXGI_GAMMA_CONTROL), "pArray")], sideeffects=False),
StdMethod(HRESULT, "SetDisplaySurface", [(ObjPointer(IDXGISurface), "pScanoutSurface")]),
@@ -213,6 +442,11 @@ DXGI_PRESENT = Flags(UINT, [
"DXGI_PRESENT_TEST",
"DXGI_PRESENT_DO_NOT_SEQUENCE",
"DXGI_PRESENT_RESTART",
+ "DXGI_PRESENT_DO_NOT_WAIT",
+ "DXGI_PRESENT_STEREO_PREFER_RIGHT",
+ "DXGI_PRESENT_STEREO_TEMPORARY_MONO",
+ "DXGI_PRESENT_RESTRICT_TO_OUTPUT",
+ "DXGI_PRESENT_USE_DURATION",
])
IDXGISwapChain.methods += [
@@ -237,7 +471,7 @@ DXGI_MWA = Flags(UINT, [
IDXGIFactory.methods += [
StdMethod(HRESULT, "EnumAdapters", [(UINT, "Adapter"), Out(Pointer(ObjPointer(IDXGIAdapter)), "ppAdapter")]),
- StdMethod(HRESULT, "MakeWindowAssociation", [(HWND, "WindowHandle"), (DXGI_MWA, "Flags")]),
+ StdMethod(HRESULT, "MakeWindowAssociation", [(HWND, "WindowHandle"), (DXGI_MWA, "Flags")], sideeffects=False),
StdMethod(HRESULT, "GetWindowAssociation", [Out(Pointer(HWND), "pWindowHandle")], sideeffects=False),
StdMethod(HRESULT, "CreateSwapChain", [(ObjPointer(IUnknown), "pDevice"), (Pointer(DXGI_SWAP_CHAIN_DESC), "pDesc"), Out(Pointer(ObjPointer(IDXGISwapChain)), "ppSwapChain")]),
StdMethod(HRESULT, "CreateSoftwareAdapter", [(HMODULE, "Module"), Out(Pointer(ObjPointer(IDXGIAdapter)), "ppAdapter")]),
@@ -251,9 +485,10 @@ IDXGIDevice.methods += [
StdMethod(HRESULT, "GetGPUThreadPriority", [Out(Pointer(INT), "pPriority")], sideeffects=False),
]
-DXGI_ADAPTER_FLAG = Enum("DXGI_ADAPTER_FLAG", [
+DXGI_ADAPTER_FLAG = FakeEnum(UINT, [
"DXGI_ADAPTER_FLAG_NONE",
"DXGI_ADAPTER_FLAG_REMOTE",
+ "DXGI_ADAPTER_FLAG_SOFTWARE",
])
DXGI_ADAPTER_DESC1 = Struct("DXGI_ADAPTER_DESC1", [
@@ -266,7 +501,7 @@ DXGI_ADAPTER_DESC1 = Struct("DXGI_ADAPTER_DESC1", [
(SIZE_T, "DedicatedSystemMemory"),
(SIZE_T, "SharedSystemMemory"),
(LUID, "AdapterLuid"),
- (UINT, "Flags"),
+ (DXGI_SWAP_CHAIN_FLAG, "Flags"),
])
DXGI_DISPLAY_COLOR_SPACE = Struct("DXGI_DISPLAY_COLOR_SPACE", [
@@ -289,6 +524,373 @@ IDXGIDevice1.methods += [
]
+dxgi = Module('dxgi')
+dxgi.addInterfaces([
+ IDXGIKeyedMutex,
+ IDXGIFactory1,
+ IDXGIDevice1,
+ IDXGIAdapter1,
+ IDXGIResource,
+])
+dxgi.addFunctions([
+ StdFunction(HRESULT, "CreateDXGIFactory", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppFactory")]),
+ StdFunction(HRESULT, "CreateDXGIFactory1", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppFactory")]),
+])
+
+
+
+#
+# DXGI 1.2
+#
+
+IDXGIDisplayControl = Interface("IDXGIDisplayControl", IUnknown)
+IDXGIDisplayControl.methods += [
+ StdMethod(BOOL, "IsStereoEnabled", [], sideeffects=False),
+ StdMethod(Void, "SetStereoEnabled", [(BOOL, "enabled")]),
+]
+
+DXGI_OUTDUPL_MOVE_RECT = Struct("DXGI_OUTDUPL_MOVE_RECT", [
+ (POINT, "SourcePoint"),
+ (RECT, "DestinationRect"),
+])
+
+DXGI_OUTDUPL_DESC = Struct("DXGI_OUTDUPL_DESC", [
+ (DXGI_MODE_DESC, "ModeDesc"),
+ (DXGI_MODE_ROTATION, "Rotation"),
+ (BOOL, "DesktopImageInSystemMemory"),
+])
+
+DXGI_OUTDUPL_POINTER_POSITION = Struct("DXGI_OUTDUPL_POINTER_POSITION", [
+ (POINT, "Position"),
+ (BOOL, "Visible"),
+])
+
+DXGI_OUTDUPL_POINTER_SHAPE_TYPE = Enum("DXGI_OUTDUPL_POINTER_SHAPE_TYPE", [
+ "DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME",
+ "DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR",
+ "DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR",
+])
+
+DXGI_OUTDUPL_POINTER_SHAPE_INFO = Struct("DXGI_OUTDUPL_POINTER_SHAPE_INFO", [
+ (UINT, "Type"),
+ (UINT, "Width"),
+ (UINT, "Height"),
+ (UINT, "Pitch"),
+ (POINT, "HotSpot"),
+])
+
+DXGI_OUTDUPL_FRAME_INFO = Struct("DXGI_OUTDUPL_FRAME_INFO", [
+ (LARGE_INTEGER, "LastPresentTime"),
+ (LARGE_INTEGER, "LastMouseUpdateTime"),
+ (UINT, "AccumulatedFrames"),
+ (BOOL, "RectsCoalesced"),
+ (BOOL, "ProtectedContentMaskedOut"),
+ (DXGI_OUTDUPL_POINTER_POSITION, "PointerPosition"),
+ (UINT, "TotalMetadataBufferSize"),
+ (UINT, "PointerShapeBufferSize"),
+])
+
+IDXGIOutputDuplication = Interface("IDXGIOutputDuplication", IDXGIObject)
+IDXGIOutputDuplication.methods += [
+ StdMethod(Void, "GetDesc", [Out(Pointer(DXGI_OUTDUPL_DESC), "pDesc")], sideeffects=False),
+ StdMethod(HRESULT, "AcquireNextFrame", [(UINT, "TimeoutInMilliseconds"), Out(Pointer(DXGI_OUTDUPL_FRAME_INFO), "pFrameInfo"), Out(Pointer(ObjPointer(IDXGIResource)), "ppDesktopResource")]),
+ StdMethod(HRESULT, "GetFrameDirtyRects", [(UINT, "DirtyRectsBufferSize"), Out(Array(RECT, "DirtyRectsBufferSize"), "pDirtyRectsBuffer"), Out(Pointer(UINT), "pDirtyRectsBufferSizeRequired")], sideeffects=False),
+ StdMethod(HRESULT, "GetFrameMoveRects", [(UINT, "MoveRectsBufferSize"), Out(Array(DXGI_OUTDUPL_MOVE_RECT, "MoveRectsBufferSize"), "pMoveRectBuffer"), Out(Pointer(UINT), "pMoveRectsBufferSizeRequired")], sideeffects=False),
+ StdMethod(HRESULT, "GetFramePointerShape", [(UINT, "PointerShapeBufferSize"), Out(OpaqueBlob(Void, "PointerShapeBufferSize"), "pPointerShapeBuffer"), Out(Pointer(UINT), "pPointerShapeBufferSizeRequired"), Out(Pointer(DXGI_OUTDUPL_POINTER_SHAPE_INFO), "pPointerShapeInfo")], sideeffects=False),
+ StdMethod(HRESULT, "MapDesktopSurface", [Out(Pointer(DXGI_MAPPED_RECT), "pLockedRect")], sideeffects=False),
+ StdMethod(HRESULT, "UnMapDesktopSurface", [], sideeffects=False),
+ StdMethod(HRESULT, "ReleaseFrame", []),
+]
+
+DXGI_ALPHA_MODE = Enum("DXGI_ALPHA_MODE", [
+ "DXGI_ALPHA_MODE_UNSPECIFIED",
+ "DXGI_ALPHA_MODE_PREMULTIPLIED",
+ "DXGI_ALPHA_MODE_STRAIGHT",
+ "DXGI_ALPHA_MODE_IGNORE",
+])
+
+IDXGISurface2 = Interface("IDXGISurface2", IDXGISurface1)
+IDXGISurface2.methods += [
+ StdMethod(HRESULT, "GetResource", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppParentResource"), Out(Pointer(UINT), "pSubresourceIndex")]),
+]
+
+DXGI_SHARED_RESOURCE_FLAG = Flags(DWORD, [
+ "DXGI_SHARED_RESOURCE_READ",
+ "DXGI_SHARED_RESOURCE_WRITE",
+])
+
+IDXGIResource1 = Interface("IDXGIResource1", IDXGIResource)
+IDXGIResource1.methods += [
+ StdMethod(HRESULT, "CreateSubresourceSurface", [(UINT, "index"), Out(Pointer(ObjPointer(IDXGISurface2)), "ppSurface")]),
+ StdMethod(HRESULT, "CreateSharedHandle", [(Pointer(Const(SECURITY_ATTRIBUTES)), "pAttributes"), (DXGI_SHARED_RESOURCE_FLAG, "dwAccess"), (LPCWSTR, "lpName"), Out(Pointer(HANDLE), "pHandle")]),
+]
+
+DXGI_OFFER_RESOURCE_PRIORITY = Enum("DXGI_OFFER_RESOURCE_PRIORITY", [
+ "DXGI_OFFER_RESOURCE_PRIORITY_LOW",
+ "DXGI_OFFER_RESOURCE_PRIORITY_NORMAL",
+ "DXGI_OFFER_RESOURCE_PRIORITY_HIGH",
+])
+
+IDXGIDevice2 = Interface("IDXGIDevice2", IDXGIDevice1)
+IDXGIDevice2.methods += [
+ StdMethod(HRESULT, "OfferResources", [(UINT, "NumResources"), (Array(Const(ObjPointer(IDXGIResource)), "NumResources"), "ppResources"), (DXGI_OFFER_RESOURCE_PRIORITY, "Priority")]),
+ StdMethod(HRESULT, "ReclaimResources", [(UINT, "NumResources"), (Array(Const(ObjPointer(IDXGIResource)), "NumResources"), "ppResources"), Out(Pointer(BOOL), "pDiscarded")]),
+ StdMethod(HRESULT, "EnqueueSetEvent", [(HANDLE, "hEvent")]),
+]
+
+DXGI_MODE_DESC1 = Struct("DXGI_MODE_DESC1", [
+ (UINT, "Width"),
+ (UINT, "Height"),
+ (DXGI_RATIONAL, "RefreshRate"),
+ (DXGI_FORMAT, "Format"),
+ (DXGI_MODE_SCANLINE_ORDER, "ScanlineOrdering"),
+ (DXGI_MODE_SCALING, "Scaling"),
+ (BOOL, "Stereo"),
+])
+
+DXGI_SCALING = Enum("DXGI_SCALING", [
+ "DXGI_SCALING_STRETCH",
+ "DXGI_SCALING_NONE",
+ "DXGI_SCALING_ASPECT_RATIO_STRETCH",
+])
+
+DXGI_SWAP_CHAIN_DESC1 = Struct("DXGI_SWAP_CHAIN_DESC1", [
+ (UINT, "Width"),
+ (UINT, "Height"),
+ (DXGI_FORMAT, "Format"),
+ (BOOL, "Stereo"),
+ (DXGI_SAMPLE_DESC, "SampleDesc"),
+ (DXGI_USAGE, "BufferUsage"),
+ (UINT, "BufferCount"),
+ (DXGI_SCALING, "Scaling"),
+ (DXGI_SWAP_EFFECT, "SwapEffect"),
+ (DXGI_ALPHA_MODE, "AlphaMode"),
+ (DXGI_SWAP_CHAIN_FLAG, "Flags"),
+])
+
+DXGI_SWAP_CHAIN_FULLSCREEN_DESC = Struct("DXGI_SWAP_CHAIN_FULLSCREEN_DESC", [
+ (DXGI_RATIONAL, "RefreshRate"),
+ (DXGI_MODE_SCANLINE_ORDER, "ScanlineOrdering"),
+ (DXGI_MODE_SCALING, "Scaling"),
+ (BOOL, "Windowed"),
+])
+
+DXGI_PRESENT_PARAMETERS = Struct("DXGI_PRESENT_PARAMETERS", [
+ (UINT, "DirtyRectsCount"),
+ (Array(RECT, "{self}.DirtyRectsCount"), "pDirtyRects"),
+ (Pointer(RECT), "pScrollRect"),
+ (Pointer(POINT), "pScrollOffset"),
+])
+
+IDXGISwapChain1 = Interface("IDXGISwapChain1", IDXGISwapChain)
+IDXGISwapChain1.methods += [
+ StdMethod(HRESULT, "GetDesc1", [(Out(Pointer(DXGI_SWAP_CHAIN_DESC1), "pDesc"))], sideeffects=False),
+ StdMethod(HRESULT, "GetFullscreenDesc", [(Out(Pointer(DXGI_SWAP_CHAIN_FULLSCREEN_DESC), "pDesc"))], sideeffects=False),
+ StdMethod(HRESULT, "GetHwnd", [(Out(Pointer(HWND), "pHwnd"))], sideeffects=False),
+ StdMethod(HRESULT, "GetCoreWindow", [(REFIID, "riid"), (Out(Pointer(ObjPointer(Void)), "ppUnk"))]),
+ StdMethod(HRESULT, "Present1", [(UINT, "SyncInterval"), (DXGI_PRESENT, "Flags"), (Pointer(Const(DXGI_PRESENT_PARAMETERS)), "pPresentParameters")]),
+ StdMethod(BOOL, "IsTemporaryMonoSupported", [], sideeffects=False),
+ StdMethod(HRESULT, "GetRestrictToOutput", [(Out(Pointer(ObjPointer(IDXGIOutput)), "ppRestrictToOutput"))]),
+ StdMethod(HRESULT, "SetBackgroundColor", [(Pointer(Const(DXGI_RGBA)), "pColor")]),
+ StdMethod(HRESULT, "GetBackgroundColor", [(Out(Pointer(DXGI_RGBA), "pColor"))], sideeffects=False),
+ StdMethod(HRESULT, "SetRotation", [(DXGI_MODE_ROTATION, "Rotation")]),
+ StdMethod(HRESULT, "GetRotation", [(Out(Pointer(DXGI_MODE_ROTATION), "pRotation"))], sideeffects=False),
+]
+
+IDXGIFactory2 = Interface("IDXGIFactory2", IDXGIFactory1)
+IDXGIFactory2.methods += [
+ StdMethod(BOOL, "IsWindowedStereoEnabled", [], sideeffects=False),
+ StdMethod(HRESULT, "CreateSwapChainForHwnd", [(ObjPointer(IUnknown), "pDevice"), (HWND, "WindowHandle"), (Pointer(Const(DXGI_SWAP_CHAIN_DESC1)), "pDesc"), (Pointer(Const(DXGI_SWAP_CHAIN_FULLSCREEN_DESC)), "pFullscreenDesc"), (ObjPointer(IDXGIOutput), "pRestrictToOutput"), Out(Pointer(ObjPointer(IDXGISwapChain1)), "ppSwapChain")]),
+ StdMethod(HRESULT, "CreateSwapChainForCoreWindow", [(ObjPointer(IUnknown), "pDevice"), (ObjPointer(IUnknown), "pWindow"), (Pointer(Const(DXGI_SWAP_CHAIN_DESC1)), "pDesc"), (ObjPointer(IDXGIOutput), "pRestrictToOutput"), Out(Pointer(ObjPointer(IDXGISwapChain1)), "ppSwapChain")]),
+ StdMethod(HRESULT, "GetSharedResourceAdapterLuid", [(HANDLE, "hResource"), Out(Pointer(LUID), "pLuid")], sideeffects=False),
+ StdMethod(HRESULT, "RegisterStereoStatusWindow", [(HWND, "WindowHandle"), (UINT, "wMsg"), Out(Pointer(DWORD), "pdwCookie")], sideeffects=False),
+ StdMethod(HRESULT, "RegisterStereoStatusEvent", [(HANDLE, "hEvent"), Out(Pointer(DWORD), "pdwCookie")], sideeffects=False),
+ StdMethod(Void, "UnregisterStereoStatus", [(DWORD, "dwCookie")], sideeffects=False),
+ StdMethod(HRESULT, "RegisterOcclusionStatusWindow", [(HWND, "WindowHandle"), (UINT, "wMsg"), Out(Pointer(DWORD), "pdwCookie")], sideeffects=False),
+ StdMethod(HRESULT, "RegisterOcclusionStatusEvent", [(HANDLE, "hEvent"), Out(Pointer(DWORD), "pdwCookie")], sideeffects=False),
+ StdMethod(Void, "UnregisterOcclusionStatus", [(DWORD, "dwCookie")], sideeffects=False),
+ StdMethod(HRESULT, "CreateSwapChainForComposition", [(ObjPointer(IUnknown), "pDevice"), (Pointer(Const(DXGI_SWAP_CHAIN_DESC1)), "pDesc"), (ObjPointer(IDXGIOutput), "pRestrictToOutput"), Out(Pointer(ObjPointer(IDXGISwapChain1)), "ppSwapChain")]),
+]
+
+DXGI_GRAPHICS_PREEMPTION_GRANULARITY = Enum("DXGI_GRAPHICS_PREEMPTION_GRANULARITY", [
+ "DXGI_GRAPHICS_PREEMPTION_DMA_BUFFER_BOUNDARY",
+ "DXGI_GRAPHICS_PREEMPTION_PRIMITIVE_BOUNDARY",
+ "DXGI_GRAPHICS_PREEMPTION_TRIANGLE_BOUNDARY",
+ "DXGI_GRAPHICS_PREEMPTION_PIXEL_BOUNDARY",
+ "DXGI_GRAPHICS_PREEMPTION_INSTRUCTION_BOUNDARY",
+])
+
+DXGI_COMPUTE_PREEMPTION_GRANULARITY = Enum("DXGI_COMPUTE_PREEMPTION_GRANULARITY", [
+ "DXGI_COMPUTE_PREEMPTION_DMA_BUFFER_BOUNDARY",
+ "DXGI_COMPUTE_PREEMPTION_DISPATCH_BOUNDARY",
+ "DXGI_COMPUTE_PREEMPTION_THREAD_GROUP_BOUNDARY",
+ "DXGI_COMPUTE_PREEMPTION_THREAD_BOUNDARY",
+ "DXGI_COMPUTE_PREEMPTION_INSTRUCTION_BOUNDARY",
+])
+
+DXGI_ADAPTER_DESC2 = Struct("DXGI_ADAPTER_DESC2", [
+ (WString, "Description"),
+ (UINT, "VendorId"),
+ (UINT, "DeviceId"),
+ (UINT, "SubSysId"),
+ (UINT, "Revision"),
+ (SIZE_T, "DedicatedVideoMemory"),
+ (SIZE_T, "DedicatedSystemMemory"),
+ (SIZE_T, "SharedSystemMemory"),
+ (LUID, "AdapterLuid"),
+ (DXGI_ADAPTER_FLAG, "Flags"),
+ (DXGI_GRAPHICS_PREEMPTION_GRANULARITY, "GraphicsPreemptionGranularity"),
+ (DXGI_COMPUTE_PREEMPTION_GRANULARITY, "ComputePreemptionGranularity"),
+])
+
+IDXGIAdapter2 = Interface("IDXGIAdapter2", IDXGIAdapter1)
+IDXGIAdapter2.methods += [
+ StdMethod(HRESULT, "GetDesc2", [Out(Pointer(DXGI_ADAPTER_DESC2), "pDesc")], sideeffects=False),
+]
+
+IDXGIOutput1 = Interface("IDXGIOutput1", IDXGIOutput)
+IDXGIOutput1.methods += [
+ StdMethod(HRESULT, "GetDisplayModeList1", [(DXGI_FORMAT, "EnumFormat"), (DXGI_ENUM_MODES, "Flags"), InOut(Pointer(UINT), "pNumModes"), Out(Array(DXGI_MODE_DESC1, "*pNumModes"), "pDesc")], sideeffects=False),
+ StdMethod(HRESULT, "FindClosestMatchingMode1", [(Pointer(Const(DXGI_MODE_DESC1)), "pModeToMatch"), Out(Pointer(DXGI_MODE_DESC1), "pClosestMatch"), (ObjPointer(IUnknown), "pConcernedDevice")], sideeffects=False),
+ StdMethod(HRESULT, "GetDisplaySurfaceData1", [(ObjPointer(IDXGIResource), "pDestination")]),
+ StdMethod(HRESULT, "DuplicateOutput", [(ObjPointer(IUnknown), "pDevice"), Out(Pointer(ObjPointer(IDXGIOutputDuplication)), "ppOutputDuplication")]),
+]
+
+dxgi.addInterfaces([
+ IDXGIDisplayControl,
+ IDXGIDevice2,
+ IDXGISwapChain1,
+ IDXGIFactory2,
+ IDXGIResource1,
+ IDXGIAdapter2,
+ IDXGIOutput1,
+])
+
+#
+# DXGI 1.3
+#
+
+DXGI_CREATE_FACTORY_FLAGS = Flags(UINT, [
+ "DXGI_CREATE_FACTORY_DEBUG",
+])
+
+dxgi.addFunctions([
+ StdFunction(HRESULT, "CreateDXGIFactory2", [(DXGI_CREATE_FACTORY_FLAGS, "Flags"), (REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppFactory")]),
+])
+
+IDXGIDevice3 = Interface("IDXGIDevice3", IDXGIDevice2)
+IDXGIDevice3.methods += [
+ StdMethod(Void, "Trim", []),
+]
+
+DXGI_MATRIX_3X2_F = Struct("DXGI_MATRIX_3X2_F", [
+ (FLOAT, "_11"),
+ (FLOAT, "_12"),
+ (FLOAT, "_21"),
+ (FLOAT, "_22"),
+ (FLOAT, "_31"),
+ (FLOAT, "_32"),
+])
+
+IDXGISwapChain2 = Interface("IDXGISwapChain2", IDXGISwapChain1)
+IDXGISwapChain2.methods += [
+ StdMethod(HRESULT, "SetSourceSize", [(UINT, "Width"), (UINT, "Height")]),
+ StdMethod(HRESULT, "GetSourceSize", [Out(Pointer(UINT), "pWidth"), Out(Pointer(UINT), "pHeight")], sideeffects=False),
+ StdMethod(HRESULT, "SetMaximumFrameLatency", [(UINT, "MaxLatency")]),
+ StdMethod(HRESULT, "GetMaximumFrameLatency", [Out(Pointer(UINT), "pMaxLatency")], sideeffects=False),
+ StdMethod(HANDLE, "GetFrameLatencyWaitableObject", [], sideeffects=False),
+ StdMethod(HRESULT, "SetMatrixTransform", [(Pointer(Const(DXGI_MATRIX_3X2_F)), "pMatrix")]),
+ StdMethod(HRESULT, "GetMatrixTransform", [Out(Pointer(DXGI_MATRIX_3X2_F), "pMatrix")], sideeffects=False),
+]
+
+IDXGIOutput2 = Interface("IDXGIOutput2", IDXGIOutput1)
+IDXGIOutput2.methods += [
+ StdMethod(BOOL, "SupportsOverlays", [], sideeffects=False),
+]
+
+IDXGIFactory3 = Interface("IDXGIFactory3", IDXGIFactory2)
+IDXGIFactory3.methods += [
+ StdMethod(DXGI_CREATE_FACTORY_FLAGS, "GetCreationFlags", [], sideeffects=False),
+]
+
+DXGI_DECODE_SWAP_CHAIN_DESC = Struct("DXGI_DECODE_SWAP_CHAIN_DESC", [
+ (UINT, "Flags"),
+])
+
+# XXX: Flags
+DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS = Enum("DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS", [
+ "DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAG_NOMINAL_RANGE",
+ "DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAG_BT709",
+ "DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAG_xvYCC",
+])
+
+IDXGIDecodeSwapChain = Interface("IDXGIDecodeSwapChain", IUnknown)
+IDXGIDecodeSwapChain.methods += [
+ StdMethod(HRESULT, "PresentBuffer", [(UINT, "BufferToPresent"), (UINT, "SyncInterval"), (DXGI_PRESENT, "Flags")]),
+ StdMethod(HRESULT, "SetSourceRect", [(Pointer(Const(RECT)), "pRect")]),
+ StdMethod(HRESULT, "SetTargetRect", [(Pointer(Const(RECT)), "pRect")]),
+ StdMethod(HRESULT, "SetDestSize", [(UINT, "Width"), (UINT, "Height")]),
+ StdMethod(HRESULT, "GetSourceRect", [Out(Pointer(RECT), "pRect")], sideeffects=False),
+ StdMethod(HRESULT, "GetTargetRect", [Out(Pointer(RECT), "pRect")], sideeffects=False),
+ StdMethod(HRESULT, "GetDestSize", [Out(Pointer(UINT), "pWidth"), Out(Pointer(UINT), "pHeight")], sideeffects=False),
+ StdMethod(HRESULT, "SetColorSpace", [(DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS, "ColorSpace")]),
+ StdMethod(DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS, "GetColorSpace", [], sideeffects=False),
+]
+
+IDXGIFactoryMedia = Interface("IDXGIFactoryMedia", IUnknown)
+IDXGIFactoryMedia.methods += [
+ StdMethod(HRESULT, "CreateSwapChainForCompositionSurfaceHandle", [(ObjPointer(IUnknown), "pDevice"), (HANDLE, "hSurface"), (Pointer(Const(DXGI_SWAP_CHAIN_DESC1)), "pDesc"), (ObjPointer(IDXGIOutput), "pRestrictToOutput"), Out(Pointer(ObjPointer(IDXGISwapChain1)), "ppSwapChain")]),
+ StdMethod(HRESULT, "CreateDecodeSwapChainForCompositionSurfaceHandle", [(ObjPointer(IUnknown), "pDevice"), (HANDLE, "hSurface"), (Pointer(DXGI_DECODE_SWAP_CHAIN_DESC), "pDesc"), (ObjPointer(IDXGIResource), "pYuvDecodeBuffers"), (ObjPointer(IDXGIOutput), "pRestrictToOutput"), Out(Pointer(ObjPointer(IDXGIDecodeSwapChain)), "ppSwapChain")]),
+]
+
+DXGI_FRAME_PRESENTATION_MODE = Enum("DXGI_FRAME_PRESENTATION_MODE", [
+ "DXGI_FRAME_PRESENTATION_MODE_COMPOSED",
+ "DXGI_FRAME_PRESENTATION_MODE_OVERLAY",
+ "DXGI_FRAME_PRESENTATION_MODE_NONE",
+])
+
+DXGI_FRAME_STATISTICS_MEDIA = Struct("DXGI_FRAME_STATISTICS_MEDIA", [
+ (UINT, "PresentCount"),
+ (UINT, "PresentRefreshCount"),
+ (UINT, "SyncRefreshCount"),
+ (LARGE_INTEGER, "SyncQPCTime"),
+ (LARGE_INTEGER, "SyncGPUTime"),
+ (DXGI_FRAME_PRESENTATION_MODE, "CompositionMode"),
+ (UINT, "ApprovedPresentDuration"),
+])
+
+IDXGISwapChainMedia = Interface("IDXGISwapChainMedia", IUnknown)
+IDXGISwapChainMedia.methods += [
+ StdMethod(HRESULT, "GetFrameStatisticsMedia", [Out(Pointer(DXGI_FRAME_STATISTICS_MEDIA), "pStats")], sideeffects=False),
+ StdMethod(HRESULT, "SetPresentDuration", [(UINT, "Duration")]),
+ StdMethod(HRESULT, "CheckPresentDurationSupport", [(UINT, "DesiredPresentDuration"), Out(Pointer(UINT), "pClosestSmallerPresentDuration"), Out(Pointer(UINT), "pClosestLargerPresentDuration")], sideeffects=False),
+]
+
+DXGI_OVERLAY_SUPPORT_FLAG = FakeEnum(UINT, [
+ "DXGI_OVERLAY_SUPPORT_FLAG_DIRECT",
+ "DXGI_OVERLAY_SUPPORT_FLAG_SCALING",
+])
+
+IDXGIOutput3 = Interface("IDXGIOutput3", IDXGIOutput2)
+IDXGIOutput3.methods += [
+ StdMethod(HRESULT, "CheckOverlaySupport", [(DXGI_FORMAT, "EnumFormat"), (ObjPointer(IUnknown), "pConcernedDevice"), Out(Pointer(DXGI_OVERLAY_SUPPORT_FLAG), "pFlags")], sideeffects=False),
+]
+
+dxgi.addInterfaces([
+ IDXGIDevice3,
+ IDXGISwapChain2,
+ IDXGISwapChainMedia,
+ IDXGIOutput3,
+ IDXGIFactory3,
+ IDXGIFactoryMedia,
+])
+
+
+
+#
+# Undocumented interfaces
+#
+
IDXGIFactoryDWM = Interface("IDXGIFactoryDWM", IUnknown)
IDXGISwapChainDWM = Interface("IDXGISwapChainDWM", IDXGIDeviceSubObject)
@@ -306,17 +908,14 @@ IDXGISwapChainDWM.methods += [
StdMethod(HRESULT, "GetContainingOutput", [Out(Pointer(ObjPointer(IDXGIOutput)), "ppOutput")]),
StdMethod(HRESULT, "GetFrameStatistics", [Out(Pointer(DXGI_FRAME_STATISTICS), "pStats")], sideeffects=False),
StdMethod(HRESULT, "GetLastPresentCount", [Out(Pointer(UINT), "pLastPresentCount")], sideeffects=False),
- StdMethod(HRESULT, "SetFullscreenState", [(BOOL, "Fullscreen"), (ObjPointer(IDXGIOutput), "pTarget")]),
- StdMethod(HRESULT, "GetFullscreenState", [Out(Pointer(BOOL), "pFullscreen"), Out(Pointer(ObjPointer(IDXGIOutput)), "ppTarget")]),
]
+IWarpPrivateAPI = Interface("IWarpPrivateAPI", IUnknown)
+IWarpPrivateAPI.methods += [
+ StdMethod(HRESULT, "WarpEscape", [(OpaquePointer(Void), "pData")]),
+]
-dxgi = Module('dxgi')
dxgi.addInterfaces([
- IDXGIFactory1,
IDXGIFactoryDWM,
-])
-dxgi.addFunctions([
- StdFunction(HRESULT, "CreateDXGIFactory", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppFactory")]),
- StdFunction(HRESULT, "CreateDXGIFactory1", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppFactory")]),
+ IWarpPrivateAPI,
])
diff --git a/specs/dxgi1_2.py b/specs/dxgi1_2.py
deleted file mode 100644
index 0e4d58d8..00000000
--- a/specs/dxgi1_2.py
+++ /dev/null
@@ -1,52 +0,0 @@
-##########################################################################
-#
-# Copyright 2013 Jeff Muizelaar
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-
-from dxgi import *
-
-
-IDXGIResource1 = Interface("IDXGIResource1", IDXGIResource)
-IDXGISurface2 = Interface("IDXGISurface2", IDXGISurface1)
-
-
-DXGI_SHARED_RESOURCE_FLAG = Flags(DWORD, [
- "DXGI_SHARED_RESOURCE_READ",
- "DXGI_SHARED_RESOURCE_WRITE",
-])
-
-
-IDXGIResource1.methods += [
- StdMethod(HRESULT, "CreateSharedHandle", [(Pointer(Const(SECURITY_ATTRIBUTES)), "pAttributes"), (DXGI_SHARED_RESOURCE_FLAG, "dwAccess"), (LPCWSTR, "lpName"), Out(Pointer(HANDLE), "pHandle")]),
- StdMethod(HRESULT, "CreateSubresourceSurface", [(UINT, "index"), Out(Pointer(ObjPointer(IDXGISurface2)), "ppSurface")]),
-]
-
-
-IDXGISurface2.methods += [
- StdMethod(HRESULT, "GetResource", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppParentResource"), Out(Pointer(UINT), "pSubresourceIndex")]),
-]
-
-dxgi.addInterfaces([
- IDXGIResource1,
-])
diff --git a/specs/dxgiformat.py b/specs/dxgiformat.py
deleted file mode 100644
index b2d2a75e..00000000
--- a/specs/dxgiformat.py
+++ /dev/null
@@ -1,132 +0,0 @@
-##########################################################################
-#
-# Copyright 2011 Jose Fonseca
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-
-from winapi import *
-
-
-DXGI_FORMAT = Enum("DXGI_FORMAT", [
- "DXGI_FORMAT_UNKNOWN",
- "DXGI_FORMAT_R32G32B32A32_TYPELESS",
- "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "DXGI_FORMAT_R32G32B32A32_UINT",
- "DXGI_FORMAT_R32G32B32A32_SINT",
- "DXGI_FORMAT_R32G32B32_TYPELESS",
- "DXGI_FORMAT_R32G32B32_FLOAT",
- "DXGI_FORMAT_R32G32B32_UINT",
- "DXGI_FORMAT_R32G32B32_SINT",
- "DXGI_FORMAT_R16G16B16A16_TYPELESS",
- "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "DXGI_FORMAT_R16G16B16A16_UNORM",
- "DXGI_FORMAT_R16G16B16A16_UINT",
- "DXGI_FORMAT_R16G16B16A16_SNORM",
- "DXGI_FORMAT_R16G16B16A16_SINT",
- "DXGI_FORMAT_R32G32_TYPELESS",
- "DXGI_FORMAT_R32G32_FLOAT",
- "DXGI_FORMAT_R32G32_UINT",
- "DXGI_FORMAT_R32G32_SINT",
- "DXGI_FORMAT_R32G8X24_TYPELESS",
- "DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
- "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
- "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT",
- "DXGI_FORMAT_R10G10B10A2_TYPELESS",
- "DXGI_FORMAT_R10G10B10A2_UNORM",
- "DXGI_FORMAT_R10G10B10A2_UINT",
- "DXGI_FORMAT_R11G11B10_FLOAT",
- "DXGI_FORMAT_R8G8B8A8_TYPELESS",
- "DXGI_FORMAT_R8G8B8A8_UNORM",
- "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "DXGI_FORMAT_R8G8B8A8_UINT",
- "DXGI_FORMAT_R8G8B8A8_SNORM",
- "DXGI_FORMAT_R8G8B8A8_SINT",
- "DXGI_FORMAT_R16G16_TYPELESS",
- "DXGI_FORMAT_R16G16_FLOAT",
- "DXGI_FORMAT_R16G16_UNORM",
- "DXGI_FORMAT_R16G16_UINT",
- "DXGI_FORMAT_R16G16_SNORM",
- "DXGI_FORMAT_R16G16_SINT",
- "DXGI_FORMAT_R32_TYPELESS",
- "DXGI_FORMAT_D32_FLOAT",
- "DXGI_FORMAT_R32_FLOAT",
- "DXGI_FORMAT_R32_UINT",
- "DXGI_FORMAT_R32_SINT",
- "DXGI_FORMAT_R24G8_TYPELESS",
- "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
- "DXGI_FORMAT_X24_TYPELESS_G8_UINT",
- "DXGI_FORMAT_R8G8_TYPELESS",
- "DXGI_FORMAT_R8G8_UNORM",
- "DXGI_FORMAT_R8G8_UINT",
- "DXGI_FORMAT_R8G8_SNORM",
- "DXGI_FORMAT_R8G8_SINT",
- "DXGI_FORMAT_R16_TYPELESS",
- "DXGI_FORMAT_R16_FLOAT",
- "DXGI_FORMAT_D16_UNORM",
- "DXGI_FORMAT_R16_UNORM",
- "DXGI_FORMAT_R16_UINT",
- "DXGI_FORMAT_R16_SNORM",
- "DXGI_FORMAT_R16_SINT",
- "DXGI_FORMAT_R8_TYPELESS",
- "DXGI_FORMAT_R8_UNORM",
- "DXGI_FORMAT_R8_UINT",
- "DXGI_FORMAT_R8_SNORM",
- "DXGI_FORMAT_R8_SINT",
- "DXGI_FORMAT_A8_UNORM",
- "DXGI_FORMAT_R1_UNORM",
- "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
- "DXGI_FORMAT_R8G8_B8G8_UNORM",
- "DXGI_FORMAT_G8R8_G8B8_UNORM",
- "DXGI_FORMAT_BC1_TYPELESS",
- "DXGI_FORMAT_BC1_UNORM",
- "DXGI_FORMAT_BC1_UNORM_SRGB",
- "DXGI_FORMAT_BC2_TYPELESS",
- "DXGI_FORMAT_BC2_UNORM",
- "DXGI_FORMAT_BC2_UNORM_SRGB",
- "DXGI_FORMAT_BC3_TYPELESS",
- "DXGI_FORMAT_BC3_UNORM",
- "DXGI_FORMAT_BC3_UNORM_SRGB",
- "DXGI_FORMAT_BC4_TYPELESS",
- "DXGI_FORMAT_BC4_UNORM",
- "DXGI_FORMAT_BC4_SNORM",
- "DXGI_FORMAT_BC5_TYPELESS",
- "DXGI_FORMAT_BC5_UNORM",
- "DXGI_FORMAT_BC5_SNORM",
- "DXGI_FORMAT_B5G6R5_UNORM",
- "DXGI_FORMAT_B5G5R5A1_UNORM",
- "DXGI_FORMAT_B8G8R8A8_UNORM",
- "DXGI_FORMAT_B8G8R8X8_UNORM",
- "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM",
- "DXGI_FORMAT_B8G8R8A8_TYPELESS",
- "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB",
- "DXGI_FORMAT_B8G8R8X8_TYPELESS",
- "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB",
- "DXGI_FORMAT_BC6H_TYPELESS",
- "DXGI_FORMAT_BC6H_UF16",
- "DXGI_FORMAT_BC6H_SF16",
- "DXGI_FORMAT_BC7_TYPELESS",
- "DXGI_FORMAT_BC7_UNORM",
- "DXGI_FORMAT_BC7_UNORM_SRGB",
-])
-
diff --git a/specs/dxgitype.py b/specs/dxgitype.py
deleted file mode 100644
index c6202b58..00000000
--- a/specs/dxgitype.py
+++ /dev/null
@@ -1,115 +0,0 @@
-##########################################################################
-#
-# Copyright 2011 Jose Fonseca
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-
-from dxgiformat import *
-
-
-HRESULT = MAKE_HRESULT([
- "DXGI_STATUS_OCCLUDED",
- "DXGI_STATUS_CLIPPED",
- "DXGI_STATUS_NO_REDIRECTION",
- "DXGI_STATUS_NO_DESKTOP_ACCESS",
- "DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE",
- "DXGI_STATUS_MODE_CHANGED",
- "DXGI_STATUS_MODE_CHANGE_IN_PROGRESS",
- "DXGI_ERROR_INVALID_CALL",
- "DXGI_ERROR_NOT_FOUND",
- "DXGI_ERROR_MORE_DATA",
- "DXGI_ERROR_UNSUPPORTED",
- "DXGI_ERROR_DEVICE_REMOVED",
- "DXGI_ERROR_DEVICE_HUNG",
- "DXGI_ERROR_DEVICE_RESET",
- "DXGI_ERROR_WAS_STILL_DRAWING",
- "DXGI_ERROR_FRAME_STATISTICS_DISJOINT",
- "DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE",
- "DXGI_ERROR_DRIVER_INTERNAL_ERROR",
- "DXGI_ERROR_NONEXCLUSIVE",
- "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE",
- "DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED",
- "DXGI_ERROR_REMOTE_OUTOFMEMORY",
-])
-
-
-DXGI_RGB = Struct("DXGI_RGB", [
- (Float, "Red"),
- (Float, "Green"),
- (Float, "Blue"),
-])
-
-DXGI_GAMMA_CONTROL = Struct("DXGI_GAMMA_CONTROL", [
- (DXGI_RGB, "Scale"),
- (DXGI_RGB, "Offset"),
- (Array(DXGI_RGB, 1025), "GammaCurve"),
-])
-
-DXGI_GAMMA_CONTROL_CAPABILITIES = Struct("DXGI_GAMMA_CONTROL_CAPABILITIES", [
- (BOOL, "ScaleAndOffsetSupported"),
- (Float, "MaxConvertedValue"),
- (Float, "MinConvertedValue"),
- (UINT, "NumGammaControlPoints"),
- (Array(Float, 1025), "ControlPointPositions"),
-])
-
-DXGI_RATIONAL = Struct("DXGI_RATIONAL", [
- (UINT, "Numerator"),
- (UINT, "Denominator"),
-])
-
-DXGI_MODE_SCANLINE_ORDER = Enum("DXGI_MODE_SCANLINE_ORDER", [
- "DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED",
- "DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE",
- "DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST",
- "DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST",
-])
-
-DXGI_MODE_SCALING = Enum("DXGI_MODE_SCALING", [
- "DXGI_MODE_SCALING_UNSPECIFIED",
- "DXGI_MODE_SCALING_CENTERED",
- "DXGI_MODE_SCALING_STRETCHED",
-])
-
-DXGI_MODE_ROTATION = Enum("DXGI_MODE_ROTATION", [
- "DXGI_MODE_ROTATION_UNSPECIFIED",
- "DXGI_MODE_ROTATION_IDENTITY",
- "DXGI_MODE_ROTATION_ROTATE90",
- "DXGI_MODE_ROTATION_ROTATE180",
- "DXGI_MODE_ROTATION_ROTATE270",
-])
-
-DXGI_MODE_DESC = Struct("DXGI_MODE_DESC", [
- (UINT, "Width"),
- (UINT, "Height"),
- (DXGI_RATIONAL, "RefreshRate"),
- (DXGI_FORMAT, "Format"),
- (DXGI_MODE_SCANLINE_ORDER, "ScanlineOrdering"),
- (DXGI_MODE_SCALING, "Scaling"),
-])
-
-DXGI_SAMPLE_DESC = Struct("DXGI_SAMPLE_DESC", [
- (UINT, "Count"),
- (UINT, "Quality"),
-])
-
diff --git a/specs/dxva2.py b/specs/dxva2.py
new file mode 100644
index 00000000..3936afac
--- /dev/null
+++ b/specs/dxva2.py
@@ -0,0 +1,458 @@
+##########################################################################
+#
+# Copyright 2012-2015 VMware, Inc.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+##########################################################################/
+
+
+from d3d9 import *
+
+
+HRESULT = MAKE_HRESULT(errors = [
+ "DXVA2_E_NOT_INITIALIZED",
+ "DXVA2_E_NEW_VIDEO_DEVICE",
+ "DXVA2_E_VIDEO_DEVICE_LOCKED",
+ "DXVA2_E_NOT_AVAILABLE",
+])
+
+DXVA2_SampleFormat = FakeEnum(UINT, [
+ "DXVA2_SampleUnknown",
+ "DXVA2_SampleProgressiveFrame",
+ "DXVA2_SampleFieldInterleavedEvenFirst",
+ "DXVA2_SampleFieldInterleavedOddFirst",
+ "DXVA2_SampleFieldSingleEven",
+ "DXVA2_SampleFieldSingleOdd",
+ "DXVA2_SampleSubStream",
+])
+
+DXVA2_VideoChromaSubSampling = FakeEnum(UINT, [
+ "DXVA2_VideoChromaSubsampling_Unknown",
+ "DXVA2_VideoChromaSubsampling_ProgressiveChroma",
+ "DXVA2_VideoChromaSubsampling_Horizontally_Cosited",
+ "DXVA2_VideoChromaSubsampling_Vertically_Cosited",
+ "DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes",
+ "DXVA2_VideoChromaSubsampling_MPEG2",
+ "DXVA2_VideoChromaSubsampling_MPEG1",
+ "DXVA2_VideoChromaSubsampling_DV_PAL",
+ "DXVA2_VideoChromaSubsampling_Cosited",
+])
+
+DXVA2_NominalRange = FakeEnum(UINT, [
+ "DXVA2_NominalRange_Unknown",
+ "DXVA2_NominalRange_Normal",
+ "DXVA2_NominalRange_Wide",
+ "DXVA2_NominalRange_0_255",
+ "DXVA2_NominalRange_16_235",
+ "DXVA2_NominalRange_48_208",
+])
+
+DXVA2_VideoTransferMatrix = FakeEnum(UINT, [
+ "DXVA2_VideoTransferMatrix_Unknown",
+ "DXVA2_VideoTransferMatrix_BT709",
+ "DXVA2_VideoTransferMatrix_BT601",
+ "DXVA2_VideoTransferMatrix_SMPTE240M",
+])
+
+DXVA2_VideoLighting = FakeEnum(UINT, [
+ "DXVA2_VideoLighting_Unknown",
+ "DXVA2_VideoLighting_bright",
+ "DXVA2_VideoLighting_office",
+ "DXVA2_VideoLighting_dim",
+ "DXVA2_VideoLighting_dark",
+])
+
+DXVA2_VideoPrimaries = FakeEnum(UINT, [
+ "DXVA2_VideoPrimaries_Unknown",
+ "DXVA2_VideoPrimaries_reserved",
+ "DXVA2_VideoPrimaries_BT709",
+ "DXVA2_VideoPrimaries_BT470_2_SysM",
+ "DXVA2_VideoPrimaries_BT470_2_SysBG",
+ "DXVA2_VideoPrimaries_SMPTE170M",
+ "DXVA2_VideoPrimaries_SMPTE240M",
+ "DXVA2_VideoPrimaries_EBU3213",
+ "DXVA2_VideoPrimaries_SMPTE_C",
+])
+
+DXVA2_VideoTransferFunction = FakeEnum(UINT, [
+ "DXVA2_VideoTransFunc_Unknown",
+ "DXVA2_VideoTransFunc_10",
+ "DXVA2_VideoTransFunc_18",
+ "DXVA2_VideoTransFunc_20",
+ "DXVA2_VideoTransFunc_22",
+ "DXVA2_VideoTransFunc_709",
+ "DXVA2_VideoTransFunc_240M",
+ "DXVA2_VideoTransFunc_sRGB",
+ "DXVA2_VideoTransFunc_28",
+])
+
+DXVA2_ExtendedFormat = Struct("DXVA2_ExtendedFormat", [
+ (DXVA2_SampleFormat, "SampleFormat"),
+ (DXVA2_VideoChromaSubSampling, "VideoChromaSubsampling"),
+ (DXVA2_NominalRange, "NominalRange"),
+ (DXVA2_VideoTransferMatrix, "VideoTransferMatrix"),
+ (DXVA2_VideoLighting, "VideoLighting"),
+ (DXVA2_VideoPrimaries, "VideoPrimaries"),
+ (DXVA2_VideoTransferFunction, "VideoTransferFunction"),
+])
+
+DXVA2_Frequency = Struct("DXVA2_Frequency", [
+ (UINT, "Numerator"),
+ (UINT, "Denominator"),
+])
+
+DXVA2_VideoDesc = Struct("DXVA2_VideoDesc", [
+ (UINT, "SampleWidth"),
+ (UINT, "SampleHeight"),
+ (DXVA2_ExtendedFormat, "SampleFormat"),
+ (D3DFORMAT, "Format"),
+ (DXVA2_Frequency, "InputSampleFreq"),
+ (DXVA2_Frequency, "OutputFrameFreq"),
+ (UINT, "UABProtectionLevel"),
+ (UINT, "Reserved"),
+])
+
+DXVA2_DeinterlaceTech = Flags(UINT, [
+ "DXVA2_DeinterlaceTech_Unknown",
+ "DXVA2_DeinterlaceTech_BOBLineReplicate",
+ "DXVA2_DeinterlaceTech_BOBVerticalStretch",
+ "DXVA2_DeinterlaceTech_BOBVerticalStretch4Tap",
+ "DXVA2_DeinterlaceTech_MedianFiltering",
+ "DXVA2_DeinterlaceTech_EdgeFiltering",
+ "DXVA2_DeinterlaceTech_FieldAdaptive",
+ "DXVA2_DeinterlaceTech_PixelAdaptive",
+ "DXVA2_DeinterlaceTech_MotionVectorSteered",
+ "DXVA2_DeinterlaceTech_InverseTelecine",
+])
+
+DXVA2_Filter = Enum("DXVA2_Filter", [
+ "DXVA2_NoiseFilterLumaLevel",
+ "DXVA2_NoiseFilterLumaThreshold",
+ "DXVA2_NoiseFilterLumaRadius",
+ "DXVA2_NoiseFilterChromaLevel",
+ "DXVA2_NoiseFilterChromaThreshold",
+ "DXVA2_NoiseFilterChromaRadius",
+ "DXVA2_DetailFilterLumaLevel",
+ "DXVA2_DetailFilterLumaThreshold",
+ "DXVA2_DetailFilterLumaRadius",
+ "DXVA2_DetailFilterChromaLevel",
+ "DXVA2_DetailFilterChromaThreshold",
+ "DXVA2_DetailFilterChromaRadius",
+])
+
+DXVA2_NoiseFilterTech = Flags(UINT, [
+ "DXVA2_NoiseFilterTech_Unsupported",
+ "DXVA2_NoiseFilterTech_Unknown",
+ "DXVA2_NoiseFilterTech_Median",
+ "DXVA2_NoiseFilterTech_Temporal",
+ "DXVA2_NoiseFilterTech_BlockNoise",
+ "DXVA2_NoiseFilterTech_MosquitoNoise",
+])
+
+DXVA2_DetailFilterTech = Flags(UINT, [
+ "DXVA2_DetailFilterTech_Unsupported",
+ "DXVA2_DetailFilterTech_Unknown",
+ "DXVA2_DetailFilterTech_Edge",
+ "DXVA2_DetailFilterTech_Sharpening",
+])
+
+DXVA2_ProcAmp = Flags(UINT, [
+ "DXVA2_ProcAmp_None",
+ "DXVA2_ProcAmp_Brightness",
+ "DXVA2_ProcAmp_Contrast",
+ "DXVA2_ProcAmp_Hue",
+ "DXVA2_ProcAmp_Saturation",
+])
+
+DXVA2_VideoProcess = Flags(UINT, [
+ "DXVA2_VideoProcess_None",
+ "DXVA2_VideoProcess_YUV2RGB",
+ "DXVA2_VideoProcess_StretchX",
+ "DXVA2_VideoProcess_StretchY",
+ "DXVA2_VideoProcess_AlphaBlend",
+ "DXVA2_VideoProcess_SubRects",
+ "DXVA2_VideoProcess_SubStreams",
+ "DXVA2_VideoProcess_SubStreamsExtended",
+ "DXVA2_VideoProcess_YUV2RGBExtended",
+ "DXVA2_VideoProcess_AlphaBlendExtended",
+ "DXVA2_VideoProcess_Constriction",
+ "DXVA2_VideoProcess_NoiseFilter",
+ "DXVA2_VideoProcess_DetailFilter",
+ "DXVA2_VideoProcess_PlanarAlpha",
+ "DXVA2_VideoProcess_LinearScaling",
+ "DXVA2_VideoProcess_GammaCompensated",
+ "DXVA2_VideoProcess_MaintainsOriginalFieldData",
+])
+
+DXVA2_VPDev = Flags(UINT, [
+ "DXVA2_VPDev_HardwareDevice",
+ "DXVA2_VPDev_EmulatedDXVA1",
+ "DXVA2_VPDev_SoftwareDevice",
+])
+
+DXVA2_SampleData = Flags(UINT, [
+ "DXVA2_SampleData_RFF",
+ "DXVA2_SampleData_TFF",
+ "DXVA2_SampleData_RFF_TFF_Present",
+])
+
+DXVA2_DestData = Flags(UINT, [
+ "DXVA2_DestData_RFF",
+ "DXVA2_DestData_TFF",
+ "DXVA2_DestData_RFF_TFF_Present",
+])
+
+DXVA2_VideoProcessorCaps = Struct("DXVA2_VideoProcessorCaps", [
+ (DXVA2_VPDev, "DeviceCaps"),
+ (D3DPOOL, "InputPool"),
+ (UINT, "NumForwardRefSamples"),
+ (UINT, "NumBackwardRefSamples"),
+ (UINT, "Reserved"),
+ (DXVA2_DeinterlaceTech, "DeinterlaceTechnology"),
+ (DXVA2_ProcAmp, "ProcAmpControlCaps"),
+ (DXVA2_VideoProcess, "VideoProcessorOperations"),
+ (DXVA2_NoiseFilterTech, "NoiseFilterTechnology"),
+ (DXVA2_DetailFilterTech, "DetailFilterTechnology"),
+])
+
+DXVA2_Fixed32 = Struct("DXVA2_Fixed32", [
+ (USHORT, "Fraction"),
+ (SHORT, "Value"),
+])
+
+DXVA2_AYUVSample8 = Struct("DXVA2_AYUVSample8", [
+ (UCHAR, "Cr"),
+ (UCHAR, "Cb"),
+ (UCHAR, "Y"),
+ (UCHAR, "Alpha"),
+])
+
+DXVA2_AYUVSample16 = Struct("DXVA2_AYUVSample16", [
+ (USHORT, "Cr"),
+ (USHORT, "Cb"),
+ (USHORT, "Y"),
+ (USHORT, "Alpha"),
+])
+
+REFERENCE_TIME = Alias("REFERENCE_TIME", LONGLONG)
+DXVA2_VideoSample = Struct("DXVA2_VideoSample", [
+ (REFERENCE_TIME, "Start"),
+ (REFERENCE_TIME, "End"),
+ (DXVA2_ExtendedFormat, "SampleFormat"),
+ (ObjPointer(IDirect3DSurface9), "SrcSurface"),
+ (RECT, "SrcRect"),
+ (RECT, "DstRect"),
+ (Array(DXVA2_AYUVSample8, 16), "Pal"),
+ (DXVA2_Fixed32, "PlanarAlpha"),
+ (DWORD, "SampleData"),
+])
+
+DXVA2_ValueRange = Struct("DXVA2_ValueRange", [
+ (DXVA2_Fixed32, "MinValue"),
+ (DXVA2_Fixed32, "MaxValue"),
+ (DXVA2_Fixed32, "DefaultValue"),
+ (DXVA2_Fixed32, "StepSize"),
+])
+
+DXVA2_ProcAmpValues = Struct("DXVA2_ProcAmpValues", [
+ (DXVA2_Fixed32, "Brightness"),
+ (DXVA2_Fixed32, "Contrast"),
+ (DXVA2_Fixed32, "Hue"),
+ (DXVA2_Fixed32, "Saturation"),
+])
+
+DXVA2_FilterValues = Struct("DXVA2_FilterValues", [
+ (DXVA2_Fixed32, "Level"),
+ (DXVA2_Fixed32, "Threshold"),
+ (DXVA2_Fixed32, "Radius"),
+])
+
+DXVA2_VideoProcessBltParams = Struct("DXVA2_VideoProcessBltParams", [
+ (REFERENCE_TIME, "TargetFrame"),
+ (RECT, "TargetRect"),
+ (SIZE, "ConstrictionSize"),
+ (UINT, "StreamingFlags"),
+ (DXVA2_AYUVSample16, "BackgroundColor"),
+ (DXVA2_ExtendedFormat, "DestFormat"),
+ (DXVA2_ProcAmpValues, "ProcAmpValues"),
+ (DXVA2_Fixed32, "Alpha"),
+ (DXVA2_FilterValues, "NoiseFilterLuma"),
+ (DXVA2_FilterValues, "NoiseFilterChroma"),
+ (DXVA2_FilterValues, "DetailFilterLuma"),
+ (DXVA2_FilterValues, "DetailFilterChroma"),
+ (DWORD, "DestData"),
+])
+
+DXVA2_BufferType = FakeEnum(UINT, [
+ "DXVA2_PictureParametersBufferType",
+ "DXVA2_MacroBlockControlBufferType",
+ "DXVA2_ResidualDifferenceBufferType",
+ "DXVA2_DeblockingControlBufferType",
+ "DXVA2_InverseQuantizationMatrixBufferType",
+ "DXVA2_SliceControlBufferType",
+ "DXVA2_BitStreamDateBufferType",
+ "DXVA2_MotionVectorBuffer",
+ "DXVA2_FilmGrainBuffer",
+])
+
+DXVA2_Type = FakeEnum(DWORD, [
+ "DXVA2_VideoDecoderRenderTarget",
+ "DXVA2_VideoProcessorRenderTarget",
+ "DXVA2_VideoSoftwareRenderTarget",
+])
+
+DXVA2_ConfigPictureDecode = Struct("DXVA2_ConfigPictureDecode", [
+ (GUID, "guidConfigBitstreamEncryption"),
+ (GUID, "guidConfigMBcontrolEncryption"),
+ (GUID, "guidConfigResidDiffEncryption"),
+ (UINT, "ConfigBitstreamRaw"),
+ (UINT, "ConfigMBcontrolRasterOrder"),
+ (UINT, "ConfigResidDiffHost"),
+ (UINT, "ConfigSpatialResid8"),
+ (UINT, "ConfigResid8Subtraction"),
+ (UINT, "ConfigSpatialHost8or9Clipping"),
+ (UINT, "ConfigSpatialResidInterleaved"),
+ (UINT, "ConfigIntraResidUnsigned"),
+ (UINT, "ConfigResidDiffAccelerator"),
+ (UINT, "ConfigHostInverseScan"),
+ (UINT, "ConfigSpecificIDCT"),
+ (UINT, "Config4GroupedCoefs"),
+ (USHORT, "ConfigMinRenderTargetBuffCount"),
+ (USHORT, "ConfigDecoderSpecific"),
+])
+
+DXVA2_AES_CTR_IV = Struct("DXVA2_AES_CTR_IV", [
+ (UINT64, "IV"),
+ (UINT64, "Count"),
+])
+
+DXVA2_DecodeBufferDesc = Struct("DXVA2_DecodeBufferDesc", [
+ (DXVA2_BufferType, "CompressedBufferType"),
+ (UINT, "BufferIndex"),
+ (UINT, "DataOffset"),
+ (UINT, "DataSize"),
+ (UINT, "FirstMBaddress"),
+ (UINT, "NumMBsInBuffer"),
+ (UINT, "Width"),
+ (UINT, "Height"),
+ (UINT, "Stride"),
+ (UINT, "ReservedBits"),
+ (Blob(VOID, "sizeof(DXVA2_AES_CTR_IV)"), "pvPVPState"),
+])
+
+DXVA2_DecodeExtensionData = Struct("DXVA2_DecodeExtensionData", [
+ (UINT, "Function"),
+ (Blob(Void, "{self}.PrivateInputDataSize"), "pPrivateInputData"),
+ (UINT, "PrivateInputDataSize"),
+ (Blob(Void, "{self}.PrivateOutputDataSize"), "pPrivateOutputData"),
+ (UINT, "PrivateOutputDataSize"),
+])
+
+DXVA2_DecodeExecuteParams = Struct("DXVA2_DecodeExecuteParams", [
+ (UINT, "NumCompBuffers"),
+ (Array(DXVA2_DecodeBufferDesc, "{self}.NumCompBuffers"), "pCompressedBuffers"),
+ (Pointer(DXVA2_DecodeExtensionData), "pExtensionData"),
+])
+
+RESET_TOKEN = Handle("resetToken", UINT)
+
+IDirect3DDeviceManager9 = Interface("IDirect3DDeviceManager9", IUnknown)
+IDirectXVideoAccelerationService = Interface("IDirectXVideoAccelerationService", IUnknown)
+IDirectXVideoDecoderService = Interface("IDirectXVideoDecoderService", IDirectXVideoAccelerationService)
+IDirectXVideoProcessorService = Interface("IDirectXVideoProcessorService", IDirectXVideoAccelerationService)
+IDirectXVideoDecoder = Interface("IDirectXVideoDecoder", IUnknown)
+IDirectXVideoProcessor = Interface("IDirectXVideoProcessor", IUnknown)
+
+IDirect3DDeviceManager9.methods += [
+ StdMethod(HRESULT, "ResetDevice", [(ObjPointer(IDirect3DDevice9), "pDevice"), (RESET_TOKEN, "resetToken")]),
+ StdMethod(HRESULT, "OpenDeviceHandle", [Out(Pointer(HANDLE), "phDevice")]),
+ StdMethod(HRESULT, "CloseDeviceHandle", [(HANDLE, "hDevice")]),
+ StdMethod(HRESULT, "TestDevice", [(HANDLE, "hDevice")]),
+ StdMethod(HRESULT, "LockDevice", [(HANDLE, "hDevice"), Out(Pointer(ObjPointer(IDirect3DDevice9)), "ppDevice"), (BOOL, "fBlock")]),
+ StdMethod(HRESULT, "UnlockDevice", [(HANDLE, "hDevice"), (BOOL, "fSaveState")]),
+ StdMethod(HRESULT, "GetVideoService", [(HANDLE, "hDevice"), (REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppService")]),
+]
+
+IDirectXVideoAccelerationService.methods += [
+ StdMethod(HRESULT, "CreateSurface", [(UINT, "Width"), (UINT, "Height"), (UINT, "BackBuffers"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), (D3DUSAGE, "Usage"), (DXVA2_Type, "DxvaType"), Out(Array(ObjPointer(IDirect3DSurface9), "1 + BackBuffers"), "ppSurface"), Out(Pointer(HANDLE), "pSharedHandle")]),
+]
+
+IDirectXVideoDecoderService.methods += [
+ StdMethod(HRESULT, "GetDecoderDeviceGuids", [Out(Pointer(UINT), "pCount"), Out(Pointer(Array(GUID, "pCount ? *pCount : 0")), "pGuids")], sideeffects=False),
+ StdMethod(HRESULT, "GetDecoderRenderTargets", [(REFGUID, "Guid"), Out(Pointer(UINT), "pCount"), Out(Pointer(Array(D3DFORMAT, "pCount ? *pCount : 0")), "pFormats")], sideeffects=False),
+ StdMethod(HRESULT, "GetDecoderConfigurations", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (OpaquePointer(Void), "pReserved"), Out(Pointer(UINT), "pCount"), Out(Pointer(Array(DXVA2_ConfigPictureDecode, "pCount ? *pCount : 0")), "ppConfigs")], sideeffects=False),
+ StdMethod(HRESULT, "CreateVideoDecoder", [(REFGUID, "Guid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (Pointer(Const(DXVA2_ConfigPictureDecode)), "pConfig"), (Array(ObjPointer(IDirect3DSurface9), "NumRenderTargets"), "ppDecoderRenderTargets"), (UINT, "NumRenderTargets"), Out(Pointer(ObjPointer(IDirectXVideoDecoder)), "ppDecode")]),
+]
+
+IDirectXVideoProcessorService.methods += [
+ StdMethod(HRESULT, "RegisterVideoProcessorSoftwareDevice", [(OpaquePointer(Void), "pCallbacks")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoProcessorDeviceGuids", [(Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), Out(Pointer(UINT), "pCount"), Out(Pointer(Array(GUID, "pCount ? *pCount : 0")), "pGuids")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoProcessorRenderTargets", [(REFGUID, "VideoProcDeviceGuid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), Out(Pointer(UINT), "pCount"), Out(Pointer(Array(D3DFORMAT, "pCount ? *pCount : 0")), "pFormats")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoProcessorSubStreamFormats", [(REFGUID, "VideoProcDeviceGuid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "RenderTargetFormat"), Out(Pointer(UINT), "pCount"), Out(Pointer(Array(D3DFORMAT, "pCount ? *pCount : 0")), "pFormats")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoProcessorCaps", [(REFGUID, "VideoProcDeviceGuid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "RenderTargetFormat"), Out(Pointer(DXVA2_VideoProcessorCaps), "pCaps")], sideeffects=False),
+ StdMethod(HRESULT, "GetProcAmpRange", [(REFGUID, "VideoProcDeviceGuid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "RenderTargetFormat"), (UINT, "ProcAmpCap"), Out(Pointer(DXVA2_ValueRange), "pRange")], sideeffects=False),
+ StdMethod(HRESULT, "GetFilterPropertyRange", [(REFGUID, "VideoProcDeviceGuid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "RenderTargetFormat"), (UINT, "FilterSetting"), Out(Pointer(DXVA2_ValueRange), "pRange")], sideeffects=False),
+ StdMethod(HRESULT, "CreateVideoProcessor", [(REFGUID, "VideoProcDeviceGuid"), (Pointer(Const(DXVA2_VideoDesc)), "pVideoDesc"), (D3DFORMAT, "RenderTargetFormat"), (UINT, "MaxNumSubStreams"), Out(Pointer(ObjPointer(IDirectXVideoProcessor)), "ppVidProcess")]),
+]
+
+IDirectXVideoDecoder.methods += [
+ StdMethod(HRESULT, "GetVideoDecoderService", [Out(Pointer(ObjPointer(IDirectXVideoDecoderService)), "ppService")]),
+ StdMethod(HRESULT, "GetCreationParameters", [Out(Pointer(GUID), "pDeviceGuid"), Out(Pointer(DXVA2_VideoDesc), "pVideoDesc"), Out(Pointer(DXVA2_ConfigPictureDecode), "pConfig"), Out(Pointer(Pointer(ObjPointer(IDirect3DSurface9))), "pDecoderRenderTargets"), Out(Pointer(UINT), "pNumSurfaces")]),
+ StdMethod(HRESULT, "GetBuffer", [(DXVA2_BufferType, "BufferType"), Out(Pointer(LinearPointer(Void, "*pBufferSize")), "ppBuffer"), Out(Pointer(UINT), "pBufferSize")]),
+ StdMethod(HRESULT, "ReleaseBuffer", [(DXVA2_BufferType, "BufferType")]),
+ StdMethod(HRESULT, "BeginFrame", [(ObjPointer(IDirect3DSurface9), "pRenderTarget"), (Blob(Void, 16), "pvPVPData")]),
+ StdMethod(HRESULT, "EndFrame", [Out(Pointer(HANDLE), "pHandleComplete")]),
+ StdMethod(HRESULT, "Execute", [(Pointer(Const(DXVA2_DecodeExecuteParams)), "pExecuteParams")]),
+]
+
+IDirectXVideoProcessor.methods += [
+ StdMethod(HRESULT, "GetVideoProcessorService", [Out(Pointer(ObjPointer(IDirectXVideoProcessorService)), "ppService")]),
+ StdMethod(HRESULT, "GetCreationParameters", [Out(Pointer(GUID), "pDeviceGuid"), Out(Pointer(DXVA2_VideoDesc), "pVideoDesc"), Out(Pointer(D3DFORMAT), "pRenderTargetFormat"), Out(Pointer(UINT), "pMaxNumSubStreams")], sideeffects=False),
+ StdMethod(HRESULT, "GetVideoProcessorCaps", [Out(Pointer(DXVA2_VideoProcessorCaps), "pCaps")], sideeffects=False),
+ StdMethod(HRESULT, "GetProcAmpRange", [(UINT, "ProcAmpCap"), Out(Pointer(DXVA2_ValueRange), "pRange")], sideeffects=False),
+ StdMethod(HRESULT, "GetFilterPropertyRange", [(UINT, "FilterSetting"), Out(Pointer(DXVA2_ValueRange), "pRange")], sideeffects=False),
+ StdMethod(HRESULT, "VideoProcessBlt", [(ObjPointer(IDirect3DSurface9), "pRenderTarget"), (Pointer(Const(DXVA2_VideoProcessBltParams)), "pBltParams"), (Array(Const(DXVA2_VideoSample), "NumSamples"), "pSamples"), (UINT, "NumSamples"), Out(Pointer(HANDLE), "pHandleComplete")]),
+]
+
+DXVA2_SurfaceType = Enum("DXVA2_SurfaceType", [
+ "DXVA2_SurfaceType_DecoderRenderTarget",
+ "DXVA2_SurfaceType_ProcessorRenderTarget",
+ "DXVA2_SurfaceType_D3DRenderTargetTexture",
+])
+
+IDirectXVideoMemoryConfiguration = Interface("IDirectXVideoMemoryConfiguration", IUnknown)
+IDirectXVideoMemoryConfiguration.methods += [
+ StdMethod(HRESULT, "GetAvailableSurfaceTypeByIndex", [(DWORD, "dwTypeIndex"), Out(Pointer(DXVA2_SurfaceType), "pdwType")], sideeffects=False),
+ StdMethod(HRESULT, "SetSurfaceType", [(DXVA2_SurfaceType, "dwType")]),
+]
+
+dxva2 = Module("dxva2")
+dxva2.addInterfaces([
+ IDirectXVideoAccelerationService,
+ IDirectXVideoDecoderService,
+ IDirectXVideoProcessorService,
+ IDirectXVideoMemoryConfiguration,
+])
+
+dxva2.addFunctions([
+ StdFunction(HRESULT, "DXVA2CreateDirect3DDeviceManager9", [Out(Pointer(RESET_TOKEN), "pResetToken"), Out(Pointer(ObjPointer(IDirect3DDeviceManager9)), "ppDeviceManager")]),
+ StdFunction(HRESULT, "DXVA2CreateVideoService", [(ObjPointer(IDirect3DDevice9), "pDD"), (REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppService")]),
+])
diff --git a/specs/eglapi.py b/specs/eglapi.py
index 39ad39c6..8379e45e 100644
--- a/specs/eglapi.py
+++ b/specs/eglapi.py
@@ -87,11 +87,11 @@ EGLSurfaceFlags = Flags(Int, [
])
EGLConformantFlags = Flags(Int, [
- 'EGL_OPENGL_BIT',
- 'EGL_OPENGL_ES_BIT',
- 'EGL_OPENGL_ES2_BIT',
- 'EGL_OPENGL_ES3_BIT_KHR',
- 'EGL_OPENVG_BIT',
+ 'EGL_OPENGL_ES_BIT', # 0x0001
+ 'EGL_OPENVG_BIT', # 0x0002
+ 'EGL_OPENGL_ES2_BIT', # 0x0004
+ 'EGL_OPENGL_BIT', # 0x0008
+ 'EGL_OPENGL_ES3_BIT', # 0x0040
])
EGLVGAlphaFormat = FakeEnum(Int, ['EGL_VG_ALPHA_FORMAT_NONPRE', 'EGL_VG_ALPHA_FORMAT_PRE'])
@@ -191,6 +191,10 @@ EGLFenceSyncNVAttribs = EGLAttribArray([
('EGL_SYNC_STATUS_NV', Flags(Int, ['EGL_SIGNALED_NV', 'EGL_UNSIGNALED_NV']))
])
+EGLPlatformDisplayAttribs = EGLAttribArray([
+ ('EGL_PLATFORM_X11_SCREEN_EXT', Int),
+])
+
EGLProc = Opaque("__eglMustCastToProperFunctionPointerType")
def GlFunction(*args, **kwargs):
@@ -207,8 +211,8 @@ eglapi.addFunctions([
Function(ConstCString, "eglQueryString", [(EGLDisplay, "dpy"), (EGLint_enum, "name")], sideeffects=False),
- Function(EGLBoolean, "eglGetConfigs", [(EGLDisplay, "dpy"), Out(Array(EGLConfig, "config_size"), "configs"), (EGLint, "config_size"), Out(Pointer(EGLint), "num_config")]),
- Function(EGLBoolean, "eglChooseConfig", [(EGLDisplay, "dpy"), (EGLConfigAttribs, "attrib_list"), Out(Array(EGLConfig, "config_size"), "configs"), (EGLint, "config_size"), Out(Pointer(EGLint), "num_config")]),
+ Function(EGLBoolean, "eglGetConfigs", [(EGLDisplay, "dpy"), Out(Array(EGLConfig, "*num_config"), "configs"), (EGLint, "config_size"), Out(Pointer(EGLint), "num_config")]),
+ Function(EGLBoolean, "eglChooseConfig", [(EGLDisplay, "dpy"), (EGLConfigAttribs, "attrib_list"), Out(Array(EGLConfig, "*num_config"), "configs"), (EGLint, "config_size"), Out(Pointer(EGLint), "num_config")]),
Function(EGLBoolean, "eglGetConfigAttrib", [(EGLDisplay, "dpy"), (EGLConfig, "config"), (EGLattrib, "attribute"), Out(Pointer(EGLint), "value")], sideeffects=False),
Function(EGLSurface, "eglCreateWindowSurface", [(EGLDisplay, "dpy"), (EGLConfig, "config"), (EGLNativeWindowType, "win"), (EGLWindowsSurfaceAttribs, "attrib_list")]),
@@ -249,6 +253,11 @@ eglapi.addFunctions([
Function(EGLProc, "eglGetProcAddress", [(ConstCString, "procname")]),
+ # EGL_EXT_platform_base
+ GlFunction(EGLDisplay, "eglGetPlatformDisplayEXT", [(EGLenum, "platform"), (OpaquePointer(Void), "native_display"), (EGLPlatformDisplayAttribs, "attrib_list")]),
+ GlFunction(EGLSurface, "eglCreatePlatformWindowSurfaceEXT", [(EGLDisplay, "dpy"), (EGLConfig, "config"), (OpaquePointer(Void), "native_window"), (EGLAttribArray([]), "attrib_list")]),
+ GlFunction(EGLSurface, "eglCreatePlatformPixmapSurfaceEXT", [(EGLDisplay, "dpy"), (EGLConfig, "config"), (OpaquePointer(Void), "native_pixmap"), (EGLAttribArray([]), "attrib_list")]),
+
# EGL_KHR_lock_surface
# EGL_KHR_lock_surface2
Function(EGLBoolean, "eglLockSurfaceKHR", [(EGLDisplay, "display"), (EGLSurface, "surface"), (EGLLockSurfaceKHRAttribs, "attrib_list")]),
diff --git a/specs/glapi.py b/specs/glapi.py
index 2a29379a..2ab59bd4 100644
--- a/specs/glapi.py
+++ b/specs/glapi.py
@@ -118,7 +118,7 @@ glapi.addFunctions([
GlFunction(Void, "glCallLists", [(GLsizei, "n"), (GLenum, "type"), (Blob(Const(GLvoid), "_glCallLists_size(n, type)"), "lists")]),
GlFunction(Void, "glDeleteLists", [(GLlist, "list"), (GLsizei, "range")]),
GlFunction(Handle("list", GLuint, "range"), "glGenLists", [(GLsizei, "range")]),
- GlFunction(Void, "glListBase", [(GLuint, "base")]),
+ GlFunction(Void, "glListBase", [(GLlist, "base")]),
GlFunction(Void, "glBegin", [(GLenum_mode, "mode")]),
GlFunction(Void, "glBitmap", [(GLsizei, "width"), (GLsizei, "height"), (GLfloat, "xorig"), (GLfloat, "yorig"), (GLfloat, "xmove"), (GLfloat, "ymove"), (Blob(Const(GLubyte), "_glBitmap_size(width, height)"), "bitmap")]),
GlFunction(Void, "glColor3b", [(GLbyte, "red"), (GLbyte, "green"), (GLbyte, "blue")]),
@@ -380,8 +380,8 @@ glapi.addFunctions([
GlFunction(Void, "glCopyTexImage2D", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border")]),
GlFunction(Void, "glCopyTexSubImage1D", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width")]),
GlFunction(Void, "glCopyTexSubImage2D", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glTexSubImage1D", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexSubImage1D_size(format, type, width)"), "pixels")]),
- GlFunction(Void, "glTexSubImage2D", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexSubImage2D_size(format, type, width, height)"), "pixels")]),
+ GlFunction(Void, "glTexSubImage1D", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage1D_size(format, type, width)"), "pixels")]),
+ GlFunction(Void, "glTexSubImage2D", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage2D_size(format, type, width, height)"), "pixels")]),
GlFunction(Void, "glBindTexture", [(GLenum, "target"), (GLtexture, "texture")]),
GlFunction(Void, "glDeleteTextures", [(GLsizei, "n"), (Array(Const(GLtexture), "n"), "textures")]),
GlFunction(Void, "glGenTextures", [(GLsizei, "n"), Out(Array(GLtexture, "n"), "textures")]),
@@ -410,7 +410,7 @@ glapi.addFunctions([
GlFunction(Void, "glBlendEquation", [(GLenum, "mode")]),
GlFunction(Void, "glDrawRangeElements", [(GLenum_mode, "mode"), (GLuint, "start"), (GLuint, "end"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices")]),
GlFunction(Void, "glTexImage3D", [(GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
- GlFunction(Void, "glTexSubImage3D", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexSubImage3D_size(format, type, width, height, depth)"), "pixels")]),
+ GlFunction(Void, "glTexSubImage3D", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
GlFunction(Void, "glCopyTexSubImage3D", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
# GL_VERSION_1_2_DEPRECATED
@@ -564,7 +564,7 @@ glapi.addFunctions([
GlFunction(Void, "glGetBufferSubData", [(GLenum, "target"), (GLintptr, "offset"), (GLsizeiptr, "size"), Out(OpaqueBlob(GLvoid, "size"), "data")], sideeffects=False),
GlFunction(GLmap, "glMapBuffer", [(GLenum, "target"), (GLenum, "access")]),
GlFunction(GLboolean, "glUnmapBuffer", [(GLenum, "target")]),
- GlFunction(Void, "glGetBufferParameteriv", [(GLenum, "target"), (GLenum, "pname"), (Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetBufferParameteriv", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetBufferPointerv", [(GLenum, "target"), (GLenum, "pname"), Out(Pointer(GLpointer), "params")], sideeffects=False),
# GL_VERSION_2_0
@@ -711,7 +711,7 @@ glapi.addFunctions([
GlFunction(Void, "glVertexAttribI4usv", [(GLuint, "index"), (Array(Const(GLushort), 4), "v")]),
GlFunction(Void, "glGetUniformuiv", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaqueArray(GLuint, "_glGetUniformuiv_size(program, location)"), "params")], sideeffects=False),
GlFunction(Void, "glBindFragDataLocation", [(GLprogram, "program"), (GLuint, "color"), (GLstringConst, "name")]),
- GlFunction(GLlocation, "glGetFragDataLocation", [(GLprogram, "program"), (GLstringConst, "name")]),
+ GlFunction(GLint, "glGetFragDataLocation", [(GLprogram, "program"), (GLstringConst, "name")], sideeffects=False),
GlFunction(Void, "glUniform1ui", [(GLlocation, "location"), (GLuint, "v0")]),
GlFunction(Void, "glUniform2ui", [(GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1")]),
GlFunction(Void, "glUniform3ui", [(GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1"), (GLuint, "v2")]),
@@ -731,8 +731,8 @@ glapi.addFunctions([
GlFunction(String(Const(GLubyte)), "glGetStringi", [(GLenum, "name"), (GLuint, "index")], sideeffects=False),
# GL_VERSION_3_1
- GlFunction(Void, "glDrawArraysInstanced", [(GLenum_mode, "mode"), (GLint, "first"), (GLsizei, "count"), (GLsizei, "primcount")]),
- GlFunction(Void, "glDrawElementsInstanced", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "primcount")]),
+ GlFunction(Void, "glDrawArraysInstanced", [(GLenum_mode, "mode"), (GLint, "first"), (GLsizei, "count"), (GLsizei, "instancecount")]),
+ GlFunction(Void, "glDrawElementsInstanced", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "instancecount")]),
GlFunction(Void, "glTexBuffer", [(GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer")]),
GlFunction(Void, "glPrimitiveRestartIndex", [(GLuint, "index")]),
@@ -751,6 +751,82 @@ glapi.addFunctions([
GlFunction(Void, "glBlendFunci", [(GLuint, "buf"), (GLenum, "src"), (GLenum, "dst")]),
GlFunction(Void, "glBlendFuncSeparatei", [(GLuint, "buf"), (GLenum, "srcRGB"), (GLenum, "dstRGB"), (GLenum, "srcAlpha"), (GLenum, "dstAlpha")]),
+ # GL_VERSION_4_1
+
+ # GL_VERSION_4_2
+
+ # GL_VERSION_4_3
+
+ # GL_VERSION_4_4
+
+ # GL_VERSION_4_5
+ GlFunction(Void, "glGetnCompressedTexImage", [(GLenum, "target"), (GLint, "lod"), (GLsizei, "bufSize"), Out(OpaqueBlob(Void, "bufSize"), "pixels")]),
+ GlFunction(Void, "glGetnTexImage", [(GLenum, "target"), (GLint, "level"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "bufSize"), Out(OpaqueBlob(Void, "bufSize"), "pixels")]),
+ GlFunction(Void, "glGetnUniformdv", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLdouble, "bufSize"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetnMapdv", [(GLenum, "target"), (GLenum, "query"), (GLsizei, "bufSize"), Out(Array(GLdouble, "bufSize"), "v")], sideeffects=False),
+ GlFunction(Void, "glGetnMapfv", [(GLenum, "target"), (GLenum, "query"), (GLsizei, "bufSize"), Out(Array(GLfloat, "bufSize"), "v")], sideeffects=False),
+ GlFunction(Void, "glGetnMapiv", [(GLenum, "target"), (GLenum, "query"), (GLsizei, "bufSize"), Out(Array(GLint, "bufSize"), "v")], sideeffects=False),
+ GlFunction(Void, "glGetnPixelMapfv", [(GLenum, "map"), (GLsizei, "bufSize"), Out(Array(GLfloat, "bufSize"), "values")]),
+ GlFunction(Void, "glGetnPixelMapuiv", [(GLenum, "map"), (GLsizei, "bufSize"), Out(Array(GLuint, "bufSize"), "values")]),
+ GlFunction(Void, "glGetnPixelMapusv", [(GLenum, "map"), (GLsizei, "bufSize"), Out(Array(GLushort, "bufSize"), "values")]),
+ GlFunction(Void, "glGetnPolygonStipple", [(GLsizei, "bufSize"), Out(Array(GLubyte, "bufSize"), "pattern")]),
+ GlFunction(Void, "glGetnColorTable", [(GLenum, "target"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "bufSize"), Out(OpaqueBlob(Void, "bufSize"), "table")], sideeffects=False),
+ GlFunction(Void, "glGetnConvolutionFilter", [(GLenum, "target"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "bufSize"), Out(OpaqueBlob(Void, "bufSize"), "image")]),
+ GlFunction(Void, "glGetnSeparableFilter", [(GLenum, "target"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "rowBufSize"), Out(OpaqueBlob(Void, "rowBufSize"), "row"), (GLsizei, "columnBufSize"), Out(OpaqueBlob(Void, "columnBufSize"), "column"), Out(GLpointer, "span")]),
+ GlFunction(Void, "glGetnHistogram", [(GLenum, "target"), (GLboolean, "reset"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "bufSize"), Out(OpaqueBlob(Void, "bufSize"), "values")]),
+ GlFunction(Void, "glGetnMinmax", [(GLenum, "target"), (GLboolean, "reset"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "bufSize"), Out(OpaqueBlob(Void, "bufSize"), "values")]),
+
+ # GL_VERSION_ES_CM_1_0
+ GlFunction(Void, "glClipPlanef", [(GLenum, "plane"), (Array(Const(GLfloat), 4), "equation")]),
+ GlFunction(Void, "glFrustumf", [(GLfloat, "left"), (GLfloat, "right"), (GLfloat, "bottom"), (GLfloat, "top"), (GLfloat, "zNear"), (GLfloat, "zFar")]),
+ GlFunction(Void, "glGetClipPlanef", [(GLenum, "plane"), Out(Array(GLfloat, 4), "equation")], sideeffects=False),
+ GlFunction(Void, "glOrthof", [(GLfloat, "left"), (GLfloat, "right"), (GLfloat, "bottom"), (GLfloat, "top"), (GLfloat, "zNear"), (GLfloat, "zFar")]),
+ GlFunction(Void, "glAlphaFuncx", [(GLenum, "func"), (GLclampx, "ref")]),
+ GlFunction(Void, "glClearColorx", [(GLclampx, "red"), (GLclampx, "green"), (GLclampx, "blue"), (GLclampx, "alpha")]),
+ GlFunction(Void, "glClearDepthx", [(GLclampx, "depth")]),
+ GlFunction(Void, "glClipPlanex", [(GLenum, "plane"), (Array(Const(GLfixed), 4), "equation")]),
+ GlFunction(Void, "glColor4x", [(GLfixed, "red"), (GLfixed, "green"), (GLfixed, "blue"), (GLfixed, "alpha")]),
+ GlFunction(Void, "glDepthRangex", [(GLclampx, "zNear"), (GLclampx, "zFar")]),
+ GlFunction(Void, "glFogx", [(GLenum, "pname"), (GLfixed, "param")]),
+ GlFunction(Void, "glFogxv", [(GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glFrustumx", [(GLfixed, "left"), (GLfixed, "right"), (GLfixed, "bottom"), (GLfixed, "top"), (GLfixed, "zNear"), (GLfixed, "zFar")]),
+ GlFunction(Void, "glGetClipPlanex", [(GLenum, "plane"), Out(Array(GLfixed, 4), "equation")], sideeffects=False),
+ GlFunction(Void, "glGetFixedv", [(GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetLightxv", [(GLenum, "light"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetMaterialxv", [(GLenum, "face"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTexEnvxv", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTexParameterxv", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glLightModelx", [(GLenum, "pname"), (GLfixed, "param")]),
+ GlFunction(Void, "glLightModelxv", [(GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glLightx", [(GLenum, "light"), (GLenum, "pname"), (GLfixed, "param")]),
+ GlFunction(Void, "glLightxv", [(GLenum, "light"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glLineWidthx", [(GLfixed, "width")]),
+ GlFunction(Void, "glLoadMatrixx", [(Array(Const(GLfixed), 16), "m")]),
+ GlFunction(Void, "glMaterialx", [(GLenum, "face"), (GLenum, "pname"), (GLfixed, "param")]),
+ GlFunction(Void, "glMaterialxv", [(GLenum, "face"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glMultMatrixx", [(Array(Const(GLfixed), 16), "m")]),
+ GlFunction(Void, "glMultiTexCoord4x", [(GLenum, "target"), (GLfixed, "s"), (GLfixed, "t"), (GLfixed, "r"), (GLfixed, "q")]),
+ GlFunction(Void, "glNormal3x", [(GLfixed, "nx"), (GLfixed, "ny"), (GLfixed, "nz")]),
+ GlFunction(Void, "glOrthox", [(GLfixed, "left"), (GLfixed, "right"), (GLfixed, "bottom"), (GLfixed, "top"), (GLfixed, "zNear"), (GLfixed, "zFar")]),
+ GlFunction(Void, "glPointParameterx", [(GLenum, "pname"), (GLfixed, "param")]),
+ GlFunction(Void, "glPointParameterxv", [(GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glPointSizex", [(GLfixed, "size")]),
+ GlFunction(Void, "glPolygonOffsetx", [(GLfixed, "factor"), (GLfixed, "units")]),
+ GlFunction(Void, "glRotatex", [(GLfixed, "angle"), (GLfixed, "x"), (GLfixed, "y"), (GLfixed, "z")]),
+ GlFunction(Void, "glSampleCoveragex", [(GLclampx, "value"), (GLboolean, "invert")]),
+ GlFunction(Void, "glScalex", [(GLfixed, "x"), (GLfixed, "y"), (GLfixed, "z")]),
+ GlFunction(Void, "glTexEnvx", [(GLenum, "target"), (GLenum, "pname"), (GLfixed, "param")]),
+ GlFunction(Void, "glTexEnvxv", [(GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTexParameterx", [(GLenum, "target"), (GLenum, "pname"), (GLfixed, "param")]),
+ GlFunction(Void, "glTexParameterxv", [(GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTranslatex", [(GLfixed, "x"), (GLfixed, "y"), (GLfixed, "z")]),
+
+ # GL_ES_VERSION_2_0
+
+ # GL_ES_VERSION_3_0
+
+ # GL_ES_VERSION_3_1
+
# GL_3DFX_tbuffer
GlFunction(Void, "glTbufferMask3DFX", [(GLuint, "mask")]),
@@ -766,6 +842,9 @@ glapi.addFunctions([
GlFunction(Void, "glBlendEquationIndexedAMD", [(GLuint, "buf"), (GLenum, "mode")]),
GlFunction(Void, "glBlendEquationSeparateIndexedAMD", [(GLuint, "buf"), (GLenum, "modeRGB"), (GLenum, "modeAlpha")]),
+ # GL_AMD_interleaved_elements
+ GlFunction(Void, "glVertexAttribParameteriAMD", [(GLuint, "index"), (GLenum, "pname"), (GLint, "param")]),
+
# GL_AMD_multi_draw_indirect
GlFunction(Void, "glMultiDrawArraysIndirectAMD", [(GLenum_mode, "mode"), (GLpointerConst, "indirect"), (GLsizei, "primcount"), (GLsizei, "stride")]),
GlFunction(Void, "glMultiDrawElementsIndirectAMD", [(GLenum_mode, "mode"), (GLenum, "type"), (GLpointerConst, "indirect"), (GLsizei, "primcount"), (GLsizei, "stride")]),
@@ -775,6 +854,9 @@ glapi.addFunctions([
GlFunction(Void, "glDeleteNamesAMD", [(GLenum, "identifier"), (GLuint, "num"), (Array(Const(GLuint), "num"), "names")]),
GlFunction(GLboolean, "glIsNameAMD", [(GLenum, "identifier"), (GLuint, "name")], sideeffects=False),
+ # GL_AMD_occlusion_query_event
+ GlFunction(Void, "glQueryObjectParameteruiAMD", [(GLenum, "target"), (GLquery, "id"), (GLenum, "pname"), (GLuint, "param")]),
+
# GL_AMD_performance_monitor
GlFunction(Void, "glGetPerfMonitorGroupsAMD", [Out(Pointer(GLint), "numGroups"), (GLsizei, "groupsSize"), Out(Array(GLuint, "groupsSize"), "groups")], sideeffects=False),
GlFunction(Void, "glGetPerfMonitorCountersAMD", [(GLuint, "group"), Out(Pointer(GLint), "numCounters"), Out(Pointer(GLint), "maxActiveCounters"), (GLsizei, "counterSize"), Out(Array(GLuint, "counterSize"), "counters")], sideeffects=False),
@@ -798,10 +880,40 @@ glapi.addFunctions([
# GL_AMD_stencil_operation_extended
GlFunction(Void, "glStencilOpValueAMD", [(GLenum, "face"), (GLuint, "value")]),
- # GL_AMD_vertex_shader_tesselator
+ # GL_AMD_vertex_shader_tessellator
GlFunction(Void, "glTessellationFactorAMD", [(GLfloat, "factor")]),
GlFunction(Void, "glTessellationModeAMD", [(GLenum, "mode")]),
+ # GL_ANGLE_framebuffer_blit
+ GlFunction(Void, "glBlitFramebufferANGLE", [(GLint, "srcX0"), (GLint, "srcY0"), (GLint, "srcX1"), (GLint, "srcY1"), (GLint, "dstX0"), (GLint, "dstY0"), (GLint, "dstX1"), (GLint, "dstY1"), (GLbitfield_attrib, "mask"), (GLenum, "filter")]),
+
+ # GL_ANGLE_framebuffer_multisample
+ GlFunction(Void, "glRenderbufferStorageMultisampleANGLE", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+
+ # GL_ANGLE_instanced_arrays
+ GlFunction(Void, "glDrawArraysInstancedANGLE", [(GLenum_mode, "mode"), (GLint, "first"), (GLsizei, "count"), (GLsizei, "primcount")]),
+ GlFunction(Void, "glDrawElementsInstancedANGLE", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "primcount")]),
+ GlFunction(Void, "glVertexAttribDivisorANGLE", [(GLuint, "index"), (GLuint, "divisor")]),
+
+ # GL_ANGLE_timer_query
+ GlFunction(Void, "glGenQueriesANGLE", [(GLsizei, "n"), Out(Array(GLquery, "n"), "ids")]),
+ GlFunction(Void, "glDeleteQueriesANGLE", [(GLsizei, "n"), (Array(Const(GLquery), "n"), "ids")]),
+ GlFunction(GLboolean, "glIsQueryANGLE", [(GLquery, "id")], sideeffects=False),
+ GlFunction(Void, "glBeginQueryANGLE", [(GLenum, "target"), (GLquery, "id")]),
+ GlFunction(Void, "glEndQueryANGLE", [(GLenum, "target")]),
+ GlFunction(Void, "glQueryCounterANGLE", [(GLquery, "id"), (GLenum, "target")]),
+ GlFunction(Void, "glGetQueryivANGLE", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetQueryObjectivANGLE", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetQueryObjectuivANGLE", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetQueryObjecti64vANGLE", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLint64, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetQueryObjectui64vANGLE", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLuint64, "_gl_param_size(pname)"), "params")], sideeffects=False),
+
+ # GL_ANGLE_translated_shader_source
+ GlFunction(Void, "glGetTranslatedShaderSourceANGLE", [(GLshader, "shader"), (GLsizei, "bufsize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "source")], sideeffects=False),
+
+ # GL_APPLE_copy_texture_levels
+ GlFunction(Void, "glCopyTextureLevelsAPPLE", [(GLtexture, "destinationTexture"), (GLtexture, "sourceTexture"), (GLint, "sourceBaseLevel"), (GLsizei, "sourceLevelCount")]),
+
# GL_APPLE_element_array
GlFunction(Void, "glElementPointerAPPLE", [(GLenum, "type"), (Blob(Const(GLvoid), "type"), "pointer")]),
GlFunction(Void, "glDrawElementArrayAPPLE", [(GLenum_mode, "mode"), (GLint, "first"), (GLsizei, "count")]),
@@ -828,11 +940,24 @@ glapi.addFunctions([
GlFunction(Void, "glFinishRenderAPPLE", []),
GlFunction(Void, "glSwapAPPLE", []),
+ # GL_APPLE_framebuffer_multisample
+ GlFunction(Void, "glRenderbufferStorageMultisampleAPPLE", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glResolveMultisampleFramebufferAPPLE", []),
+
# GL_APPLE_object_purgeable
GlFunction(GLenum, "glObjectPurgeableAPPLE", [(GLenum, "objectType"), (GLuint, "name"), (GLenum, "option")]),
GlFunction(GLenum, "glObjectUnpurgeableAPPLE", [(GLenum, "objectType"), (GLuint, "name"), (GLenum, "option")]),
GlFunction(Void, "glGetObjectParameterivAPPLE", [(GLenum, "objectType"), (GLuint, "name"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ # GL_APPLE_sync
+ GlFunction(GLsync, "glFenceSyncAPPLE", [(GLenum, "condition"), (GLbitfield, "flags")]),
+ GlFunction(GLboolean, "glIsSyncAPPLE", [(GLsync, "sync")], sideeffects=False),
+ GlFunction(Void, "glDeleteSyncAPPLE", [(GLsync, "sync")]),
+ GlFunction(GLenum, "glClientWaitSyncAPPLE", [(GLsync, "sync"), (GLbitfield_sync_flush, "flags"), (GLuint64, "timeout")]),
+ GlFunction(Void, "glWaitSyncAPPLE", [(GLsync, "sync"), (GLbitfield, "flags"), (GLuint64, "timeout")]),
+ GlFunction(Void, "glGetInteger64vAPPLE", [(GLenum, "pname"), Out(Array(GLint64, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetSyncivAPPLE", [(GLsync, "sync"), (GLenum, "pname"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLint, "(length ? *length : bufSize)"), "values")], sideeffects=False),
+
# GL_APPLE_texture_range
GlFunction(Void, "glTextureRangeAPPLE", [(GLenum, "target"), (GLsizei, "length"), (Blob(Const(GLvoid), "length"), "pointer")]),
GlFunction(Void, "glGetTexParameterPointervAPPLE", [(GLenum, "target"), (GLenum, "pname"), Out(Pointer(GLpointer), "params")], sideeffects=False),
@@ -864,10 +989,16 @@ glapi.addFunctions([
GlFunction(Void, "glDepthRangef", [(GLfloat, "n"), (GLfloat, "f")]),
GlFunction(Void, "glClearDepthf", [(GLfloat, "d")]),
+ # GL_ARB_ES3_1_compatibility
+ GlFunction(Void, "glMemoryBarrierByRegion", [(GLbitfield, "barriers")]),
+
+ # GL_ARB_ES3_2_compatibility
+ GlFunction(Void, "glPrimitiveBoundingBoxARB", [(GLfloat, "minX"), (GLfloat, "minY"), (GLfloat, "minZ"), (GLfloat, "minW"), (GLfloat, "maxX"), (GLfloat, "maxY"), (GLfloat, "maxZ"), (GLfloat, "maxW")]),
+
# GL_ARB_base_instance
- GlFunction(Void, "glDrawArraysInstancedBaseInstance", [(GLenum_mode, "mode"), (GLint, "first"), (GLsizei, "count"), (GLsizei, "primcount"), (GLuint, "baseinstance")]),
- GlFunction(Void, "glDrawElementsInstancedBaseInstance", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "primcount"), (GLuint, "baseinstance")]),
- GlFunction(Void, "glDrawElementsInstancedBaseVertexBaseInstance", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "primcount"), (GLint, "basevertex"), (GLuint, "baseinstance")]),
+ GlFunction(Void, "glDrawArraysInstancedBaseInstance", [(GLenum_mode, "mode"), (GLint, "first"), (GLsizei, "count"), (GLsizei, "instancecount"), (GLuint, "baseinstance")]),
+ GlFunction(Void, "glDrawElementsInstancedBaseInstance", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "instancecount"), (GLuint, "baseinstance")]),
+ GlFunction(Void, "glDrawElementsInstancedBaseVertexBaseInstance", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "instancecount"), (GLint, "basevertex"), (GLuint, "baseinstance")]),
# GL_ARB_bindless_texture
GlFunction(GLtextureHandle, "glGetTextureHandleARB", [(GLtexture, "texture")]),
@@ -881,11 +1012,11 @@ glapi.addFunctions([
GlFunction(Void, "glUniformHandleui64vARB", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLtextureHandle), "count"), "value")]),
GlFunction(Void, "glProgramUniformHandleui64ARB", [(GLprogram, "program"), (GLlocation, "location"), (GLtextureHandle, "value")]),
GlFunction(Void, "glProgramUniformHandleui64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLtextureHandle), "count"), "values")]),
- GlFunction(GLboolean, "glIsTextureHandleResidentARB", [(GLtextureHandle, "handle")]),
- GlFunction(GLboolean, "glIsImageHandleResidentARB", [(GLtextureHandle, "handle")]),
- GlFunction(Void, "glVertexAttribL1ui64ARB", [(GLprogram, "index"), (GLuint64EXT, "x")]),
- GlFunction(Void, "glVertexAttribL1ui64vARB", [(GLprogram, "index"), (Pointer(Const(GLuint64EXT)), "v")]),
- GlFunction(Void, "glGetVertexAttribLui64vARB", [(GLprogram, "index"), (GLenum, "pname"), Out(Array(GLuint64EXT, "_gl_param_size(pname)"), "params")]),
+ GlFunction(GLboolean, "glIsTextureHandleResidentARB", [(GLtextureHandle, "handle")], sideeffects=False),
+ GlFunction(GLboolean, "glIsImageHandleResidentARB", [(GLtextureHandle, "handle")], sideeffects=False),
+ GlFunction(Void, "glVertexAttribL1ui64ARB", [(GLuint, "index"), (GLuint64EXT, "x")]),
+ GlFunction(Void, "glVertexAttribL1ui64vARB", [(GLuint, "index"), (Pointer(Const(GLuint64EXT)), "v")]),
+ GlFunction(Void, "glGetVertexAttribLui64vARB", [(GLuint, "index"), (GLenum, "pname"), Out(Array(GLuint64EXT, "_gl_param_size(pname)"), "params")], sideeffects=False),
# GL_ARB_blend_func_extended
GlFunction(Void, "glBindFragDataLocationIndexed", [(GLprogram, "program"), (GLuint, "colorNumber"), (GLuint, "index"), (GLstringConst, "name")]),
@@ -893,21 +1024,21 @@ glapi.addFunctions([
# GL_ARB_buffer_storage
GlFunction(Void, "glBufferStorage", [ (GLenum, "target"), (GLsizeiptr, "size"), (Blob(Const(GLvoid), "size"), "data"), (GLbitfield_storage, "flags")]),
- GlFunction(Void, "glNamedBufferStorageEXT", [ (GLbuffer, "buffer"), (GLsizeiptr, "size"), (Blob(Const(GLvoid), "size"), "data"), (GLbitfield_storage, "flags")]),
# GL_ARB_cl_event
- #GlFunction(GLsync, "glCreateSyncFromCLeventARB", [(OpaquePointer("struct _cl_context"), "context"), (OpaquePointer("struct _cl_event"), "event"), (GLbitfield, "flags")]),
+ GlFunction(GLsync, "glCreateSyncFromCLeventARB", [(Opaque("struct _cl_context *"), "context"), (Opaque("struct _cl_event *"), "event"), (GLbitfield, "flags")], sideeffects=False),
# GL_ARB_clear_buffer_object
GlFunction(Void, "glClearBufferData", [(GLenum, "target"), (GLenum, "internalformat"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glClearBufferData_size(format, type)"), "data")]),
GlFunction(Void, "glClearBufferSubData", [(GLenum, "target"), (GLenum, "internalformat"), (GLintptr, "offset"), (GLsizeiptr, "size"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glClearBufferData_size(format, type)"), "data")]),
- GlFunction(Void, "glClearNamedBufferDataEXT", [(GLbuffer, "buffer"), (GLenum, "internalformat"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glClearBufferData_size(format, type)"), "data")]),
- GlFunction(Void, "glClearNamedBufferSubDataEXT", [(GLbuffer, "buffer"), (GLenum, "internalformat"), (GLsizeiptr, "offset"), (GLsizeiptr, "size"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glClearBufferData_size(format, type)"), "data")]),
# GL_ARB_clear_texture
GlFunction(Void, "glClearTexImage", [ (GLtexture, "texture"), (GLint, "level"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glClearBufferData_size(format, type)"), "data")]),
GlFunction(Void, "glClearTexSubImage", [ (GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glClearBufferData_size(format, type)"), "data")]),
+ # GL_ARB_clip_control
+ GlFunction(Void, "glClipControl", [(GLenum, "origin"), (GLenum, "depth")]),
+
# GL_ARB_color_buffer_float
GlFunction(Void, "glClampColorARB", [(GLenum, "target"), (GLenum, "clamp")]),
@@ -922,7 +1053,7 @@ glapi.addFunctions([
GlFunction(Void, "glCopyBufferSubData", [(GLenum, "readTarget"), (GLenum, "writeTarget"), (GLintptr, "readOffset"), (GLintptr, "writeOffset"), (GLsizeiptr, "size")]),
# GL_ARB_copy_image
- GlFunction(Void, "glCopyImageSubData", [(GLname("srcTarget"), "srcName"), (GLenum, "srcTarget"), (GLint, "srcLevel"), (GLint, "srcX"), (GLint, "srcY"), (GLint, "srcZ"), (GLname("dstTarget"), "dstName"), (GLenum, "dstTarget"), (GLint, "dstLevel"), (GLint, "dstX"), (GLint, "dstY"), (GLint, "dstZ"), (GLsizei, "srcWidth"), (GLsizei, "srcHeight"), (GLsizei, "srcDepth")]),
+ GlFunction(Void, "glCopyImageSubData", [(GLtexture, "srcName"), (GLenum, "srcTarget"), (GLint, "srcLevel"), (GLint, "srcX"), (GLint, "srcY"), (GLint, "srcZ"), (GLtexture, "dstName"), (GLenum, "dstTarget"), (GLint, "dstLevel"), (GLint, "dstX"), (GLint, "dstY"), (GLint, "dstZ"), (GLsizei, "srcWidth"), (GLsizei, "srcHeight"), (GLsizei, "srcDepth")]),
# GL_ARB_debug_output
GlFunction(Void, "glDebugMessageControlARB", [(GLenum, "source"), (GLenum, "type"), (GLenum, "severity"), (GLsizei, "count"), (Array(Const(GLuint), "count"), "ids"), (GLboolean, "enabled")], sideeffects=True),
@@ -930,6 +1061,105 @@ glapi.addFunctions([
GlFunction(Void, "glDebugMessageCallbackARB", [(GLDEBUGPROCARB, "callback"), (GLpointerConst, "userParam")], sideeffects=False),
GlFunction(GLuint, "glGetDebugMessageLogARB", [(GLuint, "count"), (GLsizei, "bufsize"), Out(Array(GLenum, "count"), "sources"), Out(Array(GLenum, "count"), "types"), Out(Array(GLuint, "count"), "ids"), Out(Array(GLenum, "count"), "severities"), Out(Array(GLsizei, "count"), "lengths"), Out(String(GLchar, "_glGetDebugMessageLog_length(messageLog, lengths, _result)"), "messageLog")], sideeffects=False, fail=0),
+ # GL_ARB_direct_state_access
+ GlFunction(Void, "glCreateTransformFeedbacks", [(GLsizei, "n"), Out(Array(GLfeedback, "n"), "ids")]),
+ GlFunction(Void, "glTransformFeedbackBufferBase", [(GLfeedback, "xfb"), (GLuint, "index"), (GLbuffer, "buffer")]),
+ GlFunction(Void, "glTransformFeedbackBufferRange", [(GLfeedback, "xfb"), (GLuint, "index"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
+ GlFunction(Void, "glGetTransformFeedbackiv", [(GLfeedback, "xfb"), (GLenum, "pname"), Out(Pointer(GLint), "param")], sideeffects=False),
+ GlFunction(Void, "glGetTransformFeedbacki_v", [(GLfeedback, "xfb"), (GLenum, "pname"), (GLuint, "index"), Out(Pointer(GLint), "param")], sideeffects=False),
+ GlFunction(Void, "glGetTransformFeedbacki64_v", [(GLfeedback, "xfb"), (GLenum, "pname"), (GLuint, "index"), Out(Pointer(GLint64), "param")], sideeffects=False),
+ GlFunction(Void, "glCreateBuffers", [(GLsizei, "n"), Out(Array(GLbuffer, "n"), "buffers")]),
+ GlFunction(Void, "glNamedBufferStorage", [ (GLbuffer, "buffer"), (GLsizeiptr, "size"), (Blob(Const(Void), "size"), "data"), (GLbitfield_storage, "flags")]),
+ GlFunction(Void, "glNamedBufferData", [(GLbuffer, "buffer"), (GLsizeiptr, "size"), (Blob(Const(Void), "size"), "data"), (GLenum, "usage")]),
+ GlFunction(Void, "glNamedBufferSubData", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size"), (Blob(Const(Void), "size"), "data")]),
+ GlFunction(Void, "glCopyNamedBufferSubData", [(GLbuffer, "readBuffer"), (GLbuffer, "writeBuffer"), (GLintptr, "readOffset"), (GLintptr, "writeOffset"), (GLsizeiptr, "size")]),
+ GlFunction(Void, "glClearNamedBufferData", [(GLbuffer, "buffer"), (GLenum, "internalformat"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glClearBufferData_size(format, type)"), "data")]),
+ GlFunction(Void, "glClearNamedBufferSubData", [(GLbuffer, "buffer"), (GLenum, "internalformat"), (GLintptr, "offset"), (GLsizeiptr, "size"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glClearBufferData_size(format, type)"), "data")]),
+ GlFunction(GLmap, "glMapNamedBuffer", [(GLbuffer, "buffer"), (GLenum, "access")]),
+ GlFunction(GLmap, "glMapNamedBufferRange", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "length"), (GLbitfield_access, "access")]),
+ GlFunction(GLboolean, "glUnmapNamedBuffer", [(GLbuffer, "buffer")]),
+ GlFunction(Void, "glFlushMappedNamedBufferRange", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "length")]),
+ GlFunction(Void, "glGetNamedBufferParameteriv", [(GLbuffer, "buffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedBufferParameteri64v", [(GLbuffer, "buffer"), (GLenum, "pname"), Out(Array(GLint64, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedBufferPointerv", [(GLbuffer, "buffer"), (GLenum, "pname"), Out(Pointer(GLpointer), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedBufferSubData", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size"), Out(OpaqueBlob(Void, "size"), "data")], sideeffects=False),
+ GlFunction(Void, "glCreateFramebuffers", [(GLsizei, "n"), Out(Array(GLframebuffer, "n"), "framebuffers")]),
+ GlFunction(Void, "glNamedFramebufferRenderbuffer", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "renderbuffertarget"), (GLrenderbuffer, "renderbuffer")]),
+ GlFunction(Void, "glNamedFramebufferParameteri", [(GLframebuffer, "framebuffer"), (GLenum, "pname"), (GLint, "param")]),
+ GlFunction(Void, "glNamedFramebufferTexture", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level")]),
+ GlFunction(Void, "glNamedFramebufferTextureLayer", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level"), (GLint, "layer")]),
+ GlFunction(Void, "glNamedFramebufferDrawBuffer", [(GLframebuffer, "framebuffer"), (GLenum, "buf")]),
+ GlFunction(Void, "glNamedFramebufferDrawBuffers", [(GLframebuffer, "framebuffer"), (GLsizei, "n"), (Array(Const(GLenum), "n"), "bufs")]),
+ GlFunction(Void, "glNamedFramebufferReadBuffer", [(GLframebuffer, "framebuffer"), (GLenum, "src")]),
+ GlFunction(Void, "glInvalidateNamedFramebufferData", [(GLframebuffer, "framebuffer"), (GLsizei, "numAttachments"), (Array(Const(GLenum), "numAttachments"), "attachments")]),
+ GlFunction(Void, "glInvalidateNamedFramebufferSubData", [(GLframebuffer, "framebuffer"), (GLsizei, "numAttachments"), (Array(Const(GLenum), "numAttachments"), "attachments"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glClearNamedFramebufferiv", [(GLframebuffer, "framebuffer"), (GLenum, "buffer"), (GLint, "drawbuffer"), (Array(Const(GLint), "_glClearBuffer_size(buffer)"), "value")]),
+ GlFunction(Void, "glClearNamedFramebufferuiv", [(GLframebuffer, "framebuffer"), (GLenum, "buffer"), (GLint, "drawbuffer"), (Array(Const(GLuint), "_glClearBuffer_size(buffer)"), "value")]),
+ GlFunction(Void, "glClearNamedFramebufferfv", [(GLframebuffer, "framebuffer"), (GLenum, "buffer"), (GLint, "drawbuffer"), (Array(Const(GLfloat), "_glClearBuffer_size(buffer)"), "value")]),
+ GlFunction(Void, "glClearNamedFramebufferfi", [(GLframebuffer, "framebuffer"), (GLenum, "buffer"), (GLint, "drawbuffer"), (GLfloat, "depth"), (GLint, "stencil")]),
+ GlFunction(Void, "glBlitNamedFramebuffer", [(GLframebuffer, "readFramebuffer"), (GLframebuffer, "drawFramebuffer"), (GLint, "srcX0"), (GLint, "srcY0"), (GLint, "srcX1"), (GLint, "srcY1"), (GLint, "dstX0"), (GLint, "dstY0"), (GLint, "dstX1"), (GLint, "dstY1"), (GLbitfield, "mask"), (GLenum, "filter")]),
+ GlFunction(GLenum, "glCheckNamedFramebufferStatus", [(GLframebuffer, "framebuffer"), (GLenum, "target")]),
+ GlFunction(Void, "glGetNamedFramebufferParameteriv", [(GLframebuffer, "framebuffer"), (GLenum, "pname"), Out(Pointer(GLint), "param")], sideeffects=False),
+ GlFunction(Void, "glGetNamedFramebufferAttachmentParameteriv", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glCreateRenderbuffers", [(GLsizei, "n"), Out(Array(GLrenderbuffer, "n"), "renderbuffers")]),
+ GlFunction(Void, "glNamedRenderbufferStorage", [(GLrenderbuffer, "renderbuffer"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glNamedRenderbufferStorageMultisample", [(GLrenderbuffer, "renderbuffer"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glGetNamedRenderbufferParameteriv", [(GLrenderbuffer, "renderbuffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glCreateTextures", [(GLenum, "target"), (GLsizei, "n"), Out(Array(GLtexture, "n"), "textures")]),
+ GlFunction(Void, "glTextureBuffer", [(GLtexture, "texture"), (GLenum, "internalformat"), (GLbuffer, "buffer")]),
+ GlFunction(Void, "glTextureBufferRange", [(GLtexture, "texture"), (GLenum, "internalformat"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
+ GlFunction(Void, "glTextureStorage1D", [(GLtexture, "texture"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width")]),
+ GlFunction(Void, "glTextureStorage2D", [(GLtexture, "texture"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glTextureStorage3D", [(GLtexture, "texture"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
+ GlFunction(Void, "glTextureStorage2DMultisample", [(GLtexture, "texture"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLboolean, "fixedsamplelocations")]),
+ GlFunction(Void, "glTextureStorage3DMultisample", [(GLtexture, "texture"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLboolean, "fixedsamplelocations")]),
+ GlFunction(Void, "glTextureSubImage1D", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glTexImage1D_size(format, type, width)"), "pixels")]),
+ GlFunction(Void, "glTextureSubImage2D", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glTexImage2D_size(format, type, width, height)"), "pixels")]),
+ GlFunction(Void, "glTextureSubImage3D", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
+ GlFunction(Void, "glCompressedTextureSubImage1D", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(Void), "imageSize"), "data")]),
+ GlFunction(Void, "glCompressedTextureSubImage2D", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(Void), "imageSize"), "data")]),
+ GlFunction(Void, "glCompressedTextureSubImage3D", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(Void), "imageSize"), "data")]),
+ GlFunction(Void, "glCopyTextureSubImage1D", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width")]),
+ GlFunction(Void, "glCopyTextureSubImage2D", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glCopyTextureSubImage3D", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glTextureParameterf", [(GLtexture, "texture"), (GLenum, "pname"), (GLfloat, "param")]),
+ GlFunction(Void, "glTextureParameterfv", [(GLtexture, "texture"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTextureParameteri", [(GLtexture, "texture"), (GLenum, "pname"), (GLint, "param")]),
+ GlFunction(Void, "glTextureParameterIiv", [(GLtexture, "texture"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTextureParameterIuiv", [(GLtexture, "texture"), (GLenum, "pname"), (Array(Const(GLuint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTextureParameteriv", [(GLtexture, "texture"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glGenerateTextureMipmap", [(GLtexture, "texture")]),
+ GlFunction(Void, "glBindTextureUnit", [(GLuint, "unit"), (GLtexture, "texture")]),
+ GlFunction(Void, "glGetTextureImage", [(GLtexture, "texture"), (GLint, "level"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "bufSize"), Out(GLpointer, "pixels")]),
+ GlFunction(Void, "glGetCompressedTextureImage", [(GLtexture, "texture"), (GLint, "level"), (GLsizei, "bufSize"), Out(GLpointer, "pixels")]),
+ GlFunction(Void, "glGetTextureLevelParameterfv", [(GLtexture, "texture"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureLevelParameteriv", [(GLtexture, "texture"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureParameterfv", [(GLtexture, "texture"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureParameterIiv", [(GLtexture, "texture"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureParameterIuiv", [(GLtexture, "texture"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureParameteriv", [(GLtexture, "texture"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glCreateVertexArrays", [(GLsizei, "n"), Out(Array(GLarray, "n"), "arrays")]),
+ GlFunction(Void, "glDisableVertexArrayAttrib", [(GLarray, "vaobj"), (GLuint, "index")]),
+ GlFunction(Void, "glEnableVertexArrayAttrib", [(GLarray, "vaobj"), (GLuint, "index")]),
+ GlFunction(Void, "glVertexArrayElementBuffer", [(GLarray, "vaobj"), (GLbuffer, "buffer")]),
+ GlFunction(Void, "glVertexArrayVertexBuffer", [(GLarray, "vaobj"), (GLuint, "bindingindex"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizei, "stride")]),
+ GlFunction(Void, "glVertexArrayVertexBuffers", [(GLarray, "vaobj"), (GLuint, "first"), (GLsizei, "count"), (Array(Const(GLuint), "count"), "buffers"), (Array(Const(GLintptr), "count"), "offsets"), (Array(Const(GLsizei), "count"), "strides")]),
+ GlFunction(Void, "glVertexArrayAttribBinding", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLuint, "bindingindex")]),
+ GlFunction(Void, "glVertexArrayAttribFormat", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "relativeoffset")]),
+ GlFunction(Void, "glVertexArrayAttribIFormat", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLuint, "relativeoffset")]),
+ GlFunction(Void, "glVertexArrayAttribLFormat", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLuint, "relativeoffset")]),
+ GlFunction(Void, "glVertexArrayBindingDivisor", [(GLarray, "vaobj"), (GLuint, "bindingindex"), (GLuint, "divisor")]),
+ GlFunction(Void, "glGetVertexArrayiv", [(GLarray, "vaobj"), (GLenum, "pname"), Out(Pointer(GLint), "param")], sideeffects=False),
+ GlFunction(Void, "glGetVertexArrayIndexediv", [(GLarray, "vaobj"), (GLuint, "index"), (GLenum, "pname"), Out(Pointer(GLint), "param")], sideeffects=False),
+ GlFunction(Void, "glGetVertexArrayIndexed64iv", [(GLarray, "vaobj"), (GLuint, "index"), (GLenum, "pname"), Out(Pointer(GLint64), "param")], sideeffects=False),
+ GlFunction(Void, "glCreateSamplers", [(GLsizei, "n"), Out(Array(GLsampler, "n"), "samplers")]),
+ GlFunction(Void, "glCreateProgramPipelines", [(GLsizei, "n"), Out(Array(GLpipeline, "n"), "pipelines")]),
+ GlFunction(Void, "glCreateQueries", [(GLenum, "target"), (GLsizei, "n"), Out(Array(GLquery, "n"), "ids")]),
+ GlFunction(Void, "glGetQueryBufferObjecti64v", [(GLquery, "id"), (GLbuffer, "buffer"), (GLenum, "pname"), (GLintptr, "offset")]),
+ GlFunction(Void, "glGetQueryBufferObjectiv", [(GLquery, "id"), (GLbuffer, "buffer"), (GLenum, "pname"), (GLintptr, "offset")]),
+ GlFunction(Void, "glGetQueryBufferObjectui64v", [(GLquery, "id"), (GLbuffer, "buffer"), (GLenum, "pname"), (GLintptr, "offset")]),
+ GlFunction(Void, "glGetQueryBufferObjectuiv", [(GLquery, "id"), (GLbuffer, "buffer"), (GLenum, "pname"), (GLintptr, "offset")]),
+
# GL_ARB_draw_buffers
GlFunction(Void, "glDrawBuffersARB", [(GLsizei, "n"), (Array(Const(GLenum), "n"), "bufs")]),
@@ -942,7 +1172,7 @@ glapi.addFunctions([
# GL_ARB_draw_elements_base_vertex
GlFunction(Void, "glDrawElementsBaseVertex", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLint, "basevertex")]),
GlFunction(Void, "glDrawRangeElementsBaseVertex", [(GLenum_mode, "mode"), (GLuint, "start"), (GLuint, "end"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLint, "basevertex")]),
- GlFunction(Void, "glDrawElementsInstancedBaseVertex", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "primcount"), (GLint, "basevertex")]),
+ GlFunction(Void, "glDrawElementsInstancedBaseVertex", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "instancecount"), (GLint, "basevertex")]),
GlFunction(Void, "glMultiDrawElementsBaseVertex", [(GLenum_mode, "mode"), (Array(Const(GLsizei), "drawcount"), "count"), (GLenum, "type"), (Array(Const(GLindexBuffer("count[{i}]", "type")), "drawcount"), "indices"), (GLsizei, "drawcount"), (Array(Const(GLint), "drawcount"), "basevertex")]),
# GL_ARB_draw_indirect
@@ -956,8 +1186,6 @@ glapi.addFunctions([
# GL_ARB_framebuffer_no_attachments
GlFunction(Void, "glFramebufferParameteri", [(GLenum, "target"), (GLenum, "pname"), (GLint, "param")]),
GlFunction(Void, "glGetFramebufferParameteriv", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glNamedFramebufferParameteriEXT", [(GLframebuffer, "framebuffer"), (GLenum, "pname"), (GLint, "param")]),
- GlFunction(Void, "glGetNamedFramebufferParameterivEXT", [(GLframebuffer, "framebuffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
# GL_ARB_framebuffer_object
GlFunction(GLboolean, "glIsRenderbuffer", [(GLrenderbuffer, "renderbuffer")], sideeffects=False),
@@ -965,7 +1193,7 @@ glapi.addFunctions([
GlFunction(Void, "glDeleteRenderbuffers", [(GLsizei, "n"), (Array(Const(GLrenderbuffer), "n"), "renderbuffers")]),
GlFunction(Void, "glGenRenderbuffers", [(GLsizei, "n"), Out(Array(GLrenderbuffer, "n"), "renderbuffers")]),
GlFunction(Void, "glRenderbufferStorage", [(GLenum, "target"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glGetRenderbufferParameteriv", [(GLenum, "target"), (GLenum, "pname"), (Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetRenderbufferParameteriv", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(GLboolean, "glIsFramebuffer", [(GLframebuffer, "framebuffer")], sideeffects=False),
GlFunction(Void, "glBindFramebuffer", [(GLenum, "target"), (GLframebuffer, "framebuffer")]),
GlFunction(Void, "glDeleteFramebuffers", [(GLsizei, "n"), (Array(Const(GLframebuffer), "n"), "framebuffers")]),
@@ -988,10 +1216,14 @@ glapi.addFunctions([
GlFunction(Void, "glFramebufferTextureFaceARB", [(GLenum, "target"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level"), (GLenum, "face")]),
# GL_ARB_get_program_binary
- GlFunction(Void, "glGetProgramBinary", [(GLprogram, "program"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLenum), "binaryFormat"), Out(OpaqueArray(GLvoid, "_glGetProgramBinary_size(length)"), "binary")], sideeffects=False),
+ GlFunction(Void, "glGetProgramBinary", [(GLprogram, "program"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLenum), "binaryFormat"), Out(OpaqueBlob(GLvoid, "length ? *length : bufSize"), "binary")], sideeffects=False),
GlFunction(Void, "glProgramBinary", [(GLprogram, "program"), (GLenum, "binaryFormat"), (Blob(Const(GLvoid), "length"), "binary"), (GLsizei, "length")]),
GlFunction(Void, "glProgramParameteri", [(GLprogram, "program"), (GLenum, "pname"), (GLint, "value")]),
+ # GL_ARB_get_texture_sub_image
+ GlFunction(Void, "glGetTextureSubImage", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "bufSize"), Out(GLpointer, "pixels")]),
+ GlFunction(Void, "glGetCompressedTextureSubImage", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLsizei, "bufSize"), Out(GLpointer, "pixels")]),
+
# GL_ARB_gpu_shader_fp64
GlFunction(Void, "glUniform1d", [(GLlocation, "location"), (GLdouble, "x")]),
GlFunction(Void, "glUniform2d", [(GLlocation, "location"), (GLdouble, "x"), (GLdouble, "y")]),
@@ -1012,6 +1244,44 @@ glapi.addFunctions([
GlFunction(Void, "glUniformMatrix4x3dv", [(GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*4*3"), "value")]),
GlFunction(Void, "glGetUniformdv", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaqueArray(GLdouble, "_glGetUniformdv_size(location)"), "params")], sideeffects=False),
+ # GL_ARB_gpu_shader_int64
+ GlFunction(Void, "glUniform1i64ARB", [(GLlocation, "location"), (GLint64, "x")]),
+ GlFunction(Void, "glUniform2i64ARB", [(GLlocation, "location"), (GLint64, "x"), (GLint64, "y")]),
+ GlFunction(Void, "glUniform3i64ARB", [(GLlocation, "location"), (GLint64, "x"), (GLint64, "y"), (GLint64, "z")]),
+ GlFunction(Void, "glUniform4i64ARB", [(GLlocation, "location"), (GLint64, "x"), (GLint64, "y"), (GLint64, "z"), (GLint64, "w")]),
+ GlFunction(Void, "glUniform1i64vARB", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64), "count*1"), "value")]),
+ GlFunction(Void, "glUniform2i64vARB", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64), "count*2"), "value")]),
+ GlFunction(Void, "glUniform3i64vARB", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64), "count*3"), "value")]),
+ GlFunction(Void, "glUniform4i64vARB", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64), "count*4"), "value")]),
+ GlFunction(Void, "glUniform1ui64ARB", [(GLlocation, "location"), (GLuint64, "x")]),
+ GlFunction(Void, "glUniform2ui64ARB", [(GLlocation, "location"), (GLuint64, "x"), (GLuint64, "y")]),
+ GlFunction(Void, "glUniform3ui64ARB", [(GLlocation, "location"), (GLuint64, "x"), (GLuint64, "y"), (GLuint64, "z")]),
+ GlFunction(Void, "glUniform4ui64ARB", [(GLlocation, "location"), (GLuint64, "x"), (GLuint64, "y"), (GLuint64, "z"), (GLuint64, "w")]),
+ GlFunction(Void, "glUniform1ui64vARB", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count*1"), "value")]),
+ GlFunction(Void, "glUniform2ui64vARB", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count*2"), "value")]),
+ GlFunction(Void, "glUniform3ui64vARB", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count*3"), "value")]),
+ GlFunction(Void, "glUniform4ui64vARB", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count*4"), "value")]),
+ GlFunction(Void, "glGetUniformi64vARB", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaquePointer(GLint64), "params")], sideeffects=False),
+ GlFunction(Void, "glGetUniformui64vARB", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaquePointer(GLuint64), "params")], sideeffects=False),
+ GlFunction(Void, "glGetnUniformi64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLint64, "bufSize"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetnUniformui64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLuint64, "bufSize"), "params")], sideeffects=False),
+ GlFunction(Void, "glProgramUniform1i64ARB", [(GLprogram, "program"), (GLlocation, "location"), (GLint64, "x")]),
+ GlFunction(Void, "glProgramUniform2i64ARB", [(GLprogram, "program"), (GLlocation, "location"), (GLint64, "x"), (GLint64, "y")]),
+ GlFunction(Void, "glProgramUniform3i64ARB", [(GLprogram, "program"), (GLlocation, "location"), (GLint64, "x"), (GLint64, "y"), (GLint64, "z")]),
+ GlFunction(Void, "glProgramUniform4i64ARB", [(GLprogram, "program"), (GLlocation, "location"), (GLint64, "x"), (GLint64, "y"), (GLint64, "z"), (GLint64, "w")]),
+ GlFunction(Void, "glProgramUniform1i64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64), "count"), "value")]),
+ GlFunction(Void, "glProgramUniform2i64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64), "count*2"), "value")]),
+ GlFunction(Void, "glProgramUniform3i64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64), "count*3"), "value")]),
+ GlFunction(Void, "glProgramUniform4i64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64), "count*4"), "value")]),
+ GlFunction(Void, "glProgramUniform1ui64ARB", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64, "x")]),
+ GlFunction(Void, "glProgramUniform2ui64ARB", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64, "x"), (GLuint64, "y")]),
+ GlFunction(Void, "glProgramUniform3ui64ARB", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64, "x"), (GLuint64, "y"), (GLuint64, "z")]),
+ GlFunction(Void, "glProgramUniform4ui64ARB", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64, "x"), (GLuint64, "y"), (GLuint64, "z"), (GLuint64, "w")]),
+ GlFunction(Void, "glProgramUniform1ui64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count"), "value")]),
+ GlFunction(Void, "glProgramUniform2ui64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count*2"), "value")]),
+ GlFunction(Void, "glProgramUniform3ui64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count*3"), "value")]),
+ GlFunction(Void, "glProgramUniform4ui64vARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count*4"), "value")]),
+
# GL_ARB_indirect_parameters
GlFunction(Void, "glMultiDrawArraysIndirectCountARB", [(GLenum_mode, "mode"), (GLintptr, "indirect"), (GLintptr, "drawcount"), (GLsizei, "maxdrawcount"), (GLsizei, "stride")]),
GlFunction(Void, "glMultiDrawElementsIndirectCountARB", [(GLenum_mode, "mode"), (GLenum, "type"), (GLintptr, "indirect"), (GLintptr, "drawcount"), (GLsizei, "maxdrawcount"), (GLsizei, "stride")]),
@@ -1047,10 +1317,10 @@ glapi.addFunctions([
# GL_ARB_multi_bind
GlFunction(Void, "glBindBuffersBase", [(GLenum, "target"), (GLuint, "first"), (GLsizei, "count"), (Array(Const(GLbuffer), "count"), "buffers")]),
GlFunction(Void, "glBindBuffersRange", [(GLenum, "target"), (GLuint, "first"), (GLsizei, "count"), (Array(Const(GLbuffer), "count"), "buffers"), (Array(Const(GLintptr), "count"), "offsets"), (Array(Const(GLsizeiptr), "count"), "sizes")]),
- GlFunction(Void, "glBindImageTextures", [ (GLuint, "first"), (GLsizei, "count"), (Array(Const(GLtexture), "count"), "textures")]),
- GlFunction(Void, "glBindSamplers", [ (GLuint, "first"), (GLsizei, "count"), (Array(Const(GLsampler), "count"), "samplers")]),
- GlFunction(Void, "glBindTextures", [ (GLuint, "first"), (GLsizei, "count"), (Array(Const(GLtexture), "count"), "textures")]),
- GlFunction(Void, "glBindVertexBuffers", [ (GLuint, "first"), (GLsizei, "count"), (Array(Const(GLbuffer), "count"), "buffers"), (Array(Const(GLintptr), "count"), "offsets"), (Array(Const(GLsizei), "count"), "strides")]),
+ GlFunction(Void, "glBindTextures", [(GLuint, "first"), (GLsizei, "count"), (Array(Const(GLtexture), "count"), "textures")]),
+ GlFunction(Void, "glBindSamplers", [(GLuint, "first"), (GLsizei, "count"), (Array(Const(GLsampler), "count"), "samplers")]),
+ GlFunction(Void, "glBindImageTextures", [(GLuint, "first"), (GLsizei, "count"), (Array(Const(GLtexture), "count"), "textures")]),
+ GlFunction(Void, "glBindVertexBuffers", [(GLuint, "first"), (GLsizei, "count"), (Array(Const(GLbuffer), "count"), "buffers"), (Array(Const(GLintptr), "count"), "offsets"), (Array(Const(GLsizei), "count"), "strides")]),
# GL_ARB_multi_draw_indirect
GlFunction(Void, "glMultiDrawArraysIndirect", [(GLenum_mode, "mode"), (OpaqueArray(Const(Void), "_glMultiDrawArraysIndirect_size(drawcount, stride)"), "indirect"), (GLsizei, "drawcount"), (GLsizei, "stride")]),
@@ -1105,17 +1375,20 @@ glapi.addFunctions([
GlFunction(Void, "glGetQueryObjectivARB", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetQueryObjectuivARB", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ # GL_ARB_parallel_shader_compile
+ GlFunction(Void, "glMaxShaderCompilerThreadsARB", [(GLuint, "count")]),
+
# GL_ARB_point_parameters
GlFunction(Void, "glPointParameterfARB", [(GLenum, "pname"), (GLfloat, "param")]),
GlFunction(Void, "glPointParameterfvARB", [(GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
# GL_ARB_program_interface_query
GlFunction(Void, "glGetProgramInterfaceiv", [(GLprogram, "program"), (GLenum, "programInterface"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(GLuint, "glGetProgramResourceIndex", [(GLprogram, "program"), (GLenum, "programInterface"), (OpaqueArray(Const(GLchar), "_glGetProgramResourceIndex_size(name)"), "name")], sideeffects=False),
+ GlFunction(GLuint, "glGetProgramResourceIndex", [(GLprogram, "program"), (GLenum, "programInterface"), (GLstringConst, "name")], sideeffects=False),
GlFunction(Void, "glGetProgramResourceName", [(GLprogram, "program"), (GLenum, "programInterface"), (GLuint, "index"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "name")], sideeffects=False),
GlFunction(Void, "glGetProgramResourceiv", [(GLprogram, "program"), (GLenum, "programInterface"), (GLuint, "index"), (GLsizei, "propCount"), (Array(Const(GLenum), "propCount"), "props"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLint, "bufSize"), "params")], sideeffects=False),
- GlFunction(GLlocation, "glGetProgramResourceLocation", [(GLprogram, "program"), (GLenum, "programInterface"), (GLstringConst, "name")], sideeffects=False),
- GlFunction(GLlocation, "glGetProgramResourceLocationIndex", [(GLprogram, "program"), (GLenum, "programInterface"), (GLstringConst, "name")], sideeffects=False),
+ GlFunction(GLlocation, "glGetProgramResourceLocation", [(GLprogram, "program"), (GLenum, "programInterface"), (GLstringConst, "name")]),
+ GlFunction(GLint, "glGetProgramResourceLocationIndex", [(GLprogram, "program"), (GLenum, "programInterface"), (GLstringConst, "name")], sideeffects=False),
# GL_ARB_provoking_vertex
GlFunction(Void, "glProvokingVertex", [(GLenum, "mode")]),
@@ -1142,6 +1415,11 @@ glapi.addFunctions([
GlFunction(Void, "glGetnUniformuivARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLuint, "bufSize"), "params")], sideeffects=False),
GlFunction(Void, "glGetnUniformdvARB", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLdouble, "bufSize"), "params")], sideeffects=False),
+ # GL_ARB_sample_locations
+ GlFunction(Void, "glFramebufferSampleLocationsfvARB", [(GLenum, "target"), (GLuint, "start"), (GLsizei, "count"), (Array(Const(GLfloat), "count*2"), "v")]),
+ GlFunction(Void, "glNamedFramebufferSampleLocationsfvARB", [(GLframebuffer, "framebuffer"), (GLuint, "start"), (GLsizei, "count"), (Array(Const(GLfloat), "count*2"), "v")]),
+ GlFunction(Void, "glEvaluateDepthValuesARB", []),
+
# GL_ARB_sample_shading
GlFunction(Void, "glMinSampleShadingARB", [(GLfloat, "value")]),
@@ -1276,13 +1554,13 @@ glapi.addFunctions([
# GL_ARB_shader_subroutine
GlFunction(GLlocation, "glGetSubroutineUniformLocation", [(GLprogram, "program"), (GLenum, "shadertype"), (GLstringConst, "name")]),
- GlFunction(GLuint, "glGetSubroutineIndex", [(GLprogram, "program"), (GLenum, "shadertype"), (GLstringConst, "name")]),
- GlFunction(Void, "glGetActiveSubroutineUniformiv", [(GLprogram, "program"), (GLenum, "shadertype"), (GLuint, "index"), (GLenum, "pname"), Out(OpaqueArray(GLint, "_glGetActiveSubroutineUniformiv_size(pname)"), "values")], sideeffects=False),
- GlFunction(Void, "glGetActiveSubroutineUniformName", [(GLprogram, "program"), (GLenum, "shadertype"), (GLuint, "index"), (GLsizei, "bufsize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "name")], sideeffects=False),
- GlFunction(Void, "glGetActiveSubroutineName", [(GLprogram, "program"), (GLenum, "shadertype"), (GLuint, "index"), (GLsizei, "bufsize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "name")], sideeffects=False),
- GlFunction(Void, "glUniformSubroutinesuiv", [(GLenum, "shadertype"), (GLsizei, "count"), (Array(Const(GLuint), "count"), "indices")]),
- GlFunction(Void, "glGetUniformSubroutineuiv", [(GLenum, "shadertype"), (GLlocation, "location"), Out(Pointer(GLuint), "params")], sideeffects=False),
- GlFunction(Void, "glGetProgramStageiv", [(GLprogram, "program"), (GLenum, "shadertype"), (GLenum, "pname"), Out(Pointer(GLint), "values")], sideeffects=False),
+ GlFunction(GLsubroutine, "glGetSubroutineIndex", [(GLprogram, "program"), (GLenum, "shadertype"), (GLstringConst, "name")]),
+ GlFunction(Void, "glGetActiveSubroutineUniformiv", [(GLprogram, "program"), (GLenum, "shadertype"), (GLsubroutine, "index"), (GLenum, "pname"), Out(OpaqueArray(GLint, "_glGetActiveSubroutineUniformiv_size(pname)"), "values")], sideeffects=False),
+ GlFunction(Void, "glGetActiveSubroutineUniformName", [(GLprogram, "program"), (GLenum, "shadertype"), (GLsubroutine, "index"), (GLsizei, "bufsize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "name")], sideeffects=False),
+ GlFunction(Void, "glGetActiveSubroutineName", [(GLprogram, "program"), (GLenum, "shadertype"), (GLsubroutine, "index"), (GLsizei, "bufsize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "name")], sideeffects=False),
+ GlFunction(Void, "glUniformSubroutinesuiv", [(GLenum, "shadertype"), (GLsizei, "count"), (Array(Const(GLsubroutine), "count"), "indices")]),
+ GlFunction(Void, "glGetUniformSubroutineuiv", [(GLenum, "shadertype"), (GLlocation, "location"), Out(OpaquePointer(GLuint), "params")], sideeffects=False),
+ GlFunction(Void, "glGetProgramStageiv", [(GLprogram, "program"), (GLenum, "shadertype"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "values")], sideeffects=False),
# GL_ARB_shading_language_include
GlFunction(Void, "glNamedStringARB", [(GLenum, "type"), (GLint, "namelen"), InGlString(GLchar, "namelen", "name"), (GLint, "stringlen"), InGlString(GLchar, "stringlen", "string")]),
@@ -1292,9 +1570,13 @@ glapi.addFunctions([
GlFunction(Void, "glGetNamedStringARB", [(GLint, "namelen"), InGlString(GLchar, "namelen", "name"), (GLsizei, "bufSize"), Out(Pointer(GLint), "stringlen"), OutGlString(GLchar, "stringlen", "string")], sideeffects=False),
GlFunction(Void, "glGetNamedStringivARB", [(GLint, "namelen"), InGlString(GLchar, "namelen", "name"), (GLenum, "pname"), Out(OpaqueArray(GLint, "_glGetNamedStringivARB_size(pname)"), "params")], sideeffects=False),
+ # GL_ARB_sparse_buffer
+ GlFunction(Void, "glBufferPageCommitmentARB", [(GLenum, "target"), (GLintptr, "offset"), (GLsizeiptr, "size"), (GLboolean, "commit")]),
+ GlFunction(Void, "glNamedBufferPageCommitmentEXT", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size"), (GLboolean, "commit")]),
+ GlFunction(Void, "glNamedBufferPageCommitmentARB", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size"), (GLboolean, "commit")]),
+
# GL_ARB_sparse_texture
GlFunction(Void, "glTexPageCommitmentARB", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLboolean, "resident")]),
- GlFunction(Void, "glTexturePageCommitmentEXT", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLboolean, "commit")]),
# GL_ARB_sync
GlFunction(GLsync, "glFenceSync", [(GLenum, "condition"), (GLbitfield, "flags")]),
@@ -1303,18 +1585,20 @@ glapi.addFunctions([
GlFunction(GLenum, "glClientWaitSync", [(GLsync, "sync"), (GLbitfield_sync_flush, "flags"), (GLuint64, "timeout")]),
GlFunction(Void, "glWaitSync", [(GLsync, "sync"), (GLbitfield, "flags"), (GLuint64, "timeout")]),
GlFunction(Void, "glGetInteger64v", [(GLenum, "pname"), Out(Array(GLint64, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetSynciv", [(GLsync, "sync"), (GLenum, "pname"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLint, "(length ? *length : bufSize)"), "values")], sideeffects=False),
+ GlFunction(Void, "glGetSynciv", [(GLsync, "sync"), (GLenum, "pname"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLint, "(length ? *length : bufSize)"), "values")]),
# GL_ARB_tessellation_shader
GlFunction(Void, "glPatchParameteri", [(GLenum, "pname"), (GLint, "value")]),
GlFunction(Void, "glPatchParameterfv", [(GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "values")]),
+ # GL_ARB_texture_barrier
+ GlFunction(Void, "glTextureBarrier", []),
+
# GL_ARB_texture_buffer_object
GlFunction(Void, "glTexBufferARB", [(GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer")]),
# GL_ARB_texture_buffer_range
GlFunction(Void, "glTexBufferRange", [(GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
- GlFunction(Void, "glTextureBufferRangeEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
# GL_ARB_texture_compression
GlFunction(Void, "glCompressedTexImage3DARB", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "data")]),
@@ -1328,22 +1612,17 @@ glapi.addFunctions([
# GL_ARB_texture_multisample
GlFunction(Void, "glTexImage2DMultisample", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLboolean, "fixedsamplelocations")]),
GlFunction(Void, "glTexImage3DMultisample", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLboolean, "fixedsamplelocations")]),
- GlFunction(Void, "glGetMultisamplefv", [(GLenum, "pname"), (GLuint, "index"), Out(Array(GLfloat, "_gl_param_size(pname)"), "val")], sideeffects=False),
+ GlFunction(Void, "glGetMultisamplefv", [(GLenum, "pname"), (GLuint, "index"), Out(Array(GLfloat, 2), "val")], sideeffects=False),
GlFunction(Void, "glSampleMaski", [(GLuint, "index"), (GLbitfield, "mask")]),
# GL_ARB_texture_storage
GlFunction(Void, "glTexStorage1D", [(GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width")]),
GlFunction(Void, "glTexStorage2D", [(GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
GlFunction(Void, "glTexStorage3D", [(GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
- GlFunction(Void, "glTextureStorage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width")]),
- GlFunction(Void, "glTextureStorage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glTextureStorage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
# GL_ARB_texture_storage_multisample
GlFunction(Void, "glTexStorage2DMultisample", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLboolean, "fixedsamplelocations")]),
GlFunction(Void, "glTexStorage3DMultisample", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLboolean, "fixedsamplelocations")]),
- GlFunction(Void, "glTextureStorage2DMultisampleEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLboolean, "fixedsamplelocations")]),
- GlFunction(Void, "glTextureStorage3DMultisampleEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLboolean, "fixedsamplelocations")]),
# GL_ARB_texture_view
GlFunction(Void, "glTextureView", [(GLtexture, "texture"), (GLenum, "target"), (GLtexture, "origtexture"), (GLenum, "internalformat"), (GLuint, "minlevel"), (GLuint, "numlevels"), (GLuint, "minlayer"), (GLuint, "numlayers")]),
@@ -1369,8 +1648,8 @@ glapi.addFunctions([
GlFunction(Void, "glGetQueryIndexediv", [(GLenum, "target"), (GLuint, "index"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
# GL_ARB_transform_feedback_instanced
- GlFunction(Void, "glDrawTransformFeedbackInstanced", [(GLenum_mode, "mode"), (GLfeedback, "id"), (GLsizei, "primcount")]),
- GlFunction(Void, "glDrawTransformFeedbackStreamInstanced", [(GLenum_mode, "mode"), (GLfeedback, "id"), (GLuint, "stream"), (GLsizei, "primcount")]),
+ GlFunction(Void, "glDrawTransformFeedbackInstanced", [(GLenum_mode, "mode"), (GLfeedback, "id"), (GLsizei, "instancecount")]),
+ GlFunction(Void, "glDrawTransformFeedbackStreamInstanced", [(GLenum_mode, "mode"), (GLfeedback, "id"), (GLuint, "stream"), (GLsizei, "instancecount")]),
# GL_ARB_transpose_matrix
GlFunction(Void, "glLoadTransposeMatrixfARB", [(Array(Const(GLfloat), 16), "m")]),
@@ -1412,12 +1691,6 @@ glapi.addFunctions([
GlFunction(Void, "glVertexAttribLFormat", [(GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLuint, "relativeoffset")]),
GlFunction(Void, "glVertexAttribBinding", [(GLuint, "attribindex"), (GLuint, "bindingindex")]),
GlFunction(Void, "glVertexBindingDivisor", [(GLuint, "bindingindex"), (GLuint, "divisor")]),
- GlFunction(Void, "glVertexArrayBindVertexBufferEXT", [(GLarray, "vaobj"), (GLuint, "bindingindex"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizei, "stride")]),
- GlFunction(Void, "glVertexArrayVertexAttribFormatEXT", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "relativeoffset")]),
- GlFunction(Void, "glVertexArrayVertexAttribIFormatEXT", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLuint, "relativeoffset")]),
- GlFunction(Void, "glVertexArrayVertexAttribLFormatEXT", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLuint, "relativeoffset")]),
- GlFunction(Void, "glVertexArrayVertexAttribBindingEXT", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLuint, "bindingindex")]),
- GlFunction(Void, "glVertexArrayVertexBindingDivisorEXT", [(GLarray, "vaobj"), (GLuint, "bindingindex"), (GLuint, "divisor")]),
# GL_ARB_vertex_blend
GlFunction(Void, "glWeightbvARB", [(GLint, "size"), (Array(Const(GLbyte), "size"), "weights")]),
@@ -1514,6 +1787,14 @@ glapi.addFunctions([
GlFunction(GLint, "glGetAttribLocationARB", [(GLhandleARB, "programObj"), (GLstringConstARB, "name")]),
# GL_ARB_vertex_type_2_10_10_10_rev
+ GlFunction(Void, "glVertexAttribP1ui", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "value")]),
+ GlFunction(Void, "glVertexAttribP1uiv", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (Pointer(Const(GLuint)), "value")]),
+ GlFunction(Void, "glVertexAttribP2ui", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "value")]),
+ GlFunction(Void, "glVertexAttribP2uiv", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (Pointer(Const(GLuint)), "value")]),
+ GlFunction(Void, "glVertexAttribP3ui", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "value")]),
+ GlFunction(Void, "glVertexAttribP3uiv", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (Pointer(Const(GLuint)), "value")]),
+ GlFunction(Void, "glVertexAttribP4ui", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "value")]),
+ GlFunction(Void, "glVertexAttribP4uiv", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (Pointer(Const(GLuint)), "value")]),
GlFunction(Void, "glVertexP2ui", [(GLenum, "type"), (GLuint, "value")]),
GlFunction(Void, "glVertexP2uiv", [(GLenum, "type"), (Pointer(Const(GLuint)), "value")]),
GlFunction(Void, "glVertexP3ui", [(GLenum, "type"), (GLuint, "value")]),
@@ -1544,14 +1825,6 @@ glapi.addFunctions([
GlFunction(Void, "glColorP4uiv", [(GLenum, "type"), (Pointer(Const(GLuint)), "color")]),
GlFunction(Void, "glSecondaryColorP3ui", [(GLenum, "type"), (GLuint, "color")]),
GlFunction(Void, "glSecondaryColorP3uiv", [(GLenum, "type"), (Pointer(Const(GLuint)), "color")]),
- GlFunction(Void, "glVertexAttribP1ui", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "value")]),
- GlFunction(Void, "glVertexAttribP1uiv", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (Pointer(Const(GLuint)), "value")]),
- GlFunction(Void, "glVertexAttribP2ui", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "value")]),
- GlFunction(Void, "glVertexAttribP2uiv", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (Pointer(Const(GLuint)), "value")]),
- GlFunction(Void, "glVertexAttribP3ui", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "value")]),
- GlFunction(Void, "glVertexAttribP3uiv", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (Pointer(Const(GLuint)), "value")]),
- GlFunction(Void, "glVertexAttribP4ui", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "value")]),
- GlFunction(Void, "glVertexAttribP4uiv", [(GLuint, "index"), (GLenum, "type"), (GLboolean, "normalized"), (Pointer(Const(GLuint)), "value")]),
# GL_ARB_viewport_array
GlFunction(Void, "glViewportArrayv", [(GLuint, "first"), (GLsizei, "count"), (Array(Const(GLfloat), "count*4"), "v")]),
@@ -1691,6 +1964,11 @@ glapi.addFunctions([
GlFunction(Void, "glVertexBlendEnviATI", [(GLenum, "pname"), (GLint, "param")]),
GlFunction(Void, "glVertexBlendEnvfATI", [(GLenum, "pname"), (GLfloat, "param")]),
+ # GL_EXT_base_instance
+ GlFunction(Void, "glDrawArraysInstancedBaseInstanceEXT", [(GLenum_mode, "mode"), (GLint, "first"), (GLsizei, "count"), (GLsizei, "instancecount"), (GLuint, "baseinstance")]),
+ GlFunction(Void, "glDrawElementsInstancedBaseInstanceEXT", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "instancecount"), (GLuint, "baseinstance")]),
+ GlFunction(Void, "glDrawElementsInstancedBaseVertexBaseInstanceEXT", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "instancecount"), (GLint, "basevertex"), (GLuint, "baseinstance")]),
+
# GL_EXT_bindable_uniform
GlFunction(Void, "glUniformBufferEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLbuffer, "buffer")]),
GlFunction(GLint, "glGetUniformBufferSizeEXT", [(GLprogram, "program"), (GLlocation, "location")]),
@@ -1702,12 +1980,21 @@ glapi.addFunctions([
# GL_EXT_blend_equation_separate
GlFunction(Void, "glBlendEquationSeparateEXT", [(GLenum, "modeRGB"), (GLenum, "modeAlpha")]),
+ # GL_EXT_blend_func_extended
+ GlFunction(Void, "glBindFragDataLocationIndexedEXT", [(GLprogram, "program"), (GLuint, "colorNumber"), (GLuint, "index"), (GLstringConst, "name")]),
+ GlFunction(Void, "glBindFragDataLocationEXT", [(GLprogram, "program"), (GLuint, "color"), (GLstringConst, "name")]),
+ GlFunction(GLlocation, "glGetProgramResourceLocationIndexEXT", [(GLprogram, "program"), (GLenum, "programInterface"), (GLstringConst, "name")]),
+ GlFunction(GLint, "glGetFragDataIndexEXT", [(GLprogram, "program"), (GLstringConst, "name")]),
+
# GL_EXT_blend_func_separate
GlFunction(Void, "glBlendFuncSeparateEXT", [(GLenum, "sfactorRGB"), (GLenum, "dfactorRGB"), (GLenum, "sfactorAlpha"), (GLenum, "dfactorAlpha")]),
# GL_EXT_blend_minmax
GlFunction(Void, "glBlendEquationEXT", [(GLenum, "mode")]),
+ # GL_EXT_buffer_storage
+ GlFunction(Void, "glBufferStorageEXT", [(GLenum, "target"), (GLsizeiptr, "size"), (Blob(Const(Void), "size"), "data"), (GLbitfield_storage, "flags")]),
+
# GL_EXT_color_subtable
GlFunction(Void, "glColorSubTableEXT", [(GLenum, "target"), (GLsizei, "start"), (GLsizei, "count"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glColorSubTable_size(format, type, count)"), "data")]),
GlFunction(Void, "glCopyColorSubTableEXT", [(GLenum, "target"), (GLsizei, "start"), (GLint, "x"), (GLint, "y"), (GLsizei, "width")]),
@@ -1725,10 +2012,10 @@ glapi.addFunctions([
GlFunction(Void, "glConvolutionParameterivEXT", [(GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
GlFunction(Void, "glCopyConvolutionFilter1DEXT", [(GLenum, "target"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width")]),
GlFunction(Void, "glCopyConvolutionFilter2DEXT", [(GLenum, "target"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glGetConvolutionFilterEXT", [(GLenum, "target"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetConvolutionFilterEXT_size(target, format, type)"), "image")], sideeffects=False),
+ GlFunction(Void, "glGetConvolutionFilterEXT", [(GLenum, "target"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetConvolutionFilterEXT_size(target, format, type)"), "image")]),
GlFunction(Void, "glGetConvolutionParameterfvEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetConvolutionParameterivEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetSeparableFilterEXT", [(GLenum, "target"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetSeparableFilterEXT_size(target, format, type)"), "row"), Out(OpaqueBlob(GLvoid, "_glGetSeparableFilterEXT_size(target, format, type)"), "column"), Out(OpaqueBlob(GLvoid, "_glGetSeparableFilterEXT_size(target, format, type)"), "span")], sideeffects=False),
+ GlFunction(Void, "glGetSeparableFilterEXT", [(GLenum, "target"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetSeparableFilterEXT_size(target, format, type)"), "row"), Out(OpaqueBlob(GLvoid, "_glGetSeparableFilterEXT_size(target, format, type)"), "column"), Out(OpaqueBlob(GLvoid, "_glGetSeparableFilterEXT_size(target, format, type)"), "span")]),
GlFunction(Void, "glSeparableFilter2DEXT", [(GLenum, "target"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glConvolutionFilter1D_size(format, type, width)"), "row"), (Blob(Const(GLvoid), "_glConvolutionFilter1D_size(format, type, height)"), "column")]),
# GL_EXT_coordinate_frame
@@ -1755,6 +2042,9 @@ glapi.addFunctions([
GlFunction(Void, "glTangentPointerEXT", [(GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
GlFunction(Void, "glBinormalPointerEXT", [(GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
+ # GL_EXT_copy_image
+ GlFunction(Void, "glCopyImageSubDataEXT", [(GLtexture, "srcName"), (GLenum, "srcTarget"), (GLint, "srcLevel"), (GLint, "srcX"), (GLint, "srcY"), (GLint, "srcZ"), (GLtexture, "dstName"), (GLenum, "dstTarget"), (GLint, "dstLevel"), (GLint, "dstX"), (GLint, "dstY"), (GLint, "dstZ"), (GLsizei, "srcWidth"), (GLsizei, "srcHeight"), (GLsizei, "srcDepth")]),
+
# GL_EXT_copy_texture
GlFunction(Void, "glCopyTexImage1DEXT", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLint, "border")]),
GlFunction(Void, "glCopyTexImage2DEXT", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border")]),
@@ -1763,8 +2053,8 @@ glapi.addFunctions([
GlFunction(Void, "glCopyTexSubImage3DEXT", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
# GL_EXT_cull_vertex
- GlFunction(Void, "glCullParameterdvEXT", [(GLenum, "pname"), (Array(GLdouble, 4), "params")]),
- GlFunction(Void, "glCullParameterfvEXT", [(GLenum, "pname"), (Array(GLfloat, 4), "params")]),
+ GlFunction(Void, "glCullParameterdvEXT", [(GLenum, "pname"), (Array(GLdouble, "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glCullParameterfvEXT", [(GLenum, "pname"), (Array(GLfloat, "_gl_param_size(pname)"), "params")]),
# GL_EXT_debug_label
GlFunction(Void, "glLabelObjectEXT", [(GLenum, "type"), (GLuint, "object"), (GLsizei, "length"), (GLstringConst, "label")]),
@@ -1779,72 +2069,118 @@ glapi.addFunctions([
GlFunction(Void, "glDepthBoundsEXT", [(GLclampd, "zmin"), (GLclampd, "zmax")]),
# GL_EXT_direct_state_access
+ GlFunction(Void, "glBindMultiTextureEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLtexture, "texture")]),
+ GlFunction(GLenum, "glCheckNamedFramebufferStatusEXT", [(GLframebuffer, "framebuffer"), (GLenum, "target")]),
+ GlFunction(Void, "glClearNamedBufferDataEXT", [(GLbuffer, "buffer"), (GLenum, "internalformat"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glClearBufferData_size(format, type)"), "data")]),
+ GlFunction(Void, "glClearNamedBufferSubDataEXT", [(GLbuffer, "buffer"), (GLenum, "internalformat"), (GLsizeiptr, "offset"), (GLsizeiptr, "size"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(Void), "_glClearBufferData_size(format, type)"), "data")]),
GlFunction(Void, "glClientAttribDefaultEXT", [(GLbitfield_client_attrib, "mask")]),
- GlFunction(Void, "glPushClientAttribDefaultEXT", [(GLbitfield_client_attrib, "mask")]),
- GlFunction(Void, "glMatrixLoadfEXT", [(GLenum, "mode"), (Array(Const(GLfloat), 16), "m")]),
- GlFunction(Void, "glMatrixLoaddEXT", [(GLenum, "mode"), (Array(Const(GLdouble), 16), "m")]),
- GlFunction(Void, "glMatrixMultfEXT", [(GLenum, "mode"), (Array(Const(GLfloat), 16), "m")]),
- GlFunction(Void, "glMatrixMultdEXT", [(GLenum, "mode"), (Array(Const(GLdouble), 16), "m")]),
- GlFunction(Void, "glMatrixLoadIdentityEXT", [(GLenum, "mode")]),
- GlFunction(Void, "glMatrixRotatefEXT", [(GLenum, "mode"), (GLfloat, "angle"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z")]),
- GlFunction(Void, "glMatrixRotatedEXT", [(GLenum, "mode"), (GLdouble, "angle"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z")]),
- GlFunction(Void, "glMatrixScalefEXT", [(GLenum, "mode"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z")]),
- GlFunction(Void, "glMatrixScaledEXT", [(GLenum, "mode"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z")]),
- GlFunction(Void, "glMatrixTranslatefEXT", [(GLenum, "mode"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z")]),
- GlFunction(Void, "glMatrixTranslatedEXT", [(GLenum, "mode"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z")]),
- GlFunction(Void, "glMatrixFrustumEXT", [(GLenum, "mode"), (GLdouble, "left"), (GLdouble, "right"), (GLdouble, "bottom"), (GLdouble, "top"), (GLdouble, "zNear"), (GLdouble, "zFar")]),
- GlFunction(Void, "glMatrixOrthoEXT", [(GLenum, "mode"), (GLdouble, "left"), (GLdouble, "right"), (GLdouble, "bottom"), (GLdouble, "top"), (GLdouble, "zNear"), (GLdouble, "zFar")]),
- GlFunction(Void, "glMatrixPopEXT", [(GLenum, "mode")]),
- GlFunction(Void, "glMatrixPushEXT", [(GLenum, "mode")]),
- GlFunction(Void, "glMatrixLoadTransposefEXT", [(GLenum, "mode"), (Array(Const(GLfloat), 16), "m")]),
- GlFunction(Void, "glMatrixLoadTransposedEXT", [(GLenum, "mode"), (Array(Const(GLdouble), 16), "m")]),
- GlFunction(Void, "glMatrixMultTransposefEXT", [(GLenum, "mode"), (Array(Const(GLfloat), 16), "m")]),
- GlFunction(Void, "glMatrixMultTransposedEXT", [(GLenum, "mode"), (Array(Const(GLdouble), 16), "m")]),
- GlFunction(Void, "glTextureParameterfEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (GLfloat, "param")]),
- GlFunction(Void, "glTextureParameterfvEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glTextureParameteriEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (GLint, "param")]),
- GlFunction(Void, "glTextureParameterivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glTextureImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTextureImage1DEXT_size(format, type, width)"), "pixels")]),
- GlFunction(Void, "glTextureImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTextureImage2DEXT_size(format, type, width, height)"), "pixels")]),
- GlFunction(Void, "glTextureSubImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTextureSubImage1DEXT_size(format, type, width)"), "pixels")]),
- GlFunction(Void, "glTextureSubImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTextureSubImage2DEXT_size(format, type, width, height)"), "pixels")]),
+ GlFunction(Void, "glCompressedMultiTexImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedMultiTexImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedMultiTexImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedMultiTexSubImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedMultiTexSubImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedMultiTexSubImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedTextureImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedTextureImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedTextureImage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedTextureSubImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedTextureSubImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCompressedTextureSubImage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
+ GlFunction(Void, "glCopyMultiTexImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLint, "border")]),
+ GlFunction(Void, "glCopyMultiTexImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border")]),
+ GlFunction(Void, "glCopyMultiTexSubImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width")]),
+ GlFunction(Void, "glCopyMultiTexSubImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glCopyMultiTexSubImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
GlFunction(Void, "glCopyTextureImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLint, "border")]),
GlFunction(Void, "glCopyTextureImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border")]),
GlFunction(Void, "glCopyTextureSubImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width")]),
GlFunction(Void, "glCopyTextureSubImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glGetTextureImageEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetTextureImageEXT_size(target, level, format, type)"), "pixels")]),
- GlFunction(Void, "glGetTextureParameterfvEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetTextureParameterivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetTextureLevelParameterfvEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetTextureLevelParameterivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glTextureImage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTextureImage3DEXT_size(format, type, width, height, depth)"), "pixels")]),
- GlFunction(Void, "glTextureSubImage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTextureSubImage3DEXT_size(format, type, width, height, depth)"), "pixels")]),
GlFunction(Void, "glCopyTextureSubImage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glMultiTexParameterfEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (GLfloat, "param")]),
- GlFunction(Void, "glMultiTexParameterfvEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glMultiTexParameteriEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (GLint, "param")]),
- GlFunction(Void, "glMultiTexParameterivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glMultiTexImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glMultiTexImage1DEXT_size(format, type, width)"), "pixels")]),
- GlFunction(Void, "glMultiTexImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glMultiTexImage2DEXT_size(format, type, width, height)"), "pixels")]),
- GlFunction(Void, "glMultiTexSubImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glMultiTexSubImage1DEXT_size(format, type, width)"), "pixels")]),
- GlFunction(Void, "glMultiTexSubImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glMultiTexSubImage2DEXT_size(format, type, width, height)"), "pixels")]),
- GlFunction(Void, "glCopyMultiTexImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLint, "border")]),
- GlFunction(Void, "glCopyMultiTexImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border")]),
- GlFunction(Void, "glCopyMultiTexSubImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width")]),
- GlFunction(Void, "glCopyMultiTexSubImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glDisableClientStateIndexedEXT", [(GLenum, "array"), (GLuint, "index")]),
+ GlFunction(Void, "glDisableClientStateiEXT", [(GLenum, "array"), (GLuint, "index")]),
+ #GlFunction(Void, "glDisableIndexedEXT", [(GLenum, "target"), (GLuint, "index")]),
+ GlFunction(Void, "glDisableVertexArrayAttribEXT", [(GLarray, "vaobj"), (GLuint, "index")]),
+ GlFunction(Void, "glDisableVertexArrayEXT", [(GLarray, "vaobj"), (GLenum, "array")]),
+ GlFunction(Void, "glEnableClientStateIndexedEXT", [(GLenum, "array"), (GLuint, "index")]),
+ GlFunction(Void, "glEnableClientStateiEXT", [(GLenum, "array"), (GLuint, "index")]),
+ #GlFunction(Void, "glEnableIndexedEXT", [(GLenum, "target"), (GLuint, "index")]),
+ GlFunction(Void, "glEnableVertexArrayAttribEXT", [(GLarray, "vaobj"), (GLuint, "index")]),
+ GlFunction(Void, "glEnableVertexArrayEXT", [(GLarray, "vaobj"), (GLenum, "array")]),
+ GlFunction(Void, "glFlushMappedNamedBufferRangeEXT", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "length")]),
+ GlFunction(Void, "glFramebufferDrawBufferEXT", [(GLframebuffer, "framebuffer"), (GLenum, "mode")]),
+ GlFunction(Void, "glFramebufferDrawBuffersEXT", [(GLframebuffer, "framebuffer"), (GLsizei, "n"), (Array(Const(GLenum), "n"), "bufs")]),
+ GlFunction(Void, "glFramebufferReadBufferEXT", [(GLframebuffer, "framebuffer"), (GLenum, "mode")]),
+ GlFunction(Void, "glGenerateMultiTexMipmapEXT", [(GLenum, "texunit"), (GLenum, "target")]),
+ GlFunction(Void, "glGenerateTextureMipmapEXT", [(GLtexture, "texture"), (GLenum, "target")]),
+ #GlFunction(Void, "glGetBooleanIndexedvEXT", [(GLenum, "target"), (GLuint, "index"), (Array(GLboolean, "COMPSIZE(target)"), "data")]),
+ GlFunction(Void, "glGetCompressedMultiTexImageEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "lod"), Out(OpaqueBlob(GLvoid, "_glGetCompressedMultiTexImageEXT_size(target, lod)"), "img")]),
+ GlFunction(Void, "glGetCompressedTextureImageEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "lod"), Out(OpaqueBlob(GLvoid, "_glGetCompressedTextureImageEXT_size(target, lod)"), "img")]),
+ GlFunction(Void, "glGetDoubleIndexedvEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLdouble, "_gl_param_size(target)"), "data")], sideeffects=False),
+ GlFunction(Void, "glGetDoublei_vEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLdouble, "_gl_param_size(target)"), "data")], sideeffects=False),
+ GlFunction(Void, "glGetFloatIndexedvEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLfloat, "_gl_param_size(target)"), "data")], sideeffects=False),
+ GlFunction(Void, "glGetFloati_vEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLfloat, "_gl_param_size(target)"), "data")], sideeffects=False),
+ GlFunction(Void, "glGetFramebufferParameterivEXT", [(GLframebuffer, "framebuffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ #GlFunction(Void, "glGetIntegerIndexedvEXT", [(GLenum, "target"), (GLuint, "index"), (Array(GLint, "COMPSIZE(target)"), "data")]),
+ GlFunction(Void, "glGetMultiTexEnvfvEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetMultiTexEnvivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetMultiTexGendvEXT", [(GLenum, "texunit"), (GLenum, "coord"), (GLenum, "pname"), Out(Array(GLdouble, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetMultiTexGenfvEXT", [(GLenum, "texunit"), (GLenum, "coord"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetMultiTexGenivEXT", [(GLenum, "texunit"), (GLenum, "coord"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetMultiTexImageEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetMultiTexImageEXT_size(target, level, format, type)"), "pixels")]),
- GlFunction(Void, "glGetMultiTexParameterfvEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetMultiTexParameterivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetMultiTexLevelParameterfvEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetMultiTexLevelParameterivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glMultiTexImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glMultiTexImage3DEXT_size(format, type, width, height, depth)"), "pixels")]),
- GlFunction(Void, "glMultiTexSubImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glMultiTexSubImage3DEXT_size(format, type, width, height, depth)"), "pixels")]),
- GlFunction(Void, "glCopyMultiTexSubImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glBindMultiTextureEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLtexture, "texture")]),
- GlFunction(Void, "glEnableClientStateIndexedEXT", [(GLenum, "array"), (GLuint, "index")]),
- GlFunction(Void, "glDisableClientStateIndexedEXT", [(GLenum, "array"), (GLuint, "index")]),
- GlFunction(Void, "glEnableClientStateiEXT", [(GLenum, "array"), (GLuint, "index")]),
- GlFunction(Void, "glDisableClientStateiEXT", [(GLenum, "array"), (GLuint, "index")]),
+ GlFunction(Void, "glGetMultiTexParameterIivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetMultiTexParameterIuivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetMultiTexParameterfvEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetMultiTexParameterivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedBufferParameterivEXT", [(GLbuffer, "buffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedBufferPointervEXT", [(GLbuffer, "buffer"), (GLenum, "pname"), Out(Pointer(GLpointer), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedBufferSubDataEXT", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size"), Out(OpaqueBlob(GLvoid, "size"), "data")], sideeffects=False),
+ GlFunction(Void, "glGetNamedFramebufferAttachmentParameterivEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedFramebufferParameterivEXT", [(GLframebuffer, "framebuffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedProgramLocalParameterIivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), Out(Array(GLint, 4), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedProgramLocalParameterIuivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), Out(Array(GLuint, 4), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedProgramLocalParameterdvEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), Out(Array(GLdouble, 4), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedProgramLocalParameterfvEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), Out(Array(GLfloat, 4), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedProgramStringEXT", [(GLprogram, "program"), (GLenum, "target"), (GLenum, "pname"), Out(OpaqueBlob(GLvoid, "_glGetNamedProgramStringEXT_size(program,pname)"), "string")], sideeffects=False),
+ GlFunction(Void, "glGetNamedProgramivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLenum, "pname"), Out(Pointer(GLint), "params")], sideeffects=False),
+ GlFunction(Void, "glGetNamedRenderbufferParameterivEXT", [(GLrenderbuffer, "renderbuffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetPointerIndexedvEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLpointer, "_gl_param_size(target)"), "data")], sideeffects=False),
+ GlFunction(Void, "glGetPointeri_vEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLpointer, "_gl_param_size(target)"), "data")], sideeffects=False),
+ GlFunction(Void, "glGetTextureImageEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "format"), (GLenum, "type"), Out(GLpointer, "pixels")]),
+ GlFunction(Void, "glGetTextureLevelParameterfvEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureLevelParameterivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureParameterIivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureParameterIuivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureParameterfvEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTextureParameterivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetVertexArrayIntegeri_vEXT", [(GLarray, "vaobj"), (GLuint, "index"), (GLenum, "pname"), Out(Pointer(GLint), "param")], sideeffects=False),
+ GlFunction(Void, "glGetVertexArrayIntegervEXT", [(GLarray, "vaobj"), (GLenum, "pname"), Out(Pointer(GLint), "param")], sideeffects=False),
+ GlFunction(Void, "glGetVertexArrayPointeri_vEXT", [(GLarray, "vaobj"), (GLuint, "index"), (GLenum, "pname"), Out(Pointer(GLpointer), "param")], sideeffects=False),
+ GlFunction(Void, "glGetVertexArrayPointervEXT", [(GLarray, "vaobj"), (GLenum, "pname"), Out(Pointer(GLpointer), "param")], sideeffects=False),
+ #GlFunction(GLboolean, "glIsEnabledIndexedEXT", [(GLenum, "target"), (GLuint, "index")]),
+ GlFunction(GLmap, "glMapNamedBufferEXT", [(GLbuffer, "buffer"), (GLenum, "access")]),
+ GlFunction(GLmap, "glMapNamedBufferRangeEXT", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "length"), (GLbitfield_access, "access")]),
+ GlFunction(Void, "glMatrixFrustumEXT", [(GLenum, "mode"), (GLdouble, "left"), (GLdouble, "right"), (GLdouble, "bottom"), (GLdouble, "top"), (GLdouble, "zNear"), (GLdouble, "zFar")]),
+ GlFunction(Void, "glMatrixLoadIdentityEXT", [(GLenum, "mode")]),
+ GlFunction(Void, "glMatrixLoadTransposedEXT", [(GLenum, "mode"), (Array(Const(GLdouble), 16), "m")]),
+ GlFunction(Void, "glMatrixLoadTransposefEXT", [(GLenum, "mode"), (Array(Const(GLfloat), 16), "m")]),
+ GlFunction(Void, "glMatrixLoaddEXT", [(GLenum, "mode"), (Array(Const(GLdouble), 16), "m")]),
+ GlFunction(Void, "glMatrixLoadfEXT", [(GLenum, "mode"), (Array(Const(GLfloat), 16), "m")]),
+ GlFunction(Void, "glMatrixMultTransposedEXT", [(GLenum, "mode"), (Array(Const(GLdouble), 16), "m")]),
+ GlFunction(Void, "glMatrixMultTransposefEXT", [(GLenum, "mode"), (Array(Const(GLfloat), 16), "m")]),
+ GlFunction(Void, "glMatrixMultdEXT", [(GLenum, "mode"), (Array(Const(GLdouble), 16), "m")]),
+ GlFunction(Void, "glMatrixMultfEXT", [(GLenum, "mode"), (Array(Const(GLfloat), 16), "m")]),
+ GlFunction(Void, "glMatrixOrthoEXT", [(GLenum, "mode"), (GLdouble, "left"), (GLdouble, "right"), (GLdouble, "bottom"), (GLdouble, "top"), (GLdouble, "zNear"), (GLdouble, "zFar")]),
+ GlFunction(Void, "glMatrixPopEXT", [(GLenum, "mode")]),
+ GlFunction(Void, "glMatrixPushEXT", [(GLenum, "mode")]),
+ GlFunction(Void, "glMatrixRotatedEXT", [(GLenum, "mode"), (GLdouble, "angle"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z")]),
+ GlFunction(Void, "glMatrixRotatefEXT", [(GLenum, "mode"), (GLfloat, "angle"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z")]),
+ GlFunction(Void, "glMatrixScaledEXT", [(GLenum, "mode"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z")]),
+ GlFunction(Void, "glMatrixScalefEXT", [(GLenum, "mode"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z")]),
+ GlFunction(Void, "glMatrixTranslatedEXT", [(GLenum, "mode"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z")]),
+ GlFunction(Void, "glMatrixTranslatefEXT", [(GLenum, "mode"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z")]),
+ GlFunction(Void, "glMultiTexBufferEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer")]),
GlFunction(Void, "glMultiTexCoordPointerEXT", [(GLenum, "texunit"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
GlFunction(Void, "glMultiTexEnvfEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (GLfloat, "param")]),
GlFunction(Void, "glMultiTexEnvfvEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
@@ -1856,159 +2192,157 @@ glapi.addFunctions([
GlFunction(Void, "glMultiTexGenfvEXT", [(GLenum, "texunit"), (GLenum, "coord"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
GlFunction(Void, "glMultiTexGeniEXT", [(GLenum, "texunit"), (GLenum, "coord"), (GLenum, "pname"), (GLint, "param")]),
GlFunction(Void, "glMultiTexGenivEXT", [(GLenum, "texunit"), (GLenum, "coord"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glGetMultiTexEnvfvEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetMultiTexEnvivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetMultiTexGendvEXT", [(GLenum, "texunit"), (GLenum, "coord"), (GLenum, "pname"), Out(Array(GLdouble, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetMultiTexGenfvEXT", [(GLenum, "texunit"), (GLenum, "coord"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetMultiTexGenivEXT", [(GLenum, "texunit"), (GLenum, "coord"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetFloatIndexedvEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLfloat, "_gl_param_size(target)"), "data")], sideeffects=False),
- GlFunction(Void, "glGetDoubleIndexedvEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLdouble, "_gl_param_size(target)"), "data")], sideeffects=False),
- GlFunction(Void, "glGetPointerIndexedvEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLpointer, "_gl_param_size(target)"), "data")], sideeffects=False),
- GlFunction(Void, "glGetFloati_vEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLfloat, "_gl_param_size(target)"), "data")], sideeffects=False),
- GlFunction(Void, "glGetDoublei_vEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLdouble, "_gl_param_size(target)"), "data")], sideeffects=False),
- GlFunction(Void, "glGetPointeri_vEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLpointer, "_gl_param_size(target)"), "data")], sideeffects=False),
- GlFunction(Void, "glCompressedTextureImage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedTextureImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedTextureImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedTextureSubImage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedTextureSubImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedTextureSubImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glGetCompressedTextureImageEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "lod"), Out(OpaqueBlob(GLvoid, "_glGetCompressedTextureImageEXT_size(target, lod)"), "img")]),
- GlFunction(Void, "glCompressedMultiTexImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedMultiTexImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedMultiTexImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedMultiTexSubImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedMultiTexSubImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glCompressedMultiTexSubImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "bits")]),
- GlFunction(Void, "glGetCompressedMultiTexImageEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "lod"), Out(OpaqueBlob(GLvoid, "_glGetCompressedMultiTexImageEXT_size(target, lod)"), "img")]),
- GlFunction(Void, "glNamedProgramStringEXT", [(GLprogram, "program"), (GLenum, "target"), (GLenum, "format"), (GLsizei, "len"), (String(Const(GLvoid), "len"), "string")]),
+ GlFunction(Void, "glMultiTexImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage1D_size(format, type, width)"), "pixels")]),
+ GlFunction(Void, "glMultiTexImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage2D_size(format, type, width, height)"), "pixels")]),
+ GlFunction(Void, "glMultiTexImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
+ GlFunction(Void, "glMultiTexParameterIivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glMultiTexParameterIuivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLuint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glMultiTexParameterfEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (GLfloat, "param")]),
+ GlFunction(Void, "glMultiTexParameterfvEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glMultiTexParameteriEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (GLint, "param")]),
+ GlFunction(Void, "glMultiTexParameterivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glMultiTexRenderbufferEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLrenderbuffer, "renderbuffer")]),
+ GlFunction(Void, "glMultiTexSubImage1DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage1D_size(format, type, width)"), "pixels")]),
+ GlFunction(Void, "glMultiTexSubImage2DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage2D_size(format, type, width, height)"), "pixels")]),
+ GlFunction(Void, "glMultiTexSubImage3DEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
+ GlFunction(Void, "glNamedBufferDataEXT", [(GLbuffer, "buffer"), (GLsizeiptr, "size"), (Blob(Const(GLvoid), "size"), "data"), (GLenum, "usage")]),
+ GlFunction(Void, "glNamedBufferStorageEXT", [ (GLbuffer, "buffer"), (GLsizeiptr, "size"), (Blob(Const(GLvoid), "size"), "data"), (GLbitfield_storage, "flags")]),
+ GlFunction(Void, "glNamedBufferSubDataEXT", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size"), (Blob(Const(GLvoid), "size"), "data")]),
+ GlFunction(Void, "glNamedCopyBufferSubDataEXT", [(GLbuffer, "readBuffer"), (GLbuffer, "writeBuffer"), (GLintptr, "readOffset"), (GLintptr, "writeOffset"), (GLsizeiptr, "size")]),
+ GlFunction(Void, "glNamedFramebufferParameteriEXT", [(GLframebuffer, "framebuffer"), (GLenum, "pname"), (GLint, "param")]),
+ GlFunction(Void, "glNamedFramebufferRenderbufferEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "renderbuffertarget"), (GLrenderbuffer, "renderbuffer")]),
+ GlFunction(Void, "glNamedFramebufferTexture1DEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level")]),
+ GlFunction(Void, "glNamedFramebufferTexture2DEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level")]),
+ GlFunction(Void, "glNamedFramebufferTexture3DEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level"), (GLint, "zoffset")]),
+ GlFunction(Void, "glNamedFramebufferTextureEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level")]),
+ GlFunction(Void, "glNamedFramebufferTextureFaceEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level"), (GLenum, "face")]),
+ GlFunction(Void, "glNamedFramebufferTextureLayerEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level"), (GLint, "layer")]),
GlFunction(Void, "glNamedProgramLocalParameter4dEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z"), (GLdouble, "w")]),
GlFunction(Void, "glNamedProgramLocalParameter4dvEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (Array(Const(GLdouble), 4), "params")]),
GlFunction(Void, "glNamedProgramLocalParameter4fEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z"), (GLfloat, "w")]),
GlFunction(Void, "glNamedProgramLocalParameter4fvEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (Array(Const(GLfloat), 4), "params")]),
- GlFunction(Void, "glGetNamedProgramLocalParameterdvEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), Out(Array(GLdouble, 4), "params")], sideeffects=False),
- GlFunction(Void, "glGetNamedProgramLocalParameterfvEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), Out(Array(GLfloat, 4), "params")], sideeffects=False),
- GlFunction(Void, "glGetNamedProgramivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLenum, "pname"), Out(Pointer(GLint), "params")], sideeffects=False),
- GlFunction(Void, "glGetNamedProgramStringEXT", [(GLprogram, "program"), (GLenum, "target"), (GLenum, "pname"), Out(OpaqueBlob(GLvoid, "_glGetNamedProgramStringEXT_size(program,pname)"), "string")], sideeffects=False),
- GlFunction(Void, "glNamedProgramLocalParameters4fvEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (GLsizei, "count"), (Array(Const(GLfloat), "count*4"), "params")]),
GlFunction(Void, "glNamedProgramLocalParameterI4iEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (GLint, "x"), (GLint, "y"), (GLint, "z"), (GLint, "w")]),
GlFunction(Void, "glNamedProgramLocalParameterI4ivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (Array(Const(GLint), 4), "params")]),
- GlFunction(Void, "glNamedProgramLocalParametersI4ivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (GLsizei, "count"), (Array(Const(GLint), "count*4"), "params")]),
GlFunction(Void, "glNamedProgramLocalParameterI4uiEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (GLuint, "x"), (GLuint, "y"), (GLuint, "z"), (GLuint, "w")]),
GlFunction(Void, "glNamedProgramLocalParameterI4uivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (Array(Const(GLuint), 4), "params")]),
+ GlFunction(Void, "glNamedProgramLocalParameters4fvEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (GLsizei, "count"), (Array(Const(GLfloat), "count*4"), "params")]),
+ GlFunction(Void, "glNamedProgramLocalParametersI4ivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (GLsizei, "count"), (Array(Const(GLint), "count*4"), "params")]),
GlFunction(Void, "glNamedProgramLocalParametersI4uivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), (GLsizei, "count"), (Array(Const(GLuint), "count*4"), "params")]),
- GlFunction(Void, "glGetNamedProgramLocalParameterIivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), Out(Array(GLint, 4), "params")], sideeffects=False),
- GlFunction(Void, "glGetNamedProgramLocalParameterIuivEXT", [(GLprogram, "program"), (GLenum, "target"), (GLuint, "index"), Out(Array(GLuint, 4), "params")], sideeffects=False),
- GlFunction(Void, "glTextureParameterIivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glTextureParameterIuivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLuint), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glGetTextureParameterIivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetTextureParameterIuivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glMultiTexParameterIivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glMultiTexParameterIuivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLuint), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glGetMultiTexParameterIivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetMultiTexParameterIuivEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glNamedProgramStringEXT", [(GLprogram, "program"), (GLenum, "target"), (GLenum, "format"), (GLsizei, "len"), (String(Const(GLvoid), "len"), "string")]),
+ GlFunction(Void, "glNamedRenderbufferStorageEXT", [(GLrenderbuffer, "renderbuffer"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glNamedRenderbufferStorageMultisampleCoverageEXT", [(GLrenderbuffer, "renderbuffer"), (GLsizei, "coverageSamples"), (GLsizei, "colorSamples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glNamedRenderbufferStorageMultisampleEXT", [(GLrenderbuffer, "renderbuffer"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glProgramUniform1dEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLdouble, "x")]),
+ GlFunction(Void, "glProgramUniform1dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLdouble), "count"), "value")]),
GlFunction(Void, "glProgramUniform1fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "v0")]),
- GlFunction(Void, "glProgramUniform2fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "v0"), (GLfloat, "v1")]),
- GlFunction(Void, "glProgramUniform3fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "v0"), (GLfloat, "v1"), (GLfloat, "v2")]),
- GlFunction(Void, "glProgramUniform4fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "v0"), (GLfloat, "v1"), (GLfloat, "v2"), (GLfloat, "v3")]),
- GlFunction(Void, "glProgramUniform1iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "v0")]),
- GlFunction(Void, "glProgramUniform2iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "v0"), (GLint, "v1")]),
- GlFunction(Void, "glProgramUniform3iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "v0"), (GLint, "v1"), (GLint, "v2")]),
- GlFunction(Void, "glProgramUniform4iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "v0"), (GLint, "v1"), (GLint, "v2"), (GLint, "v3")]),
GlFunction(Void, "glProgramUniform1fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count"), "value")]),
- GlFunction(Void, "glProgramUniform2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count*2"), "value")]),
- GlFunction(Void, "glProgramUniform3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count*3"), "value")]),
- GlFunction(Void, "glProgramUniform4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count*4"), "value")]),
+ GlFunction(Void, "glProgramUniform1iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "v0")]),
GlFunction(Void, "glProgramUniform1ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count"), "value")]),
- GlFunction(Void, "glProgramUniform2ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count*2"), "value")]),
- GlFunction(Void, "glProgramUniform3ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count*3"), "value")]),
- GlFunction(Void, "glProgramUniform4ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count*4"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*2*2"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*3*3"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*4*4"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix2x3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*2*3"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix3x2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*3*2"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix2x4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*2*4"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix4x2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*4*2"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix3x4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*3*4"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix4x3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*4*3"), "value")]),
GlFunction(Void, "glProgramUniform1uiEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLuint, "v0")]),
- GlFunction(Void, "glProgramUniform2uiEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1")]),
- GlFunction(Void, "glProgramUniform3uiEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1"), (GLuint, "v2")]),
- GlFunction(Void, "glProgramUniform4uiEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1"), (GLuint, "v2"), (GLuint, "v3")]),
GlFunction(Void, "glProgramUniform1uivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint), "count"), "value")]),
- GlFunction(Void, "glProgramUniform2uivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint), "count*2"), "value")]),
- GlFunction(Void, "glProgramUniform3uivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint), "count*3"), "value")]),
- GlFunction(Void, "glProgramUniform4uivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint), "count*4"), "value")]),
- GlFunction(Void, "glNamedBufferDataEXT", [(GLbuffer, "buffer"), (GLsizeiptr, "size"), (Blob(Const(GLvoid), "size"), "data"), (GLenum, "usage")]),
- GlFunction(Void, "glNamedBufferSubDataEXT", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size"), (Blob(Const(GLvoid), "size"), "data")]),
- GlFunction(GLmap, "glMapNamedBufferEXT", [(GLbuffer, "buffer"), (GLenum, "access")]),
- GlFunction(GLboolean, "glUnmapNamedBufferEXT", [(GLbuffer, "buffer")]),
- GlFunction(GLmap, "glMapNamedBufferRangeEXT", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "length"), (GLbitfield_access, "access")]),
- GlFunction(Void, "glFlushMappedNamedBufferRangeEXT", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "length")]),
- GlFunction(Void, "glNamedCopyBufferSubDataEXT", [(GLbuffer, "readBuffer"), (GLbuffer, "writeBuffer"), (GLintptr, "readOffset"), (GLintptr, "writeOffset"), (GLsizeiptr, "size")]),
- GlFunction(Void, "glGetNamedBufferParameterivEXT", [(GLbuffer, "buffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetNamedBufferPointervEXT", [(GLbuffer, "buffer"), (GLenum, "pname"), Out(Pointer(GLpointer), "params")], sideeffects=False),
- GlFunction(Void, "glGetNamedBufferSubDataEXT", [(GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size"), Out(OpaqueBlob(GLvoid, "size"), "data")], sideeffects=False),
- GlFunction(Void, "glTextureBufferEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer")]),
- GlFunction(Void, "glMultiTexBufferEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer")]),
- GlFunction(Void, "glNamedRenderbufferStorageEXT", [(GLrenderbuffer, "renderbuffer"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glGetNamedRenderbufferParameterivEXT", [(GLrenderbuffer, "renderbuffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(GLenum, "glCheckNamedFramebufferStatusEXT", [(GLframebuffer, "framebuffer"), (GLenum, "target")]),
- GlFunction(Void, "glNamedFramebufferTexture1DEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level")]),
- GlFunction(Void, "glNamedFramebufferTexture2DEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level")]),
- GlFunction(Void, "glNamedFramebufferTexture3DEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level"), (GLint, "zoffset")]),
- GlFunction(Void, "glNamedFramebufferRenderbufferEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "renderbuffertarget"), (GLrenderbuffer, "renderbuffer")]),
- GlFunction(Void, "glGetNamedFramebufferAttachmentParameterivEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGenerateTextureMipmapEXT", [(GLtexture, "texture"), (GLenum, "target")]),
- GlFunction(Void, "glGenerateMultiTexMipmapEXT", [(GLenum, "texunit"), (GLenum, "target")]),
- GlFunction(Void, "glFramebufferDrawBufferEXT", [(GLframebuffer, "framebuffer"), (GLenum, "mode")]),
- GlFunction(Void, "glFramebufferDrawBuffersEXT", [(GLframebuffer, "framebuffer"), (GLsizei, "n"), (Array(Const(GLenum), "n"), "bufs")]),
- GlFunction(Void, "glFramebufferReadBufferEXT", [(GLframebuffer, "framebuffer"), (GLenum, "mode")]),
- GlFunction(Void, "glGetFramebufferParameterivEXT", [(GLframebuffer, "framebuffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glNamedRenderbufferStorageMultisampleEXT", [(GLrenderbuffer, "renderbuffer"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glNamedRenderbufferStorageMultisampleCoverageEXT", [(GLrenderbuffer, "renderbuffer"), (GLsizei, "coverageSamples"), (GLsizei, "colorSamples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glNamedFramebufferTextureEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level")]),
- GlFunction(Void, "glNamedFramebufferTextureLayerEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level"), (GLint, "layer")]),
- GlFunction(Void, "glNamedFramebufferTextureFaceEXT", [(GLframebuffer, "framebuffer"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level"), (GLenum, "face")]),
- GlFunction(Void, "glTextureRenderbufferEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLrenderbuffer, "renderbuffer")]),
- GlFunction(Void, "glMultiTexRenderbufferEXT", [(GLenum, "texunit"), (GLenum, "target"), (GLrenderbuffer, "renderbuffer")]),
- GlFunction(Void, "glProgramUniform1dEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLdouble, "x")]),
GlFunction(Void, "glProgramUniform2dEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLdouble, "x"), (GLdouble, "y")]),
- GlFunction(Void, "glProgramUniform3dEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z")]),
- GlFunction(Void, "glProgramUniform4dEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z"), (GLdouble, "w")]),
- GlFunction(Void, "glProgramUniform1dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLdouble), "count"), "value")]),
GlFunction(Void, "glProgramUniform2dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLdouble), "count*2"), "value")]),
+ GlFunction(Void, "glProgramUniform2fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "v0"), (GLfloat, "v1")]),
+ GlFunction(Void, "glProgramUniform2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count*2"), "value")]),
+ GlFunction(Void, "glProgramUniform2iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "v0"), (GLint, "v1")]),
+ GlFunction(Void, "glProgramUniform2ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count*2"), "value")]),
+ GlFunction(Void, "glProgramUniform2uiEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1")]),
+ GlFunction(Void, "glProgramUniform2uivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint), "count*2"), "value")]),
+ GlFunction(Void, "glProgramUniform3dEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z")]),
GlFunction(Void, "glProgramUniform3dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLdouble), "count*3"), "value")]),
+ GlFunction(Void, "glProgramUniform3fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "v0"), (GLfloat, "v1"), (GLfloat, "v2")]),
+ GlFunction(Void, "glProgramUniform3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count*3"), "value")]),
+ GlFunction(Void, "glProgramUniform3iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "v0"), (GLint, "v1"), (GLint, "v2")]),
+ GlFunction(Void, "glProgramUniform3ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count*3"), "value")]),
+ GlFunction(Void, "glProgramUniform3uiEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1"), (GLuint, "v2")]),
+ GlFunction(Void, "glProgramUniform3uivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint), "count*3"), "value")]),
+ GlFunction(Void, "glProgramUniform4dEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z"), (GLdouble, "w")]),
GlFunction(Void, "glProgramUniform4dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLdouble), "count*4"), "value")]),
+ GlFunction(Void, "glProgramUniform4fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "v0"), (GLfloat, "v1"), (GLfloat, "v2"), (GLfloat, "v3")]),
+ GlFunction(Void, "glProgramUniform4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count*4"), "value")]),
+ GlFunction(Void, "glProgramUniform4iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "v0"), (GLint, "v1"), (GLint, "v2"), (GLint, "v3")]),
+ GlFunction(Void, "glProgramUniform4ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count*4"), "value")]),
+ GlFunction(Void, "glProgramUniform4uiEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1"), (GLuint, "v2"), (GLuint, "v3")]),
+ GlFunction(Void, "glProgramUniform4uivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint), "count*4"), "value")]),
GlFunction(Void, "glProgramUniformMatrix2dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*2*2"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix3dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*3*3"), "value")]),
- GlFunction(Void, "glProgramUniformMatrix4dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*4*4"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*2*2"), "value")]),
GlFunction(Void, "glProgramUniformMatrix2x3dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*2*3"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix2x3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*2*3"), "value")]),
GlFunction(Void, "glProgramUniformMatrix2x4dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*2*4"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix2x4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*2*4"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix3dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*3*3"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*3*3"), "value")]),
GlFunction(Void, "glProgramUniformMatrix3x2dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*3*2"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix3x2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*3*2"), "value")]),
GlFunction(Void, "glProgramUniformMatrix3x4dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*3*4"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix3x4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*3*4"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix4dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*4*4"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*4*4"), "value")]),
GlFunction(Void, "glProgramUniformMatrix4x2dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*4*2"), "value")]),
+ GlFunction(Void, "glProgramUniformMatrix4x2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*4*2"), "value")]),
GlFunction(Void, "glProgramUniformMatrix4x3dvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLdouble), "count*4*3"), "value")]),
- GlFunction(Void, "glVertexArrayVertexOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArrayColorOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArrayEdgeFlagOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArrayIndexOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArrayNormalOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArrayTexCoordOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArrayMultiTexCoordOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLenum, "texunit"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArrayFogCoordOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArraySecondaryColorOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArrayVertexAttribOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glVertexArrayVertexAttribIOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
- GlFunction(Void, "glEnableVertexArrayEXT", [(GLarray, "vaobj"), (GLenum, "array")]),
- GlFunction(Void, "glDisableVertexArrayEXT", [(GLarray, "vaobj"), (GLenum, "array")]),
- GlFunction(Void, "glEnableVertexArrayAttribEXT", [(GLarray, "vaobj"), (GLuint, "index")]),
- GlFunction(Void, "glDisableVertexArrayAttribEXT", [(GLarray, "vaobj"), (GLuint, "index")]),
- GlFunction(Void, "glGetVertexArrayIntegervEXT", [(GLarray, "vaobj"), (GLenum, "pname"), Out(Pointer(GLint), "param")], sideeffects=False),
- GlFunction(Void, "glGetVertexArrayPointervEXT", [(GLarray, "vaobj"), (GLenum, "pname"), Out(Pointer(GLpointer), "param")], sideeffects=False),
- GlFunction(Void, "glGetVertexArrayIntegeri_vEXT", [(GLarray, "vaobj"), (GLuint, "index"), (GLenum, "pname"), Out(Pointer(GLint), "param")], sideeffects=False),
- GlFunction(Void, "glGetVertexArrayPointeri_vEXT", [(GLarray, "vaobj"), (GLuint, "index"), (GLenum, "pname"), Out(Pointer(GLpointer), "param")], sideeffects=False),
+ GlFunction(Void, "glProgramUniformMatrix4x3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*4*3"), "value")]),
+ GlFunction(Void, "glPushClientAttribDefaultEXT", [(GLbitfield_client_attrib, "mask")]),
+ GlFunction(Void, "glTextureBufferEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer")]),
+ GlFunction(Void, "glTextureBufferRangeEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
+ GlFunction(Void, "glTextureImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage1D_size(format, type, width)"), "pixels")]),
+ GlFunction(Void, "glTextureImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage2D_size(format, type, width, height)"), "pixels")]),
+ GlFunction(Void, "glTextureImage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLenum_int, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
+ GlFunction(Void, "glTexturePageCommitmentEXT", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLboolean, "commit")]),
+ GlFunction(Void, "glTextureParameterIivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTextureParameterIuivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLuint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTextureParameterfEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (GLfloat, "param")]),
+ GlFunction(Void, "glTextureParameterfvEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTextureParameteriEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (GLint, "param")]),
+ GlFunction(Void, "glTextureParameterivEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTextureRenderbufferEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLrenderbuffer, "renderbuffer")]),
+ GlFunction(Void, "glTextureStorage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width")]),
+ GlFunction(Void, "glTextureStorage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glTextureStorage2DMultisampleEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLboolean, "fixedsamplelocations")]),
+ GlFunction(Void, "glTextureStorage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
+ GlFunction(Void, "glTextureStorage3DMultisampleEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLboolean, "fixedsamplelocations")]),
+ GlFunction(Void, "glTextureSubImage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage1D_size(format, type, width)"), "pixels")]),
+ GlFunction(Void, "glTextureSubImage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage2D_size(format, type, width, height)"), "pixels")]),
+ GlFunction(Void, "glTextureSubImage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
+ GlFunction(GLboolean, "glUnmapNamedBufferEXT", [(GLbuffer, "buffer")]),
+ GlFunction(Void, "glVertexArrayBindVertexBufferEXT", [(GLarray, "vaobj"), (GLuint, "bindingindex"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizei, "stride")]),
+ GlFunction(Void, "glVertexArrayColorOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayEdgeFlagOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayFogCoordOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayIndexOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayMultiTexCoordOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLenum, "texunit"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayNormalOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArraySecondaryColorOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayTexCoordOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayVertexAttribBindingEXT", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLuint, "bindingindex")]),
+ GlFunction(Void, "glVertexArrayVertexAttribDivisorEXT", [(GLarray, "vaobj"), (GLuint, "index"), (GLuint, "divisor")]),
+ GlFunction(Void, "glVertexArrayVertexAttribFormatEXT", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "relativeoffset")]),
+ GlFunction(Void, "glVertexArrayVertexAttribIFormatEXT", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLuint, "relativeoffset")]),
+ GlFunction(Void, "glVertexArrayVertexAttribIOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayVertexAttribLFormatEXT", [(GLarray, "vaobj"), (GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLuint, "relativeoffset")]),
+ GlFunction(Void, "glVertexArrayVertexAttribLOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayVertexAttribOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLsizei, "stride"), (GLintptr, "offset")]),
+ GlFunction(Void, "glVertexArrayVertexBindingDivisorEXT", [(GLarray, "vaobj"), (GLuint, "bindingindex"), (GLuint, "divisor")]),
+ GlFunction(Void, "glVertexArrayVertexOffsetEXT", [(GLarray, "vaobj"), (GLbuffer, "buffer"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
+
+ # GL_EXT_discard_framebuffer
+ GlFunction(Void, "glDiscardFramebufferEXT", [(GLenum, "target"), (GLsizei, "numAttachments"), (Array(Const(GLenum), "numAttachments"), "attachments")]),
+
+ # GL_EXT_disjoint_timer_query
+ GlFunction(Void, "glGenQueriesEXT", [(GLsizei, "n"), Out(Array(GLquery, "n"), "ids")]),
+ GlFunction(Void, "glDeleteQueriesEXT", [(GLsizei, "n"), (Array(Const(GLquery), "n"), "ids")]),
+ GlFunction(GLboolean, "glIsQueryEXT", [(GLquery, "id")], sideeffects=False),
+ GlFunction(Void, "glBeginQueryEXT", [(GLenum, "target"), (GLquery, "id")]),
+ GlFunction(Void, "glEndQueryEXT", [(GLenum, "target")]),
+ GlFunction(Void, "glQueryCounterEXT", [(GLquery, "id"), (GLenum, "target")]),
+ GlFunction(Void, "glGetQueryivEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetQueryObjectivEXT", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetQueryObjectuivEXT", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetQueryObjecti64vEXT", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLint64, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetQueryObjectui64vEXT", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLuint64, "_gl_param_size(pname)"), "params")], sideeffects=False),
+
+ # GL_EXT_draw_buffers
+ GlFunction(Void, "glDrawBuffersEXT", [(GLsizei, "n"), (Array(Const(GLenum), "n"), "bufs")]),
# GL_EXT_draw_buffers2
GlFunction(Void, "glColorMaskIndexedEXT", [(GLuint, "index"), (GLboolean, "r"), (GLboolean, "g"), (GLboolean, "b"), (GLboolean, "a")]),
@@ -2018,6 +2352,22 @@ glapi.addFunctions([
GlFunction(Void, "glDisableIndexedEXT", [(GLenum, "target"), (GLuint, "index")]),
GlFunction(GLboolean, "glIsEnabledIndexedEXT", [(GLenum, "target"), (GLuint, "index")], sideeffects=False),
+ # GL_EXT_draw_buffers_indexed
+ GlFunction(Void, "glEnableiEXT", [(GLenum, "target"), (GLuint, "index")]),
+ GlFunction(Void, "glDisableiEXT", [(GLenum, "target"), (GLuint, "index")]),
+ GlFunction(Void, "glBlendEquationiEXT", [(GLuint, "buf"), (GLenum, "mode")]),
+ GlFunction(Void, "glBlendEquationSeparateiEXT", [(GLuint, "buf"), (GLenum, "modeRGB"), (GLenum, "modeAlpha")]),
+ GlFunction(Void, "glBlendFunciEXT", [(GLuint, "buf"), (GLenum, "src"), (GLenum, "dst")]),
+ GlFunction(Void, "glBlendFuncSeparateiEXT", [(GLuint, "buf"), (GLenum, "srcRGB"), (GLenum, "dstRGB"), (GLenum, "srcAlpha"), (GLenum, "dstAlpha")]),
+ GlFunction(Void, "glColorMaskiEXT", [(GLuint, "index"), (GLboolean, "r"), (GLboolean, "g"), (GLboolean, "b"), (GLboolean, "a")]),
+ GlFunction(GLboolean, "glIsEnablediEXT", [(GLenum, "target"), (GLuint, "index")], sideeffects=False),
+
+ # GL_EXT_draw_elements_base_vertex
+ GlFunction(Void, "glDrawElementsBaseVertexEXT", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLint, "basevertex")]),
+ GlFunction(Void, "glDrawRangeElementsBaseVertexEXT", [(GLenum_mode, "mode"), (GLuint, "start"), (GLuint, "end"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLint, "basevertex")]),
+ GlFunction(Void, "glDrawElementsInstancedBaseVertexEXT", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "instancecount"), (GLint, "basevertex")]),
+ GlFunction(Void, "glMultiDrawElementsBaseVertexEXT", [(GLenum_mode, "mode"), (Array(Const(GLsizei), "drawcount"), "count"), (GLenum, "type"), (Array(Const(GLindexBuffer("count[{i}]", "type")), "drawcount"), "indices"), (GLsizei, "drawcount"), (Array(Const(GLint), "drawcount"), "basevertex")]),
+
# GL_EXT_draw_instanced
GlFunction(Void, "glDrawArraysInstancedEXT", [(GLenum_mode, "mode"), (GLint, "start"), (GLsizei, "count"), (GLsizei, "primcount")]),
GlFunction(Void, "glDrawElementsInstancedEXT", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLindexBuffer("count", "type"), "indices"), (GLsizei, "primcount")]),
@@ -2057,6 +2407,9 @@ glapi.addFunctions([
GlFunction(Void, "glGetFramebufferAttachmentParameterivEXT", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGenerateMipmapEXT", [(GLenum, "target")]),
+ # GL_EXT_geometry_shader
+ GlFunction(Void, "glFramebufferTextureEXT", [(GLenum, "target"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level")]),
+
# GL_EXT_geometry_shader4
GlFunction(Void, "glProgramParameteriEXT", [(GLprogram, "program"), (GLenum, "pname"), (GLint, "value")]),
@@ -2066,8 +2419,7 @@ glapi.addFunctions([
# GL_EXT_gpu_shader4
GlFunction(Void, "glGetUniformuivEXT", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaqueArray(GLuint, "_glGetUniformuivEXT_size(program, location)"), "params")], sideeffects=False),
- GlFunction(Void, "glBindFragDataLocationEXT", [(GLprogram, "program"), (GLuint, "color"), (GLstringConst, "name")]),
- GlFunction(GLlocation, "glGetFragDataLocationEXT", [(GLprogram, "program"), (GLstringConst, "name")]),
+ GlFunction(GLint, "glGetFragDataLocationEXT", [(GLprogram, "program"), (GLstringConst, "name")], sideeffects=False),
GlFunction(Void, "glUniform1uiEXT", [(GLlocation, "location"), (GLuint, "v0")]),
GlFunction(Void, "glUniform2uiEXT", [(GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1")]),
GlFunction(Void, "glUniform3uiEXT", [(GLlocation, "location"), (GLuint, "v0"), (GLuint, "v1"), (GLuint, "v2")]),
@@ -2078,10 +2430,10 @@ glapi.addFunctions([
GlFunction(Void, "glUniform4uivEXT", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint), "count*4"), "value")]),
# GL_EXT_histogram
- GlFunction(Void, "glGetHistogramEXT", [(GLenum, "target"), (GLboolean, "reset"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetHistogramEXT_size(target, format, type)"), "values")], sideeffects=False),
+ GlFunction(Void, "glGetHistogramEXT", [(GLenum, "target"), (GLboolean, "reset"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetHistogramEXT_size(target, format, type)"), "values")]),
GlFunction(Void, "glGetHistogramParameterfvEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetHistogramParameterivEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetMinmaxEXT", [(GLenum, "target"), (GLboolean, "reset"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetMinmaxEXT_size(target, format, type)"), "values")], sideeffects=False),
+ GlFunction(Void, "glGetHistogramParameterivEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glGetMinmaxEXT", [(GLenum, "target"), (GLboolean, "reset"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetMinmaxEXT_size(target, format, type)"), "values")]),
GlFunction(Void, "glGetMinmaxParameterfvEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetMinmaxParameterivEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glHistogramEXT", [(GLenum, "target"), (GLsizei, "width"), (GLenum, "internalformat"), (GLboolean, "sink")]),
@@ -2095,19 +2447,40 @@ glapi.addFunctions([
# GL_EXT_index_material
GlFunction(Void, "glIndexMaterialEXT", [(GLenum, "face"), (GLenum, "mode")]),
+ # GL_EXT_instanced_arrays
+ GlFunction(Void, "glVertexAttribDivisorEXT", [(GLuint, "index"), (GLuint, "divisor")]),
+
# GL_EXT_light_texture
GlFunction(Void, "glApplyTextureEXT", [(GLenum, "mode")]),
GlFunction(Void, "glTextureLightEXT", [(GLenum, "pname")]),
GlFunction(Void, "glTextureMaterialEXT", [(GLenum, "face"), (GLenum, "mode")]),
+ # GL_EXT_map_buffer_range
+ GlFunction(GLmap, "glMapBufferRangeEXT", [(GLenum, "target"), (GLintptr, "offset"), (GLsizeiptr, "length"), (GLbitfield_access, "access")]),
+ GlFunction(Void, "glFlushMappedBufferRangeEXT", [(GLenum, "target"), (GLintptr, "offset"), (GLsizeiptr, "length")]),
+
# GL_EXT_multi_draw_arrays
GlFunction(Void, "glMultiDrawArraysEXT", [(GLenum_mode, "mode"), (Array(Const(GLint), "primcount"), "first"), (Array(Const(GLsizei), "primcount"), "count"), (GLsizei, "primcount")]),
GlFunction(Void, "glMultiDrawElementsEXT", [(GLenum_mode, "mode"), (Array(Const(GLsizei), "primcount"), "count"), (GLenum, "type"), (Array(Const(GLindexBuffer("count[{i}]", "type")), "primcount"), "indices"), (GLsizei, "primcount")]),
+ # GL_EXT_multi_draw_indirect
+ GlFunction(Void, "glMultiDrawArraysIndirectEXT", [(GLenum_mode, "mode"), (GLpointerConst, "indirect"), (GLsizei, "drawcount"), (GLsizei, "stride")]),
+ GlFunction(Void, "glMultiDrawElementsIndirectEXT", [(GLenum_mode, "mode"), (GLenum, "type"), (GLpointerConst, "indirect"), (GLsizei, "drawcount"), (GLsizei, "stride")]),
+
# GL_EXT_multisample
GlFunction(Void, "glSampleMaskEXT", [(GLclampf, "value"), (GLboolean, "invert")]),
GlFunction(Void, "glSamplePatternEXT", [(GLenum, "pattern")]),
+ # GL_EXT_multisampled_render_to_texture
+ GlFunction(Void, "glFramebufferTexture2DMultisampleEXT", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level"), (GLsizei, "samples")]),
+
+ # GL_EXT_multiview_draw_buffers
+ GlFunction(Void, "glReadBufferIndexedEXT", [(GLenum, "src"), (GLint, "index")]),
+ GlFunction(Void, "glDrawBuffersIndexedEXT", [(GLint, "n"), (Array(Const(GLenum), "n"), "location"), (Array(Const(GLint), "n"), "indices")]),
+ GlFunction(Void, "glGetIntegeri_vEXT", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLint, "_gl_param_size(target)"), "data")], sideeffects=False),
+
+ # GL_EXT_occlusion_query_boolean
+
# GL_EXT_paletted_texture
GlFunction(Void, "glColorTableEXT", [(GLenum, "target"), (GLenum, "internalformat"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glColorTable_size(format, type, width)"), "table")]),
GlFunction(Void, "glGetColorTableEXT", [(GLenum, "target"), (GLenum, "format"), (GLenum, "type"), Out(OpaqueBlob(GLvoid, "_glGetColorTableEXT_size(target, format, type)"), "data")], sideeffects=False),
@@ -2117,8 +2490,8 @@ glapi.addFunctions([
# GL_EXT_pixel_transform
GlFunction(Void, "glPixelTransformParameteriEXT", [(GLenum, "target"), (GLenum, "pname"), (GLint, "param")]),
GlFunction(Void, "glPixelTransformParameterfEXT", [(GLenum, "target"), (GLenum, "pname"), (GLfloat, "param")]),
- GlFunction(Void, "glPixelTransformParameterivEXT", [(GLenum, "target"), (GLenum, "pname"), (Pointer(Const(GLint)), "params")]),
- GlFunction(Void, "glPixelTransformParameterfvEXT", [(GLenum, "target"), (GLenum, "pname"), (Pointer(Const(GLfloat)), "params")]),
+ GlFunction(Void, "glPixelTransformParameterivEXT", [(GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glPixelTransformParameterfvEXT", [(GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
GlFunction(Void, "glGetPixelTransformParameterivEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetPixelTransformParameterfvEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
@@ -2129,9 +2502,24 @@ glapi.addFunctions([
# GL_EXT_polygon_offset
GlFunction(Void, "glPolygonOffsetEXT", [(GLfloat, "factor"), (GLfloat, "bias")]),
+ # GL_EXT_polygon_offset_clamp
+ GlFunction(Void, "glPolygonOffsetClampEXT", [(GLfloat, "factor"), (GLfloat, "units"), (GLfloat, "clamp")]),
+
+ # GL_EXT_primitive_bounding_box
+ GlFunction(Void, "glPrimitiveBoundingBoxEXT", [(GLfloat, "minX"), (GLfloat, "minY"), (GLfloat, "minZ"), (GLfloat, "minW"), (GLfloat, "maxX"), (GLfloat, "maxY"), (GLfloat, "maxZ"), (GLfloat, "maxW")]),
+
# GL_EXT_provoking_vertex
GlFunction(Void, "glProvokingVertexEXT", [(GLenum, "mode")]),
+ # GL_EXT_raster_multisample
+ GlFunction(Void, "glRasterSamplesEXT", [(GLuint, "samples"), (GLboolean, "fixedsamplelocations")]),
+
+ # GL_EXT_robustness
+ GlFunction(GLenum, "glGetGraphicsResetStatusEXT", [], sideeffects=False),
+ GlFunction(Void, "glReadnPixelsEXT", [(GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "bufSize"), Out(OpaqueBlob(GLvoid, "bufSize"), "data")]),
+ GlFunction(Void, "glGetnUniformfvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLfloat, "bufSize"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetnUniformivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLint, "bufSize"), "params")], sideeffects=False),
+
# GL_EXT_secondary_color
GlFunction(Void, "glSecondaryColor3bEXT", [(GLbyte, "red"), (GLbyte, "green"), (GLbyte, "blue")]),
GlFunction(Void, "glSecondaryColor3bvEXT", [(Array(Const(GLbyte), 3), "v")]),
@@ -2155,11 +2543,29 @@ glapi.addFunctions([
GlFunction(Void, "glUseShaderProgramEXT", [(GLenum, "type"), (GLprogram, "program")]),
GlFunction(Void, "glActiveProgramEXT", [(GLprogram, "program")]),
GlFunction(GLprogram, "glCreateShaderProgramEXT", [(GLenum, "type"), (GLstringConst, "string")]),
+ GlFunction(Void, "glActiveShaderProgramEXT", [(GLpipeline, "pipeline"), (GLprogram, "program")]),
+ GlFunction(Void, "glBindProgramPipelineEXT", [(GLpipeline, "pipeline")]),
+ GlFunction(GLprogram, "glCreateShaderProgramvEXT", [(GLenum, "type"), (GLsizei, "count"), (Const(Array(GLstringConst, "count")), "strings")]),
+ GlFunction(Void, "glDeleteProgramPipelinesEXT", [(GLsizei, "n"), (Array(Const(GLuint), "n"), "pipelines")]),
+ GlFunction(Void, "glGenProgramPipelinesEXT", [(GLsizei, "n"), Out(Array(GLpipeline, "n"), "pipelines")]),
+ GlFunction(Void, "glGetProgramPipelineInfoLogEXT", [(GLpipeline, "pipeline"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(GLstring, "infoLog")], sideeffects=False),
+ GlFunction(Void, "glGetProgramPipelineivEXT", [(GLpipeline, "pipeline"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(GLboolean, "glIsProgramPipelineEXT", [(GLpipeline, "pipeline")], sideeffects=False),
+ GlFunction(Void, "glUseProgramStagesEXT", [(GLpipeline, "pipeline"), (GLbitfield_shader, "stages"), (GLprogram, "program")]),
+ GlFunction(Void, "glValidateProgramPipelineEXT", [(GLpipeline, "pipeline")]),
# GL_EXT_shader_image_load_store
GlFunction(Void, "glBindImageTextureEXT", [(GLuint, "index"), (GLtexture, "texture"), (GLint, "level"), (GLboolean, "layered"), (GLint, "layer"), (GLenum, "access"), (GLint, "format")]),
GlFunction(Void, "glMemoryBarrierEXT", [(GLbitfield_barrier, "barriers")]),
+ # GL_EXT_shader_pixel_local_storage2
+ GlFunction(Void, "glFramebufferPixelLocalStorageSizeEXT", [(GLframebuffer, "target"), (GLsizei, "size")]),
+ GlFunction(GLsizei, "glGetFramebufferPixelLocalStorageSizeEXT", [(GLframebuffer, "target")], sideeffects=False),
+ GlFunction(Void, "glClearPixelLocalStorageuiEXT", [(GLsizei, "offset"), (GLsizei, "n"), (Array(Const(GLuint), "n"), "values")]),
+
+ # GL_EXT_sparse_texture
+ GlFunction(Void, "glTexPageCommitmentEXT", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLboolean, "commit")]),
+
# GL_EXT_stencil_clear_tag
GlFunction(Void, "glStencilClearTagEXT", [(GLsizei, "stencilTagBits"), (GLuint, "stencilClearTag")]),
@@ -2167,21 +2573,38 @@ glapi.addFunctions([
GlFunction(Void, "glActiveStencilFaceEXT", [(GLenum, "face")]),
# GL_EXT_subtexture
- GlFunction(Void, "glTexSubImage1DEXT", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexSubImage1D_size(format, type, width)"), "pixels")]),
- GlFunction(Void, "glTexSubImage2DEXT", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexSubImage2D_size(format, type, width, height)"), "pixels")]),
+ GlFunction(Void, "glTexSubImage1DEXT", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLsizei, "width"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage1D_size(format, type, width)"), "pixels")]),
+ GlFunction(Void, "glTexSubImage2DEXT", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage2D_size(format, type, width, height)"), "pixels")]),
+
+ # GL_EXT_tessellation_shader
+ GlFunction(Void, "glPatchParameteriEXT", [(GLenum, "pname"), (GLint, "value")]),
# GL_EXT_texture3D
GlFunction(Void, "glTexImage3DEXT", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
- GlFunction(Void, "glTexSubImage3DEXT", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexSubImage3D_size(format, type, width, height, depth)"), "pixels")]),
+ GlFunction(Void, "glTexSubImage3DEXT", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
- # GL_EXT_texture_buffer_object
- GlFunction(Void, "glTexBufferEXT", [(GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer")]),
+ # GL_EXT_texture_array
+ GlFunction(Void, "glFramebufferTextureLayerEXT", [(GLenum, "target"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level"), (GLint, "layer")]),
- # GL_EXT_texture_integer
+ # GL_EXT_texture_border_clamp
GlFunction(Void, "glTexParameterIivEXT", [(GLenum, "target"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
GlFunction(Void, "glTexParameterIuivEXT", [(GLenum, "target"), (GLenum, "pname"), (Array(Const(GLuint), "_gl_param_size(pname)"), "params")]),
GlFunction(Void, "glGetTexParameterIivEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetTexParameterIuivEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glSamplerParameterIivEXT", [(GLuint, "sampler"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "param")]),
+ GlFunction(Void, "glSamplerParameterIuivEXT", [(GLuint, "sampler"), (GLenum, "pname"), (Array(Const(GLuint), "_gl_param_size(pname)"), "param")]),
+ GlFunction(Void, "glGetSamplerParameterIivEXT", [(GLuint, "sampler"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetSamplerParameterIuivEXT", [(GLuint, "sampler"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+
+ # GL_EXT_texture_buffer
+ GlFunction(Void, "glTexBufferEXT", [(GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer")]),
+ GlFunction(Void, "glTexBufferRangeEXT", [(GLenum, "target"), (GLenum, "internalformat"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
+
+ # GL_EXT_texture_buffer_object
+
+ # GL_EXT_texture_filter_minmax
+
+ # GL_EXT_texture_integer
GlFunction(Void, "glClearColorIiEXT", [(GLint, "red"), (GLint, "green"), (GLint, "blue"), (GLint, "alpha")]),
GlFunction(Void, "glClearColorIuiEXT", [(GLuint, "red"), (GLuint, "green"), (GLuint, "blue"), (GLuint, "alpha")]),
@@ -2196,9 +2619,15 @@ glapi.addFunctions([
# GL_EXT_texture_perturb_normal
GlFunction(Void, "glTextureNormalEXT", [(GLenum, "mode")]),
+ # GL_EXT_texture_storage
+ GlFunction(Void, "glTexStorage1DEXT", [(GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width")]),
+ GlFunction(Void, "glTexStorage2DEXT", [(GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glTexStorage3DEXT", [(GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
+
+ # GL_EXT_texture_view
+ GlFunction(Void, "glTextureViewEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLtexture, "origtexture"), (GLenum, "internalformat"), (GLuint, "minlevel"), (GLuint, "numlevels"), (GLuint, "minlayer"), (GLuint, "numlayers")]),
+
# GL_EXT_timer_query
- GlFunction(Void, "glGetQueryObjecti64vEXT", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLint64EXT, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetQueryObjectui64vEXT", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLuint64EXT, "_gl_param_size(pname)"), "params")], sideeffects=False),
# GL_EXT_transform_feedback
GlFunction(Void, "glBeginTransformFeedbackEXT", [(GLenum_mode, "primitiveMode")]),
@@ -2231,7 +2660,6 @@ glapi.addFunctions([
GlFunction(Void, "glVertexAttribL4dvEXT", [(GLuint, "index"), (Array(Const(GLdouble), 4), "v")]),
GlFunction(Void, "glVertexAttribLPointerEXT", [(GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (Blob(Const(GLvoid), "size"), "pointer")]),
GlFunction(Void, "glGetVertexAttribLdvEXT", [(GLuint, "index"), (GLenum, "pname"), Out(Array(GLdouble, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glVertexArrayVertexAttribLOffsetEXT", [(GLarray, "vaobj"), (GLuint, "buffer"), (GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLintptr, "offset")]),
# GL_EXT_vertex_shader
GlFunction(Void, "glBeginVertexShaderEXT", []),
@@ -2300,8 +2728,8 @@ glapi.addFunctions([
GlFunction(Void, "glGetImageTransformParameterfvHP", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
# GL_IBM_multimode_draw_arrays
- GlFunction(Void, "glMultiModeDrawArraysIBM", [(Array(Const(GLenum), "primcount"), "mode"), (Array(Const(GLint), "primcount"), "first"), (Array(Const(GLsizei), "primcount"), "count"), (GLsizei, "primcount"), (GLint, "modestride")]),
- GlFunction(Void, "glMultiModeDrawElementsIBM", [(Array(Const(GLenum), "primcount"), "mode"), (Array(Const(GLsizei), "primcount"), "count"), (GLenum, "type"), (Array(Const(GLindexBuffer("count[{i}]", "type")), "primcount"), "indices"), (GLsizei, "primcount"), (GLint, "modestride")]),
+ GlFunction(Void, "glMultiModeDrawArraysIBM", [(Array(Const(GLenum_mode), "primcount"), "mode"), (Array(Const(GLint), "primcount"), "first"), (Array(Const(GLsizei), "primcount"), "count"), (GLsizei, "primcount"), (GLint, "modestride")]),
+ GlFunction(Void, "glMultiModeDrawElementsIBM", [(Array(Const(GLenum_mode), "primcount"), "mode"), (Array(Const(GLsizei), "primcount"), "count"), (GLenum, "type"), (Array(Const(GLindexBuffer("count[{i}]", "type")), "primcount"), "indices"), (GLsizei, "primcount"), (GLint, "modestride")]),
# GL_IBM_vertex_array_lists
GlFunction(Void, "glColorPointerListIBM", [(size_bgra, "size"), (GLenum, "type"), (GLint, "stride"), (OpaquePointer(GLpointerConst), "pointer"), (GLint, "ptrstride")]),
@@ -2313,14 +2741,17 @@ glapi.addFunctions([
GlFunction(Void, "glTexCoordPointerListIBM", [(GLint, "size"), (GLenum, "type"), (GLint, "stride"), (OpaquePointer(GLpointerConst), "pointer"), (GLint, "ptrstride")]),
GlFunction(Void, "glVertexPointerListIBM", [(GLint, "size"), (GLenum, "type"), (GLint, "stride"), (OpaquePointer(GLpointerConst), "pointer"), (GLint, "ptrstride")]),
+ # GL_IMG_multisampled_render_to_texture
+ GlFunction(Void, "glRenderbufferStorageMultisampleIMG", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glFramebufferTexture2DMultisampleIMG", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level"), (GLsizei, "samples")]),
+
# GL_INGR_blend_func_separate
GlFunction(Void, "glBlendFuncSeparateINGR", [(GLenum, "sfactorRGB"), (GLenum, "dfactorRGB"), (GLenum, "sfactorAlpha"), (GLenum, "dfactorAlpha")]),
# GL_INTEL_map_texture
- # XXX: glMapTexture2DINTEL prototype in glext.h is busted
- #GlFunction(Void, "glSyncTextureINTEL", [(GLtexture, "texture")]),
- #GlFunction(Void, "glUnmapTexture2DINTEL", [(GLtexture, "texture"), (GLint, "level")]),
- #GlFunction(OpaquePointer(GLvoid), "glMapTexture2DINTEL", [(GLtexture, "texture"), (GLint, "level"), (GLbitfield, "access"), Out(Pointer(GLint), "stride"), Out(Pointer(GLenum), "layout")]),
+ GlFunction(Void, "glSyncTextureINTEL", [(GLtexture, "texture")]),
+ GlFunction(Void, "glUnmapTexture2DINTEL", [(GLtexture, "texture"), (GLint, "level")]),
+ GlFunction(OpaquePointer(GLvoid), "glMapTexture2DINTEL", [(GLtexture, "texture"), (GLint, "level"), (GLbitfield_access, "access"), Out(Pointer(GLint), "stride"), Out(Pointer(GLenum), "layout")]),
# GL_INTEL_parallel_arrays
GlFunction(Void, "glVertexPointervINTEL", [(GLint, "size"), (GLenum, "type"), (OpaqueArray(GLpointerConst, "size"), "pointer")]),
@@ -2328,6 +2759,21 @@ glapi.addFunctions([
GlFunction(Void, "glColorPointervINTEL", [(size_bgra, "size"), (GLenum, "type"), (OpaqueArray(GLpointerConst, "size"), "pointer")]),
GlFunction(Void, "glTexCoordPointervINTEL", [(GLint, "size"), (GLenum, "type"), (OpaqueArray(GLpointerConst, "size"), "pointer")]),
+ # GL_INTEL_performance_query
+ GlFunction(Void, "glBeginPerfQueryINTEL", [(GLuint, "queryHandle")], sideeffects=False),
+ GlFunction(Void, "glCreatePerfQueryINTEL", [(GLuint, "queryId"), Out(Pointer(GLuint), "queryHandle")], sideeffects=False),
+ GlFunction(Void, "glDeletePerfQueryINTEL", [(GLuint, "queryHandle")], sideeffects=False),
+ GlFunction(Void, "glEndPerfQueryINTEL", [(GLuint, "queryHandle")], sideeffects=False),
+ GlFunction(Void, "glGetFirstPerfQueryIdINTEL", [Out(Pointer(GLuint), "queryId")], sideeffects=False),
+ GlFunction(Void, "glGetNextPerfQueryIdINTEL", [(GLuint, "queryId"), Out(Pointer(GLuint), "nextQueryId")], sideeffects=False),
+ GlFunction(Void, "glGetPerfCounterInfoINTEL", [(GLuint, "queryId"), (GLuint, "counterId"), (GLuint, "counterNameLength"), Out(GLstring, "counterName"), (GLuint, "counterDescLength"), Out(GLstring, "counterDesc"), Out(Pointer(GLuint), "counterOffset"), Out(Pointer(GLuint), "counterDataSize"), Out(Pointer(GLuint), "counterTypeEnum"), Out(Pointer(GLuint), "counterDataTypeEnum"), Out(Pointer(GLuint64), "rawCounterMaxValue")], sideeffects=False),
+ GlFunction(Void, "glGetPerfQueryDataINTEL", [(GLuint, "queryHandle"), (GLuint, "flags"), (GLsizei, "dataSize"), Out(OpaqueBlob(GLvoid, "datasize"), "data"), Out(Pointer(GLuint), "bytesWritten")], sideeffects=False),
+ GlFunction(Void, "glGetPerfQueryIdByNameINTEL", [(GLstring, "queryName"), Out(Pointer(GLuint), "queryId")], sideeffects=False),
+ GlFunction(Void, "glGetPerfQueryInfoINTEL", [(GLuint, "queryId"), (GLuint, "queryNameLength"), Out(GLstring, "queryName"), Out(Pointer(GLuint), "dataSize"), Out(Pointer(GLuint), "noCounters"), Out(Pointer(GLuint), "noInstances"), Out(Pointer(GLuint), "capsMask")], sideeffects=False),
+
+ # GL_KHR_blend_equation_advanced
+ GlFunction(Void, "glBlendBarrierKHR", []),
+
# GL_KHR_debug
GlFunction(Void, "glDebugMessageControl", [(GLenum, "source"), (GLenum, "type"), (GLenum, "severity"), (GLsizei, "count"), (Array(Const(GLuint), "count"), "ids"), (GLboolean, "enabled")], sideeffects=True),
GlFunction(Void, "glDebugMessageInsert", [(GLenum, "source"), (GLenum, "type"), (GLuint, "id"), (GLenum, "severity"), (GLsizei, "length"), InGlString(GLchar, "length", "buf")], sideeffects=True),
@@ -2339,6 +2785,24 @@ glapi.addFunctions([
GlFunction(Void, "glGetObjectLabel", [(GLenum, "identifier"), (GLuint, "name"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "label")], sideeffects=False),
GlFunction(Void, "glObjectPtrLabel", [(OpaquePointer(Const(Void)), "ptr"), (GLsizei, "length"), InGlString(GLchar, "length", "label")], sideeffects=True),
GlFunction(Void, "glGetObjectPtrLabel", [(OpaquePointer(Const(Void)), "ptr"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "label")], sideeffects=False),
+ GlFunction(Void, "glDebugMessageControlKHR", [(GLenum, "source"), (GLenum, "type"), (GLenum, "severity"), (GLsizei, "count"), (Array(Const(GLuint), "count"), "ids"), (GLboolean, "enabled")], sideeffects=True),
+ GlFunction(Void, "glDebugMessageInsertKHR", [(GLenum, "source"), (GLenum, "type"), (GLuint, "id"), (GLenum, "severity"), (GLsizei, "length"), InGlString(GLchar, "length", "buf")], sideeffects=True),
+ GlFunction(Void, "glDebugMessageCallbackKHR", [(GLDEBUGPROCKHR, "callback"), (OpaquePointer(Const(Void)), "userParam")], sideeffects=False),
+ GlFunction(GLuint, "glGetDebugMessageLogKHR", [(GLuint, "count"), (GLsizei, "bufsize"), Out(Array(GLenum, "count"), "sources"), Out(Array(GLenum, "count"), "types"), Out(Array(GLuint, "count"), "ids"), Out(Array(GLenum, "count"), "severities"), Out(Array(GLsizei, "count"), "lengths"), Out(String(GLchar, "_glGetDebugMessageLog_length(messageLog, lengths, _result)"), "messageLog")], sideeffects=False, fail=0),
+ GlFunction(Void, "glPushDebugGroupKHR", [(GLenum, "source"), (GLuint, "id"), (GLsizei, "length"), InGlString(GLchar, "length", "message")], sideeffects=True),
+ GlFunction(Void, "glPopDebugGroupKHR", [], sideeffects=True),
+ GlFunction(Void, "glObjectLabelKHR", [(GLenum, "identifier"), (GLuint, "name"), (GLsizei, "length"), InGlString(GLchar, "length", "label")], sideeffects=True),
+ GlFunction(Void, "glGetObjectLabelKHR", [(GLenum, "identifier"), (GLuint, "name"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "label")], sideeffects=False),
+ GlFunction(Void, "glObjectPtrLabelKHR", [(OpaquePointer(Const(Void)), "ptr"), (GLsizei, "length"), InGlString(GLchar, "length", "label")], sideeffects=True),
+ GlFunction(Void, "glGetObjectPtrLabelKHR", [(OpaquePointer(Const(Void)), "ptr"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), OutGlString(GLchar, "length", "label")], sideeffects=False),
+ GlFunction(Void, "glGetPointervKHR", [(GLenum, "pname"), Out(Pointer(GLpointer), "params")], sideeffects=False),
+
+ # GL_KHR_robustness
+ GlFunction(GLenum, "glGetGraphicsResetStatus", [], sideeffects=False),
+ GlFunction(Void, "glReadnPixels", [(GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (GLsizei, "bufSize"), Out(OpaqueBlob(GLvoid, "bufSize"), "data")]),
+ GlFunction(Void, "glGetnUniformfv", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLfloat, "bufSize"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetnUniformiv", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLint, "bufSize"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetnUniformuiv", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "bufSize"), Out(Array(GLuint, "bufSize"), "params")], sideeffects=False),
# GL_KTX_buffer_region
# XXX: http://www.west.net/~brittain/3dsmax2.htm does not mention EXT suffix
@@ -2382,23 +2846,23 @@ glapi.addFunctions([
GlFunction(Void, "glEndConditionalRenderNVX", []),
# GL_NV_bindless_multi_draw_indirect
- GlFunction(Void, "glMultiDrawArraysIndirectBindlessNV", [(GLenum_mode, "mode"), (OpaquePointer(Const(Void)), "indirect"), (GLsizei, "drawCount"), (GLsizei, "stride"), (GLint, "vertexBufferCount")]),
- GlFunction(Void, "glMultiDrawElementsIndirectBindlessNV", [(GLenum_mode, "mode"), (GLenum, "type"), (OpaquePointer(Const(Void)), "indirect"), (GLsizei, "drawCount"), (GLsizei, "stride"), (GLint, "vertexBufferCount")]),
+ GlFunction(Void, "glMultiDrawArraysIndirectBindlessNV", [(GLenum_mode, "mode"), (GLpointerConst, "indirect"), (GLsizei, "drawCount"), (GLsizei, "stride"), (GLint, "vertexBufferCount")]),
+ GlFunction(Void, "glMultiDrawElementsIndirectBindlessNV", [(GLenum_mode, "mode"), (GLenum, "type"), (GLpointerConst, "indirect"), (GLsizei, "drawCount"), (GLsizei, "stride"), (GLint, "vertexBufferCount")]),
# GL_NV_bindless_texture
- GlFunction(GLuint64, "glGetTextureHandleNV", [(GLtexture, "texture")]),
- GlFunction(GLuint64, "glGetTextureSamplerHandleNV", [(GLtexture, "texture"), (GLsampler, "sampler")]),
- GlFunction(Void, "glMakeTextureHandleResidentNV", [(GLuint64, "handle")]),
- GlFunction(Void, "glMakeTextureHandleNonResidentNV", [(GLuint64, "handle")]),
- GlFunction(GLuint64, "glGetImageHandleNV", [(GLtexture, "texture"), (GLint, "level"), (GLboolean, "layered"), (GLint, "layer"), (GLenum, "format")]),
- GlFunction(Void, "glMakeImageHandleResidentNV", [(GLuint64, "handle"), (GLenum, "access")]),
- GlFunction(Void, "glMakeImageHandleNonResidentNV", [(GLuint64, "handle")]),
- GlFunction(Void, "glUniformHandleui64NV", [(GLlocation, "location"), (GLuint64, "value")]),
- GlFunction(Void, "glUniformHandleui64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count"), "value")]),
- GlFunction(Void, "glProgramUniformHandleui64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64, "value")]),
- GlFunction(Void, "glProgramUniformHandleui64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64), "count"), "values")]),
- GlFunction(GLboolean, "glIsTextureHandleResidentNV", [(GLuint64, "handle")], sideeffects=False),
- GlFunction(GLboolean, "glIsImageHandleResidentNV", [(GLuint64, "handle")], sideeffects=False),
+ GlFunction(GLtextureHandle, "glGetTextureHandleNV", [(GLtexture, "texture")]),
+ GlFunction(GLtextureHandle, "glGetTextureSamplerHandleNV", [(GLtexture, "texture"), (GLsampler, "sampler")]),
+ GlFunction(Void, "glMakeTextureHandleResidentNV", [(GLtextureHandle, "handle")]),
+ GlFunction(Void, "glMakeTextureHandleNonResidentNV", [(GLtextureHandle, "handle")]),
+ GlFunction(GLtextureHandle, "glGetImageHandleNV", [(GLtexture, "texture"), (GLint, "level"), (GLboolean, "layered"), (GLint, "layer"), (GLenum, "format")]),
+ GlFunction(Void, "glMakeImageHandleResidentNV", [(GLtextureHandle, "handle"), (GLenum, "access")]),
+ GlFunction(Void, "glMakeImageHandleNonResidentNV", [(GLtextureHandle, "handle")]),
+ GlFunction(Void, "glUniformHandleui64NV", [(GLlocation, "location"), (GLtextureHandle, "value")]),
+ GlFunction(Void, "glUniformHandleui64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLtextureHandle), "count"), "value")]),
+ GlFunction(Void, "glProgramUniformHandleui64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLtextureHandle, "value")]),
+ GlFunction(Void, "glProgramUniformHandleui64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLtextureHandle), "count"), "values")]),
+ GlFunction(GLboolean, "glIsTextureHandleResidentNV", [(GLtextureHandle, "handle")], sideeffects=False),
+ GlFunction(GLboolean, "glIsImageHandleResidentNV", [(GLtextureHandle, "handle")], sideeffects=False),
# GL_NV_blend_equation_advanced
GlFunction(Void, "glBlendParameteriNV", [(GLenum, "pname"), (GLint, "value")]),
@@ -2409,13 +2873,20 @@ glapi.addFunctions([
GlFunction(Void, "glEndConditionalRenderNV", []),
# GL_NV_copy_image
- GlFunction(Void, "glCopyImageSubDataNV", [(GLname("srcTarget"), "srcName"), (GLenum, "srcTarget"), (GLint, "srcLevel"), (GLint, "srcX"), (GLint, "srcY"), (GLint, "srcZ"), (GLname("dstTarget"), "dstName"), (GLenum, "dstTarget"), (GLint, "dstLevel"), (GLint, "dstX"), (GLint, "dstY"), (GLint, "dstZ"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
+ GlFunction(Void, "glCopyImageSubDataNV", [(GLtexture, "srcName"), (GLenum, "srcTarget"), (GLint, "srcLevel"), (GLint, "srcX"), (GLint, "srcY"), (GLint, "srcZ"), (GLtexture, "dstName"), (GLenum, "dstTarget"), (GLint, "dstLevel"), (GLint, "dstX"), (GLint, "dstY"), (GLint, "dstZ"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
+
+ # GL_NV_coverage_sample
+ GlFunction(Void, "glCoverageMaskNV", [(GLboolean, "mask")]),
+ GlFunction(Void, "glCoverageOperationNV", [(GLenum, "operation")]),
# GL_NV_depth_buffer_float
GlFunction(Void, "glDepthRangedNV", [(GLdouble, "zNear"), (GLdouble, "zFar")]),
GlFunction(Void, "glClearDepthdNV", [(GLdouble, "depth")]),
GlFunction(Void, "glDepthBoundsdNV", [(GLdouble, "zmin"), (GLdouble, "zmax")]),
+ # GL_NV_draw_buffers
+ GlFunction(Void, "glDrawBuffersNV", [(GLsizei, "n"), (Array(Const(GLenum), "n"), "bufs")]),
+
# GL_NV_draw_texture
GlFunction(Void, "glDrawTextureNV", [(GLtexture, "texture"), (GLsampler, "sampler"), (GLfloat, "x0"), (GLfloat, "y0"), (GLfloat, "x1"), (GLfloat, "y1"), (GLfloat, "z"), (GLfloat, "s0"), (GLfloat, "t0"), (GLfloat, "s1"), (GLfloat, "t1")]),
@@ -2455,13 +2926,16 @@ glapi.addFunctions([
# GL_NV_framebuffer_blit
GlFunction(Void, "glBlitFramebufferNV", [(GLint, "srcX0"), (GLint, "srcY0"), (GLint, "srcX1"), (GLint, "srcY1"), (GLint, "dstX0"), (GLint, "dstY0"), (GLint, "dstX1"), (GLint, "dstY1"), (GLbitfield_attrib, "mask"), (GLenum, "filter")]),
+ # GL_NV_framebuffer_mixed_samples
+ GlFunction(Void, "glCoverageModulationTableNV", [(GLsizei, "n"), (Array(Const(GLfloat), "n"), "v")]),
+ GlFunction(Void, "glGetCoverageModulationTableNV", [(GLsizei, "bufsize"), Out(Array(GLfloat, "bufsize"), "v")], sideeffects=False),
+ GlFunction(Void, "glCoverageModulationNV", [(GLenum, "components")]),
+
# GL_NV_framebuffer_multisample_coverage
GlFunction(Void, "glRenderbufferStorageMultisampleCoverageNV", [(GLenum, "target"), (GLsizei, "coverageSamples"), (GLsizei, "colorSamples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
# GL_NV_geometry_program4
GlFunction(Void, "glProgramVertexLimitNV", [(GLenum, "target"), (GLint, "limit")]),
- GlFunction(Void, "glFramebufferTextureEXT", [(GLenum, "target"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level")]),
- GlFunction(Void, "glFramebufferTextureLayerEXT", [(GLenum, "target"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level"), (GLint, "layer")]),
GlFunction(Void, "glFramebufferTextureFaceEXT", [(GLenum, "target"), (GLenum, "attachment"), (GLtexture, "texture"), (GLint, "level"), (GLenum, "face")]),
# GL_NV_gpu_program4
@@ -2487,39 +2961,39 @@ glapi.addFunctions([
GlFunction(Void, "glGetProgramSubroutineParameteruivNV", [(GLenum, "target"), (GLuint, "index"), Out(Pointer(GLuint), "param")], sideeffects=False),
# GL_NV_gpu_shader5
- GlFunction(Void, "glUniform1i64NV", [(GLint, "location"), (GLint64EXT, "x")]),
- GlFunction(Void, "glUniform2i64NV", [(GLint, "location"), (GLint64EXT, "x"), (GLint64EXT, "y")]),
- GlFunction(Void, "glUniform3i64NV", [(GLint, "location"), (GLint64EXT, "x"), (GLint64EXT, "y"), (GLint64EXT, "z")]),
- GlFunction(Void, "glUniform4i64NV", [(GLint, "location"), (GLint64EXT, "x"), (GLint64EXT, "y"), (GLint64EXT, "z"), (GLint64EXT, "w")]),
- GlFunction(Void, "glUniform1i64vNV", [(GLint, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count"), "value")]),
- GlFunction(Void, "glUniform2i64vNV", [(GLint, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*2"), "value")]),
- GlFunction(Void, "glUniform3i64vNV", [(GLint, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*3"), "value")]),
- GlFunction(Void, "glUniform4i64vNV", [(GLint, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*4"), "value")]),
- GlFunction(Void, "glUniform1ui64NV", [(GLint, "location"), (GLuint64EXT, "x")]),
- GlFunction(Void, "glUniform2ui64NV", [(GLint, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y")]),
- GlFunction(Void, "glUniform3ui64NV", [(GLint, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y"), (GLuint64EXT, "z")]),
- GlFunction(Void, "glUniform4ui64NV", [(GLint, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y"), (GLuint64EXT, "z"), (GLuint64EXT, "w")]),
- GlFunction(Void, "glUniform1ui64vNV", [(GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count"), "value")]),
- GlFunction(Void, "glUniform2ui64vNV", [(GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*2"), "value")]),
- GlFunction(Void, "glUniform3ui64vNV", [(GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*3"), "value")]),
- GlFunction(Void, "glUniform4ui64vNV", [(GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*4"), "value")]),
- GlFunction(Void, "glGetUniformi64vNV", [(GLuint, "program"), (GLint, "location"), Out(OpaqueArray(GLint64EXT, "_glGetUniformi64vNV_size(location)"), "params")], sideeffects=False),
- GlFunction(Void, "glProgramUniform1i64NV", [(GLuint, "program"), (GLint, "location"), (GLint64EXT, "x")]),
- GlFunction(Void, "glProgramUniform2i64NV", [(GLuint, "program"), (GLint, "location"), (GLint64EXT, "x"), (GLint64EXT, "y")]),
- GlFunction(Void, "glProgramUniform3i64NV", [(GLuint, "program"), (GLint, "location"), (GLint64EXT, "x"), (GLint64EXT, "y"), (GLint64EXT, "z")]),
- GlFunction(Void, "glProgramUniform4i64NV", [(GLuint, "program"), (GLint, "location"), (GLint64EXT, "x"), (GLint64EXT, "y"), (GLint64EXT, "z"), (GLint64EXT, "w")]),
- GlFunction(Void, "glProgramUniform1i64vNV", [(GLuint, "program"), (GLint, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count"), "value")]),
- GlFunction(Void, "glProgramUniform2i64vNV", [(GLuint, "program"), (GLint, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*2"), "value")]),
- GlFunction(Void, "glProgramUniform3i64vNV", [(GLuint, "program"), (GLint, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*3"), "value")]),
- GlFunction(Void, "glProgramUniform4i64vNV", [(GLuint, "program"), (GLint, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*4"), "value")]),
- GlFunction(Void, "glProgramUniform1ui64NV", [(GLuint, "program"), (GLint, "location"), (GLuint64EXT, "x")]),
- GlFunction(Void, "glProgramUniform2ui64NV", [(GLuint, "program"), (GLint, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y")]),
- GlFunction(Void, "glProgramUniform3ui64NV", [(GLuint, "program"), (GLint, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y"), (GLuint64EXT, "z")]),
- GlFunction(Void, "glProgramUniform4ui64NV", [(GLuint, "program"), (GLint, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y"), (GLuint64EXT, "z"), (GLuint64EXT, "w")]),
- GlFunction(Void, "glProgramUniform1ui64vNV", [(GLuint, "program"), (GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count"), "value")]),
- GlFunction(Void, "glProgramUniform2ui64vNV", [(GLuint, "program"), (GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*2"), "value")]),
- GlFunction(Void, "glProgramUniform3ui64vNV", [(GLuint, "program"), (GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*3"), "value")]),
- GlFunction(Void, "glProgramUniform4ui64vNV", [(GLuint, "program"), (GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*4"), "value")]),
+ GlFunction(Void, "glUniform1i64NV", [(GLlocation, "location"), (GLint64EXT, "x")]),
+ GlFunction(Void, "glUniform2i64NV", [(GLlocation, "location"), (GLint64EXT, "x"), (GLint64EXT, "y")]),
+ GlFunction(Void, "glUniform3i64NV", [(GLlocation, "location"), (GLint64EXT, "x"), (GLint64EXT, "y"), (GLint64EXT, "z")]),
+ GlFunction(Void, "glUniform4i64NV", [(GLlocation, "location"), (GLint64EXT, "x"), (GLint64EXT, "y"), (GLint64EXT, "z"), (GLint64EXT, "w")]),
+ GlFunction(Void, "glUniform1i64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count"), "value")]),
+ GlFunction(Void, "glUniform2i64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*2"), "value")]),
+ GlFunction(Void, "glUniform3i64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*3"), "value")]),
+ GlFunction(Void, "glUniform4i64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*4"), "value")]),
+ GlFunction(Void, "glUniform1ui64NV", [(GLlocation, "location"), (GLuint64EXT, "x")]),
+ GlFunction(Void, "glUniform2ui64NV", [(GLlocation, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y")]),
+ GlFunction(Void, "glUniform3ui64NV", [(GLlocation, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y"), (GLuint64EXT, "z")]),
+ GlFunction(Void, "glUniform4ui64NV", [(GLlocation, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y"), (GLuint64EXT, "z"), (GLuint64EXT, "w")]),
+ GlFunction(Void, "glUniform1ui64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count"), "value")]),
+ GlFunction(Void, "glUniform2ui64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*2"), "value")]),
+ GlFunction(Void, "glUniform3ui64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*3"), "value")]),
+ GlFunction(Void, "glUniform4ui64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*4"), "value")]),
+ GlFunction(Void, "glGetUniformi64vNV", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaqueArray(GLint64EXT, "_glGetUniformi64vNV_size(location)"), "params")], sideeffects=False),
+ GlFunction(Void, "glProgramUniform1i64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLint64EXT, "x")]),
+ GlFunction(Void, "glProgramUniform2i64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLint64EXT, "x"), (GLint64EXT, "y")]),
+ GlFunction(Void, "glProgramUniform3i64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLint64EXT, "x"), (GLint64EXT, "y"), (GLint64EXT, "z")]),
+ GlFunction(Void, "glProgramUniform4i64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLint64EXT, "x"), (GLint64EXT, "y"), (GLint64EXT, "z"), (GLint64EXT, "w")]),
+ GlFunction(Void, "glProgramUniform1i64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count"), "value")]),
+ GlFunction(Void, "glProgramUniform2i64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*2"), "value")]),
+ GlFunction(Void, "glProgramUniform3i64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*3"), "value")]),
+ GlFunction(Void, "glProgramUniform4i64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint64EXT), "count*4"), "value")]),
+ GlFunction(Void, "glProgramUniform1ui64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64EXT, "x")]),
+ GlFunction(Void, "glProgramUniform2ui64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y")]),
+ GlFunction(Void, "glProgramUniform3ui64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y"), (GLuint64EXT, "z")]),
+ GlFunction(Void, "glProgramUniform4ui64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64EXT, "x"), (GLuint64EXT, "y"), (GLuint64EXT, "z"), (GLuint64EXT, "w")]),
+ GlFunction(Void, "glProgramUniform1ui64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count"), "value")]),
+ GlFunction(Void, "glProgramUniform2ui64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*2"), "value")]),
+ GlFunction(Void, "glProgramUniform3ui64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*3"), "value")]),
+ GlFunction(Void, "glProgramUniform4ui64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count*4"), "value")]),
# GL_NV_half_float
GlFunction(Void, "glVertex2hNV", [(GLhalfNV, "x"), (GLhalfNV, "y")]),
@@ -2609,7 +3083,7 @@ glapi.addFunctions([
GlFunction(Void, "glStencilStrokePathNV", [(GLuint, "path"), (GLint, "reference"), (GLuint, "mask")]),
GlFunction(Void, "glStencilFillPathInstancedNV", [(GLsizei, "numPaths"), (GLenum, "pathNameType"), (Blob(Const(GLvoid), "_gl_Paths_size(numPaths, pathNameType, paths)"), "paths"), (GLuint, "pathBase"), (GLenum, "fillMode"), (GLuint, "mask"), (GLenum, "transformType"), (Array(Const(GLfloat), "_gl_transformType_size(numPaths, transformType)"), "transformValues")]),
GlFunction(Void, "glStencilStrokePathInstancedNV", [(GLsizei, "numPaths"), (GLenum, "pathNameType"), (Blob(Const(GLvoid), "_gl_Paths_size(numPaths, pathNameType, paths)"), "paths"), (GLuint, "pathBase"), (GLint, "reference"), (GLuint, "mask"), (GLenum, "transformType"), (Array(Const(GLfloat), "_gl_transformType_size(numPaths, transformType)"), "transformValues")]),
- GlFunction(Void, "glPathCoverDepthFuncNV", [(GLenum, "zfunc")]),
+ GlFunction(Void, "glPathCoverDepthFuncNV", [(GLenum, "func")]),
GlFunction(Void, "glPathColorGenNV", [(GLenum, "color"), (GLenum, "genMode"), (GLenum, "colorFormat"), (Array(Const(GLfloat), "_gl_PathColorGen_size(genMode, colorFormat)"), "coeffs")]),
GlFunction(Void, "glPathTexGenNV", [(GLenum, "texCoordSet"), (GLenum, "genMode"), (GLint, "components"), (Array(Const(GLfloat), "_gl_PathTexGen_size(genMode, components)"), "coeffs")]),
GlFunction(Void, "glPathFogGenNV", [(GLenum, "genMode")]),
@@ -2633,6 +3107,21 @@ glapi.addFunctions([
GlFunction(GLboolean, "glIsPointInStrokePathNV", [(GLuint, "path"), (GLfloat, "x"), (GLfloat, "y")], sideeffects=False),
GlFunction(GLfloat, "glGetPathLengthNV", [(GLuint, "path"), (GLsizei, "startSegment"), (GLsizei, "numSegments")]),
GlFunction(GLboolean, "glPointAlongPathNV", [(GLuint, "path"), (GLsizei, "startSegment"), (GLsizei, "numSegments"), (GLfloat, "distance"), Out(Array(GLfloat,1), "x"), Out(Array(GLfloat,1), "y"), Out(Array(GLfloat,1), "tangentX"), Out(Array(GLfloat,1), "tangentY")], sideeffects=False),
+ GlFunction(Void, "glMatrixLoad3x2fNV", [(GLenum, "matrixMode"), (Array(Const(GLfloat), 6), "m")]),
+ GlFunction(Void, "glMatrixLoad3x3fNV", [(GLenum, "matrixMode"), (Array(Const(GLfloat), 9), "m")]),
+ GlFunction(Void, "glMatrixLoadTranspose3x3fNV", [(GLenum, "matrixMode"), (Array(Const(GLfloat), 9), "m")]),
+ GlFunction(Void, "glMatrixMult3x2fNV", [(GLenum, "matrixMode"), (Array(Const(GLfloat), 6), "m")]),
+ GlFunction(Void, "glMatrixMult3x3fNV", [(GLenum, "matrixMode"), (Array(Const(GLfloat), 9), "m")]),
+ GlFunction(Void, "glMatrixMultTranspose3x3fNV", [(GLenum, "matrixMode"), (Array(Const(GLfloat), 9), "m")]),
+ GlFunction(Void, "glStencilThenCoverFillPathNV", [(GLuint, "path"), (GLenum, "fillMode"), (GLuint, "mask"), (GLenum, "coverMode")]),
+ GlFunction(Void, "glStencilThenCoverStrokePathNV", [(GLuint, "path"), (GLint, "reference"), (GLuint, "mask"), (GLenum, "coverMode")]),
+ GlFunction(Void, "glStencilThenCoverFillPathInstancedNV", [(GLsizei, "numPaths"), (GLenum, "pathNameType"), (Blob(Const(GLvoid), "_gl_Paths_size(numPaths, pathNameType, paths)"), "paths"), (GLuint, "pathBase"), (GLenum, "fillMode"), (GLuint, "mask"), (GLenum, "coverMode"), (GLenum, "transformType"), (Array(Const(GLfloat), "_gl_transformType_size(numPaths, transformType)"), "transformValues")]),
+ GlFunction(Void, "glStencilThenCoverStrokePathInstancedNV", [(GLsizei, "numPaths"), (GLenum, "pathNameType"), (Blob(Const(GLvoid), "_gl_Paths_size(numPaths, pathNameType, paths)"), "paths"), (GLuint, "pathBase"), (GLint, "reference"), (GLuint, "mask"), (GLenum, "coverMode"), (GLenum, "transformType"), (Array(Const(GLfloat), "_gl_transformType_size(numPaths, transformType)"), "transformValues")]),
+ GlFunction(GLenum, "glPathGlyphIndexRangeNV", [(GLenum, "fontTarget"), (String(Const(GLvoid)), "fontName"), (GLbitfield, "fontStyle"), (GLuint, "pathParameterTemplate"), (GLfloat, "emScale"), (Array(GLuint, 2), "baseAndCount")]),
+ GlFunction(GLenum, "glPathGlyphIndexArrayNV", [(GLuint, "firstPathName"), (GLenum, "fontTarget"), (String(Const(GLvoid)), "fontName"), (GLbitfield, "fontStyle"), (GLuint, "firstGlyphIndex"), (GLsizei, "numGlyphs"), (GLuint, "pathParameterTemplate"), (GLfloat, "emScale")]),
+ GlFunction(GLenum, "glPathMemoryGlyphIndexArrayNV", [(GLuint, "firstPathName"), (GLenum, "fontTarget"), (GLsizeiptr, "fontSize"), (Blob(Const(Void), "fontSize"), "fontData"), (GLsizei, "faceIndex"), (GLuint, "firstGlyphIndex"), (GLsizei, "numGlyphs"), (GLuint, "pathParameterTemplate"), (GLfloat, "emScale")]),
+ GlFunction(Void, "glProgramPathFragmentInputGenNV", [(GLprogram, "program"), (GLlocation, "location"), (GLenum, "genMode"), (GLint, "components"), (Array(Const(GLfloat), "_gl_PathTexGen_size(genMode, components)"), "coeffs")]),
+ GlFunction(Void, "glGetProgramResourcefvNV", [(GLprogram, "program"), (GLenum, "programInterface"), (GLuint, "index"), (GLsizei, "propCount"), (Array(Const(GLenum), "propCount"), "props"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLfloat, "bufSize"), "params")], sideeffects=False),
# GL_NV_pixel_data_range
GlFunction(Void, "glPixelDataRangeNV", [(GLenum, "target"), (GLsizei, "length"), (OpaqueBlob(Const(GLvoid), "length"), "pointer")]),
@@ -2654,6 +3143,9 @@ glapi.addFunctions([
GlFunction(Void, "glPrimitiveRestartNV", []),
GlFunction(Void, "glPrimitiveRestartIndexNV", [(GLuint, "index")]),
+ # GL_NV_read_buffer
+ GlFunction(Void, "glReadBufferNV", [(GLenum, "mode")]),
+
# GL_NV_register_combiners
GlFunction(Void, "glCombinerParameterfvNV", [(GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
GlFunction(Void, "glCombinerParameterfNV", [(GLenum, "pname"), (GLfloat, "param")]),
@@ -2683,11 +3175,11 @@ glapi.addFunctions([
GlFunction(Void, "glGetBufferParameterui64vNV", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLuint64EXT, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetNamedBufferParameterui64vNV", [(GLbuffer, "buffer"), (GLenum, "pname"), Out(Array(GLuint64EXT, "_gl_param_size(pname)"), "params")], sideeffects=False),
GlFunction(Void, "glGetIntegerui64vNV", [(GLenum, "value"), Out(Array(GLuint64EXT, "_gl_param_size(value)"), "result")], sideeffects=False),
- GlFunction(Void, "glUniformui64NV", [(GLint, "location"), (GLuint64EXT, "value")]),
- GlFunction(Void, "glUniformui64vNV", [(GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count"), "value")]),
- GlFunction(Void, "glGetUniformui64vNV", [(GLprogram, "program"), (GLint, "location"), Out(OpaqueArray(GLuint64EXT, "_glGetUniformui64vNV_size(program, location)"), "params")], sideeffects=False),
- GlFunction(Void, "glProgramUniformui64NV", [(GLprogram, "program"), (GLint, "location"), (GLuint64EXT, "value")]),
- GlFunction(Void, "glProgramUniformui64vNV", [(GLprogram, "program"), (GLint, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count"), "value")]),
+ GlFunction(Void, "glUniformui64NV", [(GLlocation, "location"), (GLuint64EXT, "value")]),
+ GlFunction(Void, "glUniformui64vNV", [(GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count"), "value")]),
+ GlFunction(Void, "glGetUniformui64vNV", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaqueArray(GLuint64EXT, "_glGetUniformui64vNV_size(program, location)"), "params")], sideeffects=False),
+ GlFunction(Void, "glProgramUniformui64NV", [(GLprogram, "program"), (GLlocation, "location"), (GLuint64EXT, "value")]),
+ GlFunction(Void, "glProgramUniformui64vNV", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLuint64EXT), "count"), "value")]),
# GL_NV_texture_barrier
GlFunction(Void, "glTextureBarrierNV", []),
@@ -2703,7 +3195,7 @@ glapi.addFunctions([
# GL_NV_transform_feedback
GlFunction(Void, "glBeginTransformFeedbackNV", [(GLenum_mode, "primitiveMode")]),
GlFunction(Void, "glEndTransformFeedbackNV", []),
- GlFunction(Void, "glTransformFeedbackAttribsNV", [(GLuint, "count"), (Array(Const(GLint), "count*3"), "attribs"), (GLenum, "bufferMode")]),
+ GlFunction(Void, "glTransformFeedbackAttribsNV", [(GLsizei, "count"), (Array(Const(GLint), "count*3"), "attribs"), (GLenum, "bufferMode")]),
GlFunction(Void, "glBindBufferRangeNV", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
GlFunction(Void, "glBindBufferOffsetNV", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer"), (GLintptr, "offset")]),
GlFunction(Void, "glBindBufferBaseNV", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer")]),
@@ -2879,6 +3371,94 @@ glapi.addFunctions([
GlFunction(Void, "glVideoCaptureStreamParameterfvNV", [(GLuint, "video_capture_slot"), (GLuint, "stream"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
GlFunction(Void, "glVideoCaptureStreamParameterdvNV", [(GLuint, "video_capture_slot"), (GLuint, "stream"), (GLenum, "pname"), (Array(Const(GLdouble), "_gl_param_size(pname)"), "params")]),
+ # GL_OES_blend_equation_separate
+ GlFunction(Void, "glBlendEquationSeparateOES", [(GLenum, "modeRGB"), (GLenum, "modeAlpha")]),
+
+ # GL_OES_blend_func_separate
+ GlFunction(Void, "glBlendFuncSeparateOES", [(GLenum, "sfactorRGB"), (GLenum, "dfactorRGB"), (GLenum, "sfactorAlpha"), (GLenum, "dfactorAlpha")]),
+
+ # GL_OES_blend_subtract
+ GlFunction(Void, "glBlendEquationOES", [(GLenum, "mode")]),
+
+ # GL_OES_draw_texture
+ GlFunction(Void, "glDrawTexfOES", [(GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z"), (GLfloat, "width"), (GLfloat, "height")]),
+ GlFunction(Void, "glDrawTexfvOES", [(Array(Const(GLfloat), 4), "coords")]),
+ GlFunction(Void, "glDrawTexiOES", [(GLint, "x"), (GLint, "y"), (GLint, "z"), (GLint, "width"), (GLint, "height")]),
+ GlFunction(Void, "glDrawTexivOES", [(Array(Const(GLint), 4), "coords")]),
+ GlFunction(Void, "glDrawTexsOES", [(GLshort, "x"), (GLshort, "y"), (GLshort, "z"), (GLshort, "width"), (GLshort, "height")]),
+ GlFunction(Void, "glDrawTexsvOES", [(Array(Const(GLshort), 4), "coords")]),
+
+ # GL_OES_framebuffer_object
+ GlFunction(GLboolean, "glIsRenderbufferOES", [(GLrenderbuffer, "renderbuffer")], sideeffects=False),
+ GlFunction(Void, "glBindRenderbufferOES", [(GLenum, "target"), (GLrenderbuffer, "renderbuffer")]),
+ GlFunction(Void, "glDeleteRenderbuffersOES", [(GLsizei, "n"), (Array(Const(GLrenderbuffer), "n"), "renderbuffers")]),
+ GlFunction(Void, "glGenRenderbuffersOES", [(GLsizei, "n"), Out(Array(GLrenderbuffer, "n"), "renderbuffers")]),
+ GlFunction(Void, "glRenderbufferStorageOES", [(GLenum, "target"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glGetRenderbufferParameterivOES", [(GLenum, "target"), (GLenum, "pname"), (Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(GLboolean, "glIsFramebufferOES", [(GLframebuffer, "framebuffer")], sideeffects=False),
+ GlFunction(Void, "glBindFramebufferOES", [(GLenum, "target"), (GLframebuffer, "framebuffer")]),
+ GlFunction(Void, "glDeleteFramebuffersOES", [(GLsizei, "n"), (Array(Const(GLframebuffer), "n"), "framebuffers")]),
+ GlFunction(Void, "glGenFramebuffersOES", [(GLsizei, "n"), Out(Array(GLframebuffer, "n"), "framebuffers")]),
+ GlFunction(GLenum, "glCheckFramebufferStatusOES", [(GLenum, "target")]),
+ GlFunction(Void, "glFramebufferTexture2DOES", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level")]),
+ GlFunction(Void, "glFramebufferRenderbufferOES", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "renderbuffertarget"), (GLuint, "renderbuffer")]),
+ GlFunction(Void, "glGetFramebufferAttachmentParameterivOES", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGenerateMipmapOES", [(GLenum, "target")]),
+
+ # GL_OES_get_program_binary
+ GlFunction(Void, "glGetProgramBinaryOES", [(GLprogram, "program"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLenum), "binaryFormat"), Out(OpaqueBlob(GLvoid, "length ? *length : bufSize"), "binary")], sideeffects=False),
+ GlFunction(Void, "glProgramBinaryOES", [(GLprogram, "program"), (GLenum, "binaryFormat"), (Blob(Const(GLvoid), "length"), "binary"), (GLsizei, "length")]),
+
+ # GL_OES_mapbuffer
+ GlFunction(Void, "glGetBufferPointervOES", [(GLenum, "target"), (GLenum, "pname"), Out(Pointer(GLpointer), "params")], sideeffects=False),
+ GlFunction(GLmap, "glMapBufferOES", [(GLenum, "target"), (GLenum, "access")]),
+ GlFunction(GLboolean, "glUnmapBufferOES", [(GLenum, "target")]),
+
+ # GL_OES_matrix_palette
+ GlFunction(Void, "glCurrentPaletteMatrixOES", [(GLuint, "index")]),
+ GlFunction(Void, "glLoadPaletteFromModelViewMatrixOES", []),
+ GlFunction(Void, "glMatrixIndexPointerOES", [(GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
+ GlFunction(Void, "glWeightPointerOES", [(GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
+
+ # GL_OES_point_size_array
+ GlFunction(Void, "glPointSizePointerOES", [(GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "ptr")]),
+
+ # GL_OES_query_matrix
+ GlFunction(GLbitfield, "glQueryMatrixxOES", [(Array(GLfixed, 16), "mantissa"), (Array(GLint, 16), "exponent")]),
+
+ # GL_OES_single_precision
+ GlFunction(Void, "glClearDepthfOES", [(GLclampf, "depth")]),
+ GlFunction(Void, "glClipPlanefOES", [(GLenum, "plane"), (Array(Const(GLfloat), 4), "equation")]),
+ GlFunction(Void, "glDepthRangefOES", [(GLclampf, "n"), (GLclampf, "f")]),
+ GlFunction(Void, "glFrustumfOES", [(GLfloat, "l"), (GLfloat, "r"), (GLfloat, "b"), (GLfloat, "t"), (GLfloat, "n"), (GLfloat, "f")]),
+ GlFunction(Void, "glGetClipPlanefOES", [(GLenum, "plane"), Out(Array(GLfloat, 4), "equation")], sideeffects=False),
+ GlFunction(Void, "glOrthofOES", [(GLfloat, "l"), (GLfloat, "r"), (GLfloat, "b"), (GLfloat, "t"), (GLfloat, "n"), (GLfloat, "f")]),
+
+ # GL_OES_texture_3D
+ GlFunction(Void, "glTexImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
+ GlFunction(Void, "glTexSubImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
+ GlFunction(Void, "glCopyTexSubImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
+ GlFunction(Void, "glCompressedTexImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "data")]),
+ GlFunction(Void, "glCompressedTexSubImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "data")]),
+ GlFunction(Void, "glFramebufferTexture3DOES", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level"), (GLint, "zoffset")]),
+
+ # GL_OES_texture_cube_map
+ GlFunction(Void, "glTexGenfOES", [(GLenum, "coord"), (GLenum, "pname"), (GLfloat, "param")]),
+ GlFunction(Void, "glTexGenfvOES", [(GLenum, "coord"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTexGeniOES", [(GLenum, "coord"), (GLenum, "pname"), (GLint, "param")]),
+ GlFunction(Void, "glTexGenivOES", [(GLenum, "coord"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glTexGenxOES", [(GLenum, "coord"), (GLenum, "pname"), (GLfixed, "param")]),
+ GlFunction(Void, "glTexGenxvOES", [(GLenum, "coord"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
+ GlFunction(Void, "glGetTexGenfvOES", [(GLenum, "coord"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTexGenivOES", [(GLenum, "coord"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+ GlFunction(Void, "glGetTexGenxvOES", [(GLenum, "coord"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
+
+ # GL_OES_vertex_array_object
+ GlFunction(Void, "glBindVertexArrayOES", [(GLarray, "array")]),
+ GlFunction(Void, "glDeleteVertexArraysOES", [(GLsizei, "n"), (Array(Const(GLarray), "n"), "arrays")]),
+ GlFunction(Void, "glGenVertexArraysOES", [(GLsizei, "n"), Out(Array(GLarray, "n"), "arrays")]),
+ GlFunction(GLboolean, "glIsVertexArrayOES", [(GLarray, "array")], sideeffects=False),
+
# GL_PGI_misc_hints
GlFunction(Void, "glHintPGI", [(GLenum, "target"), (GLint, "mode")]),
@@ -2912,7 +3492,7 @@ glapi.addFunctions([
# GL_SGIS_texture4D
GlFunction(Void, "glTexImage4DSGIS", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLsizei, "size4d"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (OpaqueBlob(Const(GLvoid), "_glTexImage4DSGIS_size(format, type, width, height, depth, size4d)"), "pixels")]),
- GlFunction(Void, "glTexSubImage4DSGIS", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "woffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLsizei, "size4d"), (GLenum, "format"), (GLenum, "type"), (OpaqueBlob(Const(GLvoid), "_glTexSubImage4DSGIS_size(format, type, width, height, depth, size4d)"), "pixels")]),
+ GlFunction(Void, "glTexSubImage4DSGIS", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "woffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLsizei, "size4d"), (GLenum, "format"), (GLenum, "type"), (OpaqueBlob(Const(GLvoid), "_glTexImage4D_size(format, type, width, height, depth, size4d)"), "pixels")]),
# GL_SGIS_texture_color_mask
GlFunction(Void, "glTextureColorMaskSGIS", [(GLboolean, "red"), (GLboolean, "green"), (GLboolean, "blue"), (GLboolean, "alpha")]),
diff --git a/specs/glesapi.py b/specs/glesapi.py
deleted file mode 100644
index 487d1da6..00000000
--- a/specs/glesapi.py
+++ /dev/null
@@ -1,261 +0,0 @@
-##########################################################################
-#
-# Copyright 2011 LunarG, Inc.
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-##########################################################################/
-
-
-"""GLES API description.
-"""
-
-
-from gltypes import *
-
-
-GLfixed = Alias("GLfixed", Int32)
-GLclampx = Alias("GLclampx", Int32)
-
-
-def GlFunction(*args, **kwargs):
- kwargs.setdefault('call', 'GL_APIENTRY')
- return Function(*args, **kwargs)
-
-
-glesapi = Module('GLES')
-
-
-# OpenGL ES specific functions
-glesapi.addFunctions([
- # GL_VERSION_ES_CM_1_1: GL_OES_single_precision
- GlFunction(Void, "glFrustumf", [(GLfloat, "left"), (GLfloat, "right"), (GLfloat, "bottom"), (GLfloat, "top"), (GLfloat, "zNear"), (GLfloat, "zFar")]),
- GlFunction(Void, "glOrthof", [(GLfloat, "left"), (GLfloat, "right"), (GLfloat, "bottom"), (GLfloat, "top"), (GLfloat, "zNear"), (GLfloat, "zFar")]),
-
- GlFunction(Void, "glClipPlanef", [(GLenum, "plane"), (Array(Const(GLfloat), 4), "equation")]),
- GlFunction(Void, "glGetClipPlanef", [(GLenum, "plane"), Out(Array(GLfloat, 4), "equation")], sideeffects=False),
-
- # GL_VERSION_ES_CM_1_1: GL_OES_fixed_point
- GlFunction(Void, "glAlphaFuncx", [(GLenum, "func"), (GLclampx, "ref")]),
- GlFunction(Void, "glClearColorx", [(GLclampx, "red"), (GLclampx, "green"), (GLclampx, "blue"), (GLclampx, "alpha")]),
- GlFunction(Void, "glClearDepthx", [(GLclampx, "depth")]),
- GlFunction(Void, "glColor4x", [(GLfixed, "red"), (GLfixed, "green"), (GLfixed, "blue"), (GLfixed, "alpha")]),
- GlFunction(Void, "glDepthRangex", [(GLclampx, "zNear"), (GLclampx, "zFar")]),
- GlFunction(Void, "glFogx", [(GLenum, "pname"), (GLfixed, "param")]),
- GlFunction(Void, "glFogxv", [(GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glFrustumx", [(GLfixed, "left"), (GLfixed, "right"), (GLfixed, "bottom"), (GLfixed, "top"), (GLfixed, "zNear"), (GLfixed, "zFar")]),
- GlFunction(Void, "glLightModelx", [(GLenum, "pname"), (GLfixed, "param")]),
- GlFunction(Void, "glLightModelxv", [(GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glLightx", [(GLenum, "light"), (GLenum, "pname"), (GLfixed, "param")]),
- GlFunction(Void, "glLightxv", [(GLenum, "light"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glLineWidthx", [(GLfixed, "width")]),
- GlFunction(Void, "glLoadMatrixx", [(Array(Const(GLfixed), 16), "m")]),
- GlFunction(Void, "glMaterialx", [(GLenum, "face"), (GLenum, "pname"), (GLfixed, "param")]),
- GlFunction(Void, "glMaterialxv", [(GLenum, "face"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glMultMatrixx", [(Array(Const(GLfixed), 16), "m")]),
- GlFunction(Void, "glMultiTexCoord4x", [(GLenum, "target"), (GLfixed, "s"), (GLfixed, "t"), (GLfixed, "r"), (GLfixed, "q")]),
- GlFunction(Void, "glNormal3x", [(GLfixed, "nx"), (GLfixed, "ny"), (GLfixed, "nz")]),
- GlFunction(Void, "glOrthox", [(GLfixed, "left"), (GLfixed, "right"), (GLfixed, "bottom"), (GLfixed, "top"), (GLfixed, "zNear"), (GLfixed, "zFar")]),
- GlFunction(Void, "glPointSizex", [(GLfixed, "size")]),
- GlFunction(Void, "glPolygonOffsetx", [(GLfixed, "factor"), (GLfixed, "units")]),
- GlFunction(Void, "glRotatex", [(GLfixed, "angle"), (GLfixed, "x"), (GLfixed, "y"), (GLfixed, "z")]),
- GlFunction(Void, "glSampleCoveragex", [(GLclampx, "value"), (GLboolean, "invert")]),
- GlFunction(Void, "glScalex", [(GLfixed, "x"), (GLfixed, "y"), (GLfixed, "z")]),
- GlFunction(Void, "glTexEnvx", [(GLenum, "target"), (GLenum, "pname"), (GLfixed, "param")]),
- GlFunction(Void, "glTexEnvxv", [(GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glTexParameterx", [(GLenum, "target"), (GLenum, "pname"), (GLfixed, "param")]),
- GlFunction(Void, "glTranslatex", [(GLfixed, "x"), (GLfixed, "y"), (GLfixed, "z")]),
-
- GlFunction(Void, "glClipPlanex", [(GLenum, "plane"), (Array(Const(GLfixed), 4), "equation")]),
- GlFunction(Void, "glGetClipPlanex", [(GLenum, "plane"), Out(Array(GLfixed, 4), "equation")], sideeffects=False),
- GlFunction(Void, "glGetFixedv", [(GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetLightxv", [(GLenum, "light"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetMaterialxv", [(GLenum, "face"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetTexEnvxv", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetTexParameterxv", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glPointParameterx", [(GLenum, "pname"), (GLfixed, "param")]),
- GlFunction(Void, "glPointParameterxv", [(GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glTexParameterxv", [(GLenum, "target"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
-
- # GL_ES_VERSION_2_0
-
- # all functions are already defined in OpenGL thanks to
- # GL_ARB_ES2_compatibility
-
- # GL_OES_blend_equation_separate
- GlFunction(Void, "glBlendEquationSeparateOES", [(GLenum, "modeRGB"), (GLenum, "modeAlpha")]),
-
- # GL_OES_blend_func_separate
- GlFunction(Void, "glBlendFuncSeparateOES", [(GLenum, "sfactorRGB"), (GLenum, "dfactorRGB"), (GLenum, "sfactorAlpha"), (GLenum, "dfactorAlpha")]),
-
- # GL_OES_blend_subtract
- GlFunction(Void, "glBlendEquationOES", [(GLenum, "mode")]),
-
- # GL_OES_framebuffer_object
- GlFunction(GLboolean, "glIsRenderbufferOES", [(GLrenderbuffer, "renderbuffer")], sideeffects=False),
- GlFunction(Void, "glBindRenderbufferOES", [(GLenum, "target"), (GLrenderbuffer, "renderbuffer")]),
- GlFunction(Void, "glDeleteRenderbuffersOES", [(GLsizei, "n"), (Array(Const(GLrenderbuffer), "n"), "renderbuffers")]),
- GlFunction(Void, "glGenRenderbuffersOES", [(GLsizei, "n"), Out(Array(GLrenderbuffer, "n"), "renderbuffers")]),
- GlFunction(Void, "glRenderbufferStorageOES", [(GLenum, "target"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glGetRenderbufferParameterivOES", [(GLenum, "target"), (GLenum, "pname"), (Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(GLboolean, "glIsFramebufferOES", [(GLframebuffer, "framebuffer")], sideeffects=False),
- GlFunction(Void, "glBindFramebufferOES", [(GLenum, "target"), (GLframebuffer, "framebuffer")]),
- GlFunction(Void, "glDeleteFramebuffersOES", [(GLsizei, "n"), (Array(Const(GLframebuffer), "n"), "framebuffers")]),
- GlFunction(Void, "glGenFramebuffersOES", [(GLsizei, "n"), Out(Array(GLframebuffer, "n"), "framebuffers")]),
- GlFunction(GLenum, "glCheckFramebufferStatusOES", [(GLenum, "target")]),
- GlFunction(Void, "glFramebufferTexture2DOES", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level")]),
- GlFunction(Void, "glFramebufferRenderbufferOES", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "renderbuffertarget"), (GLuint, "renderbuffer")]),
- GlFunction(Void, "glGetFramebufferAttachmentParameterivOES", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGenerateMipmapOES", [(GLenum, "target")]),
-
- # GL_OES_matrix_palette
- GlFunction(Void, "glCurrentPaletteMatrixOES", [(GLuint, "index")]),
- GlFunction(Void, "glLoadPaletteFromModelViewMatrixOES", []),
- GlFunction(Void, "glMatrixIndexPointerOES", [(GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
- GlFunction(Void, "glWeightPointerOES", [(GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
-
- # GL_OES_point_size_array
- GlFunction(Void, "glPointSizePointerOES", [(GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "ptr")]),
-
- # GL_OES_query_matrix
- GlFunction(GLbitfield, "glQueryMatrixxOES", [(Array(GLfixed, 16), "mantissa"), (Array(GLint, 16), "exponent")]),
-
- # GL_OES_texture_cube_map
- GlFunction(Void, "glTexGenfOES", [(GLenum, "coord"), (GLenum, "pname"), (GLfloat, "param")]),
- GlFunction(Void, "glTexGenfvOES", [(GLenum, "coord"), (GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glTexGeniOES", [(GLenum, "coord"), (GLenum, "pname"), (GLint, "param")]),
- GlFunction(Void, "glTexGenivOES", [(GLenum, "coord"), (GLenum, "pname"), (Array(Const(GLint), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glTexGenxOES", [(GLenum, "coord"), (GLenum, "pname"), (GLfixed, "param")]),
- GlFunction(Void, "glTexGenxvOES", [(GLenum, "coord"), (GLenum, "pname"), (Array(Const(GLfixed), "_gl_param_size(pname)"), "params")]),
- GlFunction(Void, "glGetTexGenfvOES", [(GLenum, "coord"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetTexGenivOES", [(GLenum, "coord"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetTexGenxvOES", [(GLenum, "coord"), (GLenum, "pname"), Out(Array(GLfixed, "_gl_param_size(pname)"), "params")], sideeffects=False),
-
- # GL_OES_mapbuffer
- GlFunction(Void, "glGetBufferPointervOES", [(GLenum, "target"), (GLenum, "pname"), Out(Pointer(GLpointer), "params")], sideeffects=False),
- GlFunction(GLmap, "glMapBufferOES", [(GLenum, "target"), (GLenum, "access")]),
- GlFunction(GLboolean, "glUnmapBufferOES", [(GLenum, "target")]),
-
- # GL_OES_texture_3D
- GlFunction(Void, "glTexImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexImage3D_size(format, type, width, height, depth)"), "pixels")]),
- GlFunction(Void, "glTexSubImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLenum, "type"), (Blob(Const(GLvoid), "_glTexSubImage3D_size(format, type, width, height, depth)"), "pixels")]),
- GlFunction(Void, "glCopyTexSubImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glCompressedTexImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "data")]),
- GlFunction(Void, "glCompressedTexSubImage3DOES", [(GLenum, "target"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLenum, "format"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "data")]),
- GlFunction(Void, "glFramebufferTexture3DOES", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level"), (GLint, "zoffset")]),
-
- # GL_OES_get_program_binary
- GlFunction(Void, "glGetProgramBinaryOES", [(GLprogram, "program"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLenum), "binaryFormat"), Out(OpaqueBlob(GLvoid, "length ? *length : bufSize"), "binary")], sideeffects=False),
- GlFunction(Void, "glProgramBinaryOES", [(GLprogram, "program"), (GLenum, "binaryFormat"), (Blob(Const(GLvoid), "length"), "binary"), (GLsizei, "length")]),
-
- # GL_OES_draw_texture
- GlFunction(Void, "glDrawTexfOES", [(GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z"), (GLfloat, "width"), (GLfloat, "height")]),
- GlFunction(Void, "glDrawTexfvOES", [(Array(Const(GLfloat), 4), "coords")]),
- GlFunction(Void, "glDrawTexiOES", [(GLint, "x"), (GLint, "y"), (GLint, "z"), (GLint, "width"), (GLint, "height")]),
- GlFunction(Void, "glDrawTexivOES", [(Array(Const(GLint), 4), "coords")]),
- GlFunction(Void, "glDrawTexsOES", [(GLshort, "x"), (GLshort, "y"), (GLshort, "z"), (GLshort, "width"), (GLshort, "height")]),
- GlFunction(Void, "glDrawTexsvOES", [(Array(Const(GLshort), 4), "coords")]),
-
- # GL_EXT_discard_framebuffer
- GlFunction(Void, "glDiscardFramebufferEXT", [(GLenum, "target"), (GLsizei, "numAttachments"), (Array(Const(GLenum), "numAttachments"), "attachments")]),
-
- # GL_OES_vertex_array_object
- GlFunction(Void, "glBindVertexArrayOES", [(GLarray, "array")]),
- GlFunction(Void, "glDeleteVertexArraysOES", [(GLsizei, "n"), (Array(Const(GLarray), "n"), "arrays")]),
- GlFunction(Void, "glGenVertexArraysOES", [(GLsizei, "n"), Out(Array(GLarray, "n"), "arrays")]),
- GlFunction(GLboolean, "glIsVertexArrayOES", [(GLarray, "array")], sideeffects=False),
-
- # GL_NV_coverage_sample
- GlFunction(Void, "glCoverageMaskNV", [(GLboolean, "mask")]),
- GlFunction(Void, "glCoverageOperationNV", [(GLenum, "operation")]),
-
- # GL_IMG_multisampled_render_to_texture
- GlFunction(Void, "glRenderbufferStorageMultisampleIMG", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glFramebufferTexture2DMultisampleIMG", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level"), (GLsizei, "samples")]),
-
- # GL_APPLE_framebuffer_multisample
- GlFunction(Void, "glRenderbufferStorageMultisampleAPPLE", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glResolveMultisampleFramebufferAPPLE", []),
-
- # GL_ANGLE_framebuffer_blit
- GlFunction(Void, "glBlitFramebufferANGLE", [(GLint, "srcX0"), (GLint, "srcY0"), (GLint, "srcX1"), (GLint, "srcY1"), (GLint, "dstX0"), (GLint, "dstY0"), (GLint, "dstX1"), (GLint, "dstY1"), (GLbitfield_attrib, "mask"), (GLenum, "filter")]),
-
- # GL_ANGLE_framebuffer_multisample
- GlFunction(Void, "glRenderbufferStorageMultisampleANGLE", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
-
- # GL_NV_draw_buffers
- GlFunction(Void, "glDrawBuffersNV", [(GLsizei, "n"), (Array(Const(GLenum), "n"), "bufs")]),
-
- # GL_NV_read_buffer
- GlFunction(Void, "glReadBufferNV", [(GLenum, "mode")]),
-
- # GL_EXT_occlusion_query_boolean
- GlFunction(Void, "glGenQueriesEXT", [(GLsizei, "n"), Out(Array(GLquery, "n"), "ids")]),
- GlFunction(Void, "glDeleteQueriesEXT", [(GLsizei, "n"), (Array(Const(GLquery), "n"), "ids")]),
- GlFunction(GLboolean, "glIsQueryEXT", [(GLquery, "id")], sideeffects=False),
- GlFunction(Void, "glBeginQueryEXT", [(GLenum, "target"), (GLquery, "id")]),
- GlFunction(Void, "glEndQueryEXT", [(GLenum, "target")]),
- GlFunction(Void, "glGetQueryivEXT", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- GlFunction(Void, "glGetQueryObjectuivEXT", [(GLquery, "id"), (GLenum, "pname"), Out(Array(GLuint, "_gl_param_size(pname)"), "params")], sideeffects=False),
-
- # GL_EXT_separate_shader_objects
- GlFunction(Void, "glUseProgramStagesEXT", [(GLpipeline, "pipeline"), (GLbitfield_shader, "stages"), (GLprogram, "program")]),
- GlFunction(Void, "glActiveShaderProgramEXT", [(GLpipeline, "pipeline"), (GLprogram, "program")]),
- GlFunction(GLprogram, "glCreateShaderProgramvEXT", [(GLenum, "type"), (GLsizei, "count"), (Const(Array(GLstringConst, "count")), "strings")]),
- GlFunction(Void, "glBindProgramPipelineEXT", [(GLpipeline, "pipeline")]),
- GlFunction(Void, "glDeleteProgramPipelinesEXT", [(GLsizei, "n"), (Array(Const(GLuint), "n"), "pipelines")]),
- GlFunction(Void, "glGenProgramPipelinesEXT", [(GLsizei, "n"), Out(Array(GLpipeline, "n"), "pipelines")]),
- GlFunction(GLboolean, "glIsProgramPipelineEXT", [(GLpipeline, "pipeline")], sideeffects=False),
- #GlFunction(Void, "glProgramParameteriEXT", [(GLprogram, "program"), (GLenum, "pname"), (GLint, "value")]),
- GlFunction(Void, "glGetProgramPipelineivEXT", [(GLpipeline, "pipeline"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
- #GlFunction(Void, "glProgramUniform1iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "x")]),
- #GlFunction(Void, "glProgramUniform2iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "x"), (GLint, "y")]),
- #GlFunction(Void, "glProgramUniform3iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "x"), (GLint, "y"), (GLint, "z")]),
- #GlFunction(Void, "glProgramUniform4iEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLint, "x"), (GLint, "y"), (GLint, "z"), (GLint, "w")]),
- #GlFunction(Void, "glProgramUniform1fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "x")]),
- #GlFunction(Void, "glProgramUniform2fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "x"), (GLfloat, "y")]),
- #GlFunction(Void, "glProgramUniform3fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z")]),
- #GlFunction(Void, "glProgramUniform4fEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z"), (GLfloat, "w")]),
- #GlFunction(Void, "glProgramUniform1ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count"), "value")]),
- #GlFunction(Void, "glProgramUniform2ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count*2"), "value")]),
- #GlFunction(Void, "glProgramUniform3ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count*3"), "value")]),
- #GlFunction(Void, "glProgramUniform4ivEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLint), "count*4"), "value")]),
- #GlFunction(Void, "glProgramUniform1fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count"), "value")]),
- #GlFunction(Void, "glProgramUniform2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count*2"), "value")]),
- #GlFunction(Void, "glProgramUniform3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count*3"), "value")]),
- #GlFunction(Void, "glProgramUniform4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (Array(Const(GLfloat), "count*4"), "value")]),
- #GlFunction(Void, "glProgramUniformMatrix2fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*2*2"), "value")]),
- #GlFunction(Void, "glProgramUniformMatrix3fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*3*3"), "value")]),
- #GlFunction(Void, "glProgramUniformMatrix4fvEXT", [(GLprogram, "program"), (GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*4*4"), "value")]),
- GlFunction(Void, "glValidateProgramPipelineEXT", [(GLpipeline, "pipeline")]),
- GlFunction(Void, "glGetProgramPipelineInfoLogEXT", [(GLpipeline, "pipeline"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(GLstring, "infoLog")], sideeffects=False),
-
- # GL_EXT_multisampled_render_to_texture
- #GlFunction(Void, "glRenderbufferStorageMultisampleEXT", [(GLenum, "target"), (GLsizei, "samples"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glFramebufferTexture2DMultisampleEXT", [(GLenum, "target"), (GLenum, "attachment"), (GLenum, "textarget"), (GLtexture, "texture"), (GLint, "level"), (GLsizei, "samples")]),
-
- # GL_EXT_texture_storage
- GlFunction(Void, "glTexStorage1DEXT", [(GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width")]),
- GlFunction(Void, "glTexStorage2DEXT", [(GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- GlFunction(Void, "glTexStorage3DEXT", [(GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
- #GlFunction(Void, "glTextureStorage1DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width")]),
- #GlFunction(Void, "glTextureStorage2DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height")]),
- #GlFunction(Void, "glTextureStorage3DEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLsizei, "levels"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
-])
diff --git a/specs/glparams.py b/specs/glparams.py
index 116546ac..306410b6 100644
--- a/specs/glparams.py
+++ b/specs/glparams.py
@@ -73,6 +73,7 @@ parameters = [
("", X, 1, "GL_DUP_FIRST_CUBIC_CURVE_TO_NV"), # 0x00F2
("", X, 1, "GL_DUP_LAST_CUBIC_CURVE_TO_NV"), # 0x00F4
("", X, 1, "GL_RECT_NV"), # 0x00F6
+ ("", X, 1, "GL_RELATIVE_RECT_NV"), # 0x00F7
("", X, 1, "GL_CIRCULAR_CCW_ARC_TO_NV"), # 0x00F8
("", X, 1, "GL_CIRCULAR_CW_ARC_TO_NV"), # 0x00FA
("", X, 1, "GL_CIRCULAR_TANGENT_ARC_TO_NV"), # 0x00FC
@@ -121,6 +122,7 @@ parameters = [
("", X, 1, "GL_STACK_UNDERFLOW"), # 0x0504
("", X, 1, "GL_OUT_OF_MEMORY"), # 0x0505
("", X, 1, "GL_INVALID_FRAMEBUFFER_OPERATION"), # 0x0506
+ ("", X, 1, "GL_CONTEXT_LOST"), # 0x0507
("", X, 1, "GL_2D"), # 0x0600
("", X, 1, "GL_3D"), # 0x0601
("", X, 1, "GL_3D_COLOR"), # 0x0602
@@ -343,8 +345,8 @@ parameters = [
("glGet", I, 1, "GL_MAP1_GRID_SEGMENTS"), # 0x0DD1
("glGet", F, 4, "GL_MAP2_GRID_DOMAIN"), # 0x0DD2
("glGet", I, 2, "GL_MAP2_GRID_SEGMENTS"), # 0x0DD3
- ("glGet_texture", B, 1, "GL_TEXTURE_1D"), # 0x0DE0
- ("glGet_texture", B, 1, "GL_TEXTURE_2D"), # 0x0DE1
+ ("", B, 1, "GL_TEXTURE_1D"), # 0x0DE0
+ ("", B, 1, "GL_TEXTURE_2D"), # 0x0DE1
("glGet", P, 1, "GL_FEEDBACK_BUFFER_POINTER"), # 0x0DF0
("glGet", I, 1, "GL_FEEDBACK_BUFFER_SIZE"), # 0x0DF1
("glGet", E, 1, "GL_FEEDBACK_BUFFER_TYPE"), # 0x0DF2
@@ -355,6 +357,7 @@ parameters = [
("glGetTexLevelParameter", E, 1, "GL_TEXTURE_INTERNAL_FORMAT"), # 0x1003
("glGetTexParameter,glGetSamplerParameter", F, 4, "GL_TEXTURE_BORDER_COLOR"), # 0x1004
("glGetTexLevelParameter", I, 1, "GL_TEXTURE_BORDER"), # 0x1005
+ ("glGetTexParameter", E, 1, "GL_TEXTURE_TARGET"), # 0x1006
("", X, 1, "GL_DONT_CARE"), # 0x1100
("", X, 1, "GL_FASTEST"), # 0x1101
("", X, 1, "GL_NICEST"), # 0x1102
@@ -383,7 +386,7 @@ parameters = [
("", X, 1, "GL_DOUBLE"), # 0x140A
("", X, 1, "GL_HALF_FLOAT"), # 0x140B
("", X, 1, "GL_FIXED"), # 0x140C
- ("", X, 1, "GL_INT64_NV"), # 0x140E
+ ("", X, 1, "GL_INT64_ARB"), # 0x140E
("", X, 1, "GL_UNSIGNED_INT64_ARB"), # 0x140F
("", X, 1, "GL_CLEAR"), # 0x1500
("", X, 1, "GL_AND"), # 0x1501
@@ -611,7 +614,7 @@ parameters = [
("glGet", F, 1, "GL_PACK_IMAGE_HEIGHT"), # 0x806C
("glGet", I, 1, "GL_UNPACK_SKIP_IMAGES"), # 0x806D
("glGet", F, 1, "GL_UNPACK_IMAGE_HEIGHT"), # 0x806E
- ("glGet_texture", B, 1, "GL_TEXTURE_3D"), # 0x806F
+ ("", B, 1, "GL_TEXTURE_3D"), # 0x806F
("", X, 1, "GL_PROXY_TEXTURE_3D"), # 0x8070
("glGetTexLevelParameter", I, 1, "GL_TEXTURE_DEPTH"), # 0x8071
("glGetTexParameter,glGetSamplerParameter", E, 1, "GL_TEXTURE_WRAP_R"), # 0x8072
@@ -930,7 +933,7 @@ parameters = [
("glGet", I, 1, "GL_CONTEXT_FLAGS"), # 0x821E
("glGetBufferParameter", B, 1, "GL_BUFFER_IMMUTABLE_STORAGE"), # 0x821F
("glGetBufferParameter", I, 1, "GL_BUFFER_STORAGE_FLAGS"), # 0x8220
- ("", X, 1, "GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"), # 0x8221
+ ("glGet", B, 1, "GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"), # 0x8221
("", X, 1, "GL_INDEX"), # 0x8222
("", X, 1, "GL_COMPRESSED_RED"), # 0x8225
("", X, 1, "GL_COMPRESSED_RG"), # 0x8226
@@ -960,8 +963,8 @@ parameters = [
("", X, 1, "GL_SYNC_CL_EVENT_COMPLETE_ARB"), # 0x8241
("glGet", B, 1, "GL_DEBUG_OUTPUT_SYNCHRONOUS"), # 0x8242
("glGet", I, 1, "GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH"), # 0x8243
- ("glGet", P, 1, "GL_DEBUG_CALLBACK_FUNCTION"), # 0x8244
- ("glGet", P, 1, "GL_DEBUG_CALLBACK_USER_PARAM"), # 0x8245
+ ("_glGet", P, 1, "GL_DEBUG_CALLBACK_FUNCTION"), # 0x8244
+ ("_glGet", P, 1, "GL_DEBUG_CALLBACK_USER_PARAM"), # 0x8245
("", X, 1, "GL_DEBUG_SOURCE_API"), # 0x8246
("", X, 1, "GL_DEBUG_SOURCE_WINDOW_SYSTEM"), # 0x8247
("", X, 1, "GL_DEBUG_SOURCE_SHADER_COMPILER"), # 0x8248
@@ -974,12 +977,12 @@ parameters = [
("", X, 1, "GL_DEBUG_TYPE_PORTABILITY"), # 0x824F
("", X, 1, "GL_DEBUG_TYPE_PERFORMANCE"), # 0x8250
("", X, 1, "GL_DEBUG_TYPE_OTHER"), # 0x8251
- ("", X, 1, "GL_LOSE_CONTEXT_ON_RESET_ARB"), # 0x8252
- ("", X, 1, "GL_GUILTY_CONTEXT_RESET_ARB"), # 0x8253
- ("", X, 1, "GL_INNOCENT_CONTEXT_RESET_ARB"), # 0x8254
- ("", X, 1, "GL_UNKNOWN_CONTEXT_RESET_ARB"), # 0x8255
- ("glGet", E, 1, "GL_RESET_NOTIFICATION_STRATEGY_ARB"), # 0x8256
- ("", X, 1, "GL_PROGRAM_BINARY_RETRIEVABLE_HINT"), # 0x8257
+ ("", X, 1, "GL_LOSE_CONTEXT_ON_RESET"), # 0x8252
+ ("", X, 1, "GL_GUILTY_CONTEXT_RESET"), # 0x8253
+ ("", X, 1, "GL_INNOCENT_CONTEXT_RESET"), # 0x8254
+ ("", X, 1, "GL_UNKNOWN_CONTEXT_RESET"), # 0x8255
+ ("glGet", E, 1, "GL_RESET_NOTIFICATION_STRATEGY"), # 0x8256
+ ("glGetProgram", B, 1, "GL_PROGRAM_BINARY_RETRIEVABLE_HINT"), # 0x8257
("", X, 1, "GL_PROGRAM_SEPARABLE"), # 0x8258
("glGet", I, 1, "GL_ACTIVE_PROGRAM"), # 0x8259
("glGet", I, 1, "GL_PROGRAM_PIPELINE_BINDING"), # 0x825A
@@ -989,7 +992,7 @@ parameters = [
("glGet", E, 1, "GL_LAYER_PROVOKING_VERTEX"), # 0x825E
("glGet", E, 1, "GL_VIEWPORT_INDEX_PROVOKING_VERTEX"), # 0x825F
("", X, 1, "GL_UNDEFINED_VERTEX"), # 0x8260
- ("", X, 1, "GL_NO_RESET_NOTIFICATION_ARB"), # 0x8261
+ ("", X, 1, "GL_NO_RESET_NOTIFICATION"), # 0x8261
("glGet", I, 1, "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"), # 0x8262
("glGet", I, 1, "GL_MAX_COMPUTE_UNIFORM_COMPONENTS"), # 0x8263
("glGet", I, 1, "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"), # 0x8264
@@ -1124,6 +1127,25 @@ parameters = [
("", X, 1, "GL_DISPLAY_LIST"), # 0x82E7
("glGet", I, 1, "GL_MAX_LABEL_LENGTH"), # 0x82E8
("", X, 1, "GL_NUM_SHADING_LANGUAGE_VERSIONS"), # 0x82E9
+ ("", X, 1, "GL_QUERY_TARGET"), # 0x82EA
+ #("", X, 1, "GL_TEXTURE_BINDING"), # 0x82EB
+ ("", X, 1, "GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB"), # 0x82EC
+ ("", X, 1, "GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB"), # 0x82ED
+ ("", X, 1, "GL_VERTICES_SUBMITTED_ARB"), # 0x82EE
+ ("", X, 1, "GL_PRIMITIVES_SUBMITTED_ARB"), # 0x82EF
+ ("", X, 1, "GL_VERTEX_SHADER_INVOCATIONS_ARB"), # 0x82F0
+ ("", X, 1, "GL_TESS_CONTROL_SHADER_PATCHES_ARB"), # 0x82F1
+ ("", X, 1, "GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB"), # 0x82F2
+ ("", X, 1, "GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB"), # 0x82F3
+ ("", X, 1, "GL_FRAGMENT_SHADER_INVOCATIONS_ARB"), # 0x82F4
+ ("", X, 1, "GL_COMPUTE_SHADER_INVOCATIONS_ARB"), # 0x82F5
+ ("", X, 1, "GL_CLIPPING_INPUT_PRIMITIVES_ARB"), # 0x82F6
+ ("", X, 1, "GL_CLIPPING_OUTPUT_PRIMITIVES_ARB"), # 0x82F7
+ ("", X, 1, "GL_SPARSE_BUFFER_PAGE_SIZE_ARB"), # 0x82F8
+ ("glGet", I, 1, "GL_MAX_CULL_DISTANCES"), # 0x82F9
+ ("glGet", I, 1, "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES"), # 0x82FA
+ ("glGet", E, 1, "GL_CONTEXT_RELEASE_BEHAVIOR"), # 0x82FB
+ ("glGet", E, 1, "GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH"), # 0x82FC
("", X, 1, "GL_DEPTH_PASS_INSTRUMENT_SGIX"), # 0x8310
("", X, 1, "GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX"), # 0x8311
("", X, 1, "GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX"), # 0x8312
@@ -1206,7 +1228,7 @@ parameters = [
("", X, 1, "GL_PERFQUERY_DONOT_FLUSH_INTEL"), # 0x83F9
("", X, 1, "GL_PERFQUERY_FLUSH_INTEL"), # 0x83FA
("", X, 1, "GL_PERFQUERY_WAIT_INTEL"), # 0x83FB
- ("", X, 1, "GL_TEXTURE_MEMORY_LAYOUT_INTEL"), # 0x83FF
+ ("glGetTexParameter", E, 1, "GL_TEXTURE_MEMORY_LAYOUT_INTEL"), # 0x83FF
("glGet", I, 1, "GL_FRAGMENT_LIGHTING_SGIX"), # 0x8400
("glGet", I, 1, "GL_FRAGMENT_COLOR_MATERIAL_SGIX"), # 0x8401
("glGet", I, 1, "GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX"), # 0x8402
@@ -1227,11 +1249,11 @@ parameters = [
("", X, 1, "GL_FRAGMENT_LIGHT5_SGIX"), # 0x8411
("", X, 1, "GL_FRAGMENT_LIGHT6_SGIX"), # 0x8412
("", X, 1, "GL_FRAGMENT_LIGHT7_SGIX"), # 0x8413
- ("", X, 1, "GL_PACK_RESAMPLE_SGIX"), # 0x842C
- ("", X, 1, "GL_UNPACK_RESAMPLE_SGIX"), # 0x842D
- ("", X, 1, "GL_RESAMPLE_REPLICATE_SGIX"), # 0x842E
- ("", X, 1, "GL_RESAMPLE_ZERO_FILL_SGIX"), # 0x842F
+ ("", X, 1, "GL_PACK_RESAMPLE_SGIX"), # 0x842E
+ ("", X, 1, "GL_UNPACK_RESAMPLE_SGIX"), # 0x842F
("", X, 1, "GL_RESAMPLE_DECIMATE_SGIX"), # 0x8430
+ ("", X, 1, "GL_RESAMPLE_REPLICATE_SGIX"), # 0x8433
+ ("", X, 1, "GL_RESAMPLE_ZERO_FILL_SGIX"), # 0x8434
("", X, 1, "GL_TANGENT_ARRAY_EXT"), # 0x8439
("", X, 1, "GL_BINORMAL_ARRAY_EXT"), # 0x843A
("", X, 1, "GL_CURRENT_TANGENT_EXT"), # 0x843B
@@ -1322,17 +1344,17 @@ parameters = [
("", X, 1, "GL_ALL_COMPLETED_NV"), # 0x84F2
("", X, 1, "GL_FENCE_STATUS_NV"), # 0x84F3
("", X, 1, "GL_FENCE_CONDITION_NV"), # 0x84F4
- ("glGet_texture", B, 1, "GL_TEXTURE_RECTANGLE"), # 0x84F5
+ ("", B, 1, "GL_TEXTURE_RECTANGLE"), # 0x84F5
("glGet_texture", I, 1, "GL_TEXTURE_BINDING_RECTANGLE"), # 0x84F6
("", X, 1, "GL_PROXY_TEXTURE_RECTANGLE"), # 0x84F7
("glGet", I, 1, "GL_MAX_RECTANGLE_TEXTURE_SIZE"), # 0x84F8
("", X, 1, "GL_DEPTH_STENCIL"), # 0x84F9
("", X, 1, "GL_UNSIGNED_INT_24_8"), # 0x84FA
("glGet", F, 1, "GL_MAX_TEXTURE_LOD_BIAS"), # 0x84FD
- ("glGetTexParameter", F, 1, "GL_TEXTURE_MAX_ANISOTROPY_EXT"), # 0x84FE
+ ("glGetTexParameter,glGetSamplerParameter", F, 1, "GL_TEXTURE_MAX_ANISOTROPY_EXT"), # 0x84FE
("glGet", F, 1, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT"), # 0x84FF
("", X, 1, "GL_TEXTURE_FILTER_CONTROL"), # 0x8500
- ("glGetTexParameter,glGetTexEnv", F, 1, "GL_TEXTURE_LOD_BIAS"), # 0x8501
+ ("glGetTexParameter,glGetSamplerParameter,glGetTexEnv", F, 1, "GL_TEXTURE_LOD_BIAS"), # 0x8501
("", X, 1, "GL_MODELVIEW1_STACK_DEPTH_EXT"), # 0x8502
("", X, 1, "GL_COMBINE4_NV"), # 0x8503
("glGet", F, 1, "GL_MAX_SHININESS_NV"), # 0x8504
@@ -1350,7 +1372,7 @@ parameters = [
("", X, 1, "GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT"), # 0x8510
("", X, 1, "GL_NORMAL_MAP"), # 0x8511
("", X, 1, "GL_REFLECTION_MAP"), # 0x8512
- ("glGet_texture", B, 1, "GL_TEXTURE_CUBE_MAP"), # 0x8513
+ ("", B, 1, "GL_TEXTURE_CUBE_MAP"), # 0x8513
("glGet_texture", I, 1, "GL_TEXTURE_BINDING_CUBE_MAP"), # 0x8514
("", X, 1, "GL_TEXTURE_CUBE_MAP_POSITIVE_X"), # 0x8515
("", X, 1, "GL_TEXTURE_CUBE_MAP_NEGATIVE_X"), # 0x8516
@@ -1419,8 +1441,8 @@ parameters = [
("", X, 1, "GL_COMBINER5_NV"), # 0x8555
("", X, 1, "GL_COMBINER6_NV"), # 0x8556
("", X, 1, "GL_COMBINER7_NV"), # 0x8557
- ("", X, 1, "GL_PRIMITIVE_RESTART_NV"), # 0x8558
- ("", X, 1, "GL_PRIMITIVE_RESTART_INDEX_NV"), # 0x8559
+ ("glGet", B, 1, "GL_PRIMITIVE_RESTART_NV"), # 0x8558
+ ("glGet", I, 1, "GL_PRIMITIVE_RESTART_INDEX_NV"), # 0x8559
("glGet", E, 1, "GL_FOG_DISTANCE_MODE_NV"), # 0x855A
("", X, 1, "GL_EYE_RADIAL_NV"), # 0x855B
("", X, 1, "GL_EYE_PLANE_ABSOLUTE_NV"), # 0x855C
@@ -1474,7 +1496,7 @@ parameters = [
("", X, 1, "GL_BUFFER_OBJECT_APPLE"), # 0x85B3
("", X, 1, "GL_STORAGE_CLIENT_APPLE"), # 0x85B4
("glGet", I, 1, "GL_VERTEX_ARRAY_BINDING"), # 0x85B5
- ("glGetTexParameter", X, 1, "GL_TEXTURE_RANGE_LENGTH_APPLE"), # 0x85B7
+ ("glGetTexParameter", I, 1, "GL_TEXTURE_RANGE_LENGTH_APPLE"), # 0x85B7
("", P, 1, "GL_TEXTURE_RANGE_POINTER_APPLE"), # 0x85B8
("", X, 1, "GL_YCBCR_422_APPLE"), # 0x85B9
("", X, 1, "GL_UNSIGNED_SHORT_8_8_APPLE"), # 0x85BA
@@ -1736,8 +1758,8 @@ parameters = [
("", X, 1, "GL_DOT3_RGB_EXT"), # 0x8740
# XXX: GL_DOT3_RGBA_EXT == GL_PROGRAM_BINARY_LENGTH, but you can't glGet GL_DOT3_RGBA_EXT
("glGetProgram", I, 1, "GL_PROGRAM_BINARY_LENGTH"), # 0x8741,
- ("", X, 1, "GL_MIRROR_CLAMP_ATI"), # 0x8742
- ("", X, 1, "GL_MIRROR_CLAMP_TO_EDGE"), # 0x8743
+ ("", X, 1, "GL_MIRROR_CLAMP_EXT"), # 0x8742
+ ("", X, 1, "GL_MIRROR_CLAMP_TO_EDGE"), # 0x8743
("", X, 1, "GL_MODULATE_ADD_ATI"), # 0x8744
("", X, 1, "GL_MODULATE_SIGNED_ADD_ATI"), # 0x8745
("", X, 1, "GL_MODULATE_SUBTRACT_ATI"), # 0x8746
@@ -1913,9 +1935,9 @@ parameters = [
("", X, 1, "GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI"), # 0x87F8
("", X, 1, "GL_3DC_X_AMD"), # 0x87F9
("", X, 1, "GL_3DC_XY_AMD"), # 0x87FA
- ("", X, 1, "GL_VBO_FREE_MEMORY_ATI"), # 0x87FB
- ("", X, 1, "GL_TEXTURE_FREE_MEMORY_ATI"), # 0x87FC
- ("", X, 1, "GL_RENDERBUFFER_FREE_MEMORY_ATI"), # 0x87FD
+ ("glGet", I, 1, "GL_VBO_FREE_MEMORY_ATI"), # 0x87FB
+ ("glGet", I, 1, "GL_TEXTURE_FREE_MEMORY_ATI"), # 0x87FC
+ ("glGet", I, 1, "GL_RENDERBUFFER_FREE_MEMORY_ATI"), # 0x87FD
("glGet", I, 1, "GL_NUM_PROGRAM_BINARY_FORMATS"), # 0x87FE
("glGet", E, "_glGetInteger(GL_NUM_PROGRAM_BINARY_FORMATS)", "GL_PROGRAM_BINARY_FORMATS"), # 0x87FF
("glGet", E, 1, "GL_STENCIL_BACK_FUNC"), # 0x8800
@@ -2009,7 +2031,7 @@ parameters = [
("glGetQuery", I, 1, "GL_CURRENT_QUERY"), # 0x8865
("glGetQueryObject", I, 1, "GL_QUERY_RESULT"), # 0x8866
("glGetQueryObject", B, 1, "GL_QUERY_RESULT_AVAILABLE"), # 0x8867
- ("", X, 1, "GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV"), # 0x8868
+ ("glGet", I, 1, "GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV"), # 0x8868
("glGet", I, 1, "GL_MAX_VERTEX_ATTRIBS"), # 0x8869
("glGetVertexAttrib", B, 1, "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"), # 0x886A
("glGet", I, 1, "GL_MAX_TESS_CONTROL_INPUT_COMPONENTS"), # 0x886C
@@ -2160,19 +2182,19 @@ parameters = [
("glGet", F, 1, "GL_MAX_PROGRAM_TEXEL_OFFSET"), # 0x8905
("", X, 1, "GL_PROGRAM_ATTRIB_COMPONENTS_NV"), # 0x8906
("", X, 1, "GL_PROGRAM_RESULT_COMPONENTS_NV"), # 0x8907
- ("", X, 1, "GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV"), # 0x8908
- ("", X, 1, "GL_MAX_PROGRAM_RESULT_COMPONENTS_NV"), # 0x8909
+ ("glGetProgramARB", I, 1, "GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV"), # 0x8908
+ ("glGetProgramARB", I, 1, "GL_MAX_PROGRAM_RESULT_COMPONENTS_NV"), # 0x8909
("glGet", B, 1, "GL_STENCIL_TEST_TWO_SIDE_EXT"), # 0x8910
("glGet", E, 1, "GL_ACTIVE_STENCIL_FACE_EXT"), # 0x8911
("", X, 1, "GL_MIRROR_CLAMP_TO_BORDER_EXT"), # 0x8912
("", X, 1, "GL_SAMPLES_PASSED"), # 0x8914
- ("", X, 1, "GL_GEOMETRY_VERTICES_OUT"), # 0x8916
- ("", X, 1, "GL_GEOMETRY_INPUT_TYPE"), # 0x8917
- ("", X, 1, "GL_GEOMETRY_OUTPUT_TYPE"), # 0x8918
+ ("glGetProgram", I, 1, "GL_GEOMETRY_VERTICES_OUT"), # 0x8916
+ ("glGetProgram", E, 1, "GL_GEOMETRY_INPUT_TYPE"), # 0x8917
+ ("glGetProgram", E, 1, "GL_GEOMETRY_OUTPUT_TYPE"), # 0x8918
("_glGet", I, 1, "GL_SAMPLER_BINDING"), # 0x8919
- ("glGet", B, 1, "GL_CLAMP_VERTEX_COLOR"), # 0x891A
- ("glGet", B, 1, "GL_CLAMP_FRAGMENT_COLOR"), # 0x891B
- ("glGet", B, 1, "GL_CLAMP_READ_COLOR"), # 0x891C
+ ("glGet", E, 1, "GL_CLAMP_VERTEX_COLOR"), # 0x891A
+ ("glGet", E, 1, "GL_CLAMP_FRAGMENT_COLOR"), # 0x891B
+ ("glGet", E, 1, "GL_CLAMP_READ_COLOR"), # 0x891C
("", X, 1, "GL_FIXED_ONLY"), # 0x891D
("", X, 1, "GL_TESS_CONTROL_PROGRAM_NV"), # 0x891E
("", X, 1, "GL_TESS_EVALUATION_PROGRAM_NV"), # 0x891F
@@ -2309,11 +2331,11 @@ parameters = [
("", X, 1, "GL_VOLATILE_APPLE"), # 0x8A1A
("", X, 1, "GL_RETAINED_APPLE"), # 0x8A1B
("", X, 1, "GL_UNDEFINED_APPLE"), # 0x8A1C
- ("", X, 1, "GL_PURGEABLE_APPLE"), # 0x8A1D
+ ("", B, 1, "GL_PURGEABLE_APPLE"), # 0x8A1D
("", X, 1, "GL_RGB_422_APPLE"), # 0x8A1F
- ("glGet", I, 1, "GL_UNIFORM_BUFFER_BINDING"), # 0x8A28
- ("glGet", I, 1, "GL_UNIFORM_BUFFER_START"), # 0x8A29
- ("glGet", I, 1, "GL_UNIFORM_BUFFER_SIZE"), # 0x8A2A
+ ("glGet,glGet_i", I, 1, "GL_UNIFORM_BUFFER_BINDING"), # 0x8A28
+ ("glGet_i", I, 1, "GL_UNIFORM_BUFFER_START"), # 0x8A29
+ ("glGet_i", I, 1, "GL_UNIFORM_BUFFER_SIZE"), # 0x8A2A
("glGet", I, 1, "GL_MAX_VERTEX_UNIFORM_BLOCKS"), # 0x8A2B
("glGet", I, 1, "GL_MAX_GEOMETRY_UNIFORM_BLOCKS"), # 0x8A2C
("glGet", I, 1, "GL_MAX_FRAGMENT_UNIFORM_BLOCKS"), # 0x8A2D
@@ -2342,7 +2364,7 @@ parameters = [
("glGetActiveUniformBlock", B, 1, "GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"), # 0x8A44
("glGetActiveUniformBlock", B, 1, "GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER"), # 0x8A45
("glGetActiveUniformBlock", B, 1, "GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"), # 0x8A46
- ("glGetTexParameter", E, 1, "GL_TEXTURE_SRGB_DECODE_EXT"), # 0x8A48
+ ("glGetTexParameter,glGetSamplerParameter", E, 1, "GL_TEXTURE_SRGB_DECODE_EXT"), # 0x8A48
("", X, 1, "GL_DECODE_EXT"), # 0x8A49
("", X, 1, "GL_SKIP_DECODE_EXT"), # 0x8A4A
("", X, 1, "GL_PROGRAM_PIPELINE_OBJECT_EXT"), # 0x8A4F
@@ -2419,14 +2441,14 @@ parameters = [
("glGet", E, 1, "GL_IMPLEMENTATION_COLOR_READ_FORMAT"), # 0x8B9B
("", X, 1, "GL_POINT_SIZE_ARRAY_OES"), # 0x8B9C
("glGetTexParameter", I, 4, "GL_TEXTURE_CROP_RECT_OES"), # 0x8B9D
- ("", X, 1, "GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES"), # 0x8B9E
- ("", X, 1, "GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES"), # 0x8B9F
+ ("glGet", I, 1, "GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES"), # 0x8B9E
+ ("", I, 1, "GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES"), # 0x8B9F
#("", X, 1, "GL_FRAGMENT_PROGRAM_POSITION_MESA"), # 0x8BB0
#("", X, 1, "GL_FRAGMENT_PROGRAM_CALLBACK_MESA"), # 0x8BB1
#("", X, 1, "GL_FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA"), # 0x8BB2
#("", X, 1, "GL_FRAGMENT_PROGRAM_CALLBACK_DATA_MESA"), # 0x8BB3
- #("", X, 1, "GL_VERTEX_PROGRAM_CALLBACK_MESA"), # 0x8BB4
#("", X, 1, "GL_VERTEX_PROGRAM_POSITION_MESA"), # 0x8BB4
+ #("", X, 1, "GL_VERTEX_PROGRAM_CALLBACK_MESA"), # 0x8BB5
#("", X, 1, "GL_VERTEX_PROGRAM_CALLBACK_FUNC_MESA"), # 0x8BB6
#("", X, 1, "GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA"), # 0x8BB7
("", X, 1, "GL_COUNTER_TYPE_AMD"), # 0x8BC0
@@ -2447,6 +2469,7 @@ parameters = [
#("", X, 1, "GL_TEXTURE_TARGET_QCOM"), # 0x8BDA
#("", X, 1, "GL_TEXTURE_OBJECT_VALID_QCOM"), # 0x8BDB
#("", X, 1, "GL_STATE_RESTORE"), # 0x8BDC
+ ("", X, 1, "GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT"), # 0x8BE7
#("", X, 1, "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG"), # 0x8C00
#("", X, 1, "GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG"), # 0x8C01
#("", X, 1, "GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG"), # 0x8C02
@@ -2466,9 +2489,9 @@ parameters = [
("glGetTexLevelParameter", E, 1, "GL_TEXTURE_INTENSITY_TYPE"), # 0x8C15
("glGetTexLevelParameter", E, 1, "GL_TEXTURE_DEPTH_TYPE"), # 0x8C16
("", X, 1, "GL_UNSIGNED_NORMALIZED"), # 0x8C17
- ("glGet_texture", B, 1, "GL_TEXTURE_1D_ARRAY"), # 0x8C18
+ ("", B, 1, "GL_TEXTURE_1D_ARRAY"), # 0x8C18
("", X, 1, "GL_PROXY_TEXTURE_1D_ARRAY"), # 0x8C19
- ("glGet_texture", B, 1, "GL_TEXTURE_2D_ARRAY"), # 0x8C1A
+ ("", B, 1, "GL_TEXTURE_2D_ARRAY"), # 0x8C1A
("", X, 1, "GL_PROXY_TEXTURE_2D_ARRAY"), # 0x8C1B
("glGet_texture", I, 1, "GL_TEXTURE_BINDING_1D_ARRAY"), # 0x8C1C
("glGet_texture", I, 1, "GL_TEXTURE_BINDING_2D_ARRAY"), # 0x8C1D
@@ -2482,8 +2505,8 @@ parameters = [
("glGet_texture", I, 1, "GL_TEXTURE_BUFFER_DATA_STORE_BINDING"), # 0x8C2D
("glGet_texture", E, 1, "GL_TEXTURE_BUFFER_FORMAT_ARB"), # 0x8C2E
("", B, 1, "GL_ANY_SAMPLES_PASSED"), # 0x8C2F
- ("", X, 1, "GL_SAMPLE_SHADING"), # 0x8C36
- ("", X, 1, "GL_MIN_SAMPLE_SHADING_VALUE"), # 0x8C37
+ ("glGet", B, 1, "GL_SAMPLE_SHADING"), # 0x8C36
+ ("glGet", F, 1, "GL_MIN_SAMPLE_SHADING_VALUE"), # 0x8C37
("", X, 1, "GL_R11F_G11F_B10F"), # 0x8C3A
("", X, 1, "GL_UNSIGNED_INT_10F_11F_11F_REV"), # 0x8C3B
("", X, 1, "GL_RGBA_SIGNED_COMPONENTS_EXT"), # 0x8C3C
@@ -2526,8 +2549,8 @@ parameters = [
("", X, 1, "GL_ACTIVE_VARYINGS_NV"), # 0x8C81
("", X, 1, "GL_ACTIVE_VARYING_MAX_LENGTH_NV"), # 0x8C82
("glGetProgram", I, 1, "GL_TRANSFORM_FEEDBACK_VARYINGS"), # 0x8C83
- ("", I, 1, "GL_TRANSFORM_FEEDBACK_BUFFER_START"), # 0x8C84
- ("", I, 1, "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE"), # 0x8C85
+ ("glGet_i", I, 1, "GL_TRANSFORM_FEEDBACK_BUFFER_START"), # 0x8C84
+ ("glGet_i", I, 1, "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE"), # 0x8C85
("", X, 1, "GL_TRANSFORM_FEEDBACK_RECORD_NV"), # 0x8C86
("", X, 1, "GL_PRIMITIVES_GENERATED"), # 0x8C87
("", X, 1, "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"), # 0x8C88
@@ -2537,7 +2560,7 @@ parameters = [
("", X, 1, "GL_INTERLEAVED_ATTRIBS"), # 0x8C8C
("", X, 1, "GL_SEPARATE_ATTRIBS"), # 0x8C8D
("", X, 1, "GL_TRANSFORM_FEEDBACK_BUFFER"), # 0x8C8E
- ("glGet", I, 1, "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING"), # 0x8C8F
+ ("glGet,glGet_i", I, 1, "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING"), # 0x8C8F
("", X, 1, "GL_ATC_RGB_AMD"), # 0x8C92
("", X, 1, "GL_ATC_RGBA_EXPLICIT_ALPHA_AMD"), # 0x8C93
("glGet", E, 1, "GL_POINT_SPRITE_COORD_ORIGIN"), # 0x8CA0
@@ -2584,6 +2607,22 @@ parameters = [
("", X, 1, "GL_COLOR_ATTACHMENT13"), # 0x8CED
("", X, 1, "GL_COLOR_ATTACHMENT14"), # 0x8CEE
("", X, 1, "GL_COLOR_ATTACHMENT15"), # 0x8CEF
+ ("", X, 1, "GL_COLOR_ATTACHMENT16"), # 0x8CF0
+ ("", X, 1, "GL_COLOR_ATTACHMENT17"), # 0x8CF1
+ ("", X, 1, "GL_COLOR_ATTACHMENT18"), # 0x8CF2
+ ("", X, 1, "GL_COLOR_ATTACHMENT19"), # 0x8CF3
+ ("", X, 1, "GL_COLOR_ATTACHMENT20"), # 0x8CF4
+ ("", X, 1, "GL_COLOR_ATTACHMENT21"), # 0x8CF5
+ ("", X, 1, "GL_COLOR_ATTACHMENT22"), # 0x8CF6
+ ("", X, 1, "GL_COLOR_ATTACHMENT23"), # 0x8CF7
+ ("", X, 1, "GL_COLOR_ATTACHMENT24"), # 0x8CF8
+ ("", X, 1, "GL_COLOR_ATTACHMENT25"), # 0x8CF9
+ ("", X, 1, "GL_COLOR_ATTACHMENT26"), # 0x8CFA
+ ("", X, 1, "GL_COLOR_ATTACHMENT27"), # 0x8CFB
+ ("", X, 1, "GL_COLOR_ATTACHMENT28"), # 0x8CFC
+ ("", X, 1, "GL_COLOR_ATTACHMENT29"), # 0x8CFD
+ ("", X, 1, "GL_COLOR_ATTACHMENT30"), # 0x8CFE
+ ("", X, 1, "GL_COLOR_ATTACHMENT31"), # 0x8CFF
("", X, 1, "GL_DEPTH_ATTACHMENT"), # 0x8D00
("", X, 1, "GL_STENCIL_ATTACHMENT"), # 0x8D20
("", X, 1, "GL_FRAMEBUFFER"), # 0x8D40
@@ -2605,7 +2644,7 @@ parameters = [
("glGet", I, 1, "GL_MAX_SAMPLES"), # 0x8D57
("", X, 1, "GL_TEXTURE_GEN_STR_OES"), # 0x8D60
("", X, 1, "GL_HALF_FLOAT_OES"), # 0x8D61
- ("", X, 1, "GL_RGB565_OES"), # 0x8D62
+ ("", X, 1, "GL_RGB565"), # 0x8D62
("", X, 1, "GL_ETC1_RGB8_OES"), # 0x8D64
("", X, 1, "GL_TEXTURE_EXTERNAL_OES"), # 0x8D65
("", X, 1, "GL_SAMPLER_EXTERNAL_OES"), # 0x8D66
@@ -2663,13 +2702,13 @@ parameters = [
("", X, 1, "GL_LUMINANCE_ALPHA_INTEGER_EXT"), # 0x8D9D
("glGet", B, 1, "GL_RGBA_INTEGER_MODE_EXT"), # 0x8D9E
("", X, 1, "GL_INT_2_10_10_10_REV"), # 0x8D9F
- ("", X, 1, "GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV"), # 0x8DA0
- ("", X, 1, "GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV"), # 0x8DA1
+ ("glGetProgramARB", I, 1, "GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV"), # 0x8DA0
+ ("glGetProgramARB", I, 1, "GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV"), # 0x8DA1
("", X, 1, "GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV"), # 0x8DA2
("", X, 1, "GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV"), # 0x8DA3
("", X, 1, "GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV"), # 0x8DA4
- ("", X, 1, "GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV"), # 0x8DA5
- ("", X, 1, "GL_MAX_PROGRAM_GENERIC_RESULTS_NV"), # 0x8DA6
+ ("glGetProgramARB", I, 1, "GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV"), # 0x8DA5
+ ("glGetProgramARB", I, 1, "GL_MAX_PROGRAM_GENERIC_RESULTS_NV"), # 0x8DA6
("glGetFramebufferAttachmentParameter", B, 1, "GL_FRAMEBUFFER_ATTACHMENT_LAYERED"), # 0x8DA7
("", X, 1, "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"), # 0x8DA8
("", X, 1, "GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB"), # 0x8DA9
@@ -2719,14 +2758,14 @@ parameters = [
("glGet", I, 1, "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS"), # 0x8DDF
("glGet", I, 1, "GL_MAX_GEOMETRY_OUTPUT_VERTICES"), # 0x8DE0
("glGet", I, 1, "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS"), # 0x8DE1
- ("", X, 1, "GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT"), # 0x8DE2
- ("", X, 1, "GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT"), # 0x8DE3
- ("", X, 1, "GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT"), # 0x8DE4
- ("", X, 1, "GL_ACTIVE_SUBROUTINES"), # 0x8DE5
- ("", X, 1, "GL_ACTIVE_SUBROUTINE_UNIFORMS"), # 0x8DE6
+ ("glGet", I, 1, "GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT"), # 0x8DE2
+ ("glGet", I, 1, "GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT"), # 0x8DE3
+ ("glGet", I, 1, "GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT"), # 0x8DE4
+ ("", I, 1, "GL_ACTIVE_SUBROUTINES"), # 0x8DE5
+ ("", I, 1, "GL_ACTIVE_SUBROUTINE_UNIFORMS"), # 0x8DE6
("glGet", I, 1, "GL_MAX_SUBROUTINES"), # 0x8DE7
("glGet", I, 1, "GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS"), # 0x8DE8
- ("glGetNamedString", X, 1, "GL_NAMED_STRING_LENGTH_ARB"), # 0x8DE9
+ ("glGetNamedString", I, 1, "GL_NAMED_STRING_LENGTH_ARB"), # 0x8DE9
("glGetNamedString", E, 1, "GL_NAMED_STRING_TYPE_ARB"), # 0x8DEA
("glGet", I, 1, "GL_MAX_BINDABLE_UNIFORM_SIZE_EXT"), # 0x8DED
("", X, 1, "GL_UNIFORM_BUFFER_EXT"), # 0x8DEE
@@ -2746,12 +2785,17 @@ parameters = [
("glGet", I, 1, "GL_MAX_VARYING_VECTORS"), # 0x8DFC
("glGet", I, 1, "GL_MAX_FRAGMENT_UNIFORM_VECTORS"), # 0x8DFD
("", X, 1, "GL_RENDERBUFFER_COLOR_SAMPLES_NV"), # 0x8E10
- ("", X, 1, "GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV"), # 0x8E11
+ ("glGet", I, 1, "GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV"), # 0x8E11
("", X, 1, "GL_MULTISAMPLE_COVERAGE_MODES_NV"), # 0x8E12
("", X, 1, "GL_QUERY_WAIT"), # 0x8E13
("", X, 1, "GL_QUERY_NO_WAIT"), # 0x8E14
("", X, 1, "GL_QUERY_BY_REGION_WAIT"), # 0x8E15
("", X, 1, "GL_QUERY_BY_REGION_NO_WAIT"), # 0x8E16
+ ("", X, 1, "GL_QUERY_WAIT_INVERTED"), # 0x8E17
+ ("", X, 1, "GL_QUERY_NO_WAIT_INVERTED"), # 0x8E18
+ ("", X, 1, "GL_QUERY_BY_REGION_WAIT_INVERTED"), # 0x8E19
+ ("", X, 1, "GL_QUERY_BY_REGION_NO_WAIT_INVERTED"), # 0x8E1A
+ ("", X, 1, "GL_POLYGON_OFFSET_CLAMP_EXT"), # 0x8E1B
("glGet", I, 1, "GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS"), # 0x8E1E
("glGet", I, 1, "GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS"), # 0x8E1F
("", X, 1, "GL_COLOR_SAMPLES_NV"), # 0x8E20
@@ -2761,7 +2805,7 @@ parameters = [
("glGet", I, 1, "GL_TRANSFORM_FEEDBACK_BINDING"), # 0x8E25
("", X, 1, "GL_FRAME_NV"), # 0x8E26
("", X, 1, "GL_FIELDS_NV"), # 0x8E27
- ("", X, 1, "GL_TIMESTAMP"), # 0x8E28
+ ("_glGet", I64, 1, "GL_TIMESTAMP"), # 0x8E28
("", X, 1, "GL_NUM_FILL_STREAMS_NV"), # 0x8E29
("", X, 1, "GL_PRESENT_TIME_NV"), # 0x8E2A
("", X, 1, "GL_PRESENT_DURATION_NV"), # 0x8E2B
@@ -2774,16 +2818,16 @@ parameters = [
("glGetTexParameter", E, 1, "GL_TEXTURE_SWIZZLE_B"), # 0x8E44
("glGetTexParameter", E, 1, "GL_TEXTURE_SWIZZLE_A"), # 0x8E45
("glGetTexParameter", E, 4, "GL_TEXTURE_SWIZZLE_RGBA"), # 0x8E46
- ("", X, 1, "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"), # 0x8E47
- ("", X, 1, "GL_ACTIVE_SUBROUTINE_MAX_LENGTH"), # 0x8E48
- ("", X, 1, "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"), # 0x8E49
+ ("", I, 1, "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"), # 0x8E47
+ ("", I, 1, "GL_ACTIVE_SUBROUTINE_MAX_LENGTH"), # 0x8E48
+ ("", I, 1, "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"), # 0x8E49
("", I, 1, "GL_NUM_COMPATIBLE_SUBROUTINES"), # 0x8E4A
("", I, 1, "GL_COMPATIBLE_SUBROUTINES"), # 0x8E4B
("glGet", B, 1, "GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION"), # 0x8E4C
("", X, 1, "GL_FIRST_VERTEX_CONVENTION"), # 0x8E4D
("", X, 1, "GL_LAST_VERTEX_CONVENTION"), # 0x8E4E
("glGet", E, 1, "GL_PROVOKING_VERTEX"), # 0x8E4F
- ("glGetMultisample", I, 1, "GL_SAMPLE_POSITION"), # 0x8E50
+ ("glGetMultisample", F, 2, "GL_SAMPLE_POSITION"), # 0x8E50
("glGet", B, 1, "GL_SAMPLE_MASK"), # 0x8E51
("glGet", I, 1, "GL_SAMPLE_MASK_VALUE"), # 0x8E52
("", X, 1, "GL_TEXTURE_BINDING_RENDERBUFFER_NV"), # 0x8E53
@@ -2793,22 +2837,22 @@ parameters = [
("", X, 1, "GL_INT_SAMPLER_RENDERBUFFER_NV"), # 0x8E57
("", X, 1, "GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV"), # 0x8E58
("glGet", I, 1, "GL_MAX_SAMPLE_MASK_WORDS"), # 0x8E59
- ("", X, 1, "GL_MAX_GEOMETRY_SHADER_INVOCATIONS"), # 0x8E5A
+ ("glGet", I, 1, "GL_MAX_GEOMETRY_SHADER_INVOCATIONS"), # 0x8E5A
("glGet", F, 1, "GL_MIN_FRAGMENT_INTERPOLATION_OFFSET"), # 0x8E5B
("glGet", F, 1, "GL_MAX_FRAGMENT_INTERPOLATION_OFFSET"), # 0x8E5C
("glGet", I, 1, "GL_FRAGMENT_INTERPOLATION_OFFSET_BITS"), # 0x8E5D
- ("", X, 1, "GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET"), # 0x8E5E
- ("", X, 1, "GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET"), # 0x8E5F
+ ("glGet", I, 1, "GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET"), # 0x8E5E
+ ("glGet", I, 1, "GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET"), # 0x8E5F
("glGet", I, 1, "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS"), # 0x8E70
("glGet", I, 1, "GL_MAX_VERTEX_STREAMS"), # 0x8E71
("glGet", I, 1, "GL_PATCH_VERTICES"), # 0x8E72
("glGet", F, 2, "GL_PATCH_DEFAULT_INNER_LEVEL"), # 0x8E73
("glGet", F, 4, "GL_PATCH_DEFAULT_OUTER_LEVEL"), # 0x8E74
- ("glGet", X, 1, "GL_TESS_CONTROL_OUTPUT_VERTICES"), # 0x8E75
- ("glGet", E, 1, "GL_TESS_GEN_MODE"), # 0x8E76
- ("glGet", E, 1, "GL_TESS_GEN_SPACING"), # 0x8E77
- ("glGet", E, 1, "GL_TESS_GEN_VERTEX_ORDER"), # 0x8E78
- ("glGet", E, 1, "GL_TESS_GEN_POINT_MODE"), # 0x8E79
+ ("glGetProgram", I, 1, "GL_TESS_CONTROL_OUTPUT_VERTICES"), # 0x8E75
+ ("glGetProgram", E, 1, "GL_TESS_GEN_MODE"), # 0x8E76
+ ("glGetProgram", E, 1, "GL_TESS_GEN_SPACING"), # 0x8E77
+ ("glGetProgram", E, 1, "GL_TESS_GEN_VERTEX_ORDER"), # 0x8E78
+ ("glGetProgram", E, 1, "GL_TESS_GEN_POINT_MODE"), # 0x8E79
("", X, 1, "GL_ISOLINES"), # 0x8E7A
("", X, 1, "GL_FRACTIONAL_ODD"), # 0x8E7B
("", X, 1, "GL_FRACTIONAL_EVEN"), # 0x8E7C
@@ -2826,10 +2870,10 @@ parameters = [
("glGetProgramPipeline", I, 1, "GL_TESS_CONTROL_SHADER"), # 0x8E88
("glGet", I, 1, "GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS"), # 0x8E89
("glGet", I, 1, "GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS"), # 0x8E8A
- ("", X, 1, "GL_COMPRESSED_RGBA_BPTC_UNORM_ARB"), # 0x8E8C
- ("", X, 1, "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB"), # 0x8E8D
- ("", X, 1, "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB"), # 0x8E8E
- ("", X, 1, "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB"), # 0x8E8F
+ ("", X, 1, "GL_COMPRESSED_RGBA_BPTC_UNORM"), # 0x8E8C
+ ("", X, 1, "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM"), # 0x8E8D
+ ("", X, 1, "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT"), # 0x8E8E
+ ("", X, 1, "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT"), # 0x8E8F
#("", X, 1, "GL_COVERAGE_COMPONENT_NV"), # 0x8ED0
#("", X, 1, "GL_COVERAGE_COMPONENT4_NV"), # 0x8ED1
#("", X, 1, "GL_COVERAGE_ATTACHMENT_NV"), # 0x8ED2
@@ -2838,7 +2882,7 @@ parameters = [
#("", X, 1, "GL_COVERAGE_ALL_FRAGMENTS_NV"), # 0x8ED5
#("", X, 1, "GL_COVERAGE_EDGE_FRAGMENTS_NV"), # 0x8ED6
#("", X, 1, "GL_COVERAGE_AUTOMATIC_NV"), # 0x8ED7
- ("GetBufferParameter", I64, 1, "GL_BUFFER_GPU_ADDRESS_NV"), # 0x8F1D
+ ("_glGetBufferParameter", I64, 1, "GL_BUFFER_GPU_ADDRESS_NV"), # 0x8F1D
("", X, 1, "GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV"), # 0x8F1E
("", X, 1, "GL_ELEMENT_ARRAY_UNIFIED_NV"), # 0x8F1F
("", X, 1, "GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV"), # 0x8F20
@@ -2862,7 +2906,7 @@ parameters = [
("", X, 1, "GL_FOG_COORD_ARRAY_LENGTH_NV"), # 0x8F32
("", X, 1, "GL_ELEMENT_ARRAY_LENGTH_NV"), # 0x8F33
("", X, 1, "GL_GPU_ADDRESS_NV"), # 0x8F34
- ("", X, 1, "GL_MAX_SHADER_BUFFER_ADDRESS_NV"), # 0x8F35
+ ("_glGet", I64, 1, "GL_MAX_SHADER_BUFFER_ADDRESS_NV"), # 0x8F35
("glGet", I, 1, "GL_COPY_READ_BUFFER"), # 0x8F36
("glGet", I, 1, "GL_COPY_WRITE_BUFFER"), # 0x8F37
("glGet", I, 1, "GL_MAX_IMAGE_UNITS"), # 0x8F38
@@ -2888,7 +2932,14 @@ parameters = [
("", X, 1, "GL_DOUBLE_MAT3x4"), # 0x8F4C
("", X, 1, "GL_DOUBLE_MAT4x2"), # 0x8F4D
("", X, 1, "GL_DOUBLE_MAT4x3"), # 0x8F4E
+ ("", X, 1, "GL_VERTEX_BINDING_BUFFER"), # 0x8F4F
("", X, 1, "GL_MALI_SHADER_BINARY_ARM"), # 0x8F60
+ ("", X, 1, "GL_MALI_PROGRAM_BINARY_ARM"), # 0x8F61
+ ("", X, 1, "GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT"), # 0x8F63
+ ("", X, 1, "GL_SHADER_PIXEL_LOCAL_STORAGE_EXT"), # 0x8F64
+ ("", X, 1, "GL_FETCH_PER_SAMPLE_ARM"), # 0x8F65
+ ("", X, 1, "GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM"), # 0x8F66
+ ("", X, 1, "GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT"), # 0x8F67
("", X, 1, "GL_RED_SNORM"), # 0x8F90
("", X, 1, "GL_RG_SNORM"), # 0x8F91
("", X, 1, "GL_RGB_SNORM"), # 0x8F92
@@ -2904,13 +2955,15 @@ parameters = [
("", X, 1, "GL_SIGNED_NORMALIZED"), # 0x8F9C
("glGet", B, 1, "GL_PRIMITIVE_RESTART"), # 0x8F9D
("glGet", I, 1, "GL_PRIMITIVE_RESTART_INDEX"), # 0x8F9E
- ("", X, 1, "GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB"), # 0x8F9F
+ ("glGet", I, 1, "GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB"), # 0x8F9F
("", X, 1, "GL_PERFMON_GLOBAL_MODE_QCOM"), # 0x8FA0
("", X, 1, "GL_BINNING_CONTROL_HINT_QCOM"), # 0x8FB0
("", X, 1, "GL_CPU_OPTIMIZED_QCOM"), # 0x8FB1
("", X, 1, "GL_GPU_OPTIMIZED_QCOM"), # 0x8FB2
("", X, 1, "GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM"), # 0x8FB3
("", X, 1, "GL_GPU_DISJOINT_EXT"), # 0x8FBB
+ ("", X, 1, "GL_SR8_EXT"), # 0x8FBD
+ ("", X, 1, "GL_SRG8_EXT"), # 0x8FBE
("", X, 1, "GL_SHADER_BINARY_VIV"), # 0x8FC4
("", X, 1, "GL_INT8_NV"), # 0x8FE0
("", X, 1, "GL_INT8_VEC2_NV"), # 0x8FE1
@@ -2920,9 +2973,9 @@ parameters = [
("", X, 1, "GL_INT16_VEC2_NV"), # 0x8FE5
("", X, 1, "GL_INT16_VEC3_NV"), # 0x8FE6
("", X, 1, "GL_INT16_VEC4_NV"), # 0x8FE7
- ("", X, 1, "GL_INT64_VEC2_NV"), # 0x8FE9
- ("", X, 1, "GL_INT64_VEC3_NV"), # 0x8FEA
- ("", X, 1, "GL_INT64_VEC4_NV"), # 0x8FEB
+ ("", X, 1, "GL_INT64_VEC2_ARB"), # 0x8FE9
+ ("", X, 1, "GL_INT64_VEC3_ARB"), # 0x8FEA
+ ("", X, 1, "GL_INT64_VEC4_ARB"), # 0x8FEB
("", X, 1, "GL_UNSIGNED_INT8_NV"), # 0x8FEC
("", X, 1, "GL_UNSIGNED_INT8_VEC2_NV"), # 0x8FED
("", X, 1, "GL_UNSIGNED_INT8_VEC3_NV"), # 0x8FEE
@@ -2931,9 +2984,9 @@ parameters = [
("", X, 1, "GL_UNSIGNED_INT16_VEC2_NV"), # 0x8FF1
("", X, 1, "GL_UNSIGNED_INT16_VEC3_NV"), # 0x8FF2
("", X, 1, "GL_UNSIGNED_INT16_VEC4_NV"), # 0x8FF3
- ("", X, 1, "GL_UNSIGNED_INT64_VEC2_NV"), # 0x8FF5
- ("", X, 1, "GL_UNSIGNED_INT64_VEC3_NV"), # 0x8FF6
- ("", X, 1, "GL_UNSIGNED_INT64_VEC4_NV"), # 0x8FF7
+ ("", X, 1, "GL_UNSIGNED_INT64_VEC2_ARB"), # 0x8FF5
+ ("", X, 1, "GL_UNSIGNED_INT64_VEC3_ARB"), # 0x8FF6
+ ("", X, 1, "GL_UNSIGNED_INT64_VEC4_ARB"), # 0x8FF7
("", X, 1, "GL_FLOAT16_NV"), # 0x8FF8
("", X, 1, "GL_FLOAT16_VEC2_NV"), # 0x8FF9
("", X, 1, "GL_FLOAT16_VEC3_NV"), # 0x8FFA
@@ -2948,7 +3001,7 @@ parameters = [
("", X, 1, "GL_TESSELLATION_FACTOR_AMD"), # 0x9005
("", X, 1, "GL_DISCRETE_AMD"), # 0x9006
("", X, 1, "GL_CONTINUOUS_AMD"), # 0x9007
- ("glGet_texture", B, 1, "GL_TEXTURE_CUBE_MAP_ARRAY"), # 0x9009
+ ("", B, 1, "GL_TEXTURE_CUBE_MAP_ARRAY"), # 0x9009
("glGet_texture", I, 1, "GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"), # 0x900A
("", X, 1, "GL_PROXY_TEXTURE_CUBE_MAP_ARRAY"), # 0x900B
("", X, 1, "GL_SAMPLER_CUBE_MAP_ARRAY"), # 0x900C
@@ -3118,7 +3171,7 @@ parameters = [
("", X, 1, "GL_PATH_STENCIL_VALUE_MASK_NV"), # 0x90B9
("", X, 1, "GL_SCALED_RESOLVE_FASTEST_EXT"), # 0x90BA
("", X, 1, "GL_SCALED_RESOLVE_NICEST_EXT"), # 0x90BB
- ("", X, 1, "GL_MIN_MAP_BUFFER_ALIGNMENT"), # 0x90BC
+ ("glGet", I, 1, "GL_MIN_MAP_BUFFER_ALIGNMENT"), # 0x90BC
("", X, 1, "GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV"), # 0x90BD
("", X, 1, "GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV"), # 0x90BE
("", X, 1, "GL_PATH_COVER_DEPTH_FUNC_NV"), # 0x90BF
@@ -3134,9 +3187,9 @@ parameters = [
("", X, 1, "GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV"), # 0x90D0
("", X, 1, "GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV"), # 0x90D1
("", I, 1, "GL_SHADER_STORAGE_BUFFER"), # 0x90D2
- ("", I, 1, "GL_SHADER_STORAGE_BUFFER_BINDING"), # 0x90D3
- ("", I, 1, "GL_SHADER_STORAGE_BUFFER_START"), # 0x90D4
- ("", I, 1, "GL_SHADER_STORAGE_BUFFER_SIZE"), # 0x90D5
+ ("glGet,glGet_i", I, 1, "GL_SHADER_STORAGE_BUFFER_BINDING"), # 0x90D3
+ ("glGet_i", I, 1, "GL_SHADER_STORAGE_BUFFER_START"), # 0x90D4
+ ("glGet_i", I, 1, "GL_SHADER_STORAGE_BUFFER_SIZE"), # 0x90D5
("", I, 1, "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS"), # 0x90D6
("", I, 1, "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS"), # 0x90D7
("", I, 1, "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS"), # 0x90D8
@@ -3157,7 +3210,7 @@ parameters = [
("", X, 1, "GL_COLOR_ATTACHMENT_EXT"), # 0x90F0
("", X, 1, "GL_MULTIVIEW_EXT"), # 0x90F1
("", X, 1, "GL_MAX_MULTIVIEW_BUFFERS_EXT"), # 0x90F2
- ("", X, 1, "GL_CONTEXT_ROBUST_ACCESS_EXT"), # 0x90F3
+ ("", X, 1, "GL_CONTEXT_ROBUST_ACCESS"), # 0x90F3
("", X, 1, "GL_COMPUTE_PROGRAM_NV"), # 0x90FB
("", X, 1, "GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV"), # 0x90FC
("", X, 1, "GL_TEXTURE_2D_MULTISAMPLE"), # 0x9100
@@ -3214,6 +3267,13 @@ parameters = [
("", I, 1, "GL_TEXTURE_SAMPLES_IMG"), # 0x9136
("", X, 1, "GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG"), # 0x9137
("", X, 1, "GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG"), # 0x9138
+ ("", X, 1, "GL_CUBIC_IMG"), # 0x9139
+ ("", X, 1, "GL_CUBIC_MIPMAP_NEAREST_IMG"), # 0x913A
+ ("", X, 1, "GL_CUBIC_MIPMAP_LINEAR_IMG"), # 0x913B
+ ("", X, 1, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG"), # 0x913C
+ ("", X, 1, "GL_NUM_DOWNSAMPLE_SCALES_IMG"), # 0x913D
+ ("", X, 1, "GL_DOWNSAMPLE_SCALES_IMG"), # 0x913E
+ ("", X, 1, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG"), # 0x913F
("glGet", I, 1, "GL_MAX_DEBUG_MESSAGE_LENGTH"), # 0x9143
("glGet", I, 1, "GL_MAX_DEBUG_LOGGED_MESSAGES"), # 0x9144
("glGet", I, 1, "GL_DEBUG_LOGGED_MESSAGES"), # 0x9145
@@ -3235,25 +3295,29 @@ parameters = [
("", X, 1, "GL_SAMPLER_OBJECT_AMD"), # 0x9155
("", X, 1, "GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD"), # 0x9160
("", X, 1, "GL_QUERY_BUFFER"), # 0x9192
- ("", X, 1, "GL_QUERY_BUFFER_BINDING"), # 0x9193
- ("", X, 1, "GL_QUERY_RESULT_NO_WAIT"), # 0x9194
- ("", X, 1, "GL_VIRTUAL_PAGE_SIZE_X_AMD"), # 0x9195
- ("", X, 1, "GL_VIRTUAL_PAGE_SIZE_Y_AMD"), # 0x9196
- ("", X, 1, "GL_VIRTUAL_PAGE_SIZE_Z_AMD"), # 0x9197
- ("", X, 1, "GL_MAX_SPARSE_TEXTURE_SIZE_AMD"), # 0x9198
- ("", X, 1, "GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD"), # 0x9199
- ("", X, 1, "GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS"), # 0x919A
+ ("glGet", I, 1, "GL_QUERY_BUFFER_BINDING"), # 0x9193
+ ("glGetQueryObject", I, 1, "GL_QUERY_RESULT_NO_WAIT"), # 0x9194
+ ("", X, 1, "GL_VIRTUAL_PAGE_SIZE_X_ARB"), # 0x9195
+ ("", X, 1, "GL_VIRTUAL_PAGE_SIZE_Y_ARB"), # 0x9196
+ ("", X, 1, "GL_VIRTUAL_PAGE_SIZE_Z_ARB"), # 0x9197
+ ("glGet", I, 1, "GL_MAX_SPARSE_TEXTURE_SIZE_ARB"), # 0x9198
+ ("glGet", I, 1, "GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB"), # 0x9199
+ ("glGet", I, 1, "GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS"), # 0x919A
("", X, 1, "GL_MIN_SPARSE_LEVEL_AMD"), # 0x919B
("", X, 1, "GL_MIN_LOD_WARNING_AMD"), # 0x919C
("glGetTexLevelParameter", I, 1, "GL_TEXTURE_BUFFER_OFFSET"), # 0x919D
("glGetTexLevelParameter", I, 1, "GL_TEXTURE_BUFFER_SIZE"), # 0x919E
("glGet", I, 1, "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT"), # 0x919F
+ ("", X, 1, "GL_STREAM_RASTERIZATION_AMD"), # 0x91A0
("", X, 1, "GL_VERTEX_ELEMENT_SWIZZLE_AMD"), # 0x91A4
("", X, 1, "GL_VERTEX_ID_SWIZZLE_AMD"), # 0x91A5
("", X, 1, "GL_TEXTURE_SPARSE_ARB"), # 0x91A6
("", X, 1, "GL_VIRTUAL_PAGE_SIZE_INDEX_ARB"), # 0x91A7
("", X, 1, "GL_NUM_VIRTUAL_PAGE_SIZES_ARB"), # 0x91A8
- ("", X, 1, "GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB"), # 0x91A9
+ ("glGet", B, 1, "GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB"), # 0x91A9
+ ("", X, 1, "GL_NUM_SPARSE_LEVELS_ARB"), # 0x91AA
+ ("glGet", I, 1, "GL_MAX_SHADER_COMPILER_THREADS_ARB"), # 0x91B0
+ ("glGetProgram,glGetShader", B, 1, "GL_COMPLETION_STATUS_ARB"), # 0x91B1
("glGetProgramPipeline", I, 1, "GL_COMPUTE_SHADER"), # 0x91B9
("glGet", I, 1, "GL_MAX_COMPUTE_UNIFORM_BLOCKS"), # 0x91BB
("glGet", I, 1, "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"), # 0x91BC
@@ -3266,6 +3330,9 @@ parameters = [
#("", X, 1, "GL_UNPACK_COLORSPACE_CONVERSION_WEBGL"), # 0x9243
#("", X, 1, "GL_BROWSER_DEFAULT_WEBGL"), # 0x9244
("", X, 1, "GL_SHADER_BINARY_DMP"), # 0x9250
+ ("", X, 1, "GL_SMAPHS30_PROGRAM_BINARY_DMP"), # 0x9251
+ ("", X, 1, "GL_SMAPHS_PROGRAM_BINARY_DMP"), # 0x9252
+ ("", X, 1, "GL_DMP_PROGRAM_BINARY_DMP"), # 0x9253
#("", X, 1, "GL_GCCSO_SHADER_BINARY_FJ"), # 0x9260
("", X, 1, "GL_COMPRESSED_R11_EAC"), # 0x9270
("", X, 1, "GL_COMPRESSED_SIGNED_R11_EAC"), # 0x9271
@@ -3282,7 +3349,7 @@ parameters = [
("", X, 1, "GL_UNCORRELATED_NV"), # 0x9282
("", X, 1, "GL_DISJOINT_NV"), # 0x9283
("", X, 1, "GL_CONJOINT_NV"), # 0x9284
- ("", X, 1, "GL_BLEND_ADVANCED_COHERENT_NV"), # 0x9285
+ ("", X, 1, "GL_BLEND_ADVANCED_COHERENT_KHR"), # 0x9285
("", X, 1, "GL_SRC_NV"), # 0x9286
("", X, 1, "GL_DST_NV"), # 0x9287
("", X, 1, "GL_SRC_OVER_NV"), # 0x9288
@@ -3295,18 +3362,18 @@ parameters = [
("", X, 1, "GL_DST_ATOP_NV"), # 0x928F
("", X, 1, "GL_PLUS_NV"), # 0x9291
("", X, 1, "GL_PLUS_DARKER_NV"), # 0x9292
- ("", X, 1, "GL_MULTIPLY_NV"), # 0x9294
- ("", X, 1, "GL_SCREEN_NV"), # 0x9295
- ("", X, 1, "GL_OVERLAY_NV"), # 0x9296
- ("", X, 1, "GL_DARKEN_NV"), # 0x9297
- ("", X, 1, "GL_LIGHTEN_NV"), # 0x9298
- ("", X, 1, "GL_COLORDODGE_NV"), # 0x9299
- ("", X, 1, "GL_COLORBURN_NV"), # 0x929A
- ("", X, 1, "GL_HARDLIGHT_NV"), # 0x929B
- ("", X, 1, "GL_SOFTLIGHT_NV"), # 0x929C
- ("", X, 1, "GL_DIFFERENCE_NV"), # 0x929E
+ ("", X, 1, "GL_MULTIPLY_KHR"), # 0x9294
+ ("", X, 1, "GL_SCREEN_KHR"), # 0x9295
+ ("", X, 1, "GL_OVERLAY_KHR"), # 0x9296
+ ("", X, 1, "GL_DARKEN_KHR"), # 0x9297
+ ("", X, 1, "GL_LIGHTEN_KHR"), # 0x9298
+ ("", X, 1, "GL_COLORDODGE_KHR"), # 0x9299
+ ("", X, 1, "GL_COLORBURN_KHR"), # 0x929A
+ ("", X, 1, "GL_HARDLIGHT_KHR"), # 0x929B
+ ("", X, 1, "GL_SOFTLIGHT_KHR"), # 0x929C
+ ("", X, 1, "GL_DIFFERENCE_KHR"), # 0x929E
("", X, 1, "GL_MINUS_NV"), # 0x929F
- ("", X, 1, "GL_EXCLUSION_NV"), # 0x92A0
+ ("", X, 1, "GL_EXCLUSION_KHR"), # 0x92A0
("", X, 1, "GL_CONTRAST_NV"), # 0x92A1
("", X, 1, "GL_INVERT_RGB_NV"), # 0x92A3
("", X, 1, "GL_LINEARDODGE_NV"), # 0x92A4
@@ -3315,18 +3382,20 @@ parameters = [
("", X, 1, "GL_LINEARLIGHT_NV"), # 0x92A7
("", X, 1, "GL_PINLIGHT_NV"), # 0x92A8
("", X, 1, "GL_HARDMIX_NV"), # 0x92A9
- ("", X, 1, "GL_HSL_HUE_NV"), # 0x92AD
- ("", X, 1, "GL_HSL_SATURATION_NV"), # 0x92AE
- ("", X, 1, "GL_HSL_COLOR_NV"), # 0x92AF
- ("", X, 1, "GL_HSL_LUMINOSITY_NV"), # 0x92B0
+ ("", X, 1, "GL_HSL_HUE_KHR"), # 0x92AD
+ ("", X, 1, "GL_HSL_SATURATION_KHR"), # 0x92AE
+ ("", X, 1, "GL_HSL_COLOR_KHR"), # 0x92AF
+ ("", X, 1, "GL_HSL_LUMINOSITY_KHR"), # 0x92B0
("", X, 1, "GL_PLUS_CLAMPED_NV"), # 0x92B1
("", X, 1, "GL_PLUS_CLAMPED_ALPHA_NV"), # 0x92B2
("", X, 1, "GL_MINUS_CLAMPED_NV"), # 0x92B3
("", X, 1, "GL_INVERT_OVG_NV"), # 0x92B4
+ ("glGet", F, 8, "GL_PRIMITIVE_BOUNDING_BOX_EXT"), # 0x92BE
("", X, 1, "GL_ATOMIC_COUNTER_BUFFER"), # 0x92C0
- ("", X, 1, "GL_ATOMIC_COUNTER_BUFFER_BINDING"), # 0x92C1
- ("", X, 1, "GL_ATOMIC_COUNTER_BUFFER_START"), # 0x92C2
- ("", X, 1, "GL_ATOMIC_COUNTER_BUFFER_SIZE"), # 0x92C3
+ # FIXME: Causes Mesa to segfault (issue #332). Disable for now.
+ ("_glGet,_glGet_i", I, 1, "GL_ATOMIC_COUNTER_BUFFER_BINDING"), # 0x92C1
+ ("glGet_i", I, 1, "GL_ATOMIC_COUNTER_BUFFER_START"), # 0x92C2
+ ("glGet_i", I, 1, "GL_ATOMIC_COUNTER_BUFFER_SIZE"), # 0x92C3
("", X, 1, "GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE"), # 0x92C4
("", X, 1, "GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS"), # 0x92C5
("", X, 1, "GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES"), # 0x92C6
@@ -3341,17 +3410,19 @@ parameters = [
("glGet", I, 1, "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS"), # 0x92CF
("glGet", I, 1, "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS"), # 0x92D0
("glGet", I, 1, "GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS"), # 0x92D1
- ("", X, 1, "GL_MAX_VERTEX_ATOMIC_COUNTERS"), # 0x92D2
- ("", X, 1, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"), # 0x92D3
- ("", X, 1, "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"), # 0x92D4
- ("", X, 1, "GL_MAX_GEOMETRY_ATOMIC_COUNTERS"), # 0x92D5
- ("", X, 1, "GL_MAX_FRAGMENT_ATOMIC_COUNTERS"), # 0x92D6
- ("", X, 1, "GL_MAX_COMBINED_ATOMIC_COUNTERS"), # 0x92D7
- ("", X, 1, "GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE"), # 0x92D8
- ("", X, 1, "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS"), # 0x92D9
+ ("glGet", I, 1, "GL_MAX_VERTEX_ATOMIC_COUNTERS"), # 0x92D2
+ ("glGet", I, 1, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"), # 0x92D3
+ ("glGet", I, 1, "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"), # 0x92D4
+ ("glGet", I, 1, "GL_MAX_GEOMETRY_ATOMIC_COUNTERS"), # 0x92D5
+ ("glGet", I, 1, "GL_MAX_FRAGMENT_ATOMIC_COUNTERS"), # 0x92D6
+ ("glGet", I, 1, "GL_MAX_COMBINED_ATOMIC_COUNTERS"), # 0x92D7
+ ("glGet", I, 1, "GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE"), # 0x92D8
+ ("glGetProgram", I, 1, "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS"), # 0x92D9
("", X, 1, "GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX"), # 0x92DA
("", X, 1, "GL_UNSIGNED_INT_ATOMIC_COUNTER"), # 0x92DB
- ("", X, 1, "GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS"), # 0x92DC
+ ("glGet", I, 1, "GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS"), # 0x92DC
+ ("", X, 1, "GL_FRAGMENT_COVERAGE_TO_COLOR_NV"), # 0x92DD
+ ("", X, 1, "GL_FRAGMENT_COVERAGE_COLOR_NV"), # 0x92DE
("glGet", B, 1, "GL_DEBUG_OUTPUT"), # 0x92E0
("", X, 1, "GL_UNIFORM"), # 0x92E1
("", X, 1, "GL_UNIFORM_BLOCK"), # 0x92E2
@@ -3373,49 +3444,101 @@ parameters = [
("", X, 1, "GL_FRAGMENT_SUBROUTINE_UNIFORM"), # 0x92F2
("", X, 1, "GL_COMPUTE_SUBROUTINE_UNIFORM"), # 0x92F3
("", X, 1, "GL_TRANSFORM_FEEDBACK_VARYING"), # 0x92F4
- ("", I, 1, "GL_ACTIVE_RESOURCES"), # 0x92F5
- ("", I, 1, "GL_MAX_NAME_LENGTH"), # 0x92F6
- ("", I, 1, "GL_MAX_NUM_ACTIVE_VARIABLES"), # 0x92F7
- ("", I, 1, "GL_MAX_NUM_COMPATIBLE_SUBROUTINES"), # 0x92F8
- ("", I, 1, "GL_NAME_LENGTH"), # 0x92F9
- ("", I, 1, "GL_TYPE"), # 0x92FA
- ("", I, 1, "GL_ARRAY_SIZE"), # 0x92FB
- ("", I, 1, "GL_OFFSET"), # 0x92FC
- ("", I, 1, "GL_BLOCK_INDEX"), # 0x92FD
- ("", I, 1, "GL_ARRAY_STRIDE"), # 0x92FE
- ("", I, 1, "GL_MATRIX_STRIDE"), # 0x92FF
- ("", I, 1, "GL_IS_ROW_MAJOR"), # 0x9300
- ("", I, 1, "GL_ATOMIC_COUNTER_BUFFER_INDEX"), # 0x9301
- ("", I, 1, "GL_BUFFER_BINDING"), # 0x9302
- ("", I, 1, "GL_BUFFER_DATA_SIZE"), # 0x9303
- ("", I, 1, "GL_NUM_ACTIVE_VARIABLES"), # 0x9304
- ("", I, 1, "GL_ACTIVE_VARIABLES"), # 0x9305
- ("", I, 1, "GL_REFERENCED_BY_VERTEX_SHADER"), # 0x9306
- ("", I, 1, "GL_REFERENCED_BY_TESS_CONTROL_SHADER"), # 0x9307
- ("", I, 1, "GL_REFERENCED_BY_TESS_EVALUATION_SHADER"), # 0x9308
- ("", I, 1, "GL_REFERENCED_BY_GEOMETRY_SHADER"), # 0x9309
- ("", I, 1, "GL_REFERENCED_BY_FRAGMENT_SHADER"), # 0x930A
- ("", I, 1, "GL_REFERENCED_BY_COMPUTE_SHADER"), # 0x930B
- ("", I, 1, "GL_TOP_LEVEL_ARRAY_SIZE"), # 0x930C
- ("", I, 1, "GL_TOP_LEVEL_ARRAY_STRIDE"), # 0x930D
- ("", I, 1, "GL_LOCATION"), # 0x930E
- ("", I, 1, "GL_LOCATION_INDEX"), # 0x930F
- ("", I, 1, "GL_FRAMEBUFFER_DEFAULT_WIDTH"), # 0x9310
- ("", I, 1, "GL_FRAMEBUFFER_DEFAULT_HEIGHT"), # 0x9311
- ("", I, 1, "GL_FRAMEBUFFER_DEFAULT_LAYERS"), # 0x9312
- ("", I, 1, "GL_FRAMEBUFFER_DEFAULT_SAMPLES"), # 0x9313
- ("", B, 1, "GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"), # 0x9314
- ("glGet", I, 1, "GL_MAX_FRAMEBUFFER_WIDTH"), # 0x9315
- ("glGet", I, 1, "GL_MAX_FRAMEBUFFER_HEIGHT"), # 0x9316
- ("glGet", I, 1, "GL_MAX_FRAMEBUFFER_LAYERS"), # 0x9317
- ("glGet", I, 1, "GL_MAX_FRAMEBUFFER_SAMPLES"), # 0x9318
- ("", X, 1, "GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB"), # 0x9344
- ("", X, 1, "GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB"), # 0x9345
- ("", X, 1, "GL_LOCATION_COMPONENT"), # 0x934A
+ ("", X, 1, "GL_ACTIVE_RESOURCES"), # 0x92F5
+ ("", X, 1, "GL_MAX_NAME_LENGTH"), # 0x92F6
+ ("", X, 1, "GL_MAX_NUM_ACTIVE_VARIABLES"), # 0x92F7
+ ("", X, 1, "GL_MAX_NUM_COMPATIBLE_SUBROUTINES"), # 0x92F8
+ ("", X, 1, "GL_NAME_LENGTH"), # 0x92F9
+ ("", X, 1, "GL_TYPE"), # 0x92FA
+ ("", X, 1, "GL_ARRAY_SIZE"), # 0x92FB
+ ("", X, 1, "GL_OFFSET"), # 0x92FC
+ ("", X, 1, "GL_BLOCK_INDEX"), # 0x92FD
+ ("", X, 1, "GL_ARRAY_STRIDE"), # 0x92FE
+ ("", X, 1, "GL_MATRIX_STRIDE"), # 0x92FF
+ ("", X, 1, "GL_IS_ROW_MAJOR"), # 0x9300
+ ("", X, 1, "GL_ATOMIC_COUNTER_BUFFER_INDEX"), # 0x9301
+ ("", X, 1, "GL_BUFFER_BINDING"), # 0x9302
+ ("", X, 1, "GL_BUFFER_DATA_SIZE"), # 0x9303
+ ("", X, 1, "GL_NUM_ACTIVE_VARIABLES"), # 0x9304
+ ("", X, 1, "GL_ACTIVE_VARIABLES"), # 0x9305
+ ("", X, 1, "GL_REFERENCED_BY_VERTEX_SHADER"), # 0x9306
+ ("", X, 1, "GL_REFERENCED_BY_TESS_CONTROL_SHADER"), # 0x9307
+ ("", X, 1, "GL_REFERENCED_BY_TESS_EVALUATION_SHADER"), # 0x9308
+ ("", X, 1, "GL_REFERENCED_BY_GEOMETRY_SHADER"), # 0x9309
+ ("", X, 1, "GL_REFERENCED_BY_FRAGMENT_SHADER"), # 0x930A
+ ("", X, 1, "GL_REFERENCED_BY_COMPUTE_SHADER"), # 0x930B
+ ("", X, 1, "GL_TOP_LEVEL_ARRAY_SIZE"), # 0x930C
+ ("", X, 1, "GL_TOP_LEVEL_ARRAY_STRIDE"), # 0x930D
+ ("", X, 1, "GL_LOCATION"), # 0x930E
+ ("", X, 1, "GL_LOCATION_INDEX"), # 0x930F
+ ("", X, 1, "GL_FRAMEBUFFER_DEFAULT_WIDTH"), # 0x9310
+ ("", X, 1, "GL_FRAMEBUFFER_DEFAULT_HEIGHT"), # 0x9311
+ ("", X, 1, "GL_FRAMEBUFFER_DEFAULT_LAYERS"), # 0x9312
+ ("", X, 1, "GL_FRAMEBUFFER_DEFAULT_SAMPLES"), # 0x9313
+ ("", X, 1, "GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"), # 0x9314
+ ("", X, 1, "GL_MAX_FRAMEBUFFER_WIDTH"), # 0x9315
+ ("", X, 1, "GL_MAX_FRAMEBUFFER_HEIGHT"), # 0x9316
+ ("", X, 1, "GL_MAX_FRAMEBUFFER_LAYERS"), # 0x9317
+ ("", X, 1, "GL_MAX_FRAMEBUFFER_SAMPLES"), # 0x9318
+ ("", X, 1, "GL_RASTER_MULTISAMPLE_EXT"), # 0x9327
+ ("", X, 1, "GL_RASTER_SAMPLES_EXT"), # 0x9328
+ ("", X, 1, "GL_MAX_RASTER_SAMPLES_EXT"), # 0x9329
+ ("", X, 1, "GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT"), # 0x932A
+ ("", X, 1, "GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT"), # 0x932B
+ ("", X, 1, "GL_EFFECTIVE_RASTER_SAMPLES_EXT"), # 0x932C
+ ("", X, 1, "GL_DEPTH_SAMPLES_NV"), # 0x932D
+ ("", X, 1, "GL_STENCIL_SAMPLES_NV"), # 0x932E
+ ("", X, 1, "GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV"), # 0x932F
+ ("", X, 1, "GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV"), # 0x9330
+ ("", X, 1, "GL_COVERAGE_MODULATION_TABLE_NV"), # 0x9331
+ ("", X, 1, "GL_COVERAGE_MODULATION_NV"), # 0x9332
+ ("", X, 1, "GL_COVERAGE_MODULATION_TABLE_SIZE_NV"), # 0x9333
+ ("", X, 1, "GL_WARP_SIZE_NV"), # 0x9339
+ ("", X, 1, "GL_WARPS_PER_SM_NV"), # 0x933A
+ ("", X, 1, "GL_SM_COUNT_NV"), # 0x933B
+ ("", X, 1, "GL_FILL_RECTANGLE_NV"), # 0x933C
+ ("glGet", I, 1, "GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB"), # 0x933D
+ ("glGet", I, 1, "GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB"), # 0x933E
+ ("glGet", I, 1, "GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB"), # 0x933F
+ ("", X, 1, "GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB"), # 0x9340
+ ("glGetMultisample", F, 2, "GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB"), # 0x9341
+ ("glGetFramebufferParameter", B, 1, "GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB"), # 0x9342
+ ("glGetFramebufferParameter", B, 1, "GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB"), # 0x9343
+ ("glGet", I, 1, "GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB"), # 0x9344
+ ("glGet", I, 1, "GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB"), # 0x9345
+ ("", X, 1, "GL_CONSERVATIVE_RASTERIZATION_NV"), # 0x9346
+ ("", X, 1, "GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV"), # 0x9347
+ ("", X, 1, "GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV"), # 0x9348
+ ("", X, 1, "GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV"), # 0x9349
+ ("", X, 1, "GL_LOCATION_COMPONENT"), # 0x934A
("", X, 1, "GL_TRANSFORM_FEEDBACK_BUFFER_INDEX"), # 0x934B
("", X, 1, "GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE"), # 0x934C
- ("", X, 1, "GL_CLEAR_TEXTURE"), # 0x9365
+ ("glGet", E, 1, "GL_CLIP_ORIGIN"), # 0x935C
+ ("glGet", E, 1, "GL_CLIP_DEPTH_MODE"), # 0x935D
+ ("", X, 1, "GL_NEGATIVE_ONE_TO_ONE"), # 0x935E
+ ("", X, 1, "GL_ZERO_TO_ONE"), # 0x935F
+ ("", X, 1, "GL_CLEAR_TEXTURE"), # 0x9365
+ ("glGetTexParameter", E, 1, "GL_TEXTURE_REDUCTION_MODE_ARB"), # 0x9366
+ ("", X, 1, "GL_WEIGHTED_AVERAGE_ARB"), # 0x9367
+ ("", X, 1, "GL_FONT_GLYPHS_AVAILABLE_NV"), # 0x9368
+ ("", X, 1, "GL_FONT_TARGET_UNAVAILABLE_NV"), # 0x9369
+ ("", X, 1, "GL_FONT_UNAVAILABLE_NV"), # 0x936A
+ ("", X, 1, "GL_FONT_UNINTELLIGIBLE_NV"), # 0x936B
+ ("", X, 1, "GL_STANDARD_FONT_FORMAT_NV"), # 0x936C
+ ("", X, 1, "GL_FRAGMENT_INPUT_NV"), # 0x936D
+ ("", X, 1, "GL_UNIFORM_BUFFER_UNIFIED_NV"), # 0x936E
+ ("", X, 1, "GL_UNIFORM_BUFFER_ADDRESS_NV"), # 0x936F
+ ("", X, 1, "GL_UNIFORM_BUFFER_LENGTH_NV"), # 0x9370
+ ("", X, 1, "GL_MULTISAMPLES_NV"), # 0x9371
+ ("", X, 1, "GL_SUPERSAMPLE_SCALE_X_NV"), # 0x9372
+ ("", X, 1, "GL_SUPERSAMPLE_SCALE_Y_NV"), # 0x9373
+ ("", X, 1, "GL_CONFORMANT_NV"), # 0x9374
+ ("", X, 1, "GL_CONSERVATIVE_RASTER_DILATE_NV"), # 0x9379
+ ("", X, 1, "GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV"), # 0x937A
+ ("", X, 1, "GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV"), # 0x937B
("", X, 1, "GL_NUM_SAMPLE_COUNTS"), # 0x9380
+ ("glGet", F, 2, "GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB"), # 0x9381
+ ("glGet", F, 1, "GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB"), # 0x9382
("", X, 1, "GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE"), # 0x93A0
("", X, 1, "GL_BGRA8_EXT"), # 0x93A1
("", X, 1, "GL_TEXTURE_USAGE_ANGLE"), # 0x93A2
@@ -3470,6 +3593,8 @@ parameters = [
#("", X, 1, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES"), # 0x93E7
#("", X, 1, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES"), # 0x93E8
#("", X, 1, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES"), # 0x93E9
+ ("", X, 1, "GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG"), # 0x93F0
+ ("", X, 1, "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG"), # 0x93F1
("", X, 1, "GL_PERFQUERY_COUNTER_EVENT_INTEL"), # 0x94F0
("", X, 1, "GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL"), # 0x94F1
("", X, 1, "GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL"), # 0x94F2
@@ -3485,7 +3610,34 @@ parameters = [
("", X, 1, "GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL"), # 0x94FE
("", X, 1, "GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL"), # 0x94FF
("", X, 1, "GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL"), # 0x9500
+ ("", X, 1, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR"), # 0x9630
+ ("", X, 1, "GL_MAX_VIEWS_OVR"), # 0x9631
+ ("", X, 1, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR"), # 0x9632
+ #("", X, 1, "GL_GS_SHADER_BINARY_MTK"), # 0x9640
+ #("", X, 1, "GL_GS_PROGRAM_BINARY_MTK"), # 0x9641
+ ("", X, 1, "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT"), # 0x9650
+ ("", X, 1, "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT"), # 0x9651
+ ("", X, 1, "GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT"), # 0x9652
("_glGet", B, 1, "GL_RASTER_POSITION_UNCLIPPED_IBM"), # 0x19262
+ ("", X, 1, "GL_CULL_VERTEX_IBM"), # 0x1928A
+ ("", X, 1, "GL_ALL_STATIC_DATA_IBM"), # 0x19294
+ ("", X, 1, "GL_STATIC_VERTEX_ARRAY_IBM"), # 0x19295
+ ("", X, 1, "GL_VERTEX_ARRAY_LIST_IBM"), # 0x1929E
+ ("", X, 1, "GL_NORMAL_ARRAY_LIST_IBM"), # 0x1929F
+ ("", X, 1, "GL_COLOR_ARRAY_LIST_IBM"), # 0x192A0
+ ("", X, 1, "GL_INDEX_ARRAY_LIST_IBM"), # 0x192A1
+ ("", X, 1, "GL_TEXTURE_COORD_ARRAY_LIST_IBM"), # 0x192A2
+ ("", X, 1, "GL_EDGE_FLAG_ARRAY_LIST_IBM"), # 0x192A3
+ ("", X, 1, "GL_FOG_COORDINATE_ARRAY_LIST_IBM"), # 0x192A4
+ ("", X, 1, "GL_SECONDARY_COLOR_ARRAY_LIST_IBM"), # 0x192A5
+ ("", X, 1, "GL_VERTEX_ARRAY_LIST_STRIDE_IBM"), # 0x192A8
+ ("", X, 1, "GL_NORMAL_ARRAY_LIST_STRIDE_IBM"), # 0x192A9
+ ("", X, 1, "GL_COLOR_ARRAY_LIST_STRIDE_IBM"), # 0x192AA
+ ("", X, 1, "GL_INDEX_ARRAY_LIST_STRIDE_IBM"), # 0x192AB
+ ("", X, 1, "GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM"), # 0x192AC
+ ("", X, 1, "GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM"), # 0x192AD
+ ("", X, 1, "GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM"), # 0x192AE
+ ("", X, 1, "GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM"), # 0x192AF
("", X, 1, "GL_PREFER_DOUBLEBUFFER_HINT_PGI"), # 0x1A1F8
("", X, 1, "GL_CONSERVE_MEMORY_HINT_PGI"), # 0x1A1FD
("", X, 1, "GL_RECLAIM_MEMORY_HINT_PGI"), # 0x1A1FE
@@ -3510,25 +3662,6 @@ parameters = [
("", X, 1, "GL_VERTEX_CONSISTENT_HINT_PGI"), # 0x1A22B
("", X, 1, "GL_MATERIAL_SIDE_HINT_PGI"), # 0x1A22C
("", X, 1, "GL_MAX_VERTEX_HINT_PGI"), # 0x1A22D
- ("", X, 1, "GL_CULL_VERTEX_IBM"), # 0x103050
- ("", X, 1, "GL_ALL_STATIC_DATA_IBM"), # 0x103060
- ("", X, 1, "GL_STATIC_VERTEX_ARRAY_IBM"), # 0x103061
- ("", X, 1, "GL_VERTEX_ARRAY_LIST_IBM"), # 0x103070
- ("", X, 1, "GL_NORMAL_ARRAY_LIST_IBM"), # 0x103071
- ("", X, 1, "GL_COLOR_ARRAY_LIST_IBM"), # 0x103072
- ("", X, 1, "GL_INDEX_ARRAY_LIST_IBM"), # 0x103073
- ("", X, 1, "GL_TEXTURE_COORD_ARRAY_LIST_IBM"), # 0x103074
- ("", X, 1, "GL_EDGE_FLAG_ARRAY_LIST_IBM"), # 0x103075
- ("", X, 1, "GL_FOG_COORDINATE_ARRAY_LIST_IBM"), # 0x103076
- ("", X, 1, "GL_SECONDARY_COLOR_ARRAY_LIST_IBM"), # 0x103077
- ("", X, 1, "GL_VERTEX_ARRAY_LIST_STRIDE_IBM"), # 0x103080
- ("", X, 1, "GL_NORMAL_ARRAY_LIST_STRIDE_IBM"), # 0x103081
- ("", X, 1, "GL_COLOR_ARRAY_LIST_STRIDE_IBM"), # 0x103082
- ("", X, 1, "GL_INDEX_ARRAY_LIST_STRIDE_IBM"), # 0x103083
- ("", X, 1, "GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM"), # 0x103084
- ("", X, 1, "GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM"), # 0x103085
- ("", X, 1, "GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM"), # 0x103086
- ("", X, 1, "GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM"), # 0x103087
("", X, 1, "GL_INVALID_INDEX"), # 0xFFFFFFFFu
#("", X, 1, "GL_TIMEOUT_IGNORED"), # 0xFFFFFFFFFFFFFFFFull
]
diff --git a/specs/gltypes.py b/specs/gltypes.py
index ac3dde82..a9ffc4a1 100644
--- a/specs/gltypes.py
+++ b/specs/gltypes.py
@@ -55,6 +55,9 @@ GLdouble = Alias("GLdouble", Double)
GLclampd = Alias("GLclampd", Double)
GLchar = Alias("GLchar", Char)
+GLfixed = Alias("GLfixed", Int32)
+GLclampx = Alias("GLclampx", Int32)
+
GLcharARB = Alias("GLcharARB", SChar)
GLintptrARB = Alias("GLintptrARB", Int)
GLsizeiptrARB = Alias("GLsizeiptrARB", Int)
@@ -64,6 +67,7 @@ GLhalfNV = Alias("GLhalfNV", UShort)
GLint64EXT = Alias("GLint64EXT", Int64)
GLuint64EXT = Alias("GLuint64EXT", UInt64)
GLDEBUGPROC = Opaque("GLDEBUGPROC")
+GLDEBUGPROCKHR = Opaque("GLDEBUGPROCKHR")
GLDEBUGPROCARB = Opaque("GLDEBUGPROCARB")
GLDEBUGPROCAMD = Opaque("GLDEBUGPROCAMD")
@@ -101,7 +105,7 @@ GLlocation = Handle("location", GLint, key=('program', GLhandleARB))
GLlocationARB = Handle("location", GLint, key=('programObj', GLhandleARB))
# TODO: Symbolic representation of GL_INVALID_INDEX
-GLuniformBlock = Handle("location", GLuint, key=('program', GLprogram))
+GLuniformBlock = Handle("uniformBlock", GLuint, key=('program', GLprogram))
contextKey = ('reinterpret_cast<uintptr_t>(glretrace::getCurrentContext())', UIntPtr)
@@ -117,6 +121,8 @@ GLsampler = Handle("sampler", GLuint)
GLfeedback = Handle("feedback", GLuint)
GLfence = Handle("fence", GLuint)
GLtextureHandle = Handle("textureHandle", GLuint64)
+GLsubroutine = Handle("subroutine", GLuint, key=('program', GLhandleARB))
+
# GL mappings are pointers to linear memory regions.
#
diff --git a/specs/glxapi.py b/specs/glxapi.py
index ac7525c1..0d3cd969 100644
--- a/specs/glxapi.py
+++ b/specs/glxapi.py
@@ -106,6 +106,8 @@ GLXEnum = FakeEnum(Int, [
"GLX_CONTEXT_MINOR_VERSION_ARB", # 0x2092
"GLX_CONTEXT_FLAGS_ARB", # 0x2094
"GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB", # 0x2095
+ "GLX_CONTEXT_RELEASE_BEHAVIOR_ARB", # 0x2097
+ "GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB", # 0x2098
"GLX_FLOAT_COMPONENTS_NV", # 0x20B0
"GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT", # 0x20B1
"GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB", # 0x20B2
@@ -275,7 +277,10 @@ GLXbuffer = Flags(Int, [
UnusedAttribs = AttribArray(Const(GLXEnum), [])
-GLXCommonSizeAttribs = [
+GLXCommonAttribs = [
+ ('GLX_BUFFER_SIZE', UInt),
+ ('GLX_LEVEL', Int),
+ ('GLX_AUX_BUFFERS', UInt),
('GLX_RED_SIZE', UInt),
('GLX_GREEN_SIZE', UInt),
('GLX_BLUE_SIZE', UInt),
@@ -285,60 +290,66 @@ GLXCommonSizeAttribs = [
('GLX_ACCUM_RED_SIZE', UInt),
('GLX_ACCUM_GREEN_SIZE', UInt),
('GLX_ACCUM_BLUE_SIZE', UInt),
- ('GLX_ACCUM_ALPHA_SIZE', UInt)
+ ('GLX_ACCUM_ALPHA_SIZE', UInt),
+ ('GLX_CONFIG_CAVEAT', FakeEnum(Int, ["GLX_NONE", "GLX_SLOW_CONFIG", "GLX_NON_CONFORMANT_CONFIG"])),
+ ('GLX_X_VISUAL_TYPE', FakeEnum(Int, ["GLX_TRUE_COLOR", "GLX_DIRECT_COLOR", "GLX_PSEUDO_COLOR", "GLX_STATIC_COLOR"])),
+ ('GLX_TRANSPARENT_TYPE', FakeEnum(Int, ["GLX_NONE", "GLX_TRANSPARENT_RGB", "GLX_TRANSPARENT_INDEX"])),
+ ('GLX_TRANSPARENT_INDEX_VALUE', Int),
+ ('GLX_TRANSPARENT_RED_VALUE', Int),
+ ('GLX_TRANSPARENT_GREEN_VALUE', Int),
+ ('GLX_TRANSPARENT_BLUE_VALUE', Int),
+ ('GLX_TRANSPARENT_ALPHA_VALUE', Int),
+ ('GLX_SAMPLE_BUFFERS', UInt),
+ ('GLX_SAMPLES', UInt),
]
-GLXVisualAttribs = AttribArray(GLXEnum, GLXCommonSizeAttribs + [
+GLXVisualAttribs = AttribArray(GLXEnum, GLXCommonAttribs + [
('GLX_USE_GL', None),
- ('GLX_BUFFER_SIZE', UInt),
- ('GLX_LEVEL', Int),
('GLX_RGBA', None),
('GLX_DOUBLEBUFFER', None),
('GLX_STEREO', None),
- ('GLX_AUX_BUFFERS', UInt),
- ('GLX_SAMPLE_BUFFERS', UInt),
- ('GLX_SAMPLES', UInt)],
-)
+])
-GLXFBConfigCommonAttribs = GLXCommonSizeAttribs + [
- ('GLX_BUFFER_SIZE', UInt),
- ('GLX_LEVEL', Int),
+GLXFBConfigCommonAttribs = GLXCommonAttribs + [
('GLX_DOUBLEBUFFER', Bool),
('GLX_STEREO', Bool),
- ('GLX_AUX_BUFFERS', UInt),
- ('GLX_SAMPLE_BUFFERS', UInt),
- ('GLX_SAMPLES', UInt),
('GLX_RENDER_TYPE', Flags(Int, ["GLX_RGBA_BIT", "GLX_COLOR_INDEX_BIT"])),
('GLX_DRAWABLE_TYPE', Flags(Int, ["GLX_WINDOW_BIT", "GLX_PIXMAP_BIT", "GLX_PBUFFER_BIT"])),
('GLX_X_RENDERABLE', Bool),
- ('GLX_X_VISUAL_TYPE', FakeEnum(Int, ["GLX_TRUE_COLOR", "GLX_DIRECT_COLOR", "GLX_PSEUDO_COLOR", "GLX_STATIC_COLOR"])),
- ('GLX_CONFIG_CAVEAT', FakeEnum(Int, ["GLX_NONE", "GLX_SLOW_CONFIG", "GLX_NON_CONFORMANT_CONFIG"])),
- ('GLX_TRANSPARENT_TYPE', FakeEnum(Int, ["GLX_NONE", "GLX_TRANSPARENT_RGB", "GLX_TRANSPARENT_INDEX"])),
- ('GLX_TRANSPARENT_INDEX_VALUE', Int),
- ('GLX_TRANSPARENT_RED_VALUE', Int),
- ('GLX_TRANSPARENT_GREEN_VALUE', Int),
- ('GLX_TRANSPARENT_BLUE_VALUE', Int),
- ('GLX_TRANSPARENT_ALPHA_VALUE', Int)
]
GLXFBConfigGLXAttribs = GLXFBConfigCommonAttribs + [
- ('GLX_FBCONFIG_ID', Int), # an XID, can we do better than int?
+ ('GLX_FBCONFIG_ID', GLXFBConfigID),
('GLX_MAX_PBUFFER_WIDTH', Int),
('GLX_MAX_PBUFFER_HEIGHT', Int),
('GLX_MAX_PBUFFER_PIXELS', Int),
- ('GLX_VISUAL_ID', Int) # another XID
+ ('GLX_VISUAL_ID', VisualID),
]
GLXFBConfigAttribs = AttribArray(Const(GLXEnum), GLXFBConfigGLXAttribs)
GLXFBConfigSGIXAttribs = AttribArray(GLXEnum, GLXFBConfigCommonAttribs)
+GLXContextProfileMask = Flags(Int, [
+ "GLX_CONTEXT_CORE_PROFILE_BIT_ARB",
+ "GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB",
+ "GLX_CONTEXT_ES_PROFILE_BIT_EXT",
+])
+
GLXContextARBAttribs = AttribArray(Const(GLXEnum), [
- ('GLX_RENDER_TYPE', Flags(Int, ["GLX_RGBA_BIT", "GLX_COLOR_INDEX_BIT"])),
+ ('GLX_RENDER_TYPE', FakeEnum(Int, ["GLX_RGBA_TYPE", "GLX_COLOR_INDEX_TYPE"])),
('GLX_CONTEXT_MAJOR_VERSION_ARB', Int),
('GLX_CONTEXT_MINOR_VERSION_ARB', Int),
- ('GLX_CONTEXT_FLAGS_ARB', Flags(Int, ["GLX_CONTEXT_DEBUG_BIT_ARB", "GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB", "GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB"])),
- ('GLX_CONTEXT_PROFILE_MASK_ARB', Flags(Int, ["GLX_CONTEXT_CORE_PROFILE_BIT_ARB", "GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB"])),
+ ('GLX_CONTEXT_FLAGS_ARB', Flags(Int, [
+ "GLX_CONTEXT_DEBUG_BIT_ARB",
+ "GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB",
+ "GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB",
+ ])),
+ ('GLX_CONTEXT_PROFILE_MASK_ARB', GLXContextProfileMask),
('GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB', GLXEnum),
+ ('GLX_CONTEXT_RELEASE_BEHAVIOR_ARB', FakeEnum(Int, [
+ 'GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB',
+ 'GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB',
+ ])),
])
GLXPbufferAttribs = AttribArray(Const(GLXEnum), [
@@ -354,6 +365,23 @@ GLXPbufferSGIXAttribs = AttribArray(GLXEnum, [
#('GLX_DIGITAL_MEDIA_PBUFFER_SGIX', Bool),
])
+GLXRendererAttrPointer = Polymorphic('attribute', [
+ ("GLX_RENDERER_VENDOR_ID_MESA", Pointer(UInt)),
+ ("GLX_RENDERER_DEVICE_ID_MESA", Pointer(UInt)),
+ ("GLX_RENDERER_VERSION_MESA", Array(UInt, 3)),
+ ("GLX_RENDERER_ACCELERATED_MESA", Pointer(Bool)),
+ ("GLX_RENDERER_VIDEO_MEMORY_MESA", Pointer(UInt)),
+ ("GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA", Pointer(Bool)),
+ ("GLX_RENDERER_PREFERRED_PROFILE_MESA", Pointer(GLXContextProfileMask)),
+ ("GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA", Array(UInt, 2) ),
+ ("GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA", Array(UInt, 2)),
+ ("GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA", Array(UInt, 2)),
+ ("GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA", Array(UInt, 2)),
+ ],
+ Pointer(UInt)
+)
+
+
glxapi = Module("GLX")
PROC = Opaque("__GLXextFuncPtr")
@@ -382,9 +410,9 @@ glxapi.addFunctions([
Function(Void, "glXUseXFont", [(Font, "font"), (Int, "first"), (Int, "count"), (Int, "list")]),
# GLX_VERSION_1_1
- Function((ConstCString), "glXQueryExtensionsString", [(Display, "dpy"), (Int, "screen")], sideeffects=False),
- Function((ConstCString), "glXQueryServerString", [(Display, "dpy"), (Int, "screen"), (GLXname, "name")], sideeffects=False),
- Function((ConstCString), "glXGetClientString", [(Display, "dpy"), (GLXname, "name")], sideeffects=False),
+ Function(ConstCString, "glXQueryExtensionsString", [(Display, "dpy"), (Int, "screen")], sideeffects=False),
+ Function(ConstCString, "glXQueryServerString", [(Display, "dpy"), (Int, "screen"), (GLXname, "name")], sideeffects=False),
+ Function(ConstCString, "glXGetClientString", [(Display, "dpy"), (GLXname, "name")], sideeffects=False),
# GLX_VERSION_1_2
Function(Display, "glXGetCurrentDisplay", [], sideeffects=False),
@@ -448,6 +476,12 @@ glxapi.addFunctions([
# GLX_MESA_pixmap_colormap
Function(GLXPixmap, "glXCreateGLXPixmapMESA", [(Display, "dpy"), (Pointer(XVisualInfo), "visual"), (Pixmap, "pixmap"), (Colormap, "cmap")]),
+ # GLX_MESA_query_renderer
+ GlFunction(Bool, "glXQueryCurrentRendererIntegerMESA", [(GLXEnum, "attribute"), Out(GLXRendererAttrPointer, "value")], sideeffects=False),
+ GlFunction(ConstCString, "glXQueryCurrentRendererStringMESA", [(GLXEnum, "attribute")], sideeffects=False),
+ GlFunction(Bool, "glXQueryRendererIntegerMESA", [(Display, "dpy"), (Int, "screen"), (Int, "renderer"), (GLXEnum, "attribute"), Out(GLXRendererAttrPointer, "value")], sideeffects=False),
+ GlFunction(ConstCString, "glXQueryRendererStringMESA", [(Display, "dpy"), (Int, "screen"), (Int, "renderer"), (GLXEnum, "attribute")], sideeffects=False),
+
# GLX_MESA_release_buffers
Function(Bool, "glXReleaseBuffersMESA", [(Display, "dpy"), (GLXDrawable, "drawable")]),
@@ -517,12 +551,12 @@ glxapi.addFunctions([
#Function(Bool, "glXAssociateDMPbufferSGIX", [(Display, "dpy"), (GLXPbufferSGIX, "pbuffer"), (OpaquePointer(DMparams), "params"), (DMbuffer, "dmbuffer")]),
# GLX_SGIX_fbconfig
- Function(Int, "glXGetFBConfigAttribSGIX", [(Display, "dpy"), (GLXFBConfigSGIX, "config"), (Int, "attribute"), Out(Pointer(Int), "value")]),
- Function(OpaquePointer(GLXFBConfigSGIX), "glXChooseFBConfigSGIX", [(Display, "dpy"), (Int, "screen"), (GLXFBConfigSGIXAttribs, "attrib_list"), Out(Pointer(Int), "nelements")]),
+ Function(Int, "glXGetFBConfigAttribSGIX", [(Display, "dpy"), (GLXFBConfigSGIX, "config"), (GLXEnum, "attribute"), Out(Pointer(Int), "value")]),
+ Function(Array(GLXFBConfigSGIX, "*nelements"), "glXChooseFBConfigSGIX", [(Display, "dpy"), (Int, "screen"), (GLXFBConfigSGIXAttribs, "attrib_list"), Out(Pointer(Int), "nelements")]),
Function(GLXPixmap, "glXCreateGLXPixmapWithConfigSGIX", [(Display, "dpy"), (GLXFBConfigSGIX, "config"), (Pixmap, "pixmap")]),
- Function(GLXContext, "glXCreateContextWithConfigSGIX", [(Display, "dpy"), (GLXFBConfigSGIX, "config"), (Int, "render_type"), (GLXContext, "share_list"), (Bool, "direct")]),
+ Function(GLXContext, "glXCreateContextWithConfigSGIX", [(Display, "dpy"), (GLXFBConfigSGIX, "config"), (GLXEnum, "render_type"), (GLXContext, "share_list"), (Bool, "direct")]),
Function(Pointer(XVisualInfo), "glXGetVisualFromFBConfigSGIX", [(Display, "dpy"), (GLXFBConfigSGIX, "config")]),
- Function(GLXFBConfigSGIX, "glXGetFBConfigFromVisualSGIX", [(Display, "dpy"), Out(Pointer(XVisualInfo), "vis")]),
+ Function(GLXFBConfigSGIX, "glXGetFBConfigFromVisualSGIX", [(Display, "dpy"), (Pointer(XVisualInfo), "vis")]),
# GLX_SGIX_hyperpipe
#Function(OpaquePointer(GLXHyperpipeNetworkSGIX), "glXQueryHyperpipeNetworkSGIX", [(Display, "dpy"), (OpaquePointer(Int), "npipes")]),
diff --git a/specs/scripts/.gitignore b/specs/scripts/.gitignore
index 46dcdbc0..768ef681 100644
--- a/specs/scripts/.gitignore
+++ b/specs/scripts/.gitignore
@@ -1,6 +1,5 @@
*.spec
*.tm
-*.txt
*.xml
*api.py
*enum.py
diff --git a/specs/scripts/Makefile b/specs/scripts/Makefile
index ff5ad950..23328390 100644
--- a/specs/scripts/Makefile
+++ b/specs/scripts/Makefile
@@ -5,6 +5,7 @@ all: \
glparams.py \
glxapi.py \
wglapi.py \
+ eglapi.py \
glxenum.py \
wglenum.py \
eglenum.py
@@ -27,13 +28,13 @@ download: \
%.xml:
- wget -N https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/$@
+ wget -nv -N https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/$@
%.spec:
- wget -N http://www.opengl.org/registry/oldspecs/$@
+ wget -nv -N https://www.opengl.org/registry/oldspecs/$@
%.tm:
- wget -N http://www.opengl.org/registry/oldspecs/$@
+ wget -nv -N https://www.opengl.org/registry/oldspecs/$@
glapi.py: xml2api.py gl.xml
python $^ > $@
@@ -44,6 +45,9 @@ glxapi.py: xml2api.py glx.xml
wglapi.py: xml2api.py wgl.xml
python $^ > $@
+eglapi.py: xml2api.py egl.xml
+ python $^ > $@
+
glparams.py: xml2glparams.py gl.xml
python $^ > $@
diff --git a/specs/scripts/xml2api.py b/specs/scripts/xml2api.py
index 91ec7678..e3820e09 100755
--- a/specs/scripts/xml2api.py
+++ b/specs/scripts/xml2api.py
@@ -30,6 +30,7 @@
#
+import optparse
import sys
import xml.etree.ElementTree as ET
@@ -70,7 +71,12 @@ def getType(node):
typeExpr = parser.parse_type()
if lenExpr is not None:
- typeExpr = 'Array(%s, "%s")' % (typeExpr, lenExpr)
+ if lenExpr == "1":
+ typeExpr = 'Pointer(%s)' % (typeExpr)
+ else:
+ if not lenExpr.isdigit():
+ lenExpr = '"' + lenExpr + '"'
+ typeExpr = 'Array(%s, %s)' % (typeExpr, lenExpr)
return typeExpr
@@ -102,36 +108,90 @@ def processCommand(prototypes, command):
prototypes[functionName] = prototype
-def processRequire(prototypes, node):
- requireNode = node.find('require')
- if requireNode is None:
+def processRequire(node, filterName):
+ nodeName = node.get('name')
+ if filterName is not None and nodeName != filterName:
return
- commands = requireNode.findall('command')
+
+ commands = []
+ for requireNode in node.findall('require'):
+ commands.extend(requireNode.findall('command'))
if not commands:
return
- print ' # %s' % node.get('name')
- for command in commands:
- functionName = command.get('name')
- prototype = prototypes[functionName]
- print ' %s,' % prototype
- print
+ functionNames = [command.get('name') for command in commands]
+
+ return nodeName, functionNames
-for arg in sys.argv[1:]:
- tree = ET.parse(arg)
- root = tree.getroot()
- prototypes = {}
- for commands in root.findall('commands'):
- namespace = commands.get('namespace')
- for command in commands.findall('command'):
- processCommand(prototypes, command)
+def printPrototypes(prototypes, extensionName, functionNames, skip=set()):
+ print ' # %s' % extensionName
- for feature in root.findall('feature'):
- processRequire(prototypes, feature)
+ if extensionName == 'GL_EXT_direct_state_access':
+ functionNames.sort()
+
+ for functionName in functionNames:
+ if functionName not in skip:
+ prototype = prototypes[functionName]
+ print ' %s,' % prototype
+
+ print
- extensions = root.find('extensions')
- for extension in extensions.findall('extension'):
- processRequire(prototypes, extension)
+def main():
+ optparser = optparse.OptionParser(
+ usage='\n\t%prog [options] <xml> ...',
+ version='%%prog')
+ optparser.add_option(
+ '--filter', metavar='NAME',
+ type='string', dest='filter',
+ help='filter feature/extension')
+ (options, args) = optparser.parse_args(sys.argv[1:])
+
+ global prototypes
+ global namespace
+
+ for arg in args:
+ tree = ET.parse(arg)
+ root = tree.getroot()
+
+ prototypes = {}
+
+ for commands in root.findall('commands'):
+ namespace = commands.get('namespace')
+ for command in commands.findall('command'):
+ processCommand(prototypes, command)
+
+ # Extract features
+ features = []
+ for feature in root.findall('feature'):
+ ret = processRequire(feature, options.filter)
+ if ret is not None:
+ features.append(ret)
+
+ # Extract extensions
+ extensions = []
+ for extension in root.find('extensions').findall('extension'):
+ ret = processRequire(extension, options.filter)
+ if ret is not None:
+ extensions.append(ret)
+
+ # Eliminate the functions from features that are in extensions
+ for extensionName, extensionFunctionNames in extensions:
+ for featureName, featureFunctionNames in features:
+ for functionName in extensionFunctionNames:
+ try:
+ featureFunctionNames.remove(functionName)
+ except ValueError:
+ pass
+
+ # Print all
+ skip = set()
+ for extensionName, functionNames in features + extensions:
+ printPrototypes(prototypes, extensionName, functionNames, skip)
+ skip.update(functionNames)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/specs/scripts/xml2glparams.py b/specs/scripts/xml2glparams.py
index 7e2bc351..0682f496 100755
--- a/specs/scripts/xml2glparams.py
+++ b/specs/scripts/xml2glparams.py
@@ -34,6 +34,37 @@ import sys
import xml.etree.ElementTree as ET
+def canonical(x, y):
+ assert x != y
+
+ # Prefer the shortest
+ if x.startswith(y):
+ return y
+ if y.startswith(x):
+ return x
+
+ # then _KHR
+ if x.endswith('_KHR'):
+ return x
+ if y.endswith('_KHR'):
+ return y
+
+ # then _ARB
+ if x.endswith('_ARB'):
+ return x
+ if y.endswith('_ARB'):
+ return y
+
+ # then _EXT
+ if x.endswith('_EXT'):
+ return x
+ if y.endswith('_EXT'):
+ return y
+
+ # Return the first
+ return x
+
+
for arg in sys.argv[1:]:
tree = ET.parse(arg)
root = tree.getroot()
@@ -55,7 +86,12 @@ for arg in sys.argv[1:]:
else:
continue
- params.setdefault(value, name)
+ try:
+ origName = params[value]
+ except KeyError:
+ params[value] = name
+ else:
+ params[value] = canonical(origName, name)
values = params.keys()
diff --git a/specs/stdapi.py b/specs/stdapi.py
index c2a154db..c72c264b 100644
--- a/specs/stdapi.py
+++ b/specs/stdapi.py
@@ -75,6 +75,13 @@ class Type:
visitor = MutableRebuilder()
return visitor.visit(self)
+ def depends(self, other):
+ '''Whether this type depends on another.'''
+
+ collector = Collector()
+ collector.visit(self)
+ return other in collector.types
+
class _Void(Type):
"""Singleton void type."""
@@ -261,10 +268,19 @@ Flags = Bitmask
class Array(Type):
- def __init__(self, type, length):
- Type.__init__(self, type.expr + " *")
- self.type = type
+ def __init__(self, type_, length):
+ Type.__init__(self, type_.expr + " *")
+ self.type = type_
self.length = length
+ if not isinstance(length, int):
+ assert isinstance(length, basestring)
+ # Check if length is actually a valid constant expression
+ try:
+ eval(length, {}, {})
+ except:
+ pass
+ else:
+ raise ValueError("length %r should be an integer" % length)
def visit(self, visitor, *args, **kwargs):
return visitor.visitArray(self, *args, **kwargs)
@@ -407,6 +423,12 @@ class Function:
return arg
return None
+ def getArgByType(self, type):
+ for arg in self.args:
+ if arg.type is type:
+ return arg
+ return None
+
def StdFunction(*args, **kwargs):
kwargs.setdefault('call', '__stdcall')
diff --git a/specs/wglapi.py b/specs/wglapi.py
index f75be6bd..f24a8d21 100644
--- a/specs/wglapi.py
+++ b/specs/wglapi.py
@@ -35,10 +35,10 @@ from wglenum import *
wglapi = Module("WGL")
-HGLRC = Alias("HGLRC", HANDLE)
+HGLRC = DECLARE_HANDLE("HGLRC")
PROC = Opaque("PROC")
-PFD = Flags(DWORD, [
+PFD_FLAGS = Flags(DWORD, [
"PFD_DOUBLEBUFFER",
"PFD_STEREO",
"PFD_DRAW_TO_WINDOW",
@@ -53,17 +53,29 @@ PFD = Flags(DWORD, [
"PFD_SWAP_LAYER_BUFFERS",
"PFD_GENERIC_ACCELERATED",
"PFD_SUPPORT_DIRECTDRAW",
+ "PFD_DIRECT3D_ACCELERATED",
"PFD_SUPPORT_COMPOSITION",
"PFD_DEPTH_DONTCARE",
"PFD_DOUBLEBUFFER_DONTCARE",
"PFD_STEREO_DONTCARE",
])
+PFD_TYPE = FakeEnum(BYTE, [
+ "PFD_TYPE_RGBA",
+ "PFD_TYPE_COLORINDEX",
+])
+
+PFD_PLANE = FakeEnum(BYTE, [
+ "PFD_MAIN_PLANE",
+ "PFD_OVERLAY_PLANE",
+ "PFD_UNDERLAY_PLANE",
+])
+
PIXELFORMATDESCRIPTOR = Struct("PIXELFORMATDESCRIPTOR", [
(WORD, "nSize"),
(WORD, "nVersion"),
- (PFD, "dwFlags"),
- (BYTE, "iPixelType"),
+ (PFD_FLAGS, "dwFlags"),
+ (PFD_TYPE, "iPixelType"),
(BYTE, "cColorBits"),
(BYTE, "cRedBits"),
(BYTE, "cRedShift"),
@@ -81,7 +93,7 @@ PIXELFORMATDESCRIPTOR = Struct("PIXELFORMATDESCRIPTOR", [
(BYTE, "cDepthBits"),
(BYTE, "cStencilBits"),
(BYTE, "cAuxBuffers"),
- (BYTE, "iLayerType"),
+ (PFD_PLANE, "iLayerType"),
(BYTE, "bReserved"),
(DWORD, "dwLayerMask"),
(DWORD, "dwVisibleMask"),
@@ -102,14 +114,19 @@ GLYPHMETRICSFLOAT = Struct("GLYPHMETRICSFLOAT", [
])
LPGLYPHMETRICSFLOAT = Pointer(GLYPHMETRICSFLOAT)
+WGLFontFormat = FakeEnum(Int, [
+ 'WGL_FONT_LINES',
+ 'WGL_FONT_POLYGONS',
+])
+
COLORREF = Alias("COLORREF", DWORD)
LAYERPLANEDESCRIPTOR = Struct("LAYERPLANEDESCRIPTOR", [
(WORD, "nSize"),
(WORD, "nVersion"),
- (DWORD, "dwFlags"),
- (BYTE, "iPixelType"),
+ (PFD_FLAGS, "dwFlags"),
+ (PFD_TYPE, "iPixelType"),
(BYTE, "cColorBits"),
(BYTE, "cRedBits"),
(BYTE, "cRedShift"),
@@ -127,7 +144,7 @@ LAYERPLANEDESCRIPTOR = Struct("LAYERPLANEDESCRIPTOR", [
(BYTE, "cDepthBits"),
(BYTE, "cStencilBits"),
(BYTE, "cAuxBuffers"),
- (BYTE, "iLayerPlane"),
+ (PFD_PLANE, "iLayerPlane"),
(BYTE, "bReserved"),
(COLORREF, "crTransparent"),
])
@@ -146,14 +163,21 @@ WGLContextAttribs = AttribArray(Const(WGLenum), [
"WGL_CONTEXT_DEBUG_BIT_ARB",
"WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB",
"WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB",
+ "WGL_CONTEXT_RESET_ISOLATION_BIT_ARB",
])),
('WGL_CONTEXT_PROFILE_MASK_ARB', Flags(Int, [
"WGL_CONTEXT_CORE_PROFILE_BIT_ARB",
"WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB",
- ]))
+ "WGL_CONTEXT_ES_PROFILE_BIT_EXT",
+ ])),
+ ('WGL_CONTEXT_RELEASE_BEHAVIOR_ARB', FakeEnum(Int, [
+ 'WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB',
+ 'WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB',
+ ])),
])
WGLPixelFormatAttribsList = [
+ # WGL_ARB_pixel_format/WGL_EXT_pixel_format
('WGL_DRAW_TO_WINDOW_ARB', BOOL),
('WGL_DRAW_TO_BITMAP_ARB', BOOL),
('WGL_ACCELERATION_ARB', FakeEnum(Int, ['WGL_NO_ACCELERATION_ARB', 'WGL_GENERIC_ACCELERATION_ARB', 'WGL_FULL_ACCELERATION_ARB'])),
@@ -192,13 +216,28 @@ WGLPixelFormatAttribsList = [
('WGL_AUX_BUFFERS_ARB', Int),
('WGL_SAMPLE_BUFFERS_ARB', Int),
('WGL_SAMPLES_ARB', Int),
+ # WGL_ARB_pbuffer
+ ('WGL_DRAW_TO_PBUFFER_ARB', BOOL),
+ # WGL_ARB_render_texture
+ ('WGL_BIND_TO_TEXTURE_RGB_ARB', BOOL),
+ ('WGL_BIND_TO_TEXTURE_RGBA_ARB', BOOL),
+ # WGL_NV_video_output
+ ('WGL_BIND_TO_VIDEO_RGB_NV', BOOL),
+ ('WGL_BIND_TO_VIDEO_RGBA_NV', BOOL),
+ ('WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV', BOOL),
]
WGLPixelFormatAttribs = AttribArray(Const(WGLenum), WGLPixelFormatAttribsList)
WGLPixelFormatFloatAttribs = AttribArray(Const(FLOAT), WGLPixelFormatAttribsList)
WGLCreatePbufferARBAttribs = AttribArray(Const(WGLenum), [
- ('WGL_PBUFFER_LARGEST_ARB', Int)
+ ('WGL_PBUFFER_LARGEST_ARB', Int),
+ # WGL_ARB_render_texture
+ ('WGL_TEXTURE_FORMAT_ARB', WGLenum),
+ ('WGL_TEXTURE_TARGET_ARB', WGLenum),
+ ('WGL_MIPMAP_TEXTURE_ARB', BOOL),
+ # WGL_NV_render_depth_texture
+ ('WGL_DEPTH_TEXTURE_FORMAT_NV', WGLenum),
])
CubeFaceEnum = FakeEnum(Int, [
@@ -215,12 +254,12 @@ WGLSetPbufferARBAttribs = AttribArray(Const(WGLenum), [
('WGL_CUBE_MAP_FACE_ARB', CubeFaceEnum)
])
-HPBUFFERARB = Alias("HPBUFFERARB", HANDLE)
-HPBUFFEREXT = Alias("HPBUFFEREXT", HANDLE)
-HPVIDEODEV = Alias("HPVIDEODEV", HANDLE)
-HVIDEOOUTPUTDEVICENV = Alias("HVIDEOOUTPUTDEVICENV", HANDLE)
-HVIDEOINPUTDEVICENV = Alias("HVIDEOINPUTDEVICENV", HANDLE)
-HGPUNV = Alias("HGPUNV", HANDLE)
+HPBUFFERARB = DECLARE_HANDLE("HPBUFFERARB")
+HPBUFFEREXT = DECLARE_HANDLE("HPBUFFEREXT")
+HPVIDEODEV = DECLARE_HANDLE("HPVIDEODEV")
+HVIDEOOUTPUTDEVICENV = DECLARE_HANDLE("HVIDEOOUTPUTDEVICENV")
+HVIDEOINPUTDEVICENV = DECLARE_HANDLE("HVIDEOINPUTDEVICENV")
+HGPUNV = DECLARE_HANDLE("HGPUNV")
GPU_DEVICE = Struct("_GPU_DEVICE", [
(DWORD, "cb"),
@@ -230,6 +269,7 @@ GPU_DEVICE = Struct("_GPU_DEVICE", [
(RECT, "rcVirtualScreen"),
])
+WGLlist = Handle("list", DWORD)
wglapi.addFunctions([
# WGL
@@ -237,7 +277,7 @@ wglapi.addFunctions([
StdFunction(BOOL, "wglDeleteContext", [(HGLRC, "hglrc")]),
StdFunction(HGLRC, "wglGetCurrentContext", [], sideeffects=False),
StdFunction(BOOL, "wglMakeCurrent", [(HDC, "hdc"), (HGLRC, "hglrc")]),
- StdFunction(BOOL, "wglCopyContext", [(HGLRC, "hglrcSrc"), (HGLRC, "hglrcDst"), (UINT, "mask")]),
+ StdFunction(BOOL, "wglCopyContext", [(HGLRC, "hglrcSrc"), (HGLRC, "hglrcDst"), (Flags(UINT, GLbitfield_attrib.values), "mask")]),
StdFunction(Int, "wglChoosePixelFormat", [(HDC, "hdc"), (Pointer(Const(PIXELFORMATDESCRIPTOR)), "ppfd")]),
StdFunction(Int, "wglDescribePixelFormat", [(HDC, "hdc"), (Int, "iPixelFormat"), (UINT, "nBytes"), Out(Pointer(PIXELFORMATDESCRIPTOR), "ppfd")]),
StdFunction(HDC, "wglGetCurrentDC", [], sideeffects=False),
@@ -252,11 +292,11 @@ wglapi.addFunctions([
StdFunction(Int, "wglGetLayerPaletteEntries", [(HDC, "hdc"), (Int, "iLayerPlane"), (Int, "iStart"), (Int, "cEntries"), Out(Array(COLORREF, "cEntries"), "pcr")], sideeffects=False),
StdFunction(BOOL, "wglRealizeLayerPalette", [(HDC, "hdc"), (Int, "iLayerPlane"), (BOOL, "bRealize")]),
StdFunction(BOOL, "wglSwapLayerBuffers", [(HDC, "hdc"), (UINT, "fuPlanes")]),
- StdFunction(BOOL, "wglUseFontBitmapsA", [(HDC, "hdc"), (DWORD, "first"), (DWORD, "count"), (DWORD, "listBase")]),
- StdFunction(BOOL, "wglUseFontBitmapsW", [(HDC, "hdc"), (DWORD, "first"), (DWORD, "count"), (DWORD, "listBase")]),
+ StdFunction(BOOL, "wglUseFontBitmapsA", [(HDC, "hdc"), (DWORD, "first"), (DWORD, "count"), (WGLlist, "listBase")]),
+ StdFunction(BOOL, "wglUseFontBitmapsW", [(HDC, "hdc"), (DWORD, "first"), (DWORD, "count"), (WGLlist, "listBase")]),
StdFunction(DWORD, "wglSwapMultipleBuffers", [(UINT, "n"), (Array(Const(WGLSWAP), "n"), "ps")]),
- StdFunction(BOOL, "wglUseFontOutlinesA", [(HDC, "hdc"), (DWORD, "first"), (DWORD, "count"), (DWORD, "listBase"), (FLOAT, "deviation"), (FLOAT, "extrusion"), (Int, "format"), (LPGLYPHMETRICSFLOAT, "lpgmf")]),
- StdFunction(BOOL, "wglUseFontOutlinesW", [(HDC, "hdc"), (DWORD, "first"), (DWORD, "count"), (DWORD, "listBase"), (FLOAT, "deviation"), (FLOAT, "extrusion"), (Int, "format"), (LPGLYPHMETRICSFLOAT, "lpgmf")]),
+ StdFunction(BOOL, "wglUseFontOutlinesA", [(HDC, "hdc"), (DWORD, "first"), (DWORD, "count"), (WGLlist, "listBase"), (FLOAT, "deviation"), (FLOAT, "extrusion"), (WGLFontFormat, "format"), Out(Array(GLYPHMETRICSFLOAT, "count"), "lpgmf")]),
+ StdFunction(BOOL, "wglUseFontOutlinesW", [(HDC, "hdc"), (DWORD, "first"), (DWORD, "count"), (WGLlist, "listBase"), (FLOAT, "deviation"), (FLOAT, "extrusion"), (WGLFontFormat, "format"), Out(Array(GLYPHMETRICSFLOAT, "count"), "lpgmf")]),
# WGL_ARB_buffer_region
StdFunction(HANDLE, "wglCreateBufferRegionARB", [(HDC, "hDC"), (Int, "iLayerPlane"), (UINT, "uType")]),
@@ -270,7 +310,7 @@ wglapi.addFunctions([
# WGL_ARB_pixel_format
StdFunction(BOOL, "wglGetPixelFormatAttribivARB", [(HDC, "hdc"), (Int, "iPixelFormat"), (Int, "iLayerPlane"), (UINT, "nAttributes"), (Array(WGLenum, "nAttributes"), "piAttributes"), Out(Array(Int, "nAttributes"), "piValues")], sideeffects=False),
StdFunction(BOOL, "wglGetPixelFormatAttribfvARB", [(HDC, "hdc"), (Int, "iPixelFormat"), (Int, "iLayerPlane"), (UINT, "nAttributes"), (Array(WGLenum, "nAttributes"), "piAttributes"), Out(Array(FLOAT, "nAttributes"), "pfValues")], sideeffects=False),
- StdFunction(BOOL, "wglChoosePixelFormatARB", [(HDC, "hdc"), (WGLPixelFormatAttribs, "piAttribIList"), (WGLPixelFormatFloatAttribs, "pfAttribFList"), (UINT, "nMaxFormats"), Out(Array(Int, "(*nNumFormats)"), "piFormats"), Out(Pointer(UINT), "nNumFormats")]),
+ StdFunction(BOOL, "wglChoosePixelFormatARB", [(HDC, "hdc"), (WGLPixelFormatAttribs, "piAttribIList"), (WGLPixelFormatFloatAttribs, "pfAttribFList"), (UINT, "nMaxFormats"), Out(Array(Int, "std::min(nMaxFormats, *nNumFormats)"), "piFormats"), Out(Pointer(UINT), "nNumFormats")]),
# WGL_ARB_make_current_read
StdFunction(BOOL, "wglMakeContextCurrentARB", [(HDC, "hDrawDC"), (HDC, "hReadDC"), (HGLRC, "hglrc")]),
@@ -314,7 +354,7 @@ wglapi.addFunctions([
# WGL_EXT_pixel_format
StdFunction(BOOL, "wglGetPixelFormatAttribivEXT", [(HDC, "hdc"), (Int, "iPixelFormat"), (Int, "iLayerPlane"), (UINT, "nAttributes"), (Array(WGLenum, "nAttributes"), "piAttributes"), Out(Array(Int, "nAttributes"), "piValues")], sideeffects=False),
StdFunction(BOOL, "wglGetPixelFormatAttribfvEXT", [(HDC, "hdc"), (Int, "iPixelFormat"), (Int, "iLayerPlane"), (UINT, "nAttributes"), (Array(WGLenum, "nAttributes"), "piAttributes"), Out(Array(FLOAT, "nAttributes"), "pfValues")], sideeffects=False),
- StdFunction(BOOL, "wglChoosePixelFormatEXT", [(HDC, "hdc"), (WGLPixelFormatAttribs, "piAttribIList"), (WGLPixelFormatFloatAttribs, "pfAttribFList"), (UINT, "nMaxFormats"), Out(Array(Int, "*nNumFormats"), "piFormats"), Out(Pointer(UINT), "nNumFormats")]),
+ StdFunction(BOOL, "wglChoosePixelFormatEXT", [(HDC, "hdc"), (WGLPixelFormatAttribs, "piAttribIList"), (WGLPixelFormatFloatAttribs, "pfAttribFList"), (UINT, "nMaxFormats"), Out(Array(Int, "std::min(nMaxFormats, *nNumFormats)"), "piFormats"), Out(Pointer(UINT), "nNumFormats")]),
# WGL_EXT_swap_control
StdFunction(BOOL, "wglSwapIntervalEXT", [(Int, "interval")]),
diff --git a/specs/wglenum.py b/specs/wglenum.py
index cafd28ab..ad9bbccf 100644
--- a/specs/wglenum.py
+++ b/specs/wglenum.py
@@ -158,6 +158,8 @@ WGLenum = FakeEnum(Int, [
"WGL_CONTEXT_FLAGS_ARB", # 0x2094
"ERROR_INVALID_VERSION_ARB", # 0x2095
"ERROR_INVALID_PROFILE_ARB", # 0x2096
+ "WGL_CONTEXT_RELEASE_BEHAVIOR_ARB", # 0x2097
+ "WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB", # 0x2098
"WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV", # 0x20A0
"WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV", # 0x20A1
"WGL_TEXTURE_RECTANGLE_NV", # 0x20A2
diff --git a/specs/winapi.py b/specs/winapi.py
index be501551..445039ff 100644
--- a/specs/winapi.py
+++ b/specs/winapi.py
@@ -36,6 +36,7 @@ UINT = Alias("UINT", UInt)
LONG = Alias("LONG", Long)
ULONG = Alias("ULONG", ULong)
LONGLONG = Alias("LONGLONG", LongLong)
+ULONGLONG = Alias("ULONGLONG", ULongLong)
FLOAT = Alias("FLOAT", Float)
INT8 = Alias("INT8", Int8)
@@ -46,6 +47,7 @@ INT32 = Alias("INT32", Int32)
UINT32 = Alias("UINT32", UInt32)
INT64 = Alias("INT64", Int64)
UINT64 = Alias("UINT64", UInt64)
+FLOAT32 = Alias("FLOAT32", Float)
BYTE = Alias("BYTE", UInt8)
WORD = Alias("WORD", UInt16)
@@ -59,6 +61,11 @@ BOOL = Enum("BOOL", [
"TRUE",
])
+PSTR = Alias("PSTR", CString)
+PCSTR = Alias("PCSTR", ConstCString)
+PWSTR = Alias("PWSTR", WString)
+PCWSTR = Alias("PCWSTR", ConstWString)
+
LPLONG = Pointer(LONG)
LPWORD = Pointer(WORD)
LPDWORD = Pointer(DWORD)
@@ -83,7 +90,10 @@ LPCVOID = OpaquePointer(Const(VOID))
def DECLARE_HANDLE(expr):
return Handle(expr, IntPointer(expr))
-HANDLE = DECLARE_HANDLE("HANDLE")
+# XXX: HANDLE type is often used for disjoint handle namespaces
+RAW_HANDLE = IntPointer("HANDLE")
+HANDLE = Handle("HANDLE", RAW_HANDLE)
+
HWND = DECLARE_HANDLE("HWND")
HDC = DECLARE_HANDLE("HDC")
HMONITOR = DECLARE_HANDLE("HMONITOR")
@@ -185,27 +195,36 @@ SECURITY_ATTRIBUTES = Struct("SECURITY_ATTRIBUTES", [
])
# http://msdn.microsoft.com/en-us/library/ff485842.aspx
-# http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381.aspx
-def MAKE_HRESULT(errors, ok = "S_OK", false = "S_FALSE"):
- values = [ok, false]
- values.extend(errors)
- values.extend([
- "E_PENDING", # 0x8000000A
- "E_NOTIMPL", # 0x80004001
- "E_NOINTERFACE", # 0x80004002
- "E_POINTER", # 0x80004003
- "E_ABORT", # 0x80004004
- "E_FAIL", # 0x80004005
- "E_UNEXPECTED", # 0x8000FFFF
- "E_ACCESSDENIED", # 0x80070005
- "E_HANDLE", # 0x80070006
- "E_OUTOFMEMORY", # 0x8007000E
- "E_INVALIDARG", # 0x80070057
- ])
- return Enum("HRESULT", values)
-
-HRESULT = MAKE_HRESULT([])
+# http://blogs.msdn.com/b/kirillosenkov/archive/2012/05/14/a-list-of-common-hresult-error-codes.aspx
+HRESULT = Enum("HRESULT", [
+ "S_OK", # 0x00000000
+ "S_FALSE", # 0x00000001
+ "E_PENDING", # 0x8000000A
+ "E_NOTIMPL", # 0x80004001
+ "E_NOINTERFACE", # 0x80004002
+ "E_POINTER", # 0x80004003
+ "E_ABORT", # 0x80004004
+ "E_FAIL", # 0x80004005
+ "E_UNEXPECTED", # 0x8000FFFF
+ "E_ACCESSDENIED", # 0x80070005
+ "E_HANDLE", # 0x80070006
+ "E_OUTOFMEMORY", # 0x8007000E
+ "E_INVALIDARG", # 0x80070057
+])
+def MAKE_HRESULT(errors, ok = "S_OK", false = "S_FALSE"):
+ # Always update global HRESULT
+ HRESULT.values.extend(errors)
+ if ok == "S_OK" and false == "S_FALSE":
+ # Just return global HRESULT
+ return HRESULT
+ else:
+ # Return a variation
+ values = [ok, false]
+ assert HRESULT.values[0] == "S_OK"
+ assert HRESULT.values[1] == "S_FALSE"
+ values.extend(HRESULT.values[2:])
+ return Enum("HRESULT", values)
IUnknown = Interface("IUnknown")
diff --git a/thirdparty/devcon/CMakeLists.txt b/thirdparty/devcon/CMakeLists.txt
new file mode 100644
index 00000000..290d7a22
--- /dev/null
+++ b/thirdparty/devcon/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_library (devcon STATIC
+ devcon.cpp
+)
+target_link_libraries (devcon
+ setupapi
+)
+
+install (
+ FILES "license.rtf"
+ DESTINATION ${DOC_INSTALL_DIR}
+ RENAME LICENSE-devcon.rtf
+)
diff --git a/thirdparty/devcon/devcon.cpp b/thirdparty/devcon/devcon.cpp
new file mode 100644
index 00000000..2077987e
--- /dev/null
+++ b/thirdparty/devcon/devcon.cpp
@@ -0,0 +1,946 @@
+/***************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * This source is subject to the Microsoft Public License.
+ * See http://www.microsoft.com/en-us/openness/licenses.aspx#MPL.
+ * All other rights reserved.
+ *
+ * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+ * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ ***************************************************************************/
+
+/*
+ * Interface for managing devices.
+ *
+ * http://code.msdn.microsoft.com/windowshardware/DevCon-Sample-4e95d71c
+ * http://support.microsoft.com/kb/311272
+ */
+
+
+#include "devcon.hpp"
+
+#include <string.h>
+#include <stdio.h>
+
+#include <windows.h>
+#include <tchar.h>
+#include <setupapi.h>
+#include <cfgmgr32.h>
+#include <newdev.h>
+#include <strsafe.h>
+
+
+// Not defined on MinGW and Windows SDKs before Windows 8.0
+#define PZPTSTR PTSTR *
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
+#endif
+
+#define INSTANCEID_PREFIX_CHAR TEXT('@') // character used to prefix instance ID's
+#define CLASS_PREFIX_CHAR TEXT('=') // character used to prefix class name
+#define WILD_CHAR TEXT('*') // wild character
+#define QUOTE_PREFIX_CHAR TEXT('\'') // prefix character to ignore wild characters
+
+#define MSG_FIND_TAIL_NONE_LOCAL TEXT("No matching devices found.\n")
+#define MSG_ENABLE_TAIL TEXT("%lu device(s) are enabled.\n")
+#define MSG_ENABLE_TAIL_REBOOT TEXT("The %lu device(s) are ready to be enabled. To enable the devices, restart the devices or reboot the system.\n")
+#define MSG_DISABLE_TAIL TEXT("%lu device(s) are disabled.\n")
+#define MSG_DISABLE_TAIL_REBOOT TEXT("The %lu device(s) are ready to be disabled. To disable the devices, restart the devices or reboot the system.\n")
+#define MSG_RESTART_TAIL TEXT("%lu device(s) are restarted.\n")
+#define MSG_RESTART_TAIL_REBOOT TEXT("The %lu device(s) are ready to be restarted. To restart the devices, reboot the system.\n")
+
+#define IDS_ENABLED TEXT("Enabled")
+#define IDS_ENABLED_REBOOT TEXT("Enabled on reboot")
+#define IDS_ENABLE_FAILED TEXT("Enable failed")
+#define IDS_DISABLED TEXT("Disabled")
+#define IDS_DISABLED_REBOOT TEXT("Disabled on reboot")
+#define IDS_DISABLE_FAILED TEXT("Disable failed")
+#define IDS_RESTARTED TEXT("Restarted")
+#define IDS_REQUIRES_REBOOT TEXT("Requires reboot")
+#define IDS_RESTART_FAILED TEXT("Restart failed")
+#define IDS_REMOVED TEXT("Removed")
+#define IDS_REMOVED_REBOOT TEXT("Removed on reboot")
+#define IDS_REMOVE_FAILED TEXT("Remove failed")
+
+struct IdEntry {
+ LPCTSTR String; // string looking for
+ LPCTSTR Wild; // first wild character if any
+ BOOL InstanceId;
+};
+
+
+static IdEntry
+GetIdType(LPCTSTR Id)
+/*++
+
+Routine Description:
+
+ Determine if this is instance id or hardware id and if there's any wildcards
+ instance ID is prefixed by '@'
+ wildcards are '*'
+
+
+Arguments:
+
+ Id - ptr to string to check
+
+Return Value:
+
+ IdEntry
+
+--*/
+{
+ IdEntry Entry;
+
+ Entry.InstanceId = FALSE;
+ Entry.Wild = NULL;
+ Entry.String = Id;
+
+ if(Entry.String[0] == INSTANCEID_PREFIX_CHAR) {
+ Entry.InstanceId = TRUE;
+ Entry.String = CharNext(Entry.String);
+ }
+ if(Entry.String[0] == QUOTE_PREFIX_CHAR) {
+ //
+ // prefix to treat rest of string literally
+ //
+ Entry.String = CharNext(Entry.String);
+ } else {
+ //
+ // see if any wild characters exist
+ //
+ Entry.Wild = _tcschr(Entry.String, WILD_CHAR);
+ }
+ return Entry;
+}
+
+
+static BOOL
+WildCardMatch(LPCTSTR Item, const IdEntry & MatchEntry)
+/*++
+
+Routine Description:
+
+ Compare a single item against wildcard
+ I'm sure there's better ways of implementing this
+ Other than a command-line management tools
+ it's a bad idea to use wildcards as it implies
+ assumptions about the hardware/instance ID
+ eg, it might be tempting to enumerate root\* to
+ find all root devices, however there is a CfgMgr
+ API to query status and determine if a device is
+ root enumerated, which doesn't rely on implementation
+ details.
+
+Arguments:
+
+ Item - item to find match for eg a\abcd\c
+ MatchEntry - eg *\*bc*\*
+
+Return Value:
+
+ TRUE if any match, otherwise FALSE
+
+--*/
+{
+ LPCTSTR scanItem;
+ LPCTSTR wildMark;
+ LPCTSTR nextWild;
+ size_t matchlen;
+
+ //
+ // before attempting anything else
+ // try and compare everything up to first wild
+ //
+ if(!MatchEntry.Wild) {
+ return _tcsicmp(Item, MatchEntry.String) ? FALSE : TRUE;
+ }
+ if(_tcsnicmp(Item, MatchEntry.String, MatchEntry.Wild-MatchEntry.String) != 0) {
+ return FALSE;
+ }
+ wildMark = MatchEntry.Wild;
+ scanItem = Item + (MatchEntry.Wild-MatchEntry.String);
+
+ for(;wildMark[0];) {
+ //
+ // if we get here, we're either at or past a wildcard
+ //
+ if(wildMark[0] == WILD_CHAR) {
+ //
+ // so skip wild chars
+ //
+ wildMark = CharNext(wildMark);
+ continue;
+ }
+ //
+ // find next wild-card
+ //
+ nextWild = _tcschr(wildMark, WILD_CHAR);
+ if(nextWild) {
+ //
+ // substring
+ //
+ matchlen = nextWild-wildMark;
+ } else {
+ //
+ // last portion of match
+ //
+ size_t scanlen = lstrlen(scanItem);
+ matchlen = lstrlen(wildMark);
+ if(scanlen < matchlen) {
+ return FALSE;
+ }
+ return _tcsicmp(scanItem+scanlen-matchlen, wildMark) ? FALSE : TRUE;
+ }
+ if(_istalpha(wildMark[0])) {
+ //
+ // scan for either lower or uppercase version of first character
+ //
+
+ //
+ // the code suppresses the warning 28193 for the calls to _totupper
+ // and _totlower. This suppression is done because those functions
+ // have a check return annotation on them. However, they don't return
+ // error codes and the check return annotation is really being used
+ // to indicate that the return value of the function should be looked
+ // at and/or assigned to a variable. The check return annotation means
+ // the return value should always be checked in all code paths.
+ // We assign the return values to variables but the while loop does not
+ // examine both values in all code paths (e.g. when scanItem[0] == 0,
+ // neither u nor l will be examined) and it doesn't need to examine
+ // the values in all code paths.
+ //
+#ifdef _MSC_VER
+#pragma warning( suppress: 28193)
+#endif
+ TCHAR u = _totupper(wildMark[0]);
+#ifdef _MSC_VER
+#pragma warning( suppress: 28193)
+#endif
+ TCHAR l = _totlower(wildMark[0]);
+ while(scanItem[0] && scanItem[0]!=u && scanItem[0]!=l) {
+ scanItem = CharNext(scanItem);
+ }
+ if(!scanItem[0]) {
+ //
+ // ran out of string
+ //
+ return FALSE;
+ }
+ } else {
+ //
+ // scan for first character (no case)
+ //
+ scanItem = _tcschr(scanItem, wildMark[0]);
+ if(!scanItem) {
+ //
+ // ran out of string
+ //
+ return FALSE;
+ }
+ }
+ //
+ // try and match the sub-string at wildMark against scanItem
+ //
+ if(_tcsnicmp(scanItem, wildMark, matchlen)!=0) {
+ //
+ // nope, try again
+ //
+ scanItem = CharNext(scanItem);
+ continue;
+ }
+ //
+ // substring matched
+ //
+ scanItem += matchlen;
+ wildMark += matchlen;
+ }
+ return (wildMark[0] ? FALSE : TRUE);
+}
+
+
+static BOOL
+WildCompareHwIds(PZPTSTR Array, const IdEntry & MatchEntry)
+/*++
+
+Routine Description:
+
+ Compares all strings in Array against Id
+ Use WildCardMatch to do real compare
+
+Arguments:
+
+ Array - pointer returned by GetDevMultiSz
+ MatchEntry - string to compare against
+
+Return Value:
+
+ TRUE if any match, otherwise FALSE
+
+--*/
+{
+ if(Array) {
+ while(Array[0]) {
+ if(WildCardMatch(Array[0], MatchEntry)) {
+ return TRUE;
+ }
+ Array++;
+ }
+ }
+ return FALSE;
+}
+
+
+static LPTSTR *
+GetMultiSzIndexArray(LPTSTR MultiSz)
+/*++
+
+Routine Description:
+
+ Get an index array pointing to the MultiSz passed in
+
+Arguments:
+
+ MultiSz - well formed multi-sz string
+
+Return Value:
+
+ array of strings. last entry+1 of array contains NULL
+ returns NULL on failure
+
+--*/
+{
+ LPTSTR scan;
+ LPTSTR * array;
+ int elements;
+
+ for(scan = MultiSz, elements = 0; scan[0] ;elements++) {
+ scan += lstrlen(scan)+1;
+ }
+ array = new LPTSTR[elements+2];
+ if(!array) {
+ return NULL;
+ }
+ array[0] = MultiSz;
+ array++;
+ if(elements) {
+ for(scan = MultiSz, elements = 0; scan[0]; elements++) {
+ array[elements] = scan;
+ scan += lstrlen(scan)+1;
+ }
+ }
+ array[elements] = NULL;
+ return array;
+}
+
+
+static void
+DelMultiSz(PZPTSTR Array)
+/*++
+
+Routine Description:
+
+ Deletes the string array allocated by GetDevMultiSz/GetRegMultiSz/GetMultiSzIndexArray
+
+Arguments:
+
+ Array - pointer returned by GetMultiSzIndexArray
+
+Return Value:
+
+ None
+
+--*/
+{
+ if(Array) {
+ Array--;
+ if(Array[0]) {
+ delete [] Array[0];
+ }
+ delete [] Array;
+ }
+}
+
+
+static LPTSTR *
+GetDevMultiSz(HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Prop)
+/*++
+
+Routine Description:
+
+ Get a multi-sz device property
+ and return as an array of strings
+
+Arguments:
+
+ Devs - HDEVINFO containing DevInfo
+ DevInfo - Specific device
+ Prop - SPDRP_HARDWAREID or SPDRP_COMPATIBLEIDS
+
+Return Value:
+
+ array of strings. last entry+1 of array contains NULL
+ returns NULL on failure
+
+--*/
+{
+ LPTSTR buffer;
+ DWORD size;
+ DWORD reqSize;
+ DWORD dataType;
+ LPTSTR * array;
+ DWORD szChars;
+
+ size = 8192; // initial guess, nothing magic about this
+ buffer = new TCHAR[(size/sizeof(TCHAR))+2];
+ if(!buffer) {
+ return NULL;
+ }
+ while(!SetupDiGetDeviceRegistryProperty(Devs, DevInfo, Prop, &dataType, (LPBYTE)buffer, size, &reqSize)) {
+ if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ goto failed;
+ }
+ if(dataType != REG_MULTI_SZ) {
+ goto failed;
+ }
+ size = reqSize;
+ delete [] buffer;
+ buffer = new TCHAR[(size/sizeof(TCHAR))+2];
+ if(!buffer) {
+ goto failed;
+ }
+ }
+ szChars = reqSize/sizeof(TCHAR);
+ buffer[szChars] = TEXT('\0');
+ buffer[szChars+1] = TEXT('\0');
+ array = GetMultiSzIndexArray(buffer);
+ if(array) {
+ return array;
+ }
+
+failed:
+ if(buffer) {
+ delete [] buffer;
+ }
+ return NULL;
+}
+
+
+typedef int (*CallbackFunc)(HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Index, LPVOID Context);
+
+
+static int
+EnumerateDevices(DWORD Flags, int argc, PCTSTR* argv, CallbackFunc Callback, LPVOID Context)
+/*++
+
+Routine Description:
+
+ Generic enumerator for devices that will be passed the following arguments:
+ <id> [<id>...]
+ =<class> [<id>...]
+ where <id> can either be @instance-id, or hardware-id and may contain wildcards
+ <class> is a class name
+
+Arguments:
+
+ Flags - extra enumeration flags (eg DIGCF_PRESENT)
+ argc/argv - remaining arguments on command line
+ Callback - function to call for each hit
+ Context - data to pass function for each hit
+
+Return Value:
+
+ DEVCON_xxxx
+
+--*/
+{
+ HDEVINFO devs = INVALID_HANDLE_VALUE;
+ IdEntry * templ = NULL;
+ int failcode = DEVCON_FAIL;
+ int retcode;
+ int argIndex;
+ DWORD devIndex;
+ SP_DEVINFO_DATA devInfo;
+ SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
+ BOOL doSearch = FALSE;
+ BOOL match;
+ BOOL all = FALSE;
+ GUID cls;
+ DWORD numClass = 0;
+ int skip = 0;
+
+ if(!argc) {
+ return DEVCON_USAGE;
+ }
+
+ templ = new IdEntry[argc];
+ if(!templ) {
+ goto final;
+ }
+
+ //
+ // determine if a class is specified
+ //
+ if(argc>skip && argv[skip][0]==CLASS_PREFIX_CHAR && argv[skip][1]) {
+ if(!SetupDiClassGuidsFromNameEx(argv[skip]+1, &cls, 1, &numClass, NULL, NULL) &&
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ goto final;
+ }
+ if(!numClass) {
+ failcode = DEVCON_OK;
+ goto final;
+ }
+ skip++;
+ }
+ if(argc>skip && argv[skip][0]==WILD_CHAR && !argv[skip][1]) {
+ //
+ // catch convinient case of specifying a single argument '*'
+ //
+ all = TRUE;
+ skip++;
+ } else if(argc<=skip) {
+ //
+ // at least one parameter, but no <id>'s
+ //
+ all = TRUE;
+ }
+
+ //
+ // determine if any instance id's were specified
+ //
+ // note, if =<class> was specified with no id's
+ // we'll mark it as not doSearch
+ // but will go ahead and add them all
+ //
+ for(argIndex=skip;argIndex<argc;argIndex++) {
+ templ[argIndex] = GetIdType(argv[argIndex]);
+ if(templ[argIndex].Wild || !templ[argIndex].InstanceId) {
+ //
+ // anything other than simple InstanceId's require a search
+ //
+ doSearch = TRUE;
+ }
+ }
+ if(doSearch || all) {
+ //
+ // add all id's to list
+ // if there's a class, filter on specified class
+ //
+ devs = SetupDiGetClassDevsEx(numClass ? &cls : NULL,
+ NULL,
+ NULL,
+ (numClass ? 0 : DIGCF_ALLCLASSES) | Flags,
+ NULL,
+ NULL,
+ NULL);
+
+ } else {
+ //
+ // blank list, we'll add instance id's by hand
+ //
+ devs = SetupDiCreateDeviceInfoListEx(numClass ? &cls : NULL,
+ NULL,
+ NULL,
+ NULL);
+ }
+ if(devs == INVALID_HANDLE_VALUE) {
+ goto final;
+ }
+ for(argIndex=skip;argIndex<argc;argIndex++) {
+ //
+ // add explicit instances to list (even if enumerated all,
+ // this gets around DIGCF_PRESENT)
+ // do this even if wildcards appear to be detected since they
+ // might actually be part of the instance ID of a non-present device
+ //
+ if(templ[argIndex].InstanceId) {
+ SetupDiOpenDeviceInfo(devs, templ[argIndex].String, NULL, 0, NULL);
+ }
+ }
+
+ devInfoListDetail.cbSize = sizeof(devInfoListDetail);
+ if(!SetupDiGetDeviceInfoListDetail(devs, &devInfoListDetail)) {
+ goto final;
+ }
+
+ //
+ // now enumerate them
+ //
+ if(all) {
+ doSearch = FALSE;
+ }
+
+ devInfo.cbSize = sizeof(devInfo);
+ for(devIndex=0;SetupDiEnumDeviceInfo(devs, devIndex, &devInfo);devIndex++) {
+
+ if(doSearch) {
+ for(argIndex=skip, match=FALSE;(argIndex<argc) && !match;argIndex++) {
+ TCHAR devID[MAX_DEVICE_ID_LEN];
+ LPTSTR *hwIds = NULL;
+ LPTSTR *compatIds = NULL;
+ //
+ // determine instance ID
+ //
+ if(CM_Get_Device_ID_Ex(devInfo.DevInst, devID, MAX_DEVICE_ID_LEN, 0, devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS) {
+ devID[0] = TEXT('\0');
+ }
+
+ if(templ[argIndex].InstanceId) {
+ //
+ // match on the instance ID
+ //
+ if(WildCardMatch(devID, templ[argIndex])) {
+ match = TRUE;
+ }
+ } else {
+ //
+ // determine hardware ID's
+ // and search for matches
+ //
+ hwIds = GetDevMultiSz(devs, &devInfo, SPDRP_HARDWAREID);
+ compatIds = GetDevMultiSz(devs, &devInfo, SPDRP_COMPATIBLEIDS);
+
+ if(WildCompareHwIds(hwIds, templ[argIndex]) ||
+ WildCompareHwIds(compatIds, templ[argIndex])) {
+ match = TRUE;
+ }
+ }
+ DelMultiSz(hwIds);
+ DelMultiSz(compatIds);
+ }
+ } else {
+ match = TRUE;
+ }
+ if(match) {
+ retcode = Callback(devs, &devInfo, devIndex, Context);
+ if(retcode) {
+ failcode = retcode;
+ goto final;
+ }
+ }
+ }
+
+ failcode = DEVCON_OK;
+
+final:
+ if(templ) {
+ delete [] templ;
+ }
+ if(devs != INVALID_HANDLE_VALUE) {
+ SetupDiDestroyDeviceInfoList(devs);
+ }
+ return failcode;
+
+}
+
+
+struct GenericContext {
+ DWORD count;
+ DWORD control;
+ BOOL reboot;
+ LPCTSTR strSuccess;
+ LPCTSTR strReboot;
+ LPCTSTR strFail;
+};
+
+
+static BOOL
+DumpDeviceWithInfo(HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, LPCTSTR Info)
+/*++
+
+Routine Description:
+
+ Write device instance & info to stdout
+
+Arguments:
+
+ Devs )_ uniquely identify device
+ DevInfo )
+
+Return Value:
+
+ none
+
+--*/
+{
+ TCHAR devID[MAX_DEVICE_ID_LEN];
+ BOOL b = TRUE;
+ SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
+
+ devInfoListDetail.cbSize = sizeof(devInfoListDetail);
+ if((!SetupDiGetDeviceInfoListDetail(Devs, &devInfoListDetail)) ||
+ (CM_Get_Device_ID_Ex(DevInfo->DevInst, devID, MAX_DEVICE_ID_LEN, 0, devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) {
+ StringCchCopy(devID, ARRAYSIZE(devID), TEXT("?"));
+ b = FALSE;
+ }
+
+ if(Info) {
+ _tprintf(TEXT("%-60s: %s\n"), devID, Info);
+ } else {
+ _tprintf(TEXT("%s\n"), devID);
+ }
+ return b;
+}
+
+
+static int
+ControlCallback(HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Index, LPVOID Context)
+/*++
+
+Routine Description:
+
+ Callback for use by Enable/Disable/Restart
+ Invokes DIF_PROPERTYCHANGE with correct parameters
+ uses SetupDiCallClassInstaller so cannot be done for remote devices
+ Don't use CM_xxx API's, they bypass class/co-installers and this is bad.
+
+ In Enable case, we try global first, and if still disabled, enable local
+
+Arguments:
+
+ Devs )_ uniquely identify the device
+ DevInfo )
+ Index - index of device
+ Context - GenericContext
+
+Return Value:
+
+ DEVCON_xxxx
+
+--*/
+{
+ SP_PROPCHANGE_PARAMS pcp;
+ GenericContext *pControlContext = (GenericContext*)Context;
+ SP_DEVINSTALL_PARAMS devParams;
+
+ UNREFERENCED_PARAMETER(Index);
+
+ switch(pControlContext->control) {
+ case DICS_ENABLE:
+ //
+ // enable both on global and config-specific profile
+ // do global first and see if that succeeded in enabling the device
+ // (global enable doesn't mark reboot required if device is still
+ // disabled on current config whereas vice-versa isn't true)
+ //
+ pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ pcp.StateChange = pControlContext->control;
+ pcp.Scope = DICS_FLAG_GLOBAL;
+ pcp.HwProfile = 0;
+ //
+ // don't worry if this fails, we'll get an error when we try config-
+ // specific.
+ if(SetupDiSetClassInstallParams(Devs, DevInfo, &pcp.ClassInstallHeader, sizeof(pcp))) {
+ SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, Devs, DevInfo);
+ }
+ //
+ // now enable on config-specific
+ //
+ pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ pcp.StateChange = pControlContext->control;
+ pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
+ pcp.HwProfile = 0;
+ break;
+
+ default:
+ //
+ // operate on config-specific profile
+ //
+ pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ pcp.StateChange = pControlContext->control;
+ pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
+ pcp.HwProfile = 0;
+ break;
+
+ }
+
+ if(!SetupDiSetClassInstallParams(Devs, DevInfo, &pcp.ClassInstallHeader, sizeof(pcp)) ||
+ !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, Devs, DevInfo)) {
+ //
+ // failed to invoke DIF_PROPERTYCHANGE
+ //
+ DumpDeviceWithInfo(Devs, DevInfo, pControlContext->strFail);
+ } else {
+ //
+ // see if device needs reboot
+ //
+ devParams.cbSize = sizeof(devParams);
+ if(SetupDiGetDeviceInstallParams(Devs, DevInfo, &devParams) && (devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT))) {
+ DumpDeviceWithInfo(Devs, DevInfo, pControlContext->strReboot);
+ pControlContext->reboot = TRUE;
+ } else {
+ //
+ // appears to have succeeded
+ //
+ DumpDeviceWithInfo(Devs, DevInfo, pControlContext->strSuccess);
+ }
+ pControlContext->count++;
+ }
+ return DEVCON_OK;
+}
+
+
+int
+devconEnable(int argc, PCTSTR argv[])
+/*++
+
+Routine Description:
+
+ ENABLE <id> ...
+ use EnumerateDevices to do hardwareID matching
+ for each match, attempt to enable global, and if needed, config specific
+
+Arguments:
+
+ argc/argv - remaining parameters - passed into EnumerateDevices
+
+Return Value:
+
+ DEVCON_xxxx (DEVCON_REBOOT if reboot is required)
+
+--*/
+{
+ GenericContext context;
+ int failcode = DEVCON_FAIL;
+
+ if(!argc) {
+ //
+ // arguments required
+ //
+ return DEVCON_USAGE;
+ }
+
+ context.control = DICS_ENABLE; // DICS_PROPCHANGE DICS_ENABLE DICS_DISABLE
+ context.reboot = FALSE;
+ context.count = 0;
+ context.strReboot = IDS_ENABLED_REBOOT;
+ context.strSuccess = IDS_ENABLED;
+ context.strFail = IDS_ENABLE_FAILED;
+ failcode = EnumerateDevices(DIGCF_PRESENT, argc, argv, ControlCallback, &context);
+
+ if(failcode == DEVCON_OK) {
+
+ if(!context.count) {
+ fprintf(stdout, MSG_FIND_TAIL_NONE_LOCAL);
+ } else if(!context.reboot) {
+ fprintf(stdout, MSG_ENABLE_TAIL, context.count);
+ } else {
+ fprintf(stdout, MSG_ENABLE_TAIL_REBOOT, context.count);
+ failcode = DEVCON_REBOOT;
+ }
+ }
+ return failcode;
+}
+
+
+int
+devconDisable(int argc, PCTSTR argv[])
+/*++
+
+Routine Description:
+
+ DISABLE <id> ...
+ use EnumerateDevices to do hardwareID matching
+ for each match, attempt to disable global
+
+Arguments:
+
+ argc/argv - remaining parameters - passed into EnumerateDevices
+
+Return Value:
+
+ DEVCON_xxxx (DEVCON_REBOOT if reboot is required)
+
+--*/
+{
+ GenericContext context;
+ int failcode = DEVCON_FAIL;
+
+ if(!argc) {
+ //
+ // arguments required
+ //
+ return DEVCON_USAGE;
+ }
+
+ context.control = DICS_DISABLE; // DICS_PROPCHANGE DICS_ENABLE DICS_DISABLE
+ context.reboot = FALSE;
+ context.count = 0;
+ context.strReboot = IDS_DISABLED_REBOOT;
+ context.strSuccess = IDS_DISABLED;
+ context.strFail = IDS_DISABLE_FAILED;
+ failcode = EnumerateDevices(DIGCF_PRESENT, argc, argv, ControlCallback, &context);
+
+ if(failcode == DEVCON_OK) {
+
+ if(!context.count) {
+ fprintf(stdout, MSG_FIND_TAIL_NONE_LOCAL);
+ } else if(!context.reboot) {
+ fprintf(stdout, MSG_DISABLE_TAIL, context.count);
+ } else {
+ fprintf(stdout, MSG_DISABLE_TAIL_REBOOT, context.count);
+ failcode = DEVCON_REBOOT;
+ }
+ }
+ return failcode;
+}
+
+
+int
+devconRestart(int argc, PCTSTR argv[])
+/*++
+
+Routine Description:
+
+ RESTART <id> ...
+ use EnumerateDevices to do hardwareID matching
+ for each match, attempt to restart by issueing a PROPCHANGE
+
+Arguments:
+
+ argc/argv - remaining parameters - passed into EnumerateDevices
+
+Return Value:
+
+ DEVCON_xxxx (DEVCON_REBOOT if reboot is required)
+
+--*/
+{
+ GenericContext context;
+ int failcode = DEVCON_FAIL;
+
+ if(!argc) {
+ //
+ // arguments required
+ //
+ return DEVCON_USAGE;
+ }
+
+ context.control = DICS_PROPCHANGE;
+ context.reboot = FALSE;
+ context.count = 0;
+ context.strReboot = IDS_REQUIRES_REBOOT;
+ context.strSuccess = IDS_RESTARTED;
+ context.strFail = IDS_RESTART_FAILED;
+ failcode = EnumerateDevices(DIGCF_PRESENT, argc, argv, ControlCallback, &context);
+
+ if(failcode == DEVCON_OK) {
+
+ if(!context.count) {
+ fprintf(stdout, MSG_FIND_TAIL_NONE_LOCAL);
+ } else if(!context.reboot) {
+ fprintf(stdout, MSG_RESTART_TAIL, context.count);
+ } else {
+ fprintf(stdout, MSG_RESTART_TAIL_REBOOT, context.count);
+ failcode = DEVCON_REBOOT;
+ }
+ }
+ return failcode;
+}
diff --git a/thirdparty/devcon/devcon.hpp b/thirdparty/devcon/devcon.hpp
new file mode 100644
index 00000000..6ece3731
--- /dev/null
+++ b/thirdparty/devcon/devcon.hpp
@@ -0,0 +1,70 @@
+/***************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ * This source is subject to the Microsoft Public License.
+ * See http://www.microsoft.com/en-us/openness/licenses.aspx#MPL.
+ * All other rights reserved.
+ *
+ * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+ * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ ***************************************************************************/
+
+/*
+ * Interface for managing devices.
+ *
+ * http://code.msdn.microsoft.com/windowshardware/DevCon-Sample-4e95d71c
+ * http://support.microsoft.com/kb/311272
+ */
+
+
+
+
+#pragma once
+
+
+#include <windows.h>
+#include <tchar.h>
+
+
+//
+// exit codes
+//
+#define DEVCON_OK (0)
+#define DEVCON_REBOOT (1)
+#define DEVCON_FAIL (2)
+#define DEVCON_USAGE (3)
+
+
+#define DEVCON_CLASS_DISPLAY TEXT("=DISPLAY")
+
+
+int
+devconEnable(int argc, PCTSTR argv[]);
+
+int
+devconDisable(int argc, PCTSTR argv[]);
+
+int
+devconRestart(int argc, PCTSTR argv[]);
+
+
+static inline int
+devconEnable(PCTSTR arg)
+{
+ return devconEnable(1, &arg);
+}
+
+static inline int
+devconDisable(PCTSTR arg)
+{
+ return devconDisable(1, &arg);
+}
+
+static inline int
+devconRestart(PCTSTR arg)
+{
+ return devconRestart(1, &arg);
+}
diff --git a/thirdparty/devcon/license.rtf b/thirdparty/devcon/license.rtf
new file mode 100644
index 00000000..690a7ad0
--- /dev/null
+++ b/thirdparty/devcon/license.rtf
@@ -0,0 +1,25 @@
+{\rtf1\ansi\ansicpg1252\uc1\htmautsp\deff2{\fonttbl{\f0\fcharset0 Times New Roman;}{\f2\fcharset0 MS Shell Dlg;}}{\colortbl\red0\green0\blue0;\red255\green255\blue255;}\loch\hich\dbch\pard\plain\ltrpar\itap0{\lang1033\fs16\f2\cf0 \cf0\ql{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\fs40\f2 {\ltrch MICROSOFT LIMITED PUBLIC LICENSE version 1.1}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line {\ltrch ----------------------}\line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch This license governs use of code marked as \ldblquote sample\rdblquote or \ldblquote example\rdblquote available on this web site without a license agreement, as provided under the section above titled \ldblquote NOTICE SPECIFIC TO SOFTWARE AVAILABLE ON THIS WEB SITE.\rdblquote If you use such code (the \ldblquote software\rdblquote ), you accept this license. If you do not accept the license, do not use the software.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch 1. Definitions}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch The terms \ldblquote reproduce,\rdblquote \ldblquote reproduction,\rdblquote \ldblquote derivative works,\rdblquote and \ldblquote distribution\rdblquote have the same meaning here as under U.S. copyright law. }\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch A \ldblquote contribution\rdblquote is the original software, or any additions or changes to the software.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch A \ldblquote contributor\rdblquote is any person that distributes its contribution under this license.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch \ldblquote Licensed patents\rdblquote are a contributor\rquote s patent claims that read directly on its contribution.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch 2. Grant of Rights}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (A) Copyright Grant - Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (B) Patent Grant - Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch 3. Conditions and Limitations}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (A) No Trademark License- This license does not grant you rights to use any contributors\rquote name, logo, or trademarks.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (E) The software is licensed \ldblquote as-is.\rdblquote You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 {\ltrch (F) Platform Limitation - The licenses granted in sections 2(A) and 2(B) extend only to the software or derivative works that you create that run directly on a Microsoft Windows operating system product, Microsoft run-time technology (such as the .NET Framework or Silverlight), or Microsoft application platform (such as Microsoft Office or Microsoft Dynamics).}\li0\ri0\sa0\sb0\fi0\ql\par}
+{\f2 \line \li0\ri0\sa0\sb0\fi0\ql\par}
+}
+} \ No newline at end of file
diff --git a/thirdparty/directxtex/CMakeLists.txt b/thirdparty/directxtex/CMakeLists.txt
index bd8f285a..6ed1d7e5 100644
--- a/thirdparty/directxtex/CMakeLists.txt
+++ b/thirdparty/directxtex/CMakeLists.txt
@@ -1,6 +1,6 @@
include (CheckIncludeFileCXX)
-if (DirectX_D3D11_INCLUDE_DIR)
+if (DirectX_D3D11_INCLUDE_FOUND)
include_directories (BEFORE
${DirectX_D3D11_INCLUDE_DIR}
@@ -15,25 +15,16 @@ if (DirectX_D3D11_INCLUDE_DIR)
endif ()
if (MINGW)
- # Older versions of MinGW do not include the sal.h header. Use our own.
- check_include_file_cxx (sal.h HAVE_SAL_H)
- if (NOT HAVE_SAL_H)
- include_directories (BEFORE ${CMAKE_SOURCE_DIR}/thirdparty/mingw/sal)
- endif ()
-
- # MinGW wincodec.h is incomplete. Use our own.
- include_directories (BEFORE ${CMAKE_SOURCE_DIR}/thirdparty/mingw/wincodec)
+ # Several MinGW headers are lacking. Use our own.
+ include_directories (BEFORE
+ ${CMAKE_SOURCE_DIR}/thirdparty/mingw/wincodec
+ ${CMAKE_SOURCE_DIR}/thirdparty/mingw/wrl
+ )
include_directories (BEFORE
${CMAKE_SOURCE_DIR}/dispatch # for compat.h
)
add_definitions (
- # Support static_assert, nullptr, and unique_ptr.
- #
- # `-std=c++0x` doesn't work here, as it will define __STRICT_ANSI__
- # which will prevent _isnan from being declared.
- -std=gnu++0x
-
#inhibit warnings
-w
@@ -72,4 +63,9 @@ if (DirectX_D3D11_INCLUDE_DIR)
${MINGW_GUID}
)
+ install (
+ FILES MIT.txt
+ DESTINATION ${DOC_INSTALL_DIR}
+ RENAME LICENSE-directxtex.txt
+ )
endif ()
diff --git a/thirdparty/directxtex/DirectXTex/BC.cpp b/thirdparty/directxtex/DirectXTex/BC.cpp
index c47296df..2d03d2b2 100644
--- a/thirdparty/directxtex/DirectXTex/BC.cpp
+++ b/thirdparty/directxtex/DirectXTex/BC.cpp
@@ -63,7 +63,7 @@ inline static uint16_t Encode565(_In_ const HDRColorA *pColor)
//-------------------------------------------------------------------------------------
static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
- _In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pPoints, _In_ size_t cSteps, _In_ DWORD flags)
+ _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pPoints, _In_ size_t cSteps, _In_ DWORD flags)
{
static const float fEpsilon = (0.25f / 64.0f) * (0.25f / 64.0f);
static const float pC3[] = { 2.0f/2.0f, 1.0f/2.0f, 0.0f/2.0f };
@@ -254,7 +254,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
size_t iStep;
if(fDot <= 0.0f)
iStep = 0;
- if(fDot >= fSteps)
+ else if(fDot >= fSteps)
iStep = cSteps - 1;
else
iStep = static_cast<size_t>(fDot + 0.5f);
@@ -317,7 +317,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
//-------------------------------------------------------------------------------------
-inline static void DecodeBC1( _Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_ const D3DX_BC1 *pBC )
+inline static void DecodeBC1( _Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_ const D3DX_BC1 *pBC, _In_ bool isbc1 )
{
assert( pColor && pBC );
static_assert( sizeof(D3DX_BC1) == 8, "D3DX_BC1 should be 8 bytes" );
@@ -330,14 +330,14 @@ inline static void DecodeBC1( _Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor
clr0 = XMVectorMultiply( clr0, s_Scale );
clr1 = XMVectorMultiply( clr1, s_Scale );
- clr0 = XMVectorSwizzle( clr0, 2, 1, 0, 3 );
- clr1 = XMVectorSwizzle( clr1, 2, 1, 0, 3 );
+ clr0 = XMVectorSwizzle<2, 1, 0, 3>( clr0 );
+ clr1 = XMVectorSwizzle<2, 1, 0, 3>( clr1 );
clr0 = XMVectorSelect( g_XMIdentityR3, clr0, g_XMSelect1110 );
clr1 = XMVectorSelect( g_XMIdentityR3, clr1, g_XMSelect1110 );
XMVECTOR clr2, clr3;
- if(pBC->rgb[0] <= pBC->rgb[1])
+ if ( isbc1 && (pBC->rgb[0] <= pBC->rgb[1]) )
{
clr2 = XMVectorLerp( clr0, clr1, 0.5f );
clr3 = XMVectorZero(); // Alpha of 0
@@ -366,9 +366,8 @@ inline static void DecodeBC1( _Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor
//-------------------------------------------------------------------------------------
-#pragma warning(disable: 4616 6001 6201)
-static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor,
+static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor,
_In_ bool bColorKey, _In_ float alphaRef, _In_ DWORD flags)
{
assert( pBC && pColor );
@@ -446,7 +445,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) co
if(3 != (i & 3))
{
assert( i < 15 );
- __analysis_assume( i < 15 );
+ _Analysis_assume_( i < 15 );
Error[i + 1].r += Diff.r * (7.0f / 16.0f);
Error[i + 1].g += Diff.g * (7.0f / 16.0f);
Error[i + 1].b += Diff.b * (7.0f / 16.0f);
@@ -468,7 +467,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) co
if(3 != (i & 3))
{
assert( i < 11 );
- __analysis_assume(i < 11 );
+ _Analysis_assume_( i < 11 );
Error[i + 5].r += Diff.r * (1.0f / 16.0f);
Error[i + 5].g += Diff.g * (1.0f / 16.0f);
Error[i + 5].b += Diff.b * (1.0f / 16.0f);
@@ -677,7 +676,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) co
//-------------------------------------------------------------------------------------
#ifdef COLOR_WEIGHTS
-static void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor)
+static void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor)
{
#ifdef COLOR_AVG_0WEIGHTS
// Compute avg color
@@ -717,12 +716,14 @@ static void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_count_c_(NUM_PIXELS_PER_BLOC
//-------------------------------------------------------------------------------------
// BC1 Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DXDecodeBC1(XMVECTOR *pColor, const uint8_t *pBC)
{
- const D3DX_BC1 *pBC1 = reinterpret_cast<const D3DX_BC1 *>(pBC);
- DecodeBC1( pColor, pBC1 );
+ auto pBC1 = reinterpret_cast<const D3DX_BC1 *>(pBC);
+ DecodeBC1( pColor, pBC1, true );
}
+_Use_decl_annotations_
void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD flags)
{
assert( pBC && pColor );
@@ -751,7 +752,7 @@ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD f
if(3 != (i & 3))
{
assert( i < 15 );
- __analysis_assume( i < 15 );
+ _Analysis_assume_( i < 15 );
fError[i + 1] += fDiff * (7.0f / 16.0f);
}
@@ -765,7 +766,7 @@ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD f
if(3 != (i & 3))
{
assert( i < 11 );
- __analysis_assume( i < 11 );
+ _Analysis_assume_( i < 11 );
fError[i + 5] += fDiff * (1.0f / 16.0f);
}
}
@@ -779,7 +780,7 @@ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD f
}
}
- D3DX_BC1 *pBC1 = reinterpret_cast<D3DX_BC1 *>(pBC);
+ auto pBC1 = reinterpret_cast<D3DX_BC1 *>(pBC);
EncodeBC1(pBC1, Color, true, alphaRef, flags);
}
@@ -787,21 +788,25 @@ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD f
//-------------------------------------------------------------------------------------
// BC2 Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes" );
- const D3DX_BC2 *pBC2 = reinterpret_cast<const D3DX_BC2 *>(pBC);
+ auto pBC2 = reinterpret_cast<const D3DX_BC2 *>(pBC);
// RGB part
- DecodeBC1(pColor, &pBC2->bc1);
+ DecodeBC1(pColor, &pBC2->bc1, false);
// 4-bit alpha part
DWORD dw = pBC2->bitmap[0];
for(size_t i = 0; i < 8; ++i, dw >>= 4)
+ {
+ #pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSetW( pColor[i], (float) (dw & 0xf) * (1.0f / 15.0f) );
+ }
dw = pBC2->bitmap[1];
@@ -809,6 +814,7 @@ void D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)
pColor[i] = XMVectorSetW( pColor[i], (float) (dw & 0xf) * (1.0f / 15.0f) );
}
+_Use_decl_annotations_
void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
assert( pBC && pColor );
@@ -820,7 +826,7 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( &Color[i] ), pColor[i] );
}
- D3DX_BC2 *pBC2 = reinterpret_cast<D3DX_BC2 *>(pBC);
+ auto pBC2 = reinterpret_cast<D3DX_BC2 *>(pBC);
// 4-bit alpha part. Dithered using Floyd Stienberg error diffusion.
pBC2->bitmap[0] = 0;
@@ -848,7 +854,7 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
if(3 != (i & 3))
{
assert( i < 15 );
- __analysis_assume( i < 15 );
+ _Analysis_assume_( i < 15 );
fError[i + 1] += fDiff * (7.0f / 16.0f);
}
@@ -862,7 +868,7 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
if(3 != (i & 3))
{
assert( i < 11 );
- __analysis_assume( i < 11 );
+ _Analysis_assume_( i < 11 );
fError[i + 5] += fDiff * (1.0f / 16.0f);
}
}
@@ -885,15 +891,16 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
//-------------------------------------------------------------------------------------
// BC3 Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes" );
- const D3DX_BC3 *pBC3 = reinterpret_cast<const D3DX_BC3 *>(pBC);
+ auto pBC3 = reinterpret_cast<const D3DX_BC3 *>(pBC);
// RGB part
- DecodeBC1(pColor, &pBC3->bc1);
+ DecodeBC1(pColor, &pBC3->bc1, false);
// Adaptive 3-bit alpha part
float fAlpha[8];
@@ -926,6 +933,7 @@ void D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
pColor[i] = XMVectorSetW( pColor[i], fAlpha[dw & 0x7] );
}
+_Use_decl_annotations_
void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
assert( pBC && pColor );
@@ -937,7 +945,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( &Color[i] ), pColor[i] );
}
- D3DX_BC3 *pBC3 = reinterpret_cast<D3DX_BC3 *>(pBC);
+ auto pBC3 = reinterpret_cast<D3DX_BC3 *>(pBC);
// Quantize block to A8, using Floyd Stienberg error diffusion. This
// increases the chance that colors will map directly to the quantized
@@ -971,7 +979,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
if(3 != (i & 3))
{
assert( i < 15 );
- __analysis_assume( i < 15 );
+ _Analysis_assume_( i < 15 );
fError[i + 1] += fDiff * (7.0f / 16.0f);
}
@@ -985,7 +993,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
if(3 != (i & 3))
{
assert( i < 11 );
- __analysis_assume( i < 11 );
+ _Analysis_assume_( i < 11 );
fError[i + 5] += fDiff * (1.0f / 16.0f);
}
}
@@ -1128,4 +1136,4 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
}
}
-} // namespace \ No newline at end of file
+} // namespace
diff --git a/thirdparty/directxtex/DirectXTex/BC.h b/thirdparty/directxtex/DirectXTex/BC.h
index 638058ea..26f999a3 100644
--- a/thirdparty/directxtex/DirectXTex/BC.h
+++ b/thirdparty/directxtex/DirectXTex/BC.h
@@ -13,9 +13,7 @@
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
-#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
-#endif
#include <assert.h>
@@ -28,11 +26,6 @@
#include <float.h>
-#pragma warning(push)
-#pragma warning(disable : 4005)
-#include <stdint.h>
-#pragma warning(pop)
-
namespace DirectX
{
@@ -50,7 +43,7 @@ const uint16_t F16S_MASK = 0x8000; // f16 sign mask
const uint16_t F16EM_MASK = 0x7fff; // f16 exp & mantissa mask
const uint16_t F16MAX = 0x7bff; // MAXFLT bit pattern for XMHALF
-#define SIGN_EXTEND(x,nb) ((((x)&(1<<((nb)-1)))?((~0)<<(nb)):0)|(x))
+#define SIGN_EXTEND(x,nb) ((((x)&(1<<((nb)-1)))?((~0)<<(nb)):0)|(x))
// Because these are used in SAL annotations, they need to remain macros rather than const values
#define NUM_PIXELS_PER_BLOCK 16
@@ -65,9 +58,9 @@ const size_t BC6H_MAX_SHAPES = 32;
const size_t BC7_NUM_CHANNELS = 4;
const size_t BC7_MAX_SHAPES = 64;
-const uint32_t BC67_WEIGHT_MAX = 64;
+const int32_t BC67_WEIGHT_MAX = 64;
const uint32_t BC67_WEIGHT_SHIFT = 6;
-const uint32_t BC67_WEIGHT_ROUND = 32;
+const int32_t BC67_WEIGHT_ROUND = 32;
extern const int g_aWeights2[4];
extern const int g_aWeights3[8];
@@ -79,6 +72,7 @@ enum BC_FLAGS
BC_FLAGS_DITHER_RGB = 0x10000, // Enables dithering for RGB colors for BC1-3
BC_FLAGS_DITHER_A = 0x20000, // Enables dithering for Alpha channel for BC1-3
BC_FLAGS_UNIFORM = 0x40000, // By default, uses perceptual weighting for BC1-3; this flag makes it a uniform weighting
+ BC_FLAGS_USE_3SUBSETS = 0x80000,// By default, BC7 skips mode 0 & 2; this flag adds those modes back
};
//-------------------------------------------------------------------------------------
@@ -91,7 +85,7 @@ class LDRColorA
public:
uint8_t r, g, b, a;
- LDRColorA() {}
+ LDRColorA() DIRECTX_CTOR_DEFAULT
LDRColorA(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) : r(_r), g(_g), b(_b), a(_a) {}
const uint8_t& operator [] (_In_range_(0,3) size_t uElement) const
@@ -120,14 +114,14 @@ public:
LDRColorA operator = (_In_ const HDRColorA& c);
- static void InterpolateRGB(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ size_t wcprec, _Out_ LDRColorA& out)
+ static void InterpolateRGB(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ _In_range_(2, 4) size_t wcprec, _Out_ LDRColorA& out)
{
const int* aWeights = nullptr;
switch(wcprec)
{
- case 2: aWeights = g_aWeights2; assert( wc < 4 ); __analysis_assume( wc < 4 ); break;
- case 3: aWeights = g_aWeights3; assert( wc < 8 ); __analysis_assume( wc < 8 ); break;
- case 4: aWeights = g_aWeights4; assert( wc < 16 ); __analysis_assume( wc < 16 ); break;
+ case 2: aWeights = g_aWeights2; assert( wc < 4 ); _Analysis_assume_( wc < 4 ); break;
+ case 3: aWeights = g_aWeights3; assert( wc < 8 ); _Analysis_assume_( wc < 8 ); break;
+ case 4: aWeights = g_aWeights4; assert( wc < 16 ); _Analysis_assume_( wc < 16 ); break;
default: assert(false); out.r = out.g = out.b = 0; return;
}
out.r = uint8_t((uint32_t(c0.r) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.r) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
@@ -135,33 +129,35 @@ public:
out.b = uint8_t((uint32_t(c0.b) * uint32_t(BC67_WEIGHT_MAX - aWeights[wc]) + uint32_t(c1.b) * uint32_t(aWeights[wc]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
}
- static void InterpolateA(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wa, _In_ size_t waprec, _Out_ LDRColorA& out)
+ static void InterpolateA(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wa, _In_range_(2, 4) _In_ size_t waprec, _Out_ LDRColorA& out)
{
const int* aWeights = nullptr;
switch(waprec)
{
- case 2: aWeights = g_aWeights2; assert( wa < 4 ); __analysis_assume( wa < 4 ); break;
- case 3: aWeights = g_aWeights3; assert( wa < 8 ); __analysis_assume( wa < 8 ); break;
- case 4: aWeights = g_aWeights4; assert( wa < 16 ); __analysis_assume( wa < 16 ); break;
+ case 2: aWeights = g_aWeights2; assert( wa < 4 ); _Analysis_assume_( wa < 4 ); break;
+ case 3: aWeights = g_aWeights3; assert( wa < 8 ); _Analysis_assume_( wa < 8 ); break;
+ case 4: aWeights = g_aWeights4; assert( wa < 16 ); _Analysis_assume_( wa < 16 ); break;
default: assert(false); out.a = 0; return;
}
out.a = uint8_t((uint32_t(c0.a) * uint32_t(BC67_WEIGHT_MAX - aWeights[wa]) + uint32_t(c1.a) * uint32_t(aWeights[wa]) + BC67_WEIGHT_ROUND) >> BC67_WEIGHT_SHIFT);
}
- static void Interpolate(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ size_t wa, _In_ size_t wcprec, _In_ size_t waprec, _Out_ LDRColorA& out)
+ static void Interpolate(_In_ const LDRColorA& c0, _In_ const LDRColorA& c1, _In_ size_t wc, _In_ size_t wa, _In_ _In_range_(2, 4) size_t wcprec, _In_ _In_range_(2, 4) size_t waprec, _Out_ LDRColorA& out)
{
InterpolateRGB(c0, c1, wc, wcprec, out);
InterpolateA(c0, c1, wa, waprec, out);
}
};
+static_assert( sizeof(LDRColorA) == 4, "Unexpected packing");
+
class HDRColorA
{
public:
float r, g, b, a;
public:
- HDRColorA() {}
+ HDRColorA() DIRECTX_CTOR_DEFAULT
HDRColorA(float _r, float _g, float _b, float _a) : r(_r), g(_g), b(_b), a(_a) {}
HDRColorA(const HDRColorA& c) : r(c.r), g(c.g), b(c.b), a(c.a) {}
HDRColorA(const LDRColorA& c)
@@ -322,9 +318,10 @@ class INTColor
{
public:
int r, g, b;
+ int pad;
public:
- INTColor() {}
+ INTColor() DIRECTX_CTOR_DEFAULT
INTColor(int nr, int ng, int nb) {r = nr; g = ng; b = nb;}
INTColor(const INTColor& c) {r = c.r; g = c.g; b = c.b;}
@@ -360,7 +357,7 @@ public:
int& operator [] ( _In_ uint8_t i )
{
assert(i < sizeof(INTColor) / sizeof(int));
- __analysis_assume(i < sizeof(INTColor) / sizeof(int));
+ _Analysis_assume_(i < sizeof(INTColor) / sizeof(int));
return ((int*) this)[i];
}
@@ -392,7 +389,7 @@ public:
return *this;
}
- void ToF16(_Out_cap_c_(3) HALF aF16[3], _In_ bool bSigned) const
+ void ToF16(_Out_writes_(3) HALF aF16[3], _In_ bool bSigned) const
{
aF16[0] = INT2F16(r, bSigned);
aF16[1] = INT2F16(g, bSigned);
@@ -445,6 +442,8 @@ private:
}
};
+static_assert( sizeof(INTColor) == 16, "Unexpected packing");
+
struct INTEndPntPair
{
INTColor A;
@@ -458,7 +457,7 @@ public:
uint8_t GetBit(_Inout_ size_t& uStartBit) const
{
assert(uStartBit < 128);
- __analysis_assume(uStartBit < 128);
+ _Analysis_assume_(uStartBit < 128);
size_t uIndex = uStartBit >> 3;
uint8_t ret = (m_uBits[uIndex] >> (uStartBit - (uIndex << 3))) & 0x01;
uStartBit++;
@@ -469,7 +468,7 @@ public:
{
if(uNumBits == 0) return 0;
assert(uStartBit + uNumBits <= 128 && uNumBits <= 8);
- __analysis_assume(uStartBit + uNumBits <= 128 && uNumBits <= 8);
+ _Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8);
uint8_t ret;
size_t uIndex = uStartBit >> 3;
size_t uBase = uStartBit - (uIndex << 3);
@@ -491,7 +490,7 @@ public:
void SetBit(_Inout_ size_t& uStartBit, _In_ uint8_t uValue)
{
assert(uStartBit < 128 && uValue < 2);
- __analysis_assume(uStartBit < 128 && uValue < 2);
+ _Analysis_assume_(uStartBit < 128 && uValue < 2);
size_t uIndex = uStartBit >> 3;
size_t uBase = uStartBit - (uIndex << 3);
m_uBits[uIndex] &= ~(1 << uBase);
@@ -504,7 +503,7 @@ public:
if(uNumBits == 0)
return;
assert(uStartBit + uNumBits <= 128 && uNumBits <= 8);
- __analysis_assume(uStartBit + uNumBits <= 128 && uNumBits <= 8);
+ _Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8);
assert(uValue < (1 << uNumBits));
size_t uIndex = uStartBit >> 3;
size_t uBase = uStartBit - (uIndex << 3);
@@ -529,17 +528,16 @@ private:
uint8_t m_uBits[ SizeInBytes ];
};
-#pragma warning(push)
-#pragma warning(disable : 4127 4480 4512)
-
// BC6H compression (16 bits per texel)
class D3DX_BC6H : private CBits< 16 >
{
public:
- void Decode(_In_ bool bSigned, _Out_cap_c_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) const;
- void Encode(_In_ bool bSigned, _In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn);
+ void Decode(_In_ bool bSigned, _Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) const;
+ void Encode(_In_ bool bSigned, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn);
private:
+#pragma warning(push)
+#pragma warning(disable : 4480)
enum EField : uint8_t
{
NA, // N/A
@@ -558,6 +556,7 @@ private:
BY,
BZ,
};
+#pragma warning(pop)
struct ModeDescriptor
{
@@ -574,6 +573,8 @@ private:
LDRColorA RGBAPrec[BC6H_MAX_REGIONS][2];
};
+#pragma warning(push)
+#pragma warning(disable : 4512)
struct EncodeParams
{
float fBestErr;
@@ -593,35 +594,36 @@ private:
}
}
};
+#pragma warning(pop)
static int Quantize(_In_ int iValue, _In_ int prec, _In_ bool bSigned);
static int Unquantize(_In_ int comp, _In_ uint8_t uBitsPerComp, _In_ bool bSigned);
static int FinishUnquantize(_In_ int comp, _In_ bool bSigned);
- static bool EndPointsFit(_In_ const EncodeParams* pEP, _In_count_c_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[]);
+ static bool EndPointsFit(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[]);
void GeneratePaletteQuantized(_In_ const EncodeParams* pEP, _In_ const INTEndPntPair& endPts,
- _Out_cap_c_(BC6H_MAX_INDICES) INTColor aPalette[]) const;
- float MapColorsQuantized(_In_ const EncodeParams* pEP, _In_count_(np) const INTColor aColors[], _In_ size_t np, _In_ const INTEndPntPair &endPts) const;
- float PerturbOne(_In_ const EncodeParams* pEP, _In_count_(np) const INTColor aColors[], _In_ size_t np, _In_ uint8_t ch,
+ _Out_writes_(BC6H_MAX_INDICES) INTColor aPalette[]) const;
+ float MapColorsQuantized(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ const INTEndPntPair &endPts) const;
+ float PerturbOne(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ uint8_t ch,
_In_ const INTEndPntPair& oldEndPts, _Out_ INTEndPntPair& newEndPts, _In_ float fOldErr, _In_ int do_b) const;
- void OptimizeOne(_In_ const EncodeParams* pEP, _In_count_(np) const INTColor aColors[], _In_ size_t np, _In_ float aOrgErr,
+ void OptimizeOne(_In_ const EncodeParams* pEP, _In_reads_(np) const INTColor aColors[], _In_ size_t np, _In_ float aOrgErr,
_In_ const INTEndPntPair &aOrgEndPts, _Out_ INTEndPntPair &aOptEndPts) const;
- void OptimizeEndPoints(_In_ const EncodeParams* pEP, _In_count_c_(BC6H_MAX_REGIONS) const float aOrgErr[],
- _In_count_c_(BC6H_MAX_REGIONS) const INTEndPntPair aOrgEndPts[],
- _Inout_count_c_(BC6H_MAX_REGIONS) INTEndPntPair aOptEndPts[]) const;
- static void SwapIndices(_In_ const EncodeParams* pEP, _Inout_count_c_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[],
- _In_count_c_(NUM_PIXELS_PER_BLOCK) size_t aIndices[]);
- void AssignIndices(_In_ const EncodeParams* pEP, _In_count_c_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[],
- _Out_cap_c_(NUM_PIXELS_PER_BLOCK) size_t aIndices[],
- _Out_cap_c_(BC6H_MAX_REGIONS) float aTotErr[]) const;
- void QuantizeEndPts(_In_ const EncodeParams* pEP, _Out_cap_c_(BC6H_MAX_REGIONS) INTEndPntPair* qQntEndPts) const;
- void EmitBlock(_In_ const EncodeParams* pEP, _In_count_c_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[],
- _In_count_c_(NUM_PIXELS_PER_BLOCK) const size_t aIndices[]);
+ void OptimizeEndPoints(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const float aOrgErr[],
+ _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aOrgEndPts[],
+ _Out_writes_all_(BC6H_MAX_REGIONS) INTEndPntPair aOptEndPts[]) const;
+ static void SwapIndices(_In_ const EncodeParams* pEP, _Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[],
+ _In_reads_(NUM_PIXELS_PER_BLOCK) size_t aIndices[]);
+ void AssignIndices(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[],
+ _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices[],
+ _Out_writes_(BC6H_MAX_REGIONS) float aTotErr[]) const;
+ void QuantizeEndPts(_In_ const EncodeParams* pEP, _Out_writes_(BC6H_MAX_REGIONS) INTEndPntPair* qQntEndPts) const;
+ void EmitBlock(_In_ const EncodeParams* pEP, _In_reads_(BC6H_MAX_REGIONS) const INTEndPntPair aEndPts[],
+ _In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndices[]);
void Refine(_Inout_ EncodeParams* pEP);
- static void GeneratePaletteUnquantized(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _Out_cap_c_(BC6H_MAX_INDICES) INTColor aPalette[]);
- float MapColors(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _In_ size_t np, _In_count_(np) const size_t* auIndex) const;
+ static void GeneratePaletteUnquantized(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _Out_writes_(BC6H_MAX_INDICES) INTColor aPalette[]);
+ float MapColors(_In_ const EncodeParams* pEP, _In_ size_t uRegion, _In_ size_t np, _In_reads_(np) const size_t* auIndex) const;
float RoughMSE(_Inout_ EncodeParams* pEP) const;
private:
@@ -634,8 +636,8 @@ private:
class D3DX_BC7 : private CBits< 16 >
{
public:
- void Decode(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) const;
- void Encode(_In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn);
+ void Decode(_Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut) const;
+ void Encode(bool skip3subsets, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pIn);
private:
struct ModeInfo
@@ -651,6 +653,8 @@ private:
LDRColorA RGBAPrecWithP;
};
+#pragma warning(push)
+#pragma warning(disable : 4512)
struct EncodeParams
{
uint8_t uMode;
@@ -660,6 +664,7 @@ private:
EncodeParams(const HDRColorA* const aOriginal) : aHDRPixels(aOriginal) {}
};
+#pragma warning(pop)
static uint8_t Quantize(_In_ uint8_t comp, _In_ uint8_t uPrec)
{
@@ -699,29 +704,29 @@ private:
}
void GeneratePaletteQuantized(_In_ const EncodeParams* pEP, _In_ size_t uIndexMode, _In_ const LDREndPntPair& endpts,
- _Out_cap_c_(BC7_MAX_INDICES) LDRColorA aPalette[]) const;
- float PerturbOne(_In_ const EncodeParams* pEP, _In_count_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode,
+ _Out_writes_(BC7_MAX_INDICES) LDRColorA aPalette[]) const;
+ float PerturbOne(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode,
_In_ size_t ch, _In_ const LDREndPntPair &old_endpts,
_Out_ LDREndPntPair &new_endpts, _In_ float old_err, _In_ uint8_t do_b) const;
- void Exhaustive(_In_ const EncodeParams* pEP, _In_count_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode,
+ void Exhaustive(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode,
_In_ size_t ch, _Inout_ float& fOrgErr, _Inout_ LDREndPntPair& optEndPt) const;
- void OptimizeOne(_In_ const EncodeParams* pEP, _In_count_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode,
+ void OptimizeOne(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA colors[], _In_ size_t np, _In_ size_t uIndexMode,
_In_ float orig_err, _In_ const LDREndPntPair &orig_endpts, _Out_ LDREndPntPair &opt_endpts) const;
void OptimizeEndPoints(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode,
- _In_count_c_(BC7_MAX_REGIONS) const float orig_err[],
- _In_count_c_(BC7_MAX_REGIONS) const LDREndPntPair orig_endpts[],
- _Out_cap_c_(BC7_MAX_REGIONS) LDREndPntPair opt_endpts[]) const;
+ _In_reads_(BC7_MAX_REGIONS) const float orig_err[],
+ _In_reads_(BC7_MAX_REGIONS) const LDREndPntPair orig_endpts[],
+ _Out_writes_(BC7_MAX_REGIONS) LDREndPntPair opt_endpts[]) const;
void AssignIndices(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode,
- _In_count_c_(BC7_MAX_REGIONS) LDREndPntPair endpts[],
- _Out_cap_c_(NUM_PIXELS_PER_BLOCK) size_t aIndices[], _Out_cap_c_(NUM_PIXELS_PER_BLOCK) size_t aIndices2[],
- _Out_cap_c_(BC7_MAX_REGIONS) float afTotErr[]) const;
+ _In_reads_(BC7_MAX_REGIONS) LDREndPntPair endpts[],
+ _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices[], _Out_writes_(NUM_PIXELS_PER_BLOCK) size_t aIndices2[],
+ _Out_writes_(BC7_MAX_REGIONS) float afTotErr[]) const;
void EmitBlock(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uRotation, _In_ size_t uIndexMode,
- _In_count_c_(BC7_MAX_REGIONS) const LDREndPntPair aEndPts[],
- _In_count_c_(NUM_PIXELS_PER_BLOCK) const size_t aIndex[],
- _In_count_c_(NUM_PIXELS_PER_BLOCK) const size_t aIndex2[]);
+ _In_reads_(BC7_MAX_REGIONS) const LDREndPntPair aEndPts[],
+ _In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndex[],
+ _In_reads_(NUM_PIXELS_PER_BLOCK) const size_t aIndex2[]);
float Refine(_In_ const EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uRotation, _In_ size_t uIndexMode);
- float MapColors(_In_ const EncodeParams* pEP, _In_count_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode,
+ float MapColors(_In_ const EncodeParams* pEP, _In_reads_(np) const LDRColorA aColors[], _In_ size_t np, _In_ size_t uIndexMode,
_In_ const LDREndPntPair& endPts, _In_ float fMinErr) const;
static float RoughMSE(_Inout_ EncodeParams* pEP, _In_ size_t uShape, _In_ size_t uIndexMode);
@@ -730,6 +735,8 @@ private:
};
//-------------------------------------------------------------------------------------
+#pragma warning(push)
+#pragma warning(disable : 4127)
template <bool bRange> void OptimizeAlpha(float *pX, float *pY, const float *pPoints, size_t cSteps)
{
static const float pC6[] = { 5.0f/5.0f, 4.0f/5.0f, 3.0f/5.0f, 2.0f/5.0f, 1.0f/5.0f, 0.0f/5.0f };
@@ -870,28 +877,28 @@ template <bool bRange> void OptimizeAlpha(float *pX, float *pY, const float *pPo
typedef void (*BC_DECODE)(XMVECTOR *pColor, const uint8_t *pBC);
typedef void (*BC_ENCODE)(uint8_t *pDXT, const XMVECTOR *pColor, DWORD flags);
-void D3DXDecodeBC1(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(8) const uint8_t *pBC);
-void D3DXDecodeBC2(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(16) const uint8_t *pBC);
-void D3DXDecodeBC3(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(16) const uint8_t *pBC);
-void D3DXDecodeBC4U(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(8) const uint8_t *pBC);
-void D3DXDecodeBC4S(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(8) const uint8_t *pBC);
-void D3DXDecodeBC5U(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(16) const uint8_t *pBC);
-void D3DXDecodeBC5S(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(16) const uint8_t *pBC);
-void D3DXDecodeBC6HU(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(16) const uint8_t *pBC);
-void D3DXDecodeBC6HS(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(16) const uint8_t *pBC);
-void D3DXDecodeBC7(_Out_cap_c_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_count_c_(16) const uint8_t *pBC);
-
-void D3DXEncodeBC1(_Out_cap_c_(8) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ float alphaRef, _In_ DWORD flags);
+void D3DXDecodeBC1(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC);
+void D3DXDecodeBC2(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
+void D3DXDecodeBC3(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
+void D3DXDecodeBC4U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC);
+void D3DXDecodeBC4S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC);
+void D3DXDecodeBC5U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
+void D3DXDecodeBC5S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
+void D3DXDecodeBC6HU(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
+void D3DXDecodeBC6HS(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
+void D3DXDecodeBC7(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC);
+
+void D3DXEncodeBC1(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ float alphaRef, _In_ DWORD flags);
// BC1 requires one additional parameter, so it doesn't match signature of BC_ENCODE above
-void D3DXEncodeBC2(_Out_cap_c_(16) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
-void D3DXEncodeBC3(_Out_cap_c_(16) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
-void D3DXEncodeBC4U(_Out_cap_c_(8) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
-void D3DXEncodeBC4S(_Out_cap_c_(8) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
-void D3DXEncodeBC5U(_Out_cap_c_(16) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
-void D3DXEncodeBC5S(_Out_cap_c_(16) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
-void D3DXEncodeBC6HU(_Out_cap_c_(16) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
-void D3DXEncodeBC6HS(_Out_cap_c_(16) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
-void D3DXEncodeBC7(_Out_cap_c_(16) uint8_t *pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
+void D3DXEncodeBC2(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
+void D3DXEncodeBC3(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
+void D3DXEncodeBC4U(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
+void D3DXEncodeBC4S(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
+void D3DXEncodeBC5U(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
+void D3DXEncodeBC5S(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
+void D3DXEncodeBC6HU(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
+void D3DXEncodeBC6HS(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
+void D3DXEncodeBC7(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags);
}; // namespace
diff --git a/thirdparty/directxtex/DirectXTex/BC4BC5.cpp b/thirdparty/directxtex/DirectXTex/BC4BC5.cpp
index 9cf40c7f..443adb0b 100644
--- a/thirdparty/directxtex/DirectXTex/BC4BC5.cpp
+++ b/thirdparty/directxtex/DirectXTex/BC4BC5.cpp
@@ -17,8 +17,6 @@
#include "BC.h"
-#pragma warning(disable : 4201)
-
namespace DirectX
{
@@ -37,6 +35,9 @@ namespace DirectX
// Structures
//-------------------------------------------------------------------------------------
+#pragma warning(push)
+#pragma warning(disable : 4201)
+
// BC4U/BC5U
struct BC4_UNORM
{
@@ -152,6 +153,7 @@ struct BC4_SNORM
};
};
+#pragma warning(pop)
//-------------------------------------------------------------------------------------
// Convert a floating point value to an 8-bit SNORM
@@ -164,10 +166,10 @@ static void inline FloatToSNorm( _In_ float fVal, _Out_ int8_t *piSNorm )
fVal = 0;
else
if( fVal > 1 )
- fVal = 1; // Clamp to 1
+ fVal = 1; // Clamp to 1
else
if( fVal < -1 )
- fVal = -1; // Clamp to -1
+ fVal = -1; // Clamp to -1
fVal = fVal * (int8_t) ( dwMostNeg - 1 );
@@ -181,7 +183,7 @@ static void inline FloatToSNorm( _In_ float fVal, _Out_ int8_t *piSNorm )
//------------------------------------------------------------------------------
-static void FindEndPointsBC4U( _In_count_c_(BLOCK_SIZE) const float theTexelsU[], _Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1)
+static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
float MIN_NORM;
@@ -235,7 +237,7 @@ static void FindEndPointsBC4U( _In_count_c_(BLOCK_SIZE) const float theTexelsU[]
}
}
-static void FindEndPointsBC4S(_In_count_c_(BLOCK_SIZE) const float theTexelsU[], _Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1)
+static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
float MIN_NORM;
@@ -291,7 +293,7 @@ static void FindEndPointsBC4S(_In_count_c_(BLOCK_SIZE) const float theTexelsU[],
//------------------------------------------------------------------------------
-static inline void FindEndPointsBC5U( _In_count_c_(BLOCK_SIZE) const float theTexelsU[], _In_count_c_(BLOCK_SIZE) const float theTexelsV[],
+static inline void FindEndPointsBC5U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1, _Out_ uint8_t &endpointV_0, _Out_ uint8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
@@ -299,7 +301,7 @@ static inline void FindEndPointsBC5U( _In_count_c_(BLOCK_SIZE) const float theTe
FindEndPointsBC4U( theTexelsV, endpointV_0, endpointV_1);
}
-static inline void FindEndPointsBC5S( _In_count_c_(BLOCK_SIZE) const float theTexelsU[], _In_count_c_(BLOCK_SIZE) const float theTexelsV[],
+static inline void FindEndPointsBC5S( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1, _Out_ int8_t &endpointV_0, _Out_ int8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
@@ -309,7 +311,7 @@ static inline void FindEndPointsBC5S( _In_count_c_(BLOCK_SIZE) const float theTe
//------------------------------------------------------------------------------
-static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
+static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
@@ -334,7 +336,7 @@ static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_count_c_(NUM_PIXELS_PER
}
}
-static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_count_c_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
+static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
@@ -367,32 +369,37 @@ static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_count_c_(NUM_PIXELS_PER
//-------------------------------------------------------------------------------------
// BC4 Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DXDecodeBC4U( XMVECTOR *pColor, const uint8_t *pBC )
{
assert( pColor && pBC );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
- const BC4_UNORM * pBC4 = reinterpret_cast<const BC4_UNORM*>(pBC);
+ auto pBC4 = reinterpret_cast<const BC4_UNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
+ #pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
}
}
+_Use_decl_annotations_
void D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
- const BC4_SNORM * pBC4 = reinterpret_cast<const BC4_SNORM*>(pBC);
+ auto pBC4 = reinterpret_cast<const BC4_SNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
+ #pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
}
}
+_Use_decl_annotations_
void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
{
UNREFERENCED_PARAMETER( flags );
@@ -401,7 +408,7 @@ void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
memset(pBC, 0, sizeof(BC4_UNORM));
- BC4_UNORM * pBC4 = reinterpret_cast<BC4_UNORM*>(pBC);
+ auto pBC4 = reinterpret_cast<BC4_UNORM*>(pBC);
float theTexelsU[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
@@ -413,6 +420,7 @@ void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
FindClosestUNORM(pBC4, theTexelsU);
}
+_Use_decl_annotations_
void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
{
UNREFERENCED_PARAMETER( flags );
@@ -421,7 +429,7 @@ void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
memset(pBC, 0, sizeof(BC4_UNORM));
- BC4_SNORM * pBC4 = reinterpret_cast<BC4_SNORM*>(pBC);
+ auto pBC4 = reinterpret_cast<BC4_SNORM*>(pBC);
float theTexelsU[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
@@ -437,34 +445,39 @@ void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
//-------------------------------------------------------------------------------------
// BC5 Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
- const BC4_UNORM * pBCR = reinterpret_cast<const BC4_UNORM*>(pBC);
- const BC4_UNORM * pBCG = reinterpret_cast<const BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
+ auto pBCR = reinterpret_cast<const BC4_UNORM*>(pBC);
+ auto pBCG = reinterpret_cast<const BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
+ #pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
}
}
+_Use_decl_annotations_
void D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
- const BC4_SNORM * pBCR = reinterpret_cast<const BC4_SNORM*>(pBC);
- const BC4_SNORM * pBCG = reinterpret_cast<const BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
+ auto pBCR = reinterpret_cast<const BC4_SNORM*>(pBC);
+ auto pBCG = reinterpret_cast<const BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
+ #pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
}
}
+_Use_decl_annotations_
void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
{
UNREFERENCED_PARAMETER( flags );
@@ -473,8 +486,8 @@ void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
memset(pBC, 0, sizeof(BC4_UNORM)*2);
- BC4_UNORM * pBCR = reinterpret_cast<BC4_UNORM*>(pBC);
- BC4_UNORM * pBCG = reinterpret_cast<BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
+ auto pBCR = reinterpret_cast<BC4_UNORM*>(pBC);
+ auto pBCG = reinterpret_cast<BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
@@ -498,6 +511,7 @@ void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
FindClosestUNORM(pBCG, theTexelsV);
}
+_Use_decl_annotations_
void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
{
UNREFERENCED_PARAMETER( flags );
@@ -506,8 +520,8 @@ void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
memset(pBC, 0, sizeof(BC4_UNORM)*2);
- BC4_SNORM * pBCR = reinterpret_cast<BC4_SNORM*>(pBC);
- BC4_SNORM * pBCG = reinterpret_cast<BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
+ auto pBCR = reinterpret_cast<BC4_SNORM*>(pBC);
+ auto pBCG = reinterpret_cast<BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
diff --git a/thirdparty/directxtex/DirectXTex/BC6HBC7.cpp b/thirdparty/directxtex/DirectXTex/BC6HBC7.cpp
index 2e607543..c6d8fc87 100644
--- a/thirdparty/directxtex/DirectXTex/BC6HBC7.cpp
+++ b/thirdparty/directxtex/DirectXTex/BC6HBC7.cpp
@@ -311,7 +311,7 @@ static const uint8_t g_aFixUp[3][64][3] =
// BC6H Compression
const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{
- { // 0x00 - 10 5 5 5
+ { // Mode 1 (0x00) - 10 5 5 5
{ M, 0}, { M, 1}, {GY, 4}, {BY, 4}, {BZ, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -323,7 +323,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x01 - 7 6 6 6
+ { // Mode 2 (0x01) - 7 6 6 6
{ M, 0}, { M, 1}, {GY, 5}, {GZ, 4}, {GZ, 5}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {BZ, 0}, {BZ, 1}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {BY, 5}, {BZ, 2}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -335,7 +335,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x02 - 11 5 4 4
+ { // Mode 3 (0x02) - 11 5 4 4
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -347,7 +347,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x06 - 11 4 5 4
+ { // Mode 4 (0x06) - 11 4 5 4
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -359,7 +359,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x0a - 11 4 4 5
+ { // Mode 5 (0x0a) - 11 4 4 5
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -371,7 +371,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x0e - 9 5 5 5
+ { // Mode 6 (0x0e) - 9 5 5 5
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -383,7 +383,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x12 - 8 6 5 5
+ { // Mode 7 (0x12) - 8 6 5 5
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {GZ, 4}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {BZ, 2}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -395,7 +395,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x16 - 8 5 6 5
+ { // Mode 8 (0x16) - 8 5 6 5
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {BZ, 0}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GY, 5}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -407,7 +407,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x1a - 8 5 5 6
+ { // Mode 9 (0x1a) - 8 5 5 6
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {BZ, 1}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {BY, 5}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -419,7 +419,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x1e - 6 6 6 6
+ { // Mode 10 (0x1e) - 6 6 6 6
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {GZ, 4}, {BZ, 0}, {BZ, 1}, {BY, 4}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GY, 5}, {BY, 5}, {BZ, 2}, {GY, 4}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -431,7 +431,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{ D, 3}, { D, 4},
},
- { // 0x03 - 10 10
+ { // Mode 11 (0x03) - 10 10
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -443,7 +443,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{NA, 0}, {NA, 0},
},
- { // 0x07 - 11 9
+ { // Mode 12 (0x07) - 11 9
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -455,7 +455,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{NA, 0}, {NA, 0},
},
- { // 0x0b - 12 8
+ { // Mode 13 (0x0b) - 12 8
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -467,7 +467,7 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
{NA, 0}, {NA, 0},
},
- { // 0x0f - 16 4
+ { // Mode 14 (0x0f) - 16 4
{ M, 0}, { M, 1}, { M, 2}, { M, 3}, { M, 4}, {RW, 0}, {RW, 1}, {RW, 2}, {RW, 3}, {RW, 4},
{RW, 5}, {RW, 6}, {RW, 7}, {RW, 8}, {RW, 9}, {GW, 0}, {GW, 1}, {GW, 2}, {GW, 3}, {GW, 4},
{GW, 5}, {GW, 6}, {GW, 7}, {GW, 8}, {GW, 9}, {BW, 0}, {BW, 1}, {BW, 2}, {BW, 3}, {BW, 4},
@@ -483,56 +483,56 @@ const D3DX_BC6H::ModeDescriptor D3DX_BC6H::ms_aDesc[14][82] =
// Mode, Partitions, Transformed, IndexPrec, RGBAPrec
const D3DX_BC6H::ModeInfo D3DX_BC6H::ms_aInfo[] =
{
- {0x00, 1, true, 3, LDRColorA(10,10,10,0), LDRColorA( 5, 5, 5,0), LDRColorA(5,5,5,0), LDRColorA(5,5,5,0)}, // Mode 0
- {0x01, 1, true, 3, LDRColorA( 7, 7, 7,0), LDRColorA( 6, 6, 6,0), LDRColorA(6,6,6,0), LDRColorA(6,6,6,0)}, // Mode 1
- {0x02, 1, true, 3, LDRColorA(11,11,11,0), LDRColorA( 5, 4, 4,0), LDRColorA(5,4,4,0), LDRColorA(5,4,4,0)}, // Mode 2
- {0x06, 1, true, 3, LDRColorA(11,11,11,0), LDRColorA( 4, 5, 4,0), LDRColorA(4,5,4,0), LDRColorA(4,5,4,0)}, // Mode 3
- {0x0a, 1, true, 3, LDRColorA(11,11,11,0), LDRColorA( 4, 4, 5,0), LDRColorA(4,4,5,0), LDRColorA(4,4,5,0)}, // Mode 4
- {0x0e, 1, true, 3, LDRColorA( 9, 9, 9,0), LDRColorA( 5, 5, 5,0), LDRColorA(5,5,5,0), LDRColorA(5,5,5,0)}, // Mode 5
- {0x12, 1, true, 3, LDRColorA( 8, 8, 8,0), LDRColorA( 6, 5, 5,0), LDRColorA(6,5,5,0), LDRColorA(6,5,5,0)}, // Mode 6
- {0x16, 1, true, 3, LDRColorA( 8, 8, 8,0), LDRColorA( 5, 6, 5,0), LDRColorA(5,6,5,0), LDRColorA(5,6,5,0)}, // Mode 7
- {0x1a, 1, true, 3, LDRColorA( 8, 8, 8,0), LDRColorA( 5, 5, 6,0), LDRColorA(5,5,6,0), LDRColorA(5,5,6,0)}, // Mode 8
- {0x1e, 1, false, 3, LDRColorA( 6, 6, 6,0), LDRColorA( 6, 6, 6,0), LDRColorA(6,6,6,0), LDRColorA(6,6,6,0)}, // Mode 9
- {0x03, 0, false, 4, LDRColorA(10,10,10,0), LDRColorA(10,10,10,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 10
- {0x07, 0, true, 4, LDRColorA(11,11,11,0), LDRColorA( 9, 9, 9,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 11
- {0x0b, 0, true, 4, LDRColorA(12,12,12,0), LDRColorA( 8, 8, 8,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 12
- {0x0f, 0, true, 4, LDRColorA(16,16,16,0), LDRColorA( 4, 4, 4,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 13
+ {0x00, 1, true, 3, LDRColorA(10,10,10,0), LDRColorA( 5, 5, 5,0), LDRColorA(5,5,5,0), LDRColorA(5,5,5,0)}, // Mode 1
+ {0x01, 1, true, 3, LDRColorA( 7, 7, 7,0), LDRColorA( 6, 6, 6,0), LDRColorA(6,6,6,0), LDRColorA(6,6,6,0)}, // Mode 2
+ {0x02, 1, true, 3, LDRColorA(11,11,11,0), LDRColorA( 5, 4, 4,0), LDRColorA(5,4,4,0), LDRColorA(5,4,4,0)}, // Mode 3
+ {0x06, 1, true, 3, LDRColorA(11,11,11,0), LDRColorA( 4, 5, 4,0), LDRColorA(4,5,4,0), LDRColorA(4,5,4,0)}, // Mode 4
+ {0x0a, 1, true, 3, LDRColorA(11,11,11,0), LDRColorA( 4, 4, 5,0), LDRColorA(4,4,5,0), LDRColorA(4,4,5,0)}, // Mode 5
+ {0x0e, 1, true, 3, LDRColorA( 9, 9, 9,0), LDRColorA( 5, 5, 5,0), LDRColorA(5,5,5,0), LDRColorA(5,5,5,0)}, // Mode 6
+ {0x12, 1, true, 3, LDRColorA( 8, 8, 8,0), LDRColorA( 6, 5, 5,0), LDRColorA(6,5,5,0), LDRColorA(6,5,5,0)}, // Mode 7
+ {0x16, 1, true, 3, LDRColorA( 8, 8, 8,0), LDRColorA( 5, 6, 5,0), LDRColorA(5,6,5,0), LDRColorA(5,6,5,0)}, // Mode 8
+ {0x1a, 1, true, 3, LDRColorA( 8, 8, 8,0), LDRColorA( 5, 5, 6,0), LDRColorA(5,5,6,0), LDRColorA(5,5,6,0)}, // Mode 9
+ {0x1e, 1, false, 3, LDRColorA( 6, 6, 6,0), LDRColorA( 6, 6, 6,0), LDRColorA(6,6,6,0), LDRColorA(6,6,6,0)}, // Mode 10
+ {0x03, 0, false, 4, LDRColorA(10,10,10,0), LDRColorA(10,10,10,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 11
+ {0x07, 0, true, 4, LDRColorA(11,11,11,0), LDRColorA( 9, 9, 9,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 12
+ {0x0b, 0, true, 4, LDRColorA(12,12,12,0), LDRColorA( 8, 8, 8,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 13
+ {0x0f, 0, true, 4, LDRColorA(16,16,16,0), LDRColorA( 4, 4, 4,0), LDRColorA(0,0,0,0), LDRColorA(0,0,0,0)}, // Mode 14
};
const int D3DX_BC6H::ms_aModeToInfo[] =
{
- 0, // 0x00
- 1, // 0x01
- 2, // 0x02
- 10, // 0x03
- -1, // 0x04
- -1, // 0x05
- 3, // 0x06
- 11, // 0x07
- -1, // 0x08
- -1, // 0x09
- 4, // 0x0a
- 12, // 0x0b
- -1, // 0x0c
- -1, // 0x0d
- 5, // 0x0e
- 13, // 0x0f
- -1, // 0x10
- -1, // 0x11
- 6, // 0x12
- -1, // 0x13
- -1, // 0x14
- -1, // 0x15
- 7, // 0x16
- -1, // 0x17
- -1, // 0x18
- -1, // 0x19
- 8, // 0x1a
- -1, // 0x1b
- -1, // 0x1c
- -1, // 0x1d
- 9, // 0x1e
- -1, // 0x1f
+ 0, // Mode 1 - 0x00
+ 1, // Mode 2 - 0x01
+ 2, // Mode 3 - 0x02
+ 10, // Mode 11 - 0x03
+ -1, // Invalid - 0x04
+ -1, // Invalid - 0x05
+ 3, // Mode 4 - 0x06
+ 11, // Mode 12 - 0x07
+ -1, // Invalid - 0x08
+ -1, // Invalid - 0x09
+ 4, // Mode 5 - 0x0a
+ 12, // Mode 13 - 0x0b
+ -1, // Invalid - 0x0c
+ -1, // Invalid - 0x0d
+ 5, // Mode 6 - 0x0e
+ 13, // Mode 14 - 0x0f
+ -1, // Invalid - 0x10
+ -1, // Invalid - 0x11
+ 6, // Mode 7 - 0x12
+ -1, // Reserved - 0x13
+ -1, // Invalid - 0x14
+ -1, // Invalid - 0x15
+ 7, // Mode 8 - 0x16
+ -1, // Reserved - 0x17
+ -1, // Invalid - 0x18
+ -1, // Invalid - 0x19
+ 8, // Mode 9 - 0x1a
+ -1, // Reserved - 0x1b
+ -1, // Invalid - 0x1c
+ -1, // Invalid - 0x1d
+ 9, // Mode 10 - 0x1e
+ -1, // Resreved - 0x1f
};
// BC7 compression: uPartitions, uPartitionBits, uPBits, uRotationBits, uIndexModeBits, uIndexPrec, uIndexPrec2, RGBAPrec, RGBAPrecWithP
@@ -560,18 +560,10 @@ const D3DX_BC7::ModeInfo D3DX_BC7::ms_aInfo[] =
//-------------------------------------------------------------------------------------
// Helper functions
//-------------------------------------------------------------------------------------
-template< class T >
-inline static void Swap( T& a, T& b )
-{
- T temp = a;
- a = b;
- b = temp;
-}
-
inline static bool IsFixUpOffset(_In_range_(0,2) size_t uPartitions, _In_range_(0,63) size_t uShape, _In_range_(0,15) size_t uOffset)
{
assert(uPartitions < 3 && uShape < 64 && uOffset < 16);
- __analysis_assume(uPartitions < 3 && uShape < 64 && uOffset < 16);
+ _Analysis_assume_(uPartitions < 3 && uShape < 64 && uOffset < 16);
for(size_t p = 0; p <= uPartitions; p++)
{
if(uOffset == g_aFixUp[uPartitions][uShape][p])
@@ -582,37 +574,14 @@ inline static bool IsFixUpOffset(_In_range_(0,2) size_t uPartitions, _In_range_(
return false;
}
-inline static float ErrorMetricRGB(_In_ const LDRColorA& a, _In_ const LDRColorA& b)
-{
- float er = float(a.r) - float(b.r);
- float eg = float(a.g) - float(b.g);
- float eb = float(a.b) - float(b.b);
- // weigh the components nonuniformly
- //er *= 0.299;
- //eg *= 0.587;
- //eb *= 0.114;
- return er*er + eg*eg + eb*eb;
-}
-
-inline static float ErrorMetricAlpha(_In_ const LDRColorA& a, _In_ const LDRColorA& b)
-{
- float ea = float(a.a) - float(b.a);
- return ea*ea;
-}
-
-inline static float ErrorMetric(_In_ const LDRColorA& a, _In_ const LDRColorA& b)
-{
- return ErrorMetricRGB(a, b) + ErrorMetricAlpha(a, b);
-}
-
-inline static void TransformForward(_Inout_count_c_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[])
+inline static void TransformForward(_Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[])
{
aEndPts[0].B -= aEndPts[0].A;
aEndPts[1].A -= aEndPts[0].A;
aEndPts[1].B -= aEndPts[0].A;
}
-inline static void TransformInverse(_Inout_count_c_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[], _In_ const LDRColorA& Prec, _In_ bool bSigned)
+inline static void TransformInverse(_Inout_updates_all_(BC6H_MAX_REGIONS) INTEndPntPair aEndPts[], _In_ const LDRColorA& Prec, _In_ bool bSigned)
{
INTColor WrapMask((1 << Prec.r) - 1, (1 << Prec.g) - 1, (1 << Prec.b) - 1);
aEndPts[0].B += aEndPts[0].A; aEndPts[0].B &= WrapMask;
@@ -657,9 +626,9 @@ inline static int NBits(_In_ int n, _In_ bool bIsSigned)
//-------------------------------------------------------------------------------------
-static float OptimizeRGB(_In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pPoints,
+static float OptimizeRGB(_In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pPoints,
_Out_ HDRColorA* pX, _Out_ HDRColorA* pY,
- _In_ size_t cSteps, _In_ size_t cPixels, _In_count_(cPixels) const size_t* pIndex)
+ _In_ size_t cSteps, _In_ size_t cPixels, _In_reads_(cPixels) const size_t* pIndex)
{
float fError = FLT_MAX;
const float *pC = (3 == cSteps) ? pC3 : pC4;
@@ -737,8 +706,8 @@ static float OptimizeRGB(_In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* con
}
}
- if(iDirMax & 2) Swap( X.g, Y.g );
- if(iDirMax & 1) Swap( X.b, Y.b );
+ if(iDirMax & 2) std::swap( X.g, Y.g );
+ if(iDirMax & 1) std::swap( X.b, Y.b );
// Two color block.. no need to root-find
if(fAB < 1.0f / 4096.0f)
@@ -754,7 +723,7 @@ static float OptimizeRGB(_In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* con
for(size_t iIteration = 0; iIteration < 8; iIteration++)
{
// Calculate new steps
- HDRColorA pSteps[4];
+ HDRColorA pSteps[4] = {};
for(size_t iStep = 0; iStep < cSteps; iStep++)
{
@@ -849,9 +818,9 @@ static float OptimizeRGB(_In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* con
//-------------------------------------------------------------------------------------
-static float OptimizeRGBA(_In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pPoints,
+static float OptimizeRGBA(_In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA* const pPoints,
_Out_ HDRColorA* pX, _Out_ HDRColorA* pY,
- _In_ size_t cSteps, _In_ size_t cPixels, _In_count_(cPixels) const size_t* pIndex)
+ _In_ size_t cSteps, _In_ size_t cPixels, _In_reads_(cPixels) const size_t* pIndex)
{
float fError = FLT_MAX;
const float *pC = (3 == cSteps) ? pC3 : pC4;
@@ -924,9 +893,9 @@ static float OptimizeRGBA(_In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* co
}
}
- if(iDirMax & 4) Swap(X.g, Y.g);
- if(iDirMax & 2) Swap(X.b, Y.b);
- if(iDirMax & 1) Swap(X.a, Y.a);
+ if(iDirMax & 4) std::swap(X.g, Y.g);
+ if(iDirMax & 2) std::swap(X.b, Y.b);
+ if(iDirMax & 1) std::swap(X.a, Y.a);
// Two color block.. no need to root-find
if(fAB < 1.0f / 4096.0f)
@@ -944,7 +913,6 @@ static float OptimizeRGBA(_In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* co
// Calculate new steps
HDRColorA pSteps[BC7_MAX_INDICES];
- LDRColorA aSteps[BC7_MAX_INDICES];
LDRColorA lX, lY;
lX = (X * 255.0f).ToLDRColorA();
lY = (Y * 255.0f).ToLDRColorA();
@@ -1014,13 +982,12 @@ static float OptimizeRGBA(_In_count_c_(NUM_PIXELS_PER_BLOCK) const HDRColorA* co
//-------------------------------------------------------------------------------------
-#pragma warning(disable: 4616 6001 6297)
-static float ComputeError(_Inout_ const LDRColorA& pixel, _In_count_x_(1 << uIndexPrec) const LDRColorA aPalette[],
+static float ComputeError(_Inout_ const LDRColorA& pixel, _In_reads_(1 << uIndexPrec) const LDRColorA aPalette[],
_In_ uint8_t uIndexPrec, _In_ uint8_t uIndexPrec2, _Out_opt_ size_t* pBestIndex = nullptr, _Out_opt_ size_t* pBestIndex2 = nullptr)
{
- const size_t uNumIndices = 1 << uIndexPrec;
- const size_t uNumIndices2 = 1 << uIndexPrec2;
+ const size_t uNumIndices = size_t(1) << uIndexPrec;
+ const size_t uNumIndices2 = size_t(1) << uIndexPrec2;
float fTotalErr = 0;
float fBestErr = FLT_MAX;
@@ -1029,11 +996,16 @@ static float ComputeError(_Inout_ const LDRColorA& pixel, _In_count_x_(1 << uInd
if(pBestIndex2)
*pBestIndex2 = 0;
+ XMVECTOR vpixel = XMLoadUByte4( reinterpret_cast<const XMUBYTE4*>( &pixel ) );
+
if(uIndexPrec2 == 0)
{
for(register size_t i = 0; i < uNumIndices && fBestErr > 0; i++)
{
- float fErr = ErrorMetric(pixel, aPalette[i]);
+ XMVECTOR tpixel = XMLoadUByte4( reinterpret_cast<const XMUBYTE4*>( &aPalette[i] ) );
+ // Compute ErrorMetric
+ tpixel = XMVectorSubtract( vpixel, tpixel );
+ float fErr = XMVectorGetX( XMVector4Dot( tpixel, tpixel ) );
if(fErr > fBestErr) // error increased, so we're done searching
break;
if(fErr < fBestErr)
@@ -1049,7 +1021,10 @@ static float ComputeError(_Inout_ const LDRColorA& pixel, _In_count_x_(1 << uInd
{
for(register size_t i = 0; i < uNumIndices && fBestErr > 0; i++)
{
- float fErr = ErrorMetricRGB(pixel, aPalette[i]);
+ XMVECTOR tpixel = XMLoadUByte4( reinterpret_cast<const XMUBYTE4*>( &aPalette[i] ) );
+ // Compute ErrorMetricRGB
+ tpixel = XMVectorSubtract( vpixel, tpixel );
+ float fErr = XMVectorGetX( XMVector3Dot( tpixel, tpixel ) );
if(fErr > fBestErr) // error increased, so we're done searching
break;
if(fErr < fBestErr)
@@ -1063,7 +1038,9 @@ static float ComputeError(_Inout_ const LDRColorA& pixel, _In_count_x_(1 << uInd
fBestErr = FLT_MAX;
for(register size_t i = 0; i < uNumIndices2 && fBestErr > 0; i++)
{
- float fErr = ErrorMetricAlpha(pixel, aPalette[i]);
+ // Compute ErrorMetricAlpha
+ float ea = float(pixel.a) - float(aPalette[i].a);
+ float fErr = ea*ea;
if(fErr > fBestErr) // error increased, so we're done searching
break;
if(fErr < fBestErr)
@@ -1080,7 +1057,7 @@ static float ComputeError(_Inout_ const LDRColorA& pixel, _In_count_x_(1 << uInd
}
-inline static void FillWithErrorColors( _Out_cap_c_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut )
+inline static void FillWithErrorColors( _Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA* pOut )
{
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
@@ -1098,6 +1075,7 @@ inline static void FillWithErrorColors( _Out_cap_c_(NUM_PIXELS_PER_BLOCK) HDRCol
//-------------------------------------------------------------------------------------
// BC6H Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const
{
assert(pOut );
@@ -1110,16 +1088,16 @@ void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const
}
assert( uMode < 32 );
- __analysis_assume( uMode < 32 );
+ _Analysis_assume_( uMode < 32 );
if ( ms_aModeToInfo[uMode] >= 0 )
{
assert(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aInfo));
- __analysis_assume(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aInfo));
+ _Analysis_assume_(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aInfo));
const ModeDescriptor* desc = ms_aDesc[ms_aModeToInfo[uMode]];
assert(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aDesc));
- __analysis_assume(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aDesc));
+ _Analysis_assume_(ms_aModeToInfo[uMode] < ARRAYSIZE(ms_aDesc));
const ModeInfo& info = ms_aInfo[ms_aModeToInfo[uMode]];
INTEndPntPair aEndPts[BC6H_MAX_REGIONS];
@@ -1161,7 +1139,7 @@ void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const
}
assert( uShape < 64 );
- __analysis_assume( uShape < 64 );
+ _Analysis_assume_( uShape < 64 );
// Sign extend necessary end points
if(bSigned)
@@ -1171,7 +1149,7 @@ void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const
if(bSigned || info.bTransformed)
{
assert( info.uPartitions < BC6H_MAX_REGIONS );
- __analysis_assume( info.uPartitions < BC6H_MAX_REGIONS );
+ _Analysis_assume_( info.uPartitions < BC6H_MAX_REGIONS );
for(size_t p = 0; p <= info.uPartitions; ++p)
{
if(p != 0)
@@ -1213,7 +1191,7 @@ void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const
size_t uRegion = g_aPartitionTable[info.uPartitions][uShape][i];
assert( uRegion < BC6H_MAX_REGIONS );
- __analysis_assume( uRegion < BC6H_MAX_REGIONS );
+ _Analysis_assume_( uRegion < BC6H_MAX_REGIONS );
// Unquantize endpoints and interpolate
int r1 = Unquantize(aEndPts[uRegion].A.r, info.RGBAPrec[0][0].r, bSigned);
@@ -1240,12 +1218,25 @@ void D3DX_BC6H::Decode(bool bSigned, HDRColorA* pOut) const
else
{
#ifdef _DEBUG
- OutputDebugStringA( "BC6H: Invalid mode encountered during decoding\n" );
+ const char* warnstr = "BC6H: Invalid mode encountered during decoding\n";
+ switch( uMode )
+ {
+ case 0x13: warnstr = "BC6H: Reserved mode 10011 encountered during decoding\n"; break;
+ case 0x17: warnstr = "BC6H: Reserved mode 10111 encountered during decoding\n"; break;
+ case 0x1B: warnstr = "BC6H: Reserved mode 11011 encountered during decoding\n"; break;
+ case 0x1F: warnstr = "BC6H: Reserved mode 11111 encountered during decoding\n"; break;
+ }
+ OutputDebugStringA( warnstr );
#endif
- FillWithErrorColors( pOut );
+ // Per the BC6H format spec, we must return opaque black
+ for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
+ {
+ pOut[i] = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f);
+ }
}
}
+_Use_decl_annotations_
void D3DX_BC6H::Encode(bool bSigned, const HDRColorA* const pIn)
{
assert( pIn );
@@ -1276,8 +1267,8 @@ void D3DX_BC6H::Encode(bool bSigned, const HDRColorA* const pIn)
{
if(afRoughMSE[i] > afRoughMSE[j])
{
- Swap(afRoughMSE[i], afRoughMSE[j]);
- Swap(auShape[i], auShape[j]);
+ std::swap(afRoughMSE[i], afRoughMSE[j]);
+ std::swap(auShape[i], auShape[j]);
}
}
}
@@ -1292,6 +1283,7 @@ void D3DX_BC6H::Encode(bool bSigned, const HDRColorA* const pIn)
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
int D3DX_BC6H::Quantize(int iValue, int prec, bool bSigned)
{
assert(prec > 1); // didn't bother to make it work for 1
@@ -1319,6 +1311,7 @@ int D3DX_BC6H::Quantize(int iValue, int prec, bool bSigned)
return q;
}
+_Use_decl_annotations_
int D3DX_BC6H::Unquantize(int comp, uint8_t uBitsPerComp, bool bSigned)
{
int unq = 0, s = 0;
@@ -1354,6 +1347,7 @@ int D3DX_BC6H::Unquantize(int comp, uint8_t uBitsPerComp, bool bSigned)
return unq;
}
+_Use_decl_annotations_
int D3DX_BC6H::FinishUnquantize(int comp, bool bSigned)
{
if(bSigned)
@@ -1368,6 +1362,7 @@ int D3DX_BC6H::FinishUnquantize(int comp, bool bSigned)
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
bool D3DX_BC6H::EndPointsFit(const EncodeParams* pEP, const INTEndPntPair aEndPts[])
{
assert( pEP );
@@ -1408,13 +1403,14 @@ bool D3DX_BC6H::EndPointsFit(const EncodeParams* pEP, const INTEndPntPair aEndPt
return true;
}
+_Use_decl_annotations_
void D3DX_BC6H::GeneratePaletteQuantized(const EncodeParams* pEP, const INTEndPntPair& endPts, INTColor aPalette[]) const
{
assert( pEP );
const size_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec;
- const size_t uNumIndices = 1 << uIndexPrec;
+ const size_t uNumIndices = size_t(1) << uIndexPrec;
assert( uNumIndices > 0 );
- __analysis_assume( uNumIndices > 0 );
+ _Analysis_assume_( uNumIndices > 0 );
const LDRColorA& Prec = ms_aInfo[pEP->uMode].RGBAPrec[0][0];
// scale endpoints
@@ -1430,9 +1426,16 @@ void D3DX_BC6H::GeneratePaletteQuantized(const EncodeParams* pEP, const INTEndPn
const int* aWeights = nullptr;
switch(uIndexPrec)
{
- case 3: aWeights = g_aWeights3; assert(uNumIndices <= 8); __analysis_assume(uNumIndices <= 8); break;
- case 4: aWeights = g_aWeights4; assert(uNumIndices <= 16); __analysis_assume(uNumIndices <= 16); break;
- default: assert(false); for(size_t i=0; i < uNumIndices; ++i) aPalette[i] = INTColor(0,0,0); return;
+ case 3: aWeights = g_aWeights3; assert(uNumIndices <= 8); _Analysis_assume_(uNumIndices <= 8); break;
+ case 4: aWeights = g_aWeights4; assert(uNumIndices <= 16); _Analysis_assume_(uNumIndices <= 16); break;
+ default:
+ assert(false);
+ for(size_t i = 0; i < uNumIndices; ++i)
+ {
+ #pragma prefast(suppress:22102 22103, "writing blocks in two halves confuses tool")
+ aPalette[i] = INTColor(0,0,0);
+ }
+ return;
}
for (size_t i = 0; i < uNumIndices; ++i)
@@ -1450,6 +1453,7 @@ void D3DX_BC6H::GeneratePaletteQuantized(const EncodeParams* pEP, const INTEndPn
}
// given a collection of colors and quantized endpoints, generate a palette, choose best entries, and return a single toterr
+_Use_decl_annotations_
float D3DX_BC6H::MapColorsQuantized(const EncodeParams* pEP, const INTColor aColors[], size_t np, const INTEndPntPair &endPts) const
{
assert( pEP );
@@ -1462,10 +1466,19 @@ float D3DX_BC6H::MapColorsQuantized(const EncodeParams* pEP, const INTColor aCol
float fTotErr = 0;
for(size_t i = 0; i < np; ++i)
{
- float fBestErr = Norm(aColors[i], aPalette[0]);
+ XMVECTOR vcolors = XMLoadSInt4( reinterpret_cast<const XMINT4*>( &aColors[i] ) );
+
+ // Compute ErrorMetricRGB
+ XMVECTOR tpal = XMLoadSInt4( reinterpret_cast<const XMINT4*>( &aPalette[0] ) );
+ tpal = XMVectorSubtract( vcolors, tpal );
+ float fBestErr = XMVectorGetX( XMVector3Dot( tpal, tpal ) );
+
for(int j = 1; j < uNumIndices && fBestErr > 0; ++j)
{
- float fErr = Norm(aColors[i], aPalette[j]);
+ // Compute ErrorMetricRGB
+ tpal = XMLoadSInt4( reinterpret_cast<const XMINT4*>( &aPalette[j] ) );
+ tpal = XMVectorSubtract( vcolors, tpal );
+ float fErr = XMVectorGetX( XMVector3Dot( tpal, tpal ) );
if(fErr > fBestErr) break; // error increased, so we're done searching
if(fErr < fBestErr) fBestErr = fErr;
}
@@ -1474,6 +1487,7 @@ float D3DX_BC6H::MapColorsQuantized(const EncodeParams* pEP, const INTColor aCol
return fTotErr;
}
+_Use_decl_annotations_
float D3DX_BC6H::PerturbOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, uint8_t ch,
const INTEndPntPair& oldEndPts, INTEndPntPair& newEndPts, float fOldErr, int do_b) const
{
@@ -1533,6 +1547,7 @@ float D3DX_BC6H::PerturbOne(const EncodeParams* pEP, const INTColor aColors[], s
return fMinErr;
}
+_Use_decl_annotations_
void D3DX_BC6H::OptimizeOne(const EncodeParams* pEP, const INTColor aColors[], size_t np, float aOrgErr,
const INTEndPntPair &aOrgEndPts, INTEndPntPair &aOptEndPts) const
{
@@ -1584,12 +1599,13 @@ void D3DX_BC6H::OptimizeOne(const EncodeParams* pEP, const INTColor aColors[], s
}
}
+_Use_decl_annotations_
void D3DX_BC6H::OptimizeEndPoints(const EncodeParams* pEP, const float aOrgErr[], const INTEndPntPair aOrgEndPts[], INTEndPntPair aOptEndPts[]) const
{
assert( pEP );
const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
assert( uPartitions < BC6H_MAX_REGIONS );
- __analysis_assume( uPartitions < BC6H_MAX_REGIONS );
+ _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS );
INTColor aPixels[NUM_PIXELS_PER_BLOCK];
for(size_t p = 0; p <= uPartitions; ++p)
@@ -1609,15 +1625,16 @@ void D3DX_BC6H::OptimizeEndPoints(const EncodeParams* pEP, const float aOrgErr[]
}
// Swap endpoints as needed to ensure that the indices at fix up have a 0 high-order bit
+_Use_decl_annotations_
void D3DX_BC6H::SwapIndices(const EncodeParams* pEP, INTEndPntPair aEndPts[], size_t aIndices[])
{
assert( pEP );
const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
- const size_t uNumIndices = 1 << ms_aInfo[pEP->uMode].uIndexPrec;
+ const size_t uNumIndices = size_t(1) << ms_aInfo[pEP->uMode].uIndexPrec;
const size_t uHighIndexBit = uNumIndices >> 1;
assert( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
- __analysis_assume( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
+ _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
for(size_t p = 0; p <= uPartitions; ++p)
{
@@ -1626,7 +1643,7 @@ void D3DX_BC6H::SwapIndices(const EncodeParams* pEP, INTEndPntPair aEndPts[], si
if(aIndices[i] & uHighIndexBit)
{
// high bit is set, swap the aEndPts and indices for this region
- Swap(aEndPts[p].A, aEndPts[p].B);
+ std::swap(aEndPts[p].A, aEndPts[p].B);
for(size_t j = 0; j < NUM_PIXELS_PER_BLOCK; ++j)
if(g_aPartitionTable[uPartitions][pEP->uShape][j] == p)
@@ -1636,6 +1653,7 @@ void D3DX_BC6H::SwapIndices(const EncodeParams* pEP, INTEndPntPair aEndPts[], si
}
// assign indices given a tile, shape, and quantized endpoints, return toterr for each region
+_Use_decl_annotations_
void D3DX_BC6H::AssignIndices(const EncodeParams* pEP, const INTEndPntPair aEndPts[], size_t aIndices[], float aTotErr[]) const
{
assert( pEP );
@@ -1643,7 +1661,7 @@ void D3DX_BC6H::AssignIndices(const EncodeParams* pEP, const INTEndPntPair aEndP
const uint8_t uNumIndices = 1 << ms_aInfo[pEP->uMode].uIndexPrec;
assert( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
- __analysis_assume( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
+ _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
// build list of possibles
INTColor aPalette[BC6H_MAX_REGIONS][BC6H_MAX_INDICES];
@@ -1658,7 +1676,7 @@ void D3DX_BC6H::AssignIndices(const EncodeParams* pEP, const INTEndPntPair aEndP
{
const uint8_t uRegion = g_aPartitionTable[uPartitions][pEP->uShape][i];
assert( uRegion < BC6H_MAX_REGIONS );
- __analysis_assume( uRegion < BC6H_MAX_REGIONS );
+ _Analysis_assume_( uRegion < BC6H_MAX_REGIONS );
float fBestErr = Norm(pEP->aIPixels[i], aPalette[uRegion][0]);
aIndices[i] = 0;
@@ -1676,6 +1694,7 @@ void D3DX_BC6H::AssignIndices(const EncodeParams* pEP, const INTEndPntPair aEndP
}
}
+_Use_decl_annotations_
void D3DX_BC6H::QuantizeEndPts(const EncodeParams* pEP, INTEndPntPair* aQntEndPts) const
{
assert( pEP && aQntEndPts );
@@ -1683,7 +1702,7 @@ void D3DX_BC6H::QuantizeEndPts(const EncodeParams* pEP, INTEndPntPair* aQntEndPt
const LDRColorA& Prec = ms_aInfo[pEP->uMode].RGBAPrec[0][0];
const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
assert( uPartitions < BC6H_MAX_REGIONS );
- __analysis_assume( uPartitions < BC6H_MAX_REGIONS );
+ _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS );
for(size_t p = 0; p <= uPartitions; ++p)
{
@@ -1696,6 +1715,7 @@ void D3DX_BC6H::QuantizeEndPts(const EncodeParams* pEP, INTEndPntPair* aQntEndPt
}
}
+_Use_decl_annotations_
void D3DX_BC6H::EmitBlock(const EncodeParams* pEP, const INTEndPntPair aEndPts[], const size_t aIndices[])
{
assert( pEP );
@@ -1738,12 +1758,13 @@ void D3DX_BC6H::EmitBlock(const EncodeParams* pEP, const INTEndPntPair aEndPts[]
assert(uStartBit == 128);
}
+_Use_decl_annotations_
void D3DX_BC6H::Refine(EncodeParams* pEP)
{
assert( pEP );
const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
assert( uPartitions < BC6H_MAX_REGIONS );
- __analysis_assume( uPartitions < BC6H_MAX_REGIONS );
+ _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS );
const bool bTransformed = ms_aInfo[pEP->uMode].bTransformed;
float aOrgErr[BC6H_MAX_REGIONS], aOptErr[BC6H_MAX_REGIONS];
@@ -1786,23 +1807,31 @@ void D3DX_BC6H::Refine(EncodeParams* pEP)
}
}
+_Use_decl_annotations_
void D3DX_BC6H::GeneratePaletteUnquantized(const EncodeParams* pEP, size_t uRegion, INTColor aPalette[])
{
assert( pEP );
assert( uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
- __analysis_assume( uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
+ _Analysis_assume_( uRegion < BC6H_MAX_REGIONS && pEP->uShape < BC6H_MAX_SHAPES );
const INTEndPntPair& endPts = pEP->aUnqEndPts[pEP->uShape][uRegion];
const uint8_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec;
const uint8_t uNumIndices = 1 << uIndexPrec;
- assert( uNumIndices > 0 );
- __analysis_assume( uNumIndices > 0 );
+ assert(uNumIndices > 0);
+ _Analysis_assume_(uNumIndices > 0);
const int* aWeights = nullptr;
switch(uIndexPrec)
{
- case 3: aWeights = g_aWeights3; assert(uNumIndices <= 8); __analysis_assume(uNumIndices <= 8); break;
- case 4: aWeights = g_aWeights4; assert(uNumIndices <= 16); __analysis_assume(uNumIndices <= 16); break;
- default: assert(false); for(size_t i = 0; i < uNumIndices; ++i) aPalette[i] = INTColor(0,0,0); return;
+ case 3: aWeights = g_aWeights3; assert(uNumIndices <= 8); _Analysis_assume_(uNumIndices <= 8); break;
+ case 4: aWeights = g_aWeights4; assert(uNumIndices <= 16); _Analysis_assume_(uNumIndices <= 16); break;
+ default:
+ assert(false);
+ for(size_t i = 0; i < uNumIndices; ++i)
+ {
+ #pragma prefast(suppress:22102 22103, "writing blocks in two halves confuses tool")
+ aPalette[i] = INTColor(0,0,0);
+ }
+ return;
}
for(register size_t i = 0; i < uNumIndices; ++i)
@@ -1813,6 +1842,7 @@ void D3DX_BC6H::GeneratePaletteUnquantized(const EncodeParams* pEP, size_t uRegi
}
}
+_Use_decl_annotations_
float D3DX_BC6H::MapColors(const EncodeParams* pEP, size_t uRegion, size_t np, const size_t* auIndex) const
{
assert( pEP );
@@ -1837,17 +1867,18 @@ float D3DX_BC6H::MapColors(const EncodeParams* pEP, size_t uRegion, size_t np, c
return fTotalErr;
}
+_Use_decl_annotations_
float D3DX_BC6H::RoughMSE(EncodeParams* pEP) const
{
assert( pEP );
assert( pEP->uShape < BC6H_MAX_SHAPES);
- __analysis_assume( pEP->uShape < BC6H_MAX_SHAPES);
+ _Analysis_assume_( pEP->uShape < BC6H_MAX_SHAPES);
INTEndPntPair* aEndPts = pEP->aUnqEndPts[pEP->uShape];
const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
assert( uPartitions < BC6H_MAX_REGIONS );
- __analysis_assume( uPartitions < BC6H_MAX_REGIONS );
+ _Analysis_assume_( uPartitions < BC6H_MAX_REGIONS );
size_t auPixIdx[NUM_PIXELS_PER_BLOCK];
@@ -1904,6 +1935,7 @@ float D3DX_BC6H::RoughMSE(EncodeParams* pEP) const
//-------------------------------------------------------------------------------------
// BC7 Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DX_BC7::Decode(HDRColorA* pOut) const
{
assert( pOut );
@@ -1916,7 +1948,7 @@ void D3DX_BC7::Decode(HDRColorA* pOut) const
{
const uint8_t uPartitions = ms_aInfo[uMode].uPartitions;
assert( uPartitions < BC7_MAX_REGIONS );
- __analysis_assume( uPartitions < BC7_MAX_REGIONS );
+ _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
const uint8_t uNumEndPts = (uPartitions + 1) << 1;
const uint8_t uIndexPrec = ms_aInfo[uMode].uIndexPrec;
@@ -1926,7 +1958,7 @@ void D3DX_BC7::Decode(HDRColorA* pOut) const
uint8_t P[6];
uint8_t uShape = GetBits(uStartBit, ms_aInfo[uMode].uPartitionBits);
assert( uShape < BC7_MAX_SHAPES );
- __analysis_assume( uShape < BC7_MAX_SHAPES );
+ _Analysis_assume_( uShape < BC7_MAX_SHAPES );
uint8_t uRotation = GetBits(uStartBit, ms_aInfo[uMode].uRotationBits);
assert( uRotation < 4 );
@@ -2002,7 +2034,7 @@ void D3DX_BC7::Decode(HDRColorA* pOut) const
// P-bits
assert( ms_aInfo[uMode].uPBits <= 6 );
- __analysis_assume( ms_aInfo[uMode].uPBits <= 6 );
+ _Analysis_assume_( ms_aInfo[uMode].uPBits <= 6 );
for(i = 0; i < ms_aInfo[uMode].uPBits; i++)
{
if ( uStartBit > 127 )
@@ -2094,9 +2126,9 @@ void D3DX_BC7::Decode(HDRColorA* pOut) const
switch(uRotation)
{
- case 1: Swap(outPixel.r, outPixel.a); break;
- case 2: Swap(outPixel.g, outPixel.a); break;
- case 3: Swap(outPixel.b, outPixel.a); break;
+ case 1: std::swap(outPixel.r, outPixel.a); break;
+ case 2: std::swap(outPixel.g, outPixel.a); break;
+ case 3: std::swap(outPixel.b, outPixel.a); break;
}
pOut[i] = HDRColorA(outPixel);
@@ -2105,13 +2137,15 @@ void D3DX_BC7::Decode(HDRColorA* pOut) const
else
{
#ifdef _DEBUG
- OutputDebugStringA( "BC7: Invalid mode encountered during decoding\n" );
+ OutputDebugStringA( "BC7: Reserved mode 8 encountered during decoding\n" );
#endif
- FillWithErrorColors( pOut );
+ // Per the BC7 format spec, we must return transparent black
+ memset( pOut, 0, sizeof(HDRColorA) * NUM_PIXELS_PER_BLOCK );
}
}
-void D3DX_BC7::Encode(const HDRColorA* const pIn)
+_Use_decl_annotations_
+void D3DX_BC7::Encode(bool skip3subsets, const HDRColorA* const pIn)
{
assert( pIn );
@@ -2129,12 +2163,18 @@ void D3DX_BC7::Encode(const HDRColorA* const pIn)
for(EP.uMode = 0; EP.uMode < 8 && fMSEBest > 0; ++EP.uMode)
{
- const size_t uShapes = 1 << ms_aInfo[EP.uMode].uPartitionBits;
+ if ( skip3subsets && (EP.uMode == 0 || EP.uMode == 2) )
+ {
+ // 3 subset modes tend to be used rarely and add significant compression time
+ continue;
+ }
+
+ const size_t uShapes = size_t(1) << ms_aInfo[EP.uMode].uPartitionBits;
assert( uShapes <= BC7_MAX_SHAPES );
- __analysis_assume( uShapes <= BC7_MAX_SHAPES );
+ _Analysis_assume_( uShapes <= BC7_MAX_SHAPES );
- const size_t uNumRots = 1 << ms_aInfo[EP.uMode].uRotationBits;
- const size_t uNumIdxMode = 1 << ms_aInfo[EP.uMode].uIndexModeBits;
+ const size_t uNumRots = size_t(1) << ms_aInfo[EP.uMode].uRotationBits;
+ const size_t uNumIdxMode = size_t(1) << ms_aInfo[EP.uMode].uIndexModeBits;
// Number of rough cases to look at. reasonable values of this are 1, uShapes/4, and uShapes
// uShapes/4 gets nearly all the cases; you can increase that a bit (say by 3 or 4) if you really want to squeeze the last bit out
const size_t uItems = std::max<size_t>(1, uShapes >> 2);
@@ -2145,9 +2185,9 @@ void D3DX_BC7::Encode(const HDRColorA* const pIn)
{
switch(r)
{
- case 1: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) Swap(EP.aLDRPixels[i].r, EP.aLDRPixels[i].a); break;
- case 2: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) Swap(EP.aLDRPixels[i].g, EP.aLDRPixels[i].a); break;
- case 3: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) Swap(EP.aLDRPixels[i].b, EP.aLDRPixels[i].a); break;
+ case 1: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].r, EP.aLDRPixels[i].a); break;
+ case 2: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].g, EP.aLDRPixels[i].a); break;
+ case 3: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].b, EP.aLDRPixels[i].a); break;
}
for(size_t im = 0; im < uNumIdxMode && fMSEBest > 0; ++im)
@@ -2166,8 +2206,8 @@ void D3DX_BC7::Encode(const HDRColorA* const pIn)
{
if(afRoughMSE[i] > afRoughMSE[j])
{
- Swap(afRoughMSE[i], afRoughMSE[j]);
- Swap(auShape[i], auShape[j]);
+ std::swap(afRoughMSE[i], afRoughMSE[j]);
+ std::swap(auShape[i], auShape[j]);
}
}
}
@@ -2185,9 +2225,9 @@ void D3DX_BC7::Encode(const HDRColorA* const pIn)
switch(r)
{
- case 1: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) Swap(EP.aLDRPixels[i].r, EP.aLDRPixels[i].a); break;
- case 2: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) Swap(EP.aLDRPixels[i].g, EP.aLDRPixels[i].a); break;
- case 3: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) Swap(EP.aLDRPixels[i].b, EP.aLDRPixels[i].a); break;
+ case 1: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].r, EP.aLDRPixels[i].a); break;
+ case 2: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].g, EP.aLDRPixels[i].a); break;
+ case 3: for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++) std::swap(EP.aLDRPixels[i].b, EP.aLDRPixels[i].a); break;
}
}
}
@@ -2197,17 +2237,18 @@ void D3DX_BC7::Encode(const HDRColorA* const pIn)
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DX_BC7::GeneratePaletteQuantized(const EncodeParams* pEP, size_t uIndexMode, const LDREndPntPair& endPts, LDRColorA aPalette[]) const
{
assert( pEP );
const size_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec;
const size_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2;
- const size_t uNumIndices = 1 << uIndexPrec;
- const size_t uNumIndices2 = 1 << uIndexPrec2;
+ const size_t uNumIndices = size_t(1) << uIndexPrec;
+ const size_t uNumIndices2 = size_t(1) << uIndexPrec2;
assert( uNumIndices > 0 && uNumIndices2 > 0 );
- __analysis_assume( uNumIndices > 0 && uNumIndices2 > 0 );
+ _Analysis_assume_( uNumIndices > 0 && uNumIndices2 > 0 );
assert( (uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES) );
- __analysis_assume( (uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES) );
+ _Analysis_assume_( (uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES) );
LDRColorA a = Unquantize(endPts.A, ms_aInfo[pEP->uMode].RGBAPrecWithP);
LDRColorA b = Unquantize(endPts.B, ms_aInfo[pEP->uMode].RGBAPrecWithP);
@@ -2225,6 +2266,7 @@ void D3DX_BC7::GeneratePaletteQuantized(const EncodeParams* pEP, size_t uIndexMo
}
}
+_Use_decl_annotations_
float D3DX_BC7::PerturbOne(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, size_t ch,
const LDREndPntPair &oldEndPts, LDREndPntPair &newEndPts, float fOldErr, uint8_t do_b) const
{
@@ -2266,6 +2308,7 @@ float D3DX_BC7::PerturbOne(const EncodeParams* pEP, const LDRColorA aColors[], s
// perturb the endpoints at least -3 to 3.
// always ensure endpoint ordering is preserved (no need to overlap the scan)
+_Use_decl_annotations_
void D3DX_BC7::Exhaustive(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, size_t ch,
float& fOrgErr, LDREndPntPair& optEndPt) const
{
@@ -2336,6 +2379,7 @@ void D3DX_BC7::Exhaustive(const EncodeParams* pEP, const LDRColorA aColors[], si
}
}
+_Use_decl_annotations_
void D3DX_BC7::OptimizeOne(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode,
float fOrgErr, const LDREndPntPair& org, LDREndPntPair& opt) const
{
@@ -2401,13 +2445,14 @@ void D3DX_BC7::OptimizeOne(const EncodeParams* pEP, const LDRColorA aColors[], s
Exhaustive(pEP, aColors, np, uIndexMode, ch, fOptErr, opt);
}
+_Use_decl_annotations_
void D3DX_BC7::OptimizeEndPoints(const EncodeParams* pEP, size_t uShape, size_t uIndexMode, const float afOrgErr[],
const LDREndPntPair aOrgEndPts[], LDREndPntPair aOptEndPts[]) const
{
assert( pEP );
const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
assert( uPartitions < BC7_MAX_REGIONS && uShape < BC7_MAX_SHAPES );
- __analysis_assume( uPartitions < BC7_MAX_REGIONS && uShape < BC7_MAX_SHAPES );
+ _Analysis_assume_( uPartitions < BC7_MAX_REGIONS && uShape < BC7_MAX_SHAPES );
LDRColorA aPixels[NUM_PIXELS_PER_BLOCK];
@@ -2423,16 +2468,17 @@ void D3DX_BC7::OptimizeEndPoints(const EncodeParams* pEP, size_t uShape, size_t
}
}
+_Use_decl_annotations_
void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uIndexMode, LDREndPntPair endPts[], size_t aIndices[], size_t aIndices2[],
float afTotErr[]) const
{
assert( pEP );
assert( uShape < BC7_MAX_SHAPES );
- __analysis_assume( uShape < BC7_MAX_SHAPES );
+ _Analysis_assume_( uShape < BC7_MAX_SHAPES );
const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
assert( uPartitions < BC7_MAX_REGIONS );
- __analysis_assume( uPartitions < BC7_MAX_REGIONS );
+ _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
const uint8_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec;
const uint8_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2;
@@ -2440,14 +2486,13 @@ void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uInd
const uint8_t uNumIndices2 = 1 << uIndexPrec2;
assert( (uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES) );
- __analysis_assume( (uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES) );
+ _Analysis_assume_( (uNumIndices <= BC7_MAX_INDICES) && (uNumIndices2 <= BC7_MAX_INDICES) );
const uint8_t uHighestIndexBit = uNumIndices >> 1;
const uint8_t uHighestIndexBit2 = uNumIndices2 >> 1;
LDRColorA aPalette[BC7_MAX_REGIONS][BC7_MAX_INDICES];
// build list of possibles
- LDREndPntPair adjusted_endPts;
for(size_t p = 0; p <= uPartitions; p++)
{
GeneratePaletteQuantized(pEP, uIndexMode, endPts[p], aPalette[p]);
@@ -2458,7 +2503,7 @@ void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uInd
{
uint8_t uRegion = g_aPartitionTable[uPartitions][uShape][i];
assert( uRegion < BC7_MAX_REGIONS );
- __analysis_assume( uRegion < BC7_MAX_REGIONS );
+ _Analysis_assume_( uRegion < BC7_MAX_REGIONS );
afTotErr[uRegion] += ComputeError(pEP->aLDRPixels[i], aPalette[uRegion], uIndexPrec, uIndexPrec2, &(aIndices[i]), &(aIndices2[i]));
}
@@ -2469,7 +2514,7 @@ void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uInd
{
if(aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit)
{
- Swap(endPts[p].A, endPts[p].B);
+ std::swap(endPts[p].A, endPts[p].B);
for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
if(g_aPartitionTable[uPartitions][uShape][i] == p)
aIndices[i] = uNumIndices - 1 - aIndices[i];
@@ -2483,9 +2528,9 @@ void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uInd
{
if(aIndices[g_aFixUp[uPartitions][uShape][p]] & uHighestIndexBit)
{
- Swap(endPts[p].A.r, endPts[p].B.r);
- Swap(endPts[p].A.g, endPts[p].B.g);
- Swap(endPts[p].A.b, endPts[p].B.b);
+ std::swap(endPts[p].A.r, endPts[p].B.r);
+ std::swap(endPts[p].A.g, endPts[p].B.g);
+ std::swap(endPts[p].A.b, endPts[p].B.b);
for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
if(g_aPartitionTable[uPartitions][uShape][i] == p)
aIndices[i] = uNumIndices - 1 - aIndices[i];
@@ -2494,7 +2539,7 @@ void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uInd
if(aIndices2[0] & uHighestIndexBit2)
{
- Swap(endPts[p].A.a, endPts[p].B.a);
+ std::swap(endPts[p].A.a, endPts[p].B.a);
for(register size_t i = 0; i < NUM_PIXELS_PER_BLOCK; i++)
aIndices2[i] = uNumIndices2 - 1 - aIndices2[i];
}
@@ -2503,12 +2548,13 @@ void D3DX_BC7::AssignIndices(const EncodeParams* pEP, size_t uShape, size_t uInd
}
}
+_Use_decl_annotations_
void D3DX_BC7::EmitBlock(const EncodeParams* pEP, size_t uShape, size_t uRotation, size_t uIndexMode, const LDREndPntPair aEndPts[], const size_t aIndex[], const size_t aIndex2[])
{
assert( pEP );
const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
assert( uPartitions < BC7_MAX_REGIONS );
- __analysis_assume( uPartitions < BC7_MAX_REGIONS );
+ _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
const size_t uPBits = ms_aInfo[pEP->uMode].uPBits;
const size_t uIndexPrec = ms_aInfo[pEP->uMode].uIndexPrec;
@@ -2525,7 +2571,7 @@ void D3DX_BC7::EmitBlock(const EncodeParams* pEP, size_t uShape, size_t uRotatio
if(uPBits)
{
- const size_t uNumEP = (1 + uPartitions) << 1;
+ const size_t uNumEP = size_t(1 + uPartitions) << 1;
uint8_t aPVote[BC7_MAX_REGIONS << 1] = {0,0,0,0,0,0};
uint8_t aCount[BC7_MAX_REGIONS << 1] = {0,0,0,0,0,0};
for(uint8_t ch = 0; ch < BC7_NUM_CHANNELS; ch++)
@@ -2544,12 +2590,12 @@ void D3DX_BC7::EmitBlock(const EncodeParams* pEP, size_t uShape, size_t uRotatio
SetBits(uStartBit, RGBAPrec[ch], aEndPts[i].B[ch] >> 1);
size_t idx = ep++ * uPBits / uNumEP;
assert(idx < (BC7_MAX_REGIONS << 1));
- __analysis_assume(idx < (BC7_MAX_REGIONS << 1));
+ _Analysis_assume_(idx < (BC7_MAX_REGIONS << 1));
aPVote[idx] += aEndPts[i].A[ch] & 0x01;
aCount[idx]++;
idx = ep++ * uPBits / uNumEP;
assert(idx < (BC7_MAX_REGIONS << 1));
- __analysis_assume(idx < (BC7_MAX_REGIONS << 1));
+ _Analysis_assume_(idx < (BC7_MAX_REGIONS << 1));
aPVote[idx] += aEndPts[i].B[ch] & 0x01;
aCount[idx]++;
}
@@ -2589,16 +2635,17 @@ void D3DX_BC7::EmitBlock(const EncodeParams* pEP, size_t uShape, size_t uRotatio
assert(uStartBit == 128);
}
+_Use_decl_annotations_
float D3DX_BC7::Refine(const EncodeParams* pEP, size_t uShape, size_t uRotation, size_t uIndexMode)
{
assert( pEP );
assert( uShape < BC7_MAX_SHAPES );
- __analysis_assume( uShape < BC7_MAX_SHAPES );
+ _Analysis_assume_( uShape < BC7_MAX_SHAPES );
const LDREndPntPair* aEndPts = pEP->aEndPts[uShape];
const size_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
assert( uPartitions < BC7_MAX_REGIONS );
- __analysis_assume( uPartitions < BC7_MAX_REGIONS );
+ _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
LDREndPntPair aOrgEndPts[BC7_MAX_REGIONS];
LDREndPntPair aOptEndPts[BC7_MAX_REGIONS];
@@ -2637,6 +2684,7 @@ float D3DX_BC7::Refine(const EncodeParams* pEP, size_t uShape, size_t uRotation,
}
}
+_Use_decl_annotations_
float D3DX_BC7::MapColors(const EncodeParams* pEP, const LDRColorA aColors[], size_t np, size_t uIndexMode, const LDREndPntPair& endPts, float fMinErr) const
{
assert( pEP );
@@ -2659,16 +2707,17 @@ float D3DX_BC7::MapColors(const EncodeParams* pEP, const LDRColorA aColors[], si
return fTotalErr;
}
+_Use_decl_annotations_
float D3DX_BC7::RoughMSE(EncodeParams* pEP, size_t uShape, size_t uIndexMode)
{
assert( pEP );
assert( uShape < BC7_MAX_SHAPES );
- __analysis_assume( uShape < BC7_MAX_SHAPES );
+ _Analysis_assume_( uShape < BC7_MAX_SHAPES );
LDREndPntPair* aEndPts = pEP->aEndPts[uShape];
const uint8_t uPartitions = ms_aInfo[pEP->uMode].uPartitions;
assert( uPartitions < BC7_MAX_REGIONS );
- __analysis_assume( uPartitions < BC7_MAX_REGIONS );
+ _Analysis_assume_( uPartitions < BC7_MAX_REGIONS );
const uint8_t uIndexPrec = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec2 : ms_aInfo[pEP->uMode].uIndexPrec;
const uint8_t uIndexPrec2 = uIndexMode ? ms_aInfo[pEP->uMode].uIndexPrec : ms_aInfo[pEP->uMode].uIndexPrec2;
@@ -2770,6 +2819,7 @@ float D3DX_BC7::RoughMSE(EncodeParams* pEP, size_t uShape, size_t uIndexMode)
//-------------------------------------------------------------------------------------
// BC6H Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DXDecodeBC6HU(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
@@ -2777,6 +2827,7 @@ void D3DXDecodeBC6HU(XMVECTOR *pColor, const uint8_t *pBC)
reinterpret_cast< const D3DX_BC6H* >( pBC )->Decode(false, reinterpret_cast<HDRColorA*>(pColor));
}
+_Use_decl_annotations_
void D3DXDecodeBC6HS(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
@@ -2784,6 +2835,7 @@ void D3DXDecodeBC6HS(XMVECTOR *pColor, const uint8_t *pBC)
reinterpret_cast< const D3DX_BC6H* >( pBC )->Decode(true, reinterpret_cast<HDRColorA*>(pColor));
}
+_Use_decl_annotations_
void D3DXEncodeBC6HU(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER(flags);
@@ -2792,6 +2844,7 @@ void D3DXEncodeBC6HU(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
reinterpret_cast< D3DX_BC6H* >( pBC )->Encode(false, reinterpret_cast<const HDRColorA*>(pColor));
}
+_Use_decl_annotations_
void D3DXEncodeBC6HS(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER(flags);
@@ -2804,6 +2857,7 @@ void D3DXEncodeBC6HS(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
//-------------------------------------------------------------------------------------
// BC7 Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void D3DXDecodeBC7(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
@@ -2811,12 +2865,12 @@ void D3DXDecodeBC7(XMVECTOR *pColor, const uint8_t *pBC)
reinterpret_cast< const D3DX_BC7* >( pBC )->Decode(reinterpret_cast<HDRColorA*>(pColor));
}
+_Use_decl_annotations_
void D3DXEncodeBC7(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
- UNREFERENCED_PARAMETER(flags);
assert( pBC && pColor );
static_assert( sizeof(D3DX_BC7) == 16, "D3DX_BC7 should be 16 bytes" );
- reinterpret_cast< D3DX_BC7* >( pBC )->Encode(reinterpret_cast<const HDRColorA*>(pColor));
+ reinterpret_cast< D3DX_BC7* >( pBC )->Encode( !(flags& BC_FLAGS_USE_3SUBSETS), reinterpret_cast<const HDRColorA*>(pColor));
}
-} // namespace \ No newline at end of file
+} // namespace
diff --git a/thirdparty/directxtex/DirectXTex/BCDirectCompute.cpp b/thirdparty/directxtex/DirectXTex/BCDirectCompute.cpp
new file mode 100644
index 00000000..0976dc12
--- /dev/null
+++ b/thirdparty/directxtex/DirectXTex/BCDirectCompute.cpp
@@ -0,0 +1,616 @@
+//-------------------------------------------------------------------------------------
+// BCDirectCompute.cpp
+//
+// Direct3D 11 Compute Shader BC Compressor
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//-------------------------------------------------------------------------------------
+
+#include "directxtexp.h"
+
+#include "BCDirectCompute.h"
+
+#if defined(_DEBUG) || defined(PROFILE)
+#pragma comment(lib,"dxguid.lib")
+#endif
+
+using Microsoft::WRL::ComPtr;
+
+namespace
+{
+ #include "Shaders\Compiled\BC7Encode_EncodeBlockCS.inc"
+ #include "Shaders\Compiled\BC7Encode_TryMode02CS.inc"
+ #include "Shaders\Compiled\BC7Encode_TryMode137CS.inc"
+ #include "Shaders\Compiled\BC7Encode_TryMode456CS.inc"
+ #include "Shaders\Compiled\BC6HEncode_EncodeBlockCS.inc"
+ #include "Shaders\Compiled\BC6HEncode_TryModeG10CS.inc"
+ #include "Shaders\Compiled\BC6HEncode_TryModeLE10CS.inc"
+
+ struct BufferBC6HBC7
+ {
+ UINT color[4];
+ };
+
+ struct ConstantsBC6HBC7
+ {
+ UINT tex_width;
+ UINT num_block_x;
+ UINT format;
+ UINT mode_id;
+ UINT start_block_id;
+ UINT num_total_blocks;
+ float alpha_weight;
+ UINT reserved;
+ };
+
+ static_assert( sizeof(ConstantsBC6HBC7) == sizeof(UINT)*8, "Constant buffer size mismatch" );
+
+ inline void RunComputeShader( ID3D11DeviceContext* pContext,
+ ID3D11ComputeShader* shader,
+ ID3D11ShaderResourceView** pSRVs,
+ UINT srvCount,
+ ID3D11Buffer* pCB,
+ ID3D11UnorderedAccessView* pUAV,
+ UINT X )
+ {
+ // Force UAV to nullptr before setting SRV since we are swapping buffers
+ ID3D11UnorderedAccessView* nullUAV = nullptr;
+ pContext->CSSetUnorderedAccessViews( 0, 1, &nullUAV, nullptr );
+
+ pContext->CSSetShader( shader, nullptr, 0 );
+ pContext->CSSetShaderResources( 0, srvCount, pSRVs );
+ pContext->CSSetUnorderedAccessViews( 0, 1, &pUAV, nullptr );
+ pContext->CSSetConstantBuffers( 0, 1, &pCB );
+ pContext->Dispatch( X, 1, 1 );
+ }
+
+ inline void ResetContext( ID3D11DeviceContext* pContext )
+ {
+ ID3D11UnorderedAccessView* nullUAV = nullptr;
+ pContext->CSSetUnorderedAccessViews( 0, 1, &nullUAV, nullptr );
+
+ ID3D11ShaderResourceView* nullSRV[3] = { nullptr, nullptr, nullptr };
+ pContext->CSSetShaderResources( 0, 3, nullSRV );
+
+ ID3D11Buffer* nullBuffer[1] = { nullptr };
+ pContext->CSSetConstantBuffers( 0, 1, nullBuffer );
+ }
+};
+
+namespace DirectX
+{
+
+GPUCompressBC::GPUCompressBC() :
+ m_bcformat(DXGI_FORMAT_UNKNOWN),
+ m_srcformat(DXGI_FORMAT_UNKNOWN),
+ m_alphaWeight(1.f),
+ m_width(0),
+ m_height(0)
+{
+}
+
+
+//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
+HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
+{
+ if ( !pDevice )
+ return E_INVALIDARG;
+
+ // Check for DirectCompute support
+ D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel();
+
+ if ( fl < D3D_FEATURE_LEVEL_10_0 )
+ {
+ // DirectCompute not supported on Feature Level 9.x hardware
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
+
+ if ( fl < D3D_FEATURE_LEVEL_11_0 )
+ {
+ // DirectCompute support on Feature Level 10.x hardware is optional, and this function needs it
+ D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts;
+ HRESULT hr = pDevice->CheckFeatureSupport( D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) );
+ if ( FAILED(hr) )
+ {
+ memset( &hwopts, 0, sizeof(hwopts) );
+ }
+
+ if ( !hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x )
+ {
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
+ }
+
+ // Save a device reference and obtain immediate context
+ m_device = pDevice;
+
+ pDevice->GetImmediateContext( m_context.ReleaseAndGetAddressOf() );
+ assert( m_context );
+
+ //--- Create compute shader library: BC6H -----------------------------------------
+
+ // Modes 11-14
+ HRESULT hr = pDevice->CreateComputeShader( BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ return hr;
+
+ // Modes 1-10
+ hr = pDevice->CreateComputeShader( BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ return hr;
+
+ // Encode
+ hr = pDevice->CreateComputeShader( BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ return hr;
+
+ //--- Create compute shader library: BC7 ------------------------------------------
+
+ // Modes 4, 5, 6
+ hr = pDevice->CreateComputeShader( BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ return hr;
+
+ // Modes 1, 3, 7
+ hr = pDevice->CreateComputeShader( BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ return hr;
+
+ // Modes 0, 2
+ hr = pDevice->CreateComputeShader( BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ return hr;
+
+ // Encode
+ hr = pDevice->CreateComputeShader( BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ return hr;
+
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
+HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format, float alphaWeight, bool skip3subsets )
+{
+ if ( !width || !height || alphaWeight < 0.f )
+ return E_INVALIDARG;
+
+#ifdef _M_X64
+ if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) )
+ return E_INVALIDARG;
+#endif
+
+ m_width = width;
+ m_height = height;
+
+ m_alphaWeight = alphaWeight;
+
+ m_skip3Subsets = skip3subsets;
+
+ size_t xblocks = std::max<size_t>( 1, (width + 3) >> 2 );
+ size_t yblocks = std::max<size_t>( 1, (height + 3) >> 2 );
+ size_t num_blocks = xblocks * yblocks;
+
+ switch( format )
+ {
+ // BC6H GPU compressor takes RGBAF32 as input
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ m_srcformat = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ break;
+
+ // BC7 GPU compressor takes RGBA32 as input
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ break;
+
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ break;
+
+ default:
+ m_bcformat = m_srcformat = DXGI_FORMAT_UNKNOWN;
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
+
+ m_bcformat = format;
+
+ auto pDevice = m_device.Get();
+ if ( !pDevice )
+ return E_POINTER;
+
+ // Create structured buffers
+ size_t bufferSize = num_blocks * sizeof( BufferBC6HBC7 );
+ {
+ D3D11_BUFFER_DESC desc;
+ memset( &desc, 0, sizeof(desc) );
+ desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
+ desc.StructureByteStride = sizeof( BufferBC6HBC7 );
+ desc.ByteWidth = static_cast<UINT>( bufferSize );
+
+ HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_output.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+
+ hr = pDevice->CreateBuffer( &desc, nullptr, m_err1.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+
+ hr = pDevice->CreateBuffer( &desc, nullptr, m_err2.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+ }
+
+ // Create staging output buffer
+ {
+ D3D11_BUFFER_DESC desc;
+ memset( &desc, 0, sizeof(desc) );
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc.ByteWidth = static_cast<UINT>( bufferSize );
+
+ HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+ }
+
+ // Create constant buffer
+ {
+ D3D11_BUFFER_DESC desc;
+ memset( &desc, 0, sizeof(desc) );
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.ByteWidth = sizeof( ConstantsBC6HBC7 );
+
+ HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+ }
+
+ // Create shader resource views
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+ memset( &desc, 0, sizeof(desc) );
+ desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
+ desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+
+ HRESULT hr = pDevice->CreateShaderResourceView( m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+
+ hr = pDevice->CreateShaderResourceView( m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+ }
+
+ // Create unordered access views
+ {
+ D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
+ memset( &desc, 0, sizeof(desc) );
+ desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
+ desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+
+ HRESULT hr = pDevice->CreateUnorderedAccessView( m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+
+ hr = pDevice->CreateUnorderedAccessView( m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+
+ hr = pDevice->CreateUnorderedAccessView( m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+ }
+
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
+HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
+{
+ if ( !srcImage.pixels || !destImage.pixels )
+ return E_INVALIDARG;
+
+ if ( srcImage.width != destImage.width
+ || srcImage.height != destImage.height
+ || srcImage.width != m_width
+ || srcImage.height != m_height
+ || srcImage.format != m_srcformat
+ || destImage.format != m_bcformat )
+ {
+ return E_UNEXPECTED;
+ }
+
+ //--- Create input texture --------------------------------------------------------
+ auto pDevice = m_device.Get();
+ if ( !pDevice )
+ return E_POINTER;
+
+ // We need to avoid the hardware doing additional colorspace conversion
+ DXGI_FORMAT inputFormat = ( m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat;
+
+ ComPtr<ID3D11Texture2D> sourceTex;
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ memset( &desc, 0, sizeof(desc) );
+ desc.Width = static_cast<UINT>( srcImage.width );
+ desc.Height = static_cast<UINT>( srcImage.height );
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = inputFormat;
+ desc.SampleDesc.Count = 1;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+
+ D3D11_SUBRESOURCE_DATA initData;
+ initData.pSysMem = srcImage.pixels;
+ initData.SysMemPitch = static_cast<DWORD>( srcImage.rowPitch );
+ initData.SysMemSlicePitch = static_cast<DWORD>( srcImage.slicePitch );
+
+ HRESULT hr = pDevice->CreateTexture2D( &desc, &initData, sourceTex.GetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+ }
+
+ ComPtr<ID3D11ShaderResourceView> sourceSRV;
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+ memset( &desc, 0, sizeof(desc) );
+ desc.Texture2D.MipLevels = 1;
+ desc.Format = inputFormat;
+ desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+
+ HRESULT hr = pDevice->CreateShaderResourceView( sourceTex.Get(), &desc, sourceSRV.GetAddressOf() );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+ }
+
+ //--- Compress using DirectCompute ------------------------------------------------
+ bool isbc7 = false;
+ switch( m_bcformat )
+ {
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ break;
+
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ isbc7 = true;
+ break;
+
+ default:
+ return E_UNEXPECTED;
+ }
+
+ const UINT MAX_BLOCK_BATCH = 64;
+
+ auto pContext = m_context.Get();
+ if ( !pContext )
+ return E_UNEXPECTED;
+
+ size_t xblocks = std::max<size_t>( 1, (m_width + 3) >> 2 );
+ size_t yblocks = std::max<size_t>( 1, (m_height + 3) >> 2 );
+
+ UINT num_total_blocks = static_cast<UINT>( xblocks * yblocks );
+ UINT num_blocks = num_total_blocks;
+ int start_block_id = 0;
+ while (num_blocks > 0)
+ {
+ UINT n = std::min<UINT>( num_blocks, MAX_BLOCK_BATCH );
+ UINT uThreadGroupCount = n;
+
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
+ if ( FAILED(hr) )
+ return hr;
+
+ ConstantsBC6HBC7 param;
+ param.tex_width = static_cast<UINT>( srcImage.width );
+ param.num_block_x = static_cast<UINT>( xblocks );
+ param.format = m_bcformat;
+ param.mode_id = 0;
+ param.start_block_id = start_block_id;
+ param.num_total_blocks = num_total_blocks;
+ param.alpha_weight = m_alphaWeight;
+ memcpy( mapped.pData, &param, sizeof( param ) );
+
+ pContext->Unmap( m_constBuffer.Get(), 0 );
+ }
+
+ if ( isbc7 )
+ {
+ //--- BC7 -----------------------------------------------------------------
+ ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
+ RunComputeShader( pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
+ m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
+
+ for ( UINT i = 0; i < 3; ++i )
+ {
+ static const UINT modes[] = { 1, 3, 7 };
+
+ // Mode 1: err1 -> err2
+ // Mode 3: err2 -> err1
+ // Mode 7: err1 -> err2
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
+ if ( FAILED(hr) )
+ {
+ ResetContext( pContext );
+ return hr;
+ }
+
+ ConstantsBC6HBC7 param;
+ param.tex_width = static_cast<UINT>( srcImage.width );
+ param.num_block_x = static_cast<UINT>( xblocks );
+ param.format = m_bcformat;
+ param.mode_id = modes[i];
+ param.start_block_id = start_block_id;
+ param.num_total_blocks = num_total_blocks;
+ param.alpha_weight = m_alphaWeight;
+ memcpy( mapped.pData, &param, sizeof( param ) );
+ pContext->Unmap( m_constBuffer.Get(), 0 );
+ }
+
+ pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
+ RunComputeShader( pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
+ (i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount );
+ }
+
+ if ( !m_skip3Subsets )
+ {
+ // 3 subset modes tend to be used rarely and add significant compression time
+ for ( UINT i = 0; i < 2; ++i )
+ {
+ static const UINT modes[] = { 0, 2 };
+ // Mode 0: err2 -> err1
+ // Mode 2: err1 -> err2
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
+ if ( FAILED(hr) )
+ {
+ ResetContext( pContext );
+ return hr;
+ }
+
+ ConstantsBC6HBC7 param;
+ param.tex_width = static_cast<UINT>( srcImage.width );
+ param.num_block_x = static_cast<UINT>( xblocks );
+ param.format = m_bcformat;
+ param.mode_id = modes[i];
+ param.start_block_id = start_block_id;
+ param.num_total_blocks = num_total_blocks;
+ param.alpha_weight = m_alphaWeight;
+ memcpy( mapped.pData, &param, sizeof( param ) );
+ pContext->Unmap( m_constBuffer.Get(), 0 );
+ }
+
+ pSRVs[1] = (i & 1) ? m_err1SRV.Get() : m_err2SRV.Get();
+ RunComputeShader( pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
+ (i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount );
+ }
+ }
+
+ pSRVs[1] = m_err2SRV.Get();
+ RunComputeShader( pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
+ m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
+ }
+ else
+ {
+ //--- BC6H ----------------------------------------------------------------
+ ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
+ RunComputeShader( pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
+ m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
+
+ for ( UINT i = 0; i < 10; ++i )
+ {
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
+ if ( FAILED(hr) )
+ {
+ ResetContext( pContext );
+ return hr;
+ }
+
+ ConstantsBC6HBC7 param;
+ param.tex_width = static_cast<UINT>( srcImage.width );
+ param.num_block_x = static_cast<UINT>( xblocks );
+ param.format = m_bcformat;
+ param.mode_id = i;
+ param.start_block_id = start_block_id;
+ param.num_total_blocks = num_total_blocks;
+ memcpy( mapped.pData, &param, sizeof( param ) );
+ pContext->Unmap( m_constBuffer.Get(), 0 );
+ }
+
+ pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
+ RunComputeShader( pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
+ (i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
+ }
+
+ pSRVs[1] = m_err1SRV.Get();
+ RunComputeShader( pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
+ m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
+ }
+
+ start_block_id += n;
+ num_blocks -= n;
+ }
+
+ ResetContext( pContext );
+
+ //--- Copy output texture back to CPU ---------------------------------------------
+
+ pContext->CopyResource( m_outputCPU.Get(), m_output.Get() );
+
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ HRESULT hr = pContext->Map( m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped );
+ if ( SUCCEEDED(hr) )
+ {
+ const uint8_t *pSrc = reinterpret_cast<const uint8_t *>( mapped.pData );
+ uint8_t *pDest = destImage.pixels;
+
+ size_t pitch = xblocks * sizeof( BufferBC6HBC7 );
+
+ size_t rows = std::max<size_t>( 1, ( destImage.height + 3 ) >> 2 );
+
+ for( size_t h = 0; h < rows; ++h )
+ {
+ memcpy( pDest, pSrc, destImage.rowPitch );
+
+ pSrc += pitch;
+ pDest += destImage.rowPitch;
+ }
+
+ pContext->Unmap( m_outputCPU.Get(), 0 );
+ }
+
+ return hr;
+}
+
+}; // namespace \ No newline at end of file
diff --git a/thirdparty/directxtex/DirectXTex/BCDirectCompute.h b/thirdparty/directxtex/DirectXTex/BCDirectCompute.h
new file mode 100644
index 00000000..8bbfa75a
--- /dev/null
+++ b/thirdparty/directxtex/DirectXTex/BCDirectCompute.h
@@ -0,0 +1,67 @@
+//-------------------------------------------------------------------------------------
+// BCDirectCompute.h
+//
+// Direct3D 11 Compute Shader BC Compressor
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//-------------------------------------------------------------------------------------
+
+#pragma once
+
+namespace DirectX
+{
+
+class GPUCompressBC
+{
+public:
+ GPUCompressBC();
+
+ HRESULT Initialize( _In_ ID3D11Device* pDevice );
+
+ HRESULT Prepare( _In_ size_t width, _In_ size_t height, _In_ DXGI_FORMAT format, _In_ float alphaWeight = 1.f, _In_ bool skip3subsets = true );
+
+ HRESULT Compress( _In_ const Image& srcImage, _In_ const Image& destImage );
+
+ DXGI_FORMAT GetSourceFormat() const { return m_srcformat; }
+
+private:
+ DXGI_FORMAT m_bcformat;
+ DXGI_FORMAT m_srcformat;
+ float m_alphaWeight;
+ bool m_skip3Subsets;
+ size_t m_width;
+ size_t m_height;
+
+ Microsoft::WRL::ComPtr<ID3D11Device> m_device;
+ Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_context;
+
+ Microsoft::WRL::ComPtr<ID3D11Buffer> m_err1;
+ Microsoft::WRL::ComPtr<ID3D11UnorderedAccessView> m_err1UAV;
+ Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_err1SRV;
+
+ Microsoft::WRL::ComPtr<ID3D11Buffer> m_err2;
+ Microsoft::WRL::ComPtr<ID3D11UnorderedAccessView> m_err2UAV;
+ Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_err2SRV;
+
+ Microsoft::WRL::ComPtr<ID3D11Buffer> m_output;
+ Microsoft::WRL::ComPtr<ID3D11Buffer> m_outputCPU;
+ Microsoft::WRL::ComPtr<ID3D11UnorderedAccessView> m_outputUAV;
+ Microsoft::WRL::ComPtr<ID3D11Buffer> m_constBuffer;
+
+ // Compute shader library
+ Microsoft::WRL::ComPtr<ID3D11ComputeShader> m_BC6H_tryModeG10CS;
+ Microsoft::WRL::ComPtr<ID3D11ComputeShader> m_BC6H_tryModeLE10CS;
+ Microsoft::WRL::ComPtr<ID3D11ComputeShader> m_BC6H_encodeBlockCS;
+
+ Microsoft::WRL::ComPtr<ID3D11ComputeShader> m_BC7_tryMode456CS;
+ Microsoft::WRL::ComPtr<ID3D11ComputeShader> m_BC7_tryMode137CS;
+ Microsoft::WRL::ComPtr<ID3D11ComputeShader> m_BC7_tryMode02CS;
+ Microsoft::WRL::ComPtr<ID3D11ComputeShader> m_BC7_encodeBlockCS;
+};
+
+}; // namespace \ No newline at end of file
diff --git a/thirdparty/directxtex/DirectXTex/DDS.h b/thirdparty/directxtex/DirectXTex/DDS.h
index 6e913957..4d74620c 100644
--- a/thirdparty/directxtex/DirectXTex/DDS.h
+++ b/thirdparty/directxtex/DirectXTex/DDS.h
@@ -18,12 +18,15 @@
// http://go.microsoft.com/fwlink/?LinkId=248926
//--------------------------------------------------------------------------------------
-#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
-#endif
+#if defined(_XBOX_ONE) && defined(_TITLE)
+#include <d3d11_x.h>
+#else
#include <dxgiformat.h>
+#endif
+// VS 2010's stdint.h conflicts with intsafe.h
#pragma warning(push)
#pragma warning(disable : 4005)
#include <stdint.h>
@@ -95,6 +98,9 @@ extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 =
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 };
+extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_YUY2 =
+ { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 };
+
extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
@@ -169,20 +175,34 @@ extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 =
#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION
-typedef enum DDS_RESOURCE_DIMENSION
+enum DDS_RESOURCE_DIMENSION
{
DDS_DIMENSION_TEXTURE1D = 2,
DDS_DIMENSION_TEXTURE2D = 3,
DDS_DIMENSION_TEXTURE3D = 4,
-} DDS_RESOURCE_DIMENSION;
+};
// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG
-typedef enum DDS_RESOURCE_MISC_FLAG
+enum DDS_RESOURCE_MISC_FLAG
+{
+ DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L,
+};
+
+enum DDS_MISC_FLAGS2
{
- DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L,
-} DDS_RESOURCE_MISC_FLAG;
+ DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L,
+};
+
+enum DDS_ALPHA_MODE
+{
+ DDS_ALPHA_MODE_UNKNOWN = 0,
+ DDS_ALPHA_MODE_STRAIGHT = 1,
+ DDS_ALPHA_MODE_PREMULTIPLIED = 2,
+ DDS_ALPHA_MODE_OPAQUE = 3,
+ DDS_ALPHA_MODE_CUSTOM = 4,
+};
-typedef struct
+struct DDS_HEADER
{
uint32_t dwSize;
uint32_t dwFlags;
@@ -198,17 +218,20 @@ typedef struct
uint32_t dwCaps3;
uint32_t dwCaps4;
uint32_t dwReserved2;
-} DDS_HEADER;
+};
-typedef struct
+struct DDS_HEADER_DXT10
{
DXGI_FORMAT dxgiFormat;
uint32_t resourceDimension;
uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG
uint32_t arraySize;
- uint32_t reserved;
-} DDS_HEADER_DXT10;
+ uint32_t miscFlags2; // see DDS_MISC_FLAGS2
+};
#pragma pack(pop)
+static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" );
+static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch");
+
}; // namespace
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTex.h b/thirdparty/directxtex/DirectXTex/DirectXTex.h
index c4d4b73c..0320e747 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTex.h
+++ b/thirdparty/directxtex/DirectXTex/DirectXTex.h
@@ -13,62 +13,104 @@
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
-#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
+
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (_WIN32_WINNT <= _WIN32_WINNT_WIN8)
+#error WIC is not supported on Windows Phone 8.0
#endif
+// VS 2010's stdint.h conflicts with intsafe.h
#pragma warning(push)
#pragma warning(disable : 4005)
#include <stdint.h>
#pragma warning(pop)
#include <algorithm>
+#include <functional>
+
+#if defined(_XBOX_ONE) && defined(_TITLE)
+#include <d3d11_x.h>
+#define DCOMMON_H_INCLUDED
+#else
+#include <d3d11_1.h>
+#endif
+
+#include <ocidl.h>
+
+// VS 2010 doesn't support explicit calling convention for std::function
+#ifndef DIRECTX_STD_CALLCONV
+#if defined(_MSC_VER) && (_MSC_VER < 1700)
+#define DIRECTX_STD_CALLCONV
+#else
+#define DIRECTX_STD_CALLCONV __cdecl
+#endif
+#endif
-#include <dxgiformat.h>
-#include <d3d11.h>
+// VS 2010/2012 do not support =default =delete
+#ifndef DIRECTX_CTOR_DEFAULT
+#if defined(_MSC_VER) && (_MSC_VER < 1800)
+#define DIRECTX_CTOR_DEFAULT {}
+#define DIRECTX_CTOR_DELETE ;
+#else
+#define DIRECTX_CTOR_DEFAULT =default;
+#define DIRECTX_CTOR_DELETE =delete;
+#endif
+#endif
-#define DIRECTX_TEX_VERSION 100
+#define DIRECTX_TEX_VERSION 132
namespace DirectX
{
+
//---------------------------------------------------------------------------------
// DXGI Format Utilities
- bool IsValid( _In_ DXGI_FORMAT fmt );
- bool IsCompressed( _In_ DXGI_FORMAT fmt );
- bool IsPacked( _In_ DXGI_FORMAT fmt );
- bool IsVideo( _In_ DXGI_FORMAT fmt );
- bool IsSRGB( _In_ DXGI_FORMAT fmt );
- bool IsTypeless( _In_ DXGI_FORMAT fmt );
+ bool __cdecl IsValid( _In_ DXGI_FORMAT fmt );
+ bool __cdecl IsCompressed( _In_ DXGI_FORMAT fmt );
+ bool __cdecl IsPacked( _In_ DXGI_FORMAT fmt );
+ bool __cdecl IsVideo( _In_ DXGI_FORMAT fmt );
+ bool __cdecl IsPlanar( _In_ DXGI_FORMAT fmt );
+ bool __cdecl IsPalettized( _In_ DXGI_FORMAT fmt );
+ bool __cdecl IsDepthStencil(_In_ DXGI_FORMAT fmt );
+ bool __cdecl IsSRGB( _In_ DXGI_FORMAT fmt );
+ bool __cdecl IsTypeless( _In_ DXGI_FORMAT fmt, _In_ bool partialTypeless = true );
+
+ bool __cdecl HasAlpha( _In_ DXGI_FORMAT fmt );
- size_t BitsPerPixel( _In_ DXGI_FORMAT fmt );
+ size_t __cdecl BitsPerPixel( _In_ DXGI_FORMAT fmt );
+
+ size_t __cdecl BitsPerColor( _In_ DXGI_FORMAT fmt );
enum CP_FLAGS
{
CP_FLAGS_NONE = 0x0, // Normal operation
CP_FLAGS_LEGACY_DWORD = 0x1, // Assume pitch is DWORD aligned instead of BYTE aligned
+ CP_FLAGS_PARAGRAPH = 0x2, // Assume pitch is 16-byte aligned instead of BYTE aligned
+ CP_FLAGS_YMM = 0x4, // Assume pitch is 32-byte aligned instead of BYTE aligned
+ CP_FLAGS_ZMM = 0x8, // Assume pitch is 64-byte aligned instead of BYTE aligned
+ CP_FLAGS_PAGE4K = 0x200, // Assume pitch is 4096-byte aligned instead of BYTE aligned
CP_FLAGS_24BPP = 0x10000, // Override with a legacy 24 bits-per-pixel format size
CP_FLAGS_16BPP = 0x20000, // Override with a legacy 16 bits-per-pixel format size
CP_FLAGS_8BPP = 0x40000, // Override with a legacy 8 bits-per-pixel format size
};
- void ComputePitch( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height,
- _Out_ size_t& rowPitch, _Out_ size_t& slicePitch, _In_ DWORD flags = CP_FLAGS_NONE );
+ void __cdecl ComputePitch( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height,
+ _Out_ size_t& rowPitch, _Out_ size_t& slicePitch, _In_ DWORD flags = CP_FLAGS_NONE );
- size_t ComputeScanlines( _In_ DXGI_FORMAT fmt, _In_ size_t height );
+ size_t __cdecl ComputeScanlines( _In_ DXGI_FORMAT fmt, _In_ size_t height );
- DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT fmt );
- DXGI_FORMAT MakeTypeless( _In_ DXGI_FORMAT fmt );
- DXGI_FORMAT MakeTypelessUNORM( _In_ DXGI_FORMAT fmt );
- DXGI_FORMAT MakeTypelessFLOAT( _In_ DXGI_FORMAT fmt );
+ DXGI_FORMAT __cdecl MakeSRGB( _In_ DXGI_FORMAT fmt );
+ DXGI_FORMAT __cdecl MakeTypeless( _In_ DXGI_FORMAT fmt );
+ DXGI_FORMAT __cdecl MakeTypelessUNORM( _In_ DXGI_FORMAT fmt );
+ DXGI_FORMAT __cdecl MakeTypelessFLOAT( _In_ DXGI_FORMAT fmt );
//---------------------------------------------------------------------------------
// Texture metadata
enum TEX_DIMENSION
// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION
{
- TEX_DIMENSION_TEXTURE1D = 2,
- TEX_DIMENSION_TEXTURE2D = 3,
- TEX_DIMENSION_TEXTURE3D = 4,
+ TEX_DIMENSION_TEXTURE1D = 2,
+ TEX_DIMENSION_TEXTURE2D = 3,
+ TEX_DIMENSION_TEXTURE3D = 4,
};
enum TEX_MISC_FLAG
@@ -77,6 +119,21 @@ namespace DirectX
TEX_MISC_TEXTURECUBE = 0x4L,
};
+ enum TEX_MISC_FLAG2
+ {
+ TEX_MISC2_ALPHA_MODE_MASK = 0x7L,
+ };
+
+ enum TEX_ALPHA_MODE
+ // Matches DDS_ALPHA_MODE, encoded in MISC_FLAGS2
+ {
+ TEX_ALPHA_MODE_UNKNOWN = 0,
+ TEX_ALPHA_MODE_STRAIGHT = 1,
+ TEX_ALPHA_MODE_PREMULTIPLIED = 2,
+ TEX_ALPHA_MODE_OPAQUE = 3,
+ TEX_ALPHA_MODE_CUSTOM = 4,
+ };
+
struct TexMetadata
{
size_t width;
@@ -85,11 +142,22 @@ namespace DirectX
size_t arraySize; // For cubemap, this is a multiple of 6
size_t mipLevels;
uint32_t miscFlags;
+ uint32_t miscFlags2;
DXGI_FORMAT format;
TEX_DIMENSION dimension;
- size_t ComputeIndex( _In_ size_t mip, _In_ size_t item, _In_ size_t slice ) const;
+ size_t __cdecl ComputeIndex( _In_ size_t mip, _In_ size_t item, _In_ size_t slice ) const;
// Returns size_t(-1) to indicate an out-of-range error
+
+ bool __cdecl IsCubemap() const { return (miscFlags & TEX_MISC_TEXTURECUBE) != 0; }
+ // Helper for miscFlags
+
+ bool __cdecl IsPMAlpha() const { return ((miscFlags2 & TEX_MISC2_ALPHA_MODE_MASK) == TEX_ALPHA_MODE_PREMULTIPLIED) != 0; }
+ void __cdecl SetAlphaMode( TEX_ALPHA_MODE mode ) { miscFlags2 = (miscFlags2 & ~TEX_MISC2_ALPHA_MODE_MASK) | static_cast<uint32_t>(mode); }
+ // Helpers for miscFlags2
+
+ bool __cdecl IsVolumemap() const { return (dimension == TEX_DIMENSION_TEXTURE3D); }
+ // Helper for dimension
};
enum DDS_FLAGS
@@ -111,8 +179,14 @@ namespace DirectX
DDS_FLAGS_NO_16BPP = 0x10,
// Conversions avoid use of 565, 5551, and 4444 formats and instead expand to 8888 to avoid use of optional WDDM 1.2 formats
+ DDS_FLAGS_EXPAND_LUMINANCE = 0x20,
+ // When loading legacy luminance formats expand replicating the color channels rather than leaving them packed (L8, L16, A8L8)
+
DDS_FLAGS_FORCE_DX10_EXT = 0x10000,
// Always use the 'DX10' header extension for DDS writer (i.e. don't try to write DX9 compatible DDS files)
+
+ DDS_FLAGS_FORCE_DX10_EXT_MISC2 = 0x20000,
+ // DDS_FLAGS_FORCE_DX10_EXT including miscFlags2 information (result may not be compatible with D3DX10 or D3DX11)
};
enum WIC_FLAGS
@@ -129,11 +203,14 @@ namespace DirectX
// Loads 565, 5551, and 4444 formats as 8888 to avoid use of optional WDDM 1.2 formats
WIC_FLAGS_ALLOW_MONO = 0x8,
- // Loads 1-bit monochrome (black & white) as R1_UNORM rather than 8-bit greyscale
+ // Loads 1-bit monochrome (black & white) as R1_UNORM rather than 8-bit grayscale
WIC_FLAGS_ALL_FRAMES = 0x10,
// Loads all images in a multi-frame file, converting/resizing to match the first frame as needed, defaults to 0th frame otherwise
+ WIC_FLAGS_IGNORE_SRGB = 0x20,
+ // Ignores sRGB metadata if present in the file
+
WIC_FLAGS_DITHER = 0x10000,
// Use ordered 4x4 dithering for any required conversions
@@ -147,20 +224,20 @@ namespace DirectX
// Filtering mode to use for any required image resizing (only needed when loading arrays of differently sized images; defaults to Fant)
};
- HRESULT GetMetadataFromDDSMemory( _In_bytecount_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
- _Out_ TexMetadata& metadata );
- HRESULT GetMetadataFromDDSFile( _In_z_ LPCWSTR szFile, DWORD flags,
- _Out_ TexMetadata& metadata );
+ HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
+ _Out_ TexMetadata& metadata );
+ HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
+ _Out_ TexMetadata& metadata );
- HRESULT GetMetadataFromTGAMemory( _In_bytecount_(size) LPCVOID pSource, _In_ size_t size,
- _Out_ TexMetadata& metadata );
- HRESULT GetMetadataFromTGAFile( _In_z_ LPCWSTR szFile,
- _Out_ TexMetadata& metadata );
+ HRESULT __cdecl GetMetadataFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
+ _Out_ TexMetadata& metadata );
+ HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ LPCWSTR szFile,
+ _Out_ TexMetadata& metadata );
- HRESULT GetMetadataFromWICMemory( _In_bytecount_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
- _Out_ TexMetadata& metadata );
- HRESULT GetMetadataFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
- _Out_ TexMetadata& metadata );
+ HRESULT __cdecl GetMetadataFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
+ _Out_ TexMetadata& metadata );
+ HRESULT __cdecl GetMetadataFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
+ _Out_ TexMetadata& metadata );
//---------------------------------------------------------------------------------
// Bitmap image container
@@ -177,33 +254,40 @@ namespace DirectX
class ScratchImage
{
public:
- ScratchImage() : _nimages(0), _size(0), _image(0), _memory(0) {}
+ ScratchImage()
+ : _nimages(0), _size(0), _image(nullptr), _memory(nullptr) {}
+ ScratchImage(ScratchImage&& moveFrom)
+ : _nimages(0), _size(0), _image(nullptr), _memory(nullptr) { *this = std::move(moveFrom); }
~ScratchImage() { Release(); }
- HRESULT Initialize( _In_ const TexMetadata& mdata );
+ ScratchImage& __cdecl operator= (ScratchImage&& moveFrom);
- HRESULT Initialize1D( _In_ DXGI_FORMAT fmt, _In_ size_t length, _In_ size_t arraySize, _In_ size_t mipLevels );
- HRESULT Initialize2D( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels );
- HRESULT Initialize3D( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t depth, _In_ size_t mipLevels );
- HRESULT InitializeCube( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t nCubes, _In_ size_t mipLevels );
+ HRESULT __cdecl Initialize( _In_ const TexMetadata& mdata, _In_ DWORD flags = CP_FLAGS_NONE );
- HRESULT InitializeFromImage( _In_ const Image& srcImage, _In_ bool allow1D = false );
- HRESULT InitializeArrayFromImages( _In_count_(nImages) const Image* images, _In_ size_t nImages, _In_ bool allow1D = false );
- HRESULT InitializeCubeFromImages( _In_count_(nImages) const Image* images, _In_ size_t nImages );
- HRESULT Initialize3DFromImages( _In_count_(depth) const Image* images, _In_ size_t depth );
+ HRESULT __cdecl Initialize1D( _In_ DXGI_FORMAT fmt, _In_ size_t length, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
+ HRESULT __cdecl Initialize2D( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
+ HRESULT __cdecl Initialize3D( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t depth, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
+ HRESULT __cdecl InitializeCube( _In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t nCubes, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
- void Release();
+ HRESULT __cdecl InitializeFromImage( _In_ const Image& srcImage, _In_ bool allow1D = false, _In_ DWORD flags = CP_FLAGS_NONE );
+ HRESULT __cdecl InitializeArrayFromImages( _In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ bool allow1D = false, _In_ DWORD flags = CP_FLAGS_NONE );
+ HRESULT __cdecl InitializeCubeFromImages( _In_reads_(nImages) const Image* images, _In_ size_t nImages, _In_ DWORD flags = CP_FLAGS_NONE );
+ HRESULT __cdecl Initialize3DFromImages( _In_reads_(depth) const Image* images, _In_ size_t depth, _In_ DWORD flags = CP_FLAGS_NONE );
- bool OverrideFormat( _In_ DXGI_FORMAT f );
+ void __cdecl Release();
- const TexMetadata& GetMetadata() const { return _metadata; }
- const Image* GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const;
+ bool __cdecl OverrideFormat( _In_ DXGI_FORMAT f );
- const Image* GetImages() const { return _image; }
- size_t GetImageCount() const { return _nimages; }
+ const TexMetadata& __cdecl GetMetadata() const { return _metadata; }
+ const Image* __cdecl GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const;
- uint8_t* GetPixels() const { return _memory; }
- size_t GetPixelsSize() const { return _size; }
+ const Image* __cdecl GetImages() const { return _image; }
+ size_t __cdecl GetImageCount() const { return _nimages; }
+
+ uint8_t* __cdecl GetPixels() const { return _memory; }
+ size_t __cdecl GetPixelsSize() const { return _size; }
+
+ bool __cdecl IsAlphaAllOpaque() const;
private:
size_t _nimages;
@@ -222,15 +306,18 @@ namespace DirectX
class Blob
{
public:
- Blob() : _buffer(0), _size(0) {}
+ Blob() : _buffer(nullptr), _size(0) {}
+ Blob(Blob&& moveFrom) : _buffer(nullptr), _size(0) { *this = std::move(moveFrom); }
~Blob() { Release(); }
- HRESULT Initialize( _In_ size_t size );
+ Blob& __cdecl operator= (Blob&& moveFrom);
+
+ HRESULT __cdecl Initialize( _In_ size_t size );
- void Release();
+ void __cdecl Release();
- void *GetBufferPointer() const { return _buffer; }
- size_t GetBufferSize() const { return _size; }
+ void *__cdecl GetBufferPointer() const { return _buffer; }
+ size_t __cdecl GetBufferSize() const { return _size; }
private:
void* _buffer;
@@ -245,43 +332,47 @@ namespace DirectX
// Image I/O
// DDS operations
- HRESULT LoadFromDDSMemory( _In_bytecount_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
- _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
- HRESULT LoadFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
- _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
+ HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
+ _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
+ HRESULT __cdecl LoadFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
+ _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
- HRESULT SaveToDDSMemory( _In_ const Image& image, _In_ DWORD flags,
- _Out_ Blob& blob );
- HRESULT SaveToDDSMemory( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags,
- _Out_ Blob& blob );
+ HRESULT __cdecl SaveToDDSMemory( _In_ const Image& image, _In_ DWORD flags,
+ _Out_ Blob& blob );
+ HRESULT __cdecl SaveToDDSMemory( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags,
+ _Out_ Blob& blob );
- HRESULT SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
- HRESULT SaveToDDSFile( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
+ HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
+ HRESULT __cdecl SaveToDDSFile( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
// TGA operations
- HRESULT LoadFromTGAMemory( _In_bytecount_(size) LPCVOID pSource, _In_ size_t size,
- _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
- HRESULT LoadFromTGAFile( _In_z_ LPCWSTR szFile,
- _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
+ HRESULT __cdecl LoadFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
+ _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
+ HRESULT __cdecl LoadFromTGAFile( _In_z_ LPCWSTR szFile,
+ _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
- HRESULT SaveToTGAMemory( _In_ const Image& image, _Out_ Blob& blob );
- HRESULT SaveToTGAFile( _In_ const Image& image, _In_z_ LPCWSTR szFile );
+ HRESULT __cdecl SaveToTGAMemory( _In_ const Image& image, _Out_ Blob& blob );
+ HRESULT __cdecl SaveToTGAFile( _In_ const Image& image, _In_z_ LPCWSTR szFile );
// WIC operations
- HRESULT LoadFromWICMemory( _In_bytecount_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
- _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
- HRESULT LoadFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
- _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
-
- HRESULT SaveToWICMemory( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
- _Out_ Blob& blob, _In_opt_ const GUID* targetFormat = nullptr );
- HRESULT SaveToWICMemory( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
- _Out_ Blob& blob, _In_opt_ const GUID* targetFormat = nullptr );
-
- HRESULT SaveToWICFile( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
- _In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr );
- HRESULT SaveToWICFile( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
- _In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr );
+ HRESULT __cdecl LoadFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
+ _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
+ HRESULT __cdecl LoadFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
+ _Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
+
+ HRESULT __cdecl SaveToWICMemory( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
+ _Out_ Blob& blob, _In_opt_ const GUID* targetFormat = nullptr,
+ _In_opt_ std::function<void DIRECTX_STD_CALLCONV(IPropertyBag2*)> setCustomProps = nullptr );
+ HRESULT __cdecl SaveToWICMemory( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
+ _Out_ Blob& blob, _In_opt_ const GUID* targetFormat = nullptr,
+ _In_opt_ std::function<void DIRECTX_STD_CALLCONV(IPropertyBag2*)> setCustomProps = nullptr );
+
+ HRESULT __cdecl SaveToWICFile( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
+ _In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
+ _In_opt_ std::function<void DIRECTX_STD_CALLCONV(IPropertyBag2*)> setCustomProps = nullptr );
+ HRESULT __cdecl SaveToWICFile( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
+ _In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
+ _In_opt_ std::function<void DIRECTX_STD_CALLCONV(IPropertyBag2*)> setCustomProps = nullptr );
enum WICCodecs
{
@@ -294,7 +385,7 @@ namespace DirectX
WIC_CODEC_ICO, // Windows Icon (.ico)
};
- REFGUID GetWICCodec( _In_ WICCodecs codec );
+ REFGUID __cdecl GetWICCodec( _In_ WICCodecs codec );
//---------------------------------------------------------------------------------
// Texture conversion, resizing, mipmap generation, and block compression
@@ -309,20 +400,34 @@ namespace DirectX
TEX_FR_FLIP_VERTICAL = 0x10,
};
- HRESULT FlipRotate( _In_ const Image& srcImage, _In_ DWORD flags, _Out_ ScratchImage& image );
- HRESULT FlipRotate( _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _In_ DWORD flags, _Out_ ScratchImage& result );
+ HRESULT __cdecl FlipRotate( _In_ const Image& srcImage, _In_ DWORD flags, _Out_ ScratchImage& image );
+ HRESULT __cdecl FlipRotate( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ DWORD flags, _Out_ ScratchImage& result );
// Flip and/or rotate image
enum TEX_FILTER_FLAGS
{
TEX_FILTER_DEFAULT = 0,
- // Clamp filtering only
+ TEX_FILTER_WRAP_U = 0x1,
+ TEX_FILTER_WRAP_V = 0x2,
+ TEX_FILTER_WRAP_W = 0x4,
+ TEX_FILTER_WRAP = ( TEX_FILTER_WRAP_U | TEX_FILTER_WRAP_V | TEX_FILTER_WRAP_W ),
+ TEX_FILTER_MIRROR_U = 0x10,
+ TEX_FILTER_MIRROR_V = 0x20,
+ TEX_FILTER_MIRROR_W = 0x40,
+ TEX_FILTER_MIRROR = ( TEX_FILTER_MIRROR_U | TEX_FILTER_MIRROR_V | TEX_FILTER_MIRROR_W ),
+ // Wrap vs. Mirror vs. Clamp filtering options
TEX_FILTER_SEPARATE_ALPHA = 0x100,
// Resize color and alpha channel independently
+ TEX_FILTER_RGB_COPY_RED = 0x1000,
+ TEX_FILTER_RGB_COPY_GREEN = 0x2000,
+ TEX_FILTER_RGB_COPY_BLUE = 0x4000,
+ // When converting RGB to R, defaults to using grayscale. These flags indicate copying a specific channel instead
+ // When converting RGB to RG, defaults to copying RED | GREEN. These flags control which channels are selected instead.
+
TEX_FILTER_DITHER = 0x10000,
// Use ordered 4x4 dithering for any required conversions
TEX_FILTER_DITHER_DIFFUSION = 0x20000,
@@ -331,44 +436,75 @@ namespace DirectX
TEX_FILTER_POINT = 0x100000,
TEX_FILTER_LINEAR = 0x200000,
TEX_FILTER_CUBIC = 0x300000,
+ TEX_FILTER_BOX = 0x400000,
TEX_FILTER_FANT = 0x400000, // Equiv to Box filtering for mipmap generation
+ TEX_FILTER_TRIANGLE = 0x500000,
// Filtering mode to use for any required image resizing
TEX_FILTER_SRGB_IN = 0x1000000,
TEX_FILTER_SRGB_OUT = 0x2000000,
- TEX_FILTER_SRGB = 0x3000000,
+ TEX_FILTER_SRGB = ( TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT ),
// sRGB <-> RGB for use in conversion operations
// if the input format type is IsSRGB(), then SRGB_IN is on by default
// if the output format type is IsSRGB(), then SRGB_OUT is on by default
+
+ TEX_FILTER_FORCE_NON_WIC = 0x10000000,
+ // Forces use of the non-WIC path when both are an option
+
+ TEX_FILTER_FORCE_WIC = 0x20000000,
+ // Forces use of the WIC path even when logic would have picked a non-WIC path when both are an option
};
- HRESULT Resize( _In_ const Image& srcImage, _In_ size_t width, _In_ size_t height, _In_ DWORD filter,
- _Out_ ScratchImage& image );
- HRESULT Resize( _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _In_ size_t width, _In_ size_t height, _In_ DWORD filter, _Out_ ScratchImage& result );
+ HRESULT __cdecl Resize( _In_ const Image& srcImage, _In_ size_t width, _In_ size_t height, _In_ DWORD filter,
+ _Out_ ScratchImage& image );
+ HRESULT __cdecl Resize( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ size_t width, _In_ size_t height, _In_ DWORD filter, _Out_ ScratchImage& result );
// Resize the image to width x height. Defaults to Fant filtering.
// Note for a complex resize, the result will always have mipLevels == 1
- HRESULT Convert( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold,
- _Out_ ScratchImage& image );
- HRESULT Convert( _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold, _Out_ ScratchImage& result );
+ HRESULT __cdecl Convert( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold,
+ _Out_ ScratchImage& image );
+ HRESULT __cdecl Convert( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold, _Out_ ScratchImage& result );
// Convert the image to a new format
- HRESULT GenerateMipMaps( _In_ const Image& baseImage, _In_ DWORD filter, _In_ size_t levels,
- _Out_ ScratchImage& mipChain, bool allow1D = false );
- HRESULT GenerateMipMaps( _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _In_ DWORD filter, _In_ size_t levels, _Out_ ScratchImage& mipChain );
+ HRESULT __cdecl ConvertToSinglePlane( _In_ const Image& srcImage, _Out_ ScratchImage& image );
+ HRESULT __cdecl ConvertToSinglePlane( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _Out_ ScratchImage& image );
+ // Converts the image from a planar format to an equivalent non-planar format
+
+ HRESULT __cdecl GenerateMipMaps( _In_ const Image& baseImage, _In_ DWORD filter, _In_ size_t levels,
+ _Inout_ ScratchImage& mipChain, _In_ bool allow1D = false );
+ HRESULT __cdecl GenerateMipMaps( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ DWORD filter, _In_ size_t levels, _Inout_ ScratchImage& mipChain );
// levels of '0' indicates a full mipchain, otherwise is generates that number of total levels (including the source base image)
// Defaults to Fant filtering which is equivalent to a box filter
- HRESULT GenerateMipMaps3D( _In_count_(depth) const Image* baseImages, _In_ size_t depth, _In_ DWORD filter, _In_ size_t levels,
- _Out_ ScratchImage& mipChain );
- HRESULT GenerateMipMaps3D( _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _In_ DWORD filter, _In_ size_t levels, _Out_ ScratchImage& mipChain );
+ HRESULT __cdecl GenerateMipMaps3D( _In_reads_(depth) const Image* baseImages, _In_ size_t depth, _In_ DWORD filter, _In_ size_t levels,
+ _Out_ ScratchImage& mipChain );
+ HRESULT __cdecl GenerateMipMaps3D( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ DWORD filter, _In_ size_t levels, _Out_ ScratchImage& mipChain );
// levels of '0' indicates a full mipchain, otherwise is generates that number of total levels (including the source base image)
// Defaults to Fant filtering which is equivalent to a box filter
+ enum TEX_PMALPHA_FLAGS
+ {
+ TEX_PMALPHA_DEFAULT = 0,
+
+ TEX_PMALPHA_IGNORE_SRGB = 0x1,
+ // ignores sRGB colorspace conversions
+
+ TEX_PMALPHA_SRGB_IN = 0x1000000,
+ TEX_PMALPHA_SRGB_OUT = 0x2000000,
+ TEX_PMALPHA_SRGB = ( TEX_PMALPHA_SRGB_IN | TEX_PMALPHA_SRGB_OUT ),
+ // if the input format type is IsSRGB(), then SRGB_IN is on by default
+ // if the output format type is IsSRGB(), then SRGB_OUT is on by default
+ };
+
+ HRESULT __cdecl PremultiplyAlpha( _In_ const Image& srcImage, _In_ DWORD flags, _Out_ ScratchImage& image );
+ HRESULT __cdecl PremultiplyAlpha( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _Out_ ScratchImage& result );
+ // Converts to a premultiplied alpha version of the texture
+
enum TEX_COMPRESS_FLAGS
{
TEX_COMPRESS_DEFAULT = 0,
@@ -385,19 +521,34 @@ namespace DirectX
TEX_COMPRESS_UNIFORM = 0x40000,
// Uniform color weighting for BC1-3 compression; by default uses perceptual weighting
+ TEX_COMPRESS_BC7_USE_3SUBSETS = 0x80000,
+ // Enables exhaustive search for BC7 compress for mode 0 and 2; by default skips trying these modes
+
+ TEX_COMPRESS_SRGB_IN = 0x1000000,
+ TEX_COMPRESS_SRGB_OUT = 0x2000000,
+ TEX_COMPRESS_SRGB = ( TEX_COMPRESS_SRGB_IN | TEX_COMPRESS_SRGB_OUT ),
+ // if the input format type is IsSRGB(), then SRGB_IN is on by default
+ // if the output format type is IsSRGB(), then SRGB_OUT is on by default
+
TEX_COMPRESS_PARALLEL = 0x10000000,
// Compress is free to use multithreading to improve performance (by default it does not use multithreading)
};
- HRESULT Compress( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef,
- _Out_ ScratchImage& cImage );
- HRESULT Compress( _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef, _Out_ ScratchImage& cImages );
+ HRESULT __cdecl Compress( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef,
+ _Out_ ScratchImage& cImage );
+ HRESULT __cdecl Compress( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef, _Out_ ScratchImage& cImages );
// Note that alphaRef is only used by BC1. 0.5f is a typical value to use
- HRESULT Decompress( _In_ const Image& cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage& image );
- HRESULT Decompress( _In_count_(nimages) const Image* cImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _In_ DXGI_FORMAT format, _Out_ ScratchImage& images );
+ HRESULT __cdecl Compress( _In_ ID3D11Device* pDevice, _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress,
+ _In_ float alphaWeight, _Out_ ScratchImage& image );
+ HRESULT __cdecl Compress( _In_ ID3D11Device* pDevice, _In_ const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaWeight, _Out_ ScratchImage& cImages );
+ // DirectCompute-based compression (alphaWeight is only used by BC7. 1.0 is the typical value to use)
+
+ HRESULT __cdecl Decompress( _In_ const Image& cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage& image );
+ HRESULT __cdecl Decompress( _In_reads_(nimages) const Image* cImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ DXGI_FORMAT format, _Out_ ScratchImage& images );
//---------------------------------------------------------------------------------
// Normal map operations
@@ -426,10 +577,10 @@ namespace DirectX
// Computes a crude occlusion term stored in the alpha channel
};
- HRESULT ComputeNormalMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
- _In_ DXGI_FORMAT format, _Out_ ScratchImage& normalMap );
- HRESULT ComputeNormalMap( _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _In_ DWORD flags, _In_ float amplitude, _In_ DXGI_FORMAT format, _Out_ ScratchImage& normalMaps );
+ HRESULT __cdecl ComputeNormalMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
+ _In_ DXGI_FORMAT format, _Out_ ScratchImage& normalMap );
+ HRESULT __cdecl ComputeNormalMap( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ DWORD flags, _In_ float amplitude, _In_ DXGI_FORMAT format, _Out_ ScratchImage& normalMaps );
//---------------------------------------------------------------------------------
// Misc image operations
@@ -440,26 +591,53 @@ namespace DirectX
size_t w;
size_t h;
- Rect() {}
+ Rect() DIRECTX_CTOR_DEFAULT
Rect( size_t _x, size_t _y, size_t _w, size_t _h ) : x(_x), y(_y), w(_w), h(_h) {}
};
- HRESULT CopyRectangle( _In_ const Image& srcImage, _In_ const Rect& srcRect, _In_ const Image& dstImage,
- _In_ DWORD filter, _In_ size_t xOffset, _In_ size_t yOffset );
+ HRESULT __cdecl CopyRectangle( _In_ const Image& srcImage, _In_ const Rect& srcRect, _In_ const Image& dstImage,
+ _In_ DWORD filter, _In_ size_t xOffset, _In_ size_t yOffset );
+
+ enum CMSE_FLAGS
+ {
+ CMSE_DEFAULT = 0,
- HRESULT ComputeMSE( _In_ const Image& image1, _In_ const Image& image2, _Out_ float& mse, _Out_opt_cap_c_(4) float* mseV );
+ CMSE_IMAGE1_SRGB = 0x1,
+ CMSE_IMAGE2_SRGB = 0x2,
+ // Indicates that image needs gamma correction before comparision
+
+ CMSE_IGNORE_RED = 0x10,
+ CMSE_IGNORE_GREEN = 0x20,
+ CMSE_IGNORE_BLUE = 0x40,
+ CMSE_IGNORE_ALPHA = 0x80,
+ // Ignore the channel when computing MSE
+
+ CMSE_IMAGE1_X2_BIAS = 0x100,
+ CMSE_IMAGE2_X2_BIAS = 0x200,
+ // Indicates that image should be scaled and biased before comparison (i.e. UNORM -> SNORM)
+ };
+
+ HRESULT __cdecl ComputeMSE( _In_ const Image& image1, _In_ const Image& image2, _Out_ float& mse, _Out_writes_opt_(4) float* mseV, _In_ DWORD flags = 0 );
//---------------------------------------------------------------------------------
// Direct3D 11 functions
- bool IsSupportedTexture( _In_ ID3D11Device* pDevice, _In_ const TexMetadata& metadata );
+ bool __cdecl IsSupportedTexture( _In_ ID3D11Device* pDevice, _In_ const TexMetadata& metadata );
+
+ HRESULT __cdecl CreateTexture( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _Outptr_ ID3D11Resource** ppResource );
+
+ HRESULT __cdecl CreateShaderResourceView( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _Outptr_ ID3D11ShaderResourceView** ppSRV );
- HRESULT CreateTexture( _In_ ID3D11Device* pDevice, _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _Deref_out_ ID3D11Resource** ppResource );
+ HRESULT __cdecl CreateTextureEx( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB,
+ _Outptr_ ID3D11Resource** ppResource );
- HRESULT CreateShaderResourceView( _In_ ID3D11Device* pDevice, _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _Deref_out_ ID3D11ShaderResourceView** ppSRV );
+ HRESULT __cdecl CreateShaderResourceViewEx( _In_ ID3D11Device* pDevice, _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ D3D11_USAGE usage, _In_ unsigned int bindFlags, _In_ unsigned int cpuAccessFlags, _In_ unsigned int miscFlags, _In_ bool forceSRGB,
+ _Outptr_ ID3D11ShaderResourceView** ppSRV );
- HRESULT CaptureTexture( _In_ ID3D11Device* pDevice, _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, _Out_ ScratchImage& result );
+ HRESULT __cdecl CaptureTexture( _In_ ID3D11Device* pDevice, _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource* pSource, _Out_ ScratchImage& result );
#include "DirectXTex.inl"
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTex.inl b/thirdparty/directxtex/DirectXTex/DirectXTex.inl
index 909cd402..a6e806ba 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTex.inl
+++ b/thirdparty/directxtex/DirectXTex/DirectXTex.inl
@@ -13,24 +13,20 @@
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
-#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
-#endif
//=====================================================================================
// DXGI Format Utilities
//=====================================================================================
-inline bool IsValid( DXGI_FORMAT fmt )
+_Use_decl_annotations_
+inline bool __cdecl IsValid( DXGI_FORMAT fmt )
{
-#ifdef DXGI_1_2_FORMATS
- return ( static_cast<size_t>(fmt) >= 1 && static_cast<size_t>(fmt) <= 115 );
-#else
- return ( static_cast<size_t>(fmt) >= 1 && static_cast<size_t>(fmt) <= 99 );
-#endif
+ return ( static_cast<size_t>(fmt) >= 1 && static_cast<size_t>(fmt) <= 120 );
}
-inline bool IsCompressed( DXGI_FORMAT fmt )
+_Use_decl_annotations_
+inline bool __cdecl IsCompressed(DXGI_FORMAT fmt)
{
switch ( fmt )
{
@@ -62,14 +58,65 @@ inline bool IsCompressed( DXGI_FORMAT fmt )
}
}
-inline bool IsPacked( DXGI_FORMAT fmt )
+_Use_decl_annotations_
+inline bool __cdecl IsPacked(DXGI_FORMAT fmt)
{
- return ( (fmt == DXGI_FORMAT_R8G8_B8G8_UNORM) || (fmt == DXGI_FORMAT_G8R8_G8B8_UNORM) );
+ switch( fmt )
+ {
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_YUY2: // 4:2:2 8-bit
+ case DXGI_FORMAT_Y210: // 4:2:2 10-bit
+ case DXGI_FORMAT_Y216: // 4:2:2 16-bit
+ return true;
+
+ default:
+ return false;
+ }
}
-inline bool IsVideo( DXGI_FORMAT fmt )
+_Use_decl_annotations_
+inline bool __cdecl IsPlanar(DXGI_FORMAT fmt)
+{
+ switch ( static_cast<int>(fmt) )
+ {
+ case DXGI_FORMAT_NV12: // 4:2:0 8-bit
+ case DXGI_FORMAT_P010: // 4:2:0 10-bit
+ case DXGI_FORMAT_P016: // 4:2:0 16-bit
+ case DXGI_FORMAT_420_OPAQUE:// 4:2:0 8-bit
+ case DXGI_FORMAT_NV11: // 4:1:1 8-bit
+ return true;
+
+ case 118 /* DXGI_FORMAT_D16_UNORM_S8_UINT */:
+ case 119 /* DXGI_FORMAT_R16_UNORM_X8_TYPELESS */:
+ case 120 /* DXGI_FORMAT_X16_TYPELESS_G8_UINT */:
+ // These are Xbox One platform specific types
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+_Use_decl_annotations_
+inline bool __cdecl IsPalettized(DXGI_FORMAT fmt)
+{
+ switch( fmt )
+ {
+ case DXGI_FORMAT_AI44:
+ case DXGI_FORMAT_IA44:
+ case DXGI_FORMAT_P8:
+ case DXGI_FORMAT_A8P8:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+_Use_decl_annotations_
+inline bool __cdecl IsVideo(DXGI_FORMAT fmt)
{
-#ifdef DXGI_1_2_FORMATS
switch ( fmt )
{
case DXGI_FORMAT_AYUV:
@@ -83,7 +130,6 @@ inline bool IsVideo( DXGI_FORMAT fmt )
case DXGI_FORMAT_Y216:
case DXGI_FORMAT_NV11:
// These video formats can be used with the 3D pipeline through special view mappings
- return true;
case DXGI_FORMAT_420_OPAQUE:
case DXGI_FORMAT_AI44:
@@ -96,13 +142,33 @@ inline bool IsVideo( DXGI_FORMAT fmt )
default:
return false;
}
-#else // !DXGI_1_2_FORMATS
- UNREFERENCED_PARAMETER(fmt);
- return false;
-#endif
}
-inline bool IsSRGB( DXGI_FORMAT fmt )
+_Use_decl_annotations_
+inline bool __cdecl IsDepthStencil(DXGI_FORMAT fmt)
+{
+ switch( static_cast<int>(fmt) )
+ {
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ case DXGI_FORMAT_D16_UNORM:
+ case 118 /* DXGI_FORMAT_D16_UNORM_S8_UINT */:
+ case 119 /* DXGI_FORMAT_R16_UNORM_X8_TYPELESS */:
+ case 120 /* DXGI_FORMAT_X16_TYPELESS_G8_UINT */:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+_Use_decl_annotations_
+inline bool __cdecl IsSRGB(DXGI_FORMAT fmt)
{
switch( fmt )
{
@@ -120,24 +186,21 @@ inline bool IsSRGB( DXGI_FORMAT fmt )
}
}
-inline bool IsTypeless( DXGI_FORMAT fmt )
+_Use_decl_annotations_
+inline bool __cdecl IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
{
- switch( fmt )
+ switch( static_cast<int>(fmt) )
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32_TYPELESS:
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
case DXGI_FORMAT_R32G32_TYPELESS:
case DXGI_FORMAT_R32G8X24_TYPELESS:
- case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
- case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
case DXGI_FORMAT_R16G16_TYPELESS:
case DXGI_FORMAT_R32_TYPELESS:
case DXGI_FORMAT_R24G8_TYPELESS:
- case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
- case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
case DXGI_FORMAT_R8G8_TYPELESS:
case DXGI_FORMAT_R16_TYPELESS:
case DXGI_FORMAT_R8_TYPELESS:
@@ -152,15 +215,47 @@ inline bool IsTypeless( DXGI_FORMAT fmt )
case DXGI_FORMAT_BC7_TYPELESS:
return true;
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ return partialTypeless;
+
+ case 119 /* DXGI_FORMAT_R16_UNORM_X8_TYPELESS */:
+ case 120 /* DXGI_FORMAT_X16_TYPELESS_G8_UINT */:
+ // These are Xbox One platform specific types
+ return partialTypeless;
+
default:
return false;
}
}
-inline size_t ComputeScanlines( _In_ DXGI_FORMAT fmt, _In_ size_t height )
+_Use_decl_annotations_
+inline bool __cdecl HasAlpha(DXGI_FORMAT fmt)
{
- switch ( fmt )
+ switch( static_cast<int>(fmt) )
{
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_A8_UNORM:
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB:
@@ -170,21 +265,51 @@ inline size_t ComputeScanlines( _In_ DXGI_FORMAT fmt, _In_ size_t height )
case DXGI_FORMAT_BC3_TYPELESS:
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB:
- case DXGI_FORMAT_BC4_TYPELESS:
- case DXGI_FORMAT_BC4_UNORM:
- case DXGI_FORMAT_BC4_SNORM:
- case DXGI_FORMAT_BC5_TYPELESS:
- case DXGI_FORMAT_BC5_UNORM:
- case DXGI_FORMAT_BC5_SNORM:
- case DXGI_FORMAT_BC6H_TYPELESS:
- case DXGI_FORMAT_BC6H_UF16:
- case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB:
- return std::max<size_t>( 1, (height + 3) / 4 );
+ case DXGI_FORMAT_AYUV:
+ case DXGI_FORMAT_Y410:
+ case DXGI_FORMAT_Y416:
+ case DXGI_FORMAT_AI44:
+ case DXGI_FORMAT_IA44:
+ case DXGI_FORMAT_A8P8:
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return true;
+
+ case 116 /* DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT */:
+ case 117 /* DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT */:
+ // These are Xbox One platform specific types
+ return true;
default:
+ return false;
+ }
+}
+
+_Use_decl_annotations_
+inline size_t __cdecl ComputeScanlines(DXGI_FORMAT fmt, size_t height)
+{
+ if ( IsCompressed(fmt) )
+ {
+ return std::max<size_t>( 1, (height + 3) / 4 );
+ }
+ else if ( fmt == DXGI_FORMAT_NV11 )
+ {
+ // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
+ return height * 2;
+ }
+ else if ( IsPlanar(fmt) )
+ {
+ return height + ( ( height + 1 ) >> 1 );
+ }
+ else
+ {
return height;
}
}
@@ -192,7 +317,8 @@ inline size_t ComputeScanlines( _In_ DXGI_FORMAT fmt, _In_ size_t height )
//=====================================================================================
// Image I/O
//=====================================================================================
-inline HRESULT SaveToDDSMemory( const Image& image, DWORD flags, Blob& blob )
+_Use_decl_annotations_
+inline HRESULT __cdecl SaveToDDSMemory(const Image& image, DWORD flags, Blob& blob)
{
TexMetadata mdata;
memset( &mdata, 0, sizeof(mdata) );
@@ -207,7 +333,8 @@ inline HRESULT SaveToDDSMemory( const Image& image, DWORD flags, Blob& blob )
return SaveToDDSMemory( &image, 1, mdata, flags, blob );
}
-inline HRESULT SaveToDDSFile( const Image& image, DWORD flags, LPCWSTR szFile )
+_Use_decl_annotations_
+inline HRESULT __cdecl SaveToDDSFile(const Image& image, DWORD flags, LPCWSTR szFile)
{
TexMetadata mdata;
memset( &mdata, 0, sizeof(mdata) );
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexCompress.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexCompress.cpp
index 9c1bfbd8..52fb3d45 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexCompress.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexCompress.cpp
@@ -17,11 +17,12 @@
#ifdef _OPENMP
#include <omp.h>
-#pragma warning(disable : 4616 6001 6993)
+#pragma warning(disable : 4616 6993)
#endif
#include "BC.h"
+
namespace DirectX
{
@@ -31,13 +32,46 @@ inline static DWORD _GetBCFlags( _In_ DWORD compress )
static_assert( TEX_COMPRESS_A_DITHER == BC_FLAGS_DITHER_A, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_DITHER == (BC_FLAGS_DITHER_RGB | BC_FLAGS_DITHER_A), "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_UNIFORM == BC_FLAGS_UNIFORM, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
- return ( compress & (BC_FLAGS_DITHER_RGB|BC_FLAGS_DITHER_A|BC_FLAGS_UNIFORM) );
+ static_assert( TEX_COMPRESS_BC7_USE_3SUBSETS == BC_FLAGS_USE_3SUBSETS, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
+ return ( compress & (BC_FLAGS_DITHER_RGB|BC_FLAGS_DITHER_A|BC_FLAGS_UNIFORM|BC_FLAGS_USE_3SUBSETS) );
+}
+
+inline static DWORD _GetSRGBFlags( _In_ DWORD compress )
+{
+ static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
+ static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
+ static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
+ return ( compress & TEX_COMPRESS_SRGB );
+}
+
+inline static bool _DetermineEncoderSettings( _In_ DXGI_FORMAT format, _Out_ BC_ENCODE& pfEncode, _Out_ size_t& blocksize, _Out_ DWORD& cflags )
+{
+ switch(format)
+ {
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB: pfEncode = nullptr; blocksize = 8; cflags = 0; break;
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB: pfEncode = D3DXEncodeBC2; blocksize = 16; cflags = 0; break;
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB: pfEncode = D3DXEncodeBC3; blocksize = 16; cflags = 0; break;
+ case DXGI_FORMAT_BC4_UNORM: pfEncode = D3DXEncodeBC4U; blocksize = 8; cflags = TEX_FILTER_RGB_COPY_RED; break;
+ case DXGI_FORMAT_BC4_SNORM: pfEncode = D3DXEncodeBC4S; blocksize = 8; cflags = TEX_FILTER_RGB_COPY_RED; break;
+ case DXGI_FORMAT_BC5_UNORM: pfEncode = D3DXEncodeBC5U; blocksize = 16; cflags = TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN; break;
+ case DXGI_FORMAT_BC5_SNORM: pfEncode = D3DXEncodeBC5S; blocksize = 16; cflags = TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN; break;
+ case DXGI_FORMAT_BC6H_UF16: pfEncode = D3DXEncodeBC6HU; blocksize = 16; cflags = 0; break;
+ case DXGI_FORMAT_BC6H_SF16: pfEncode = D3DXEncodeBC6HS; blocksize = 16; cflags = 0; break;
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB: pfEncode = D3DXEncodeBC7; blocksize = 16; cflags = 0; break;
+ default: pfEncode = nullptr; blocksize = 0; cflags = 0; return false;
+ }
+
+ return true;
}
//-------------------------------------------------------------------------------------
static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
- _In_ float alphaRef, _In_ bool degenerate )
+ _In_ DWORD srgb, _In_ float alphaRef )
{
if ( !image.pixels || !result.pixels )
return E_POINTER;
@@ -64,25 +98,9 @@ static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _
// Determine BC format encoder
BC_ENCODE pfEncode;
size_t blocksize;
- switch(result.format)
- {
- case DXGI_FORMAT_BC1_UNORM:
- case DXGI_FORMAT_BC1_UNORM_SRGB: pfEncode = nullptr; blocksize = 8; break;
- case DXGI_FORMAT_BC2_UNORM:
- case DXGI_FORMAT_BC2_UNORM_SRGB: pfEncode = D3DXEncodeBC2; blocksize = 16; break;
- case DXGI_FORMAT_BC3_UNORM:
- case DXGI_FORMAT_BC3_UNORM_SRGB: pfEncode = D3DXEncodeBC3; blocksize = 16; break;
- case DXGI_FORMAT_BC4_UNORM: pfEncode = D3DXEncodeBC4U; blocksize = 8; break;
- case DXGI_FORMAT_BC4_SNORM: pfEncode = D3DXEncodeBC4S; blocksize = 8; break;
- case DXGI_FORMAT_BC5_UNORM: pfEncode = D3DXEncodeBC5U; blocksize = 16; break;
- case DXGI_FORMAT_BC5_SNORM: pfEncode = D3DXEncodeBC5S; blocksize = 16; break;
- case DXGI_FORMAT_BC6H_UF16: pfEncode = D3DXEncodeBC6HU; blocksize = 16; break;
- case DXGI_FORMAT_BC6H_SF16: pfEncode = D3DXEncodeBC6HS; blocksize = 16; break;
- case DXGI_FORMAT_BC7_UNORM:
- case DXGI_FORMAT_BC7_UNORM_SRGB: pfEncode = D3DXEncodeBC7; blocksize = 16; break;
- default:
+ DWORD cflags;
+ if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
- }
XMVECTOR temp[16];
const uint8_t *pSrc = image.pixels;
@@ -91,55 +109,65 @@ static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _
{
const uint8_t *sptr = pSrc;
uint8_t* dptr = pDest;
- for( size_t count = 0; count < rowPitch; count += sbpp*4 )
+ size_t ph = std::min<size_t>( 4, image.height - h );
+ size_t w = 0;
+ for( size_t count = 0; (count < result.rowPitch) && (w < image.width); count += blocksize, w += 4 )
{
- if ( !_LoadScanline( &temp[0], 4, sptr, rowPitch, format ) )
+ size_t pw = std::min<size_t>( 4, image.width - w );
+ assert( pw > 0 && ph > 0 );
+
+ if ( !_LoadScanline( &temp[0], pw, sptr, rowPitch, format ) )
return E_FAIL;
- if ( image.height > 1 )
+ if ( ph > 1 )
{
- if ( !_LoadScanline( &temp[4], 4, sptr + rowPitch, rowPitch, format ) )
+ if ( !_LoadScanline( &temp[4], pw, sptr + rowPitch, rowPitch, format ) )
return E_FAIL;
- if ( image.height > 2 )
+ if ( ph > 2 )
{
- if ( !_LoadScanline( &temp[8], 4, sptr + rowPitch*2, rowPitch, format ) )
+ if ( !_LoadScanline( &temp[8], pw, sptr + rowPitch*2, rowPitch, format ) )
return E_FAIL;
- if ( !_LoadScanline( &temp[12], 4, sptr + rowPitch*3, rowPitch, format ) )
- return E_FAIL;
+ if ( ph > 3 )
+ {
+ if ( !_LoadScanline( &temp[12], pw, sptr + rowPitch*3, rowPitch, format ) )
+ return E_FAIL;
+ }
}
}
- if ( degenerate )
+ if ( pw != 4 || ph != 4 )
{
- assert( image.width < 4 || image.height < 4 );
- const size_t uSrc[] = { 0, 0, 0, 1 };
+ // Replicate pixels for partial block
+ static const size_t uSrc[] = { 0, 0, 0, 1 };
- if ( image.width < 4 )
+ if ( pw < 4 )
{
- for( size_t t=0; t < image.height && t < 4; ++t )
+ for( size_t t = 0; t < ph && t < 4; ++t )
{
- for( size_t s = image.width; s < 4; ++s )
+ for( size_t s = pw; s < 4; ++s )
{
- temp[ t*4 + s ] = temp[ t*4 + uSrc[s] ];
+#pragma prefast(suppress: 26000, "PREFAST false positive")
+ temp[ (t << 2) | s ] = temp[ (t << 2) | uSrc[s] ];
}
}
}
- if ( image.height < 4 )
+ if ( ph < 4 )
{
- for( size_t t=image.height; t < 4; ++t )
+ for( size_t t = ph; t < 4; ++t )
{
- for( size_t s =0; s < 4; ++s )
+ for( size_t s = 0; s < 4; ++s )
{
- temp[ t*4 + s ] = temp[ uSrc[t]*4 + s ];
+#pragma prefast(suppress: 26000, "PREFAST false positive")
+ temp[ (t << 2) | s ] = temp[ (uSrc[t] << 2) | s ];
}
}
}
}
- _ConvertScanline( temp, 16, result.format, format, 0 );
+ _ConvertScanline( temp, 16, result.format, format, cflags | srgb );
if ( pfEncode )
pfEncode( dptr, temp, bcflags );
@@ -161,14 +189,11 @@ static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _
//-------------------------------------------------------------------------------------
#ifdef _OPENMP
static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
- _In_ float alphaRef )
+ _In_ DWORD srgb, _In_ float alphaRef )
{
if ( !image.pixels || !result.pixels )
return E_POINTER;
- // Parallel version doesn't support degenerate case
- assert( ((image.width % 4) == 0) && ((image.height % 4) == 0 ) );
-
assert( image.width == result.width );
assert( image.height == result.height );
@@ -189,35 +214,19 @@ static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image&
// Determine BC format encoder
BC_ENCODE pfEncode;
size_t blocksize;
- switch(result.format)
- {
- case DXGI_FORMAT_BC1_UNORM:
- case DXGI_FORMAT_BC1_UNORM_SRGB: pfEncode = nullptr; blocksize = 8; break;
- case DXGI_FORMAT_BC2_UNORM:
- case DXGI_FORMAT_BC2_UNORM_SRGB: pfEncode = D3DXEncodeBC2; blocksize = 16; break;
- case DXGI_FORMAT_BC3_UNORM:
- case DXGI_FORMAT_BC3_UNORM_SRGB: pfEncode = D3DXEncodeBC3; blocksize = 16; break;
- case DXGI_FORMAT_BC4_UNORM: pfEncode = D3DXEncodeBC4U; blocksize = 8; break;
- case DXGI_FORMAT_BC4_SNORM: pfEncode = D3DXEncodeBC4S; blocksize = 8; break;
- case DXGI_FORMAT_BC5_UNORM: pfEncode = D3DXEncodeBC5U; blocksize = 16; break;
- case DXGI_FORMAT_BC5_SNORM: pfEncode = D3DXEncodeBC5S; blocksize = 16; break;
- case DXGI_FORMAT_BC6H_UF16: pfEncode = D3DXEncodeBC6HU; blocksize = 16; break;
- case DXGI_FORMAT_BC6H_SF16: pfEncode = D3DXEncodeBC6HS; blocksize = 16; break;
- case DXGI_FORMAT_BC7_UNORM:
- case DXGI_FORMAT_BC7_UNORM_SRGB: pfEncode = D3DXEncodeBC7; blocksize = 16; break;
- default:
+ DWORD cflags;
+ if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
- }
// Refactored version of loop to support parallel independance
- const size_t nBlocks = std::max<size_t>(1, image.width / 4) * std::max<size_t>(1, image.height / 4);
+ const size_t nBlocks = std::max<size_t>(1, (image.width + 3) / 4 ) * std::max<size_t>(1, (image.height + 3) / 4 );
bool fail = false;
#pragma omp parallel for
for( int nb=0; nb < static_cast<int>( nBlocks ); ++nb )
{
- const size_t nbWidth = std::max<size_t>(1, image.width / 4);
+ const size_t nbWidth = std::max<size_t>(1, (image.width + 3) / 4 );
const size_t y = nb / nbWidth;
const size_t x = nb - (y*nbWidth);
@@ -229,20 +238,61 @@ static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image&
uint8_t *pDest = result.pixels + (nb*blocksize);
+ size_t ph = std::min<size_t>( 4, image.height - y );
+ size_t pw = std::min<size_t>( 4, image.width - x );
+ assert( pw > 0 && ph > 0 );
+
XMVECTOR temp[16];
- if ( !_LoadScanline( &temp[0], 4, pSrc, rowPitch, format ) )
+ if ( !_LoadScanline( &temp[0], pw, pSrc, rowPitch, format ) )
fail = true;
- if ( !_LoadScanline( &temp[4], 4, pSrc + rowPitch, rowPitch, format ) )
- fail = true;
+ if ( ph > 1 )
+ {
+ if ( !_LoadScanline( &temp[4], pw, pSrc + rowPitch, rowPitch, format ) )
+ fail = true;
- if ( !_LoadScanline( &temp[8], 4, pSrc + rowPitch*2, rowPitch, format ) )
- fail = true;
+ if ( ph > 2 )
+ {
+ if ( !_LoadScanline( &temp[8], pw, pSrc + rowPitch*2, rowPitch, format ) )
+ fail = true;
- if ( !_LoadScanline( &temp[12], 4, pSrc + rowPitch*3, rowPitch, format ) )
- fail = true;
+ if ( ph > 3 )
+ {
+ if ( !_LoadScanline( &temp[12], pw, pSrc + rowPitch*3, rowPitch, format ) )
+ fail = true;
+ }
+ }
+ }
+
+ if ( pw != 4 || ph != 4 )
+ {
+ // Replicate pixels for partial block
+ static const size_t uSrc[] = { 0, 0, 0, 1 };
+
+ if ( pw < 4 )
+ {
+ for( size_t t = 0; t < ph && t < 4; ++t )
+ {
+ for( size_t s = pw; s < 4; ++s )
+ {
+ temp[ (t << 2) | s ] = temp[ (t << 2) | uSrc[s] ];
+ }
+ }
+ }
+
+ if ( ph < 4 )
+ {
+ for( size_t t = ph; t < 4; ++t )
+ {
+ for( size_t s = 0; s < 4; ++s )
+ {
+ temp[ (t << 2) | s ] = temp[ (uSrc[t] << 2) | s ];
+ }
+ }
+ }
+ }
- _ConvertScanline( temp, 16, result.format, format, 0 );
+ _ConvertScanline( temp, 16, result.format, format, cflags | srgb );
if ( pfEncode )
pfEncode( pDest, temp, bcflags );
@@ -313,21 +363,6 @@ static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result
assert( cImage.width == result.width );
assert( cImage.height == result.height );
- // Image must be a multiple of 4 (degenerate cases of 1x1, 1x2, 2x1, and 2x2 are allowed)
- size_t width = cImage.width;
- if ( (width % 4) != 0 )
- {
- if ( width != 1 && width != 2 )
- return E_INVALIDARG;
- }
-
- size_t height = cImage.height;
- if ( (height % 4) != 0 )
- {
- if ( height != 1 && height != 2 )
- return E_INVALIDARG;
- }
-
const DXGI_FORMAT format = result.format;
size_t dbpp = BitsPerPixel( format );
if ( !dbpp )
@@ -390,26 +425,34 @@ static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result
{
const uint8_t *sptr = pSrc;
uint8_t* dptr = pDest;
- for( size_t count = 0; count < cImage.rowPitch; count += sbpp )
+ size_t ph = std::min<size_t>( 4, cImage.height - h );
+ size_t w = 0;
+ for( size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4 )
{
pfDecode( temp, sptr );
_ConvertScanline( temp, 16, format, cformat, 0 );
- if ( !_StoreScanline( dptr, rowPitch, format, &temp[0], 4 ) )
+ size_t pw = std::min<size_t>( 4, cImage.width - w );
+ assert( pw > 0 && ph > 0 );
+
+ if ( !_StoreScanline( dptr, rowPitch, format, &temp[0], pw ) )
return E_FAIL;
- if ( result.height > 1 )
+ if ( ph > 1 )
{
- if ( !_StoreScanline( dptr + rowPitch, rowPitch, format, &temp[4], 4 ) )
+ if ( !_StoreScanline( dptr + rowPitch, rowPitch, format, &temp[4], pw ) )
return E_FAIL;
- if ( result.height > 2 )
+ if ( ph > 2 )
{
- if ( !_StoreScanline( dptr + rowPitch*2, rowPitch, format, &temp[8], 4 ) )
+ if ( !_StoreScanline( dptr + rowPitch*2, rowPitch, format, &temp[8], pw ) )
return E_FAIL;
- if ( !_StoreScanline( dptr + rowPitch*3, rowPitch, format, &temp[12], 4 ) )
- return E_FAIL;
+ if ( ph > 3 )
+ {
+ if ( !_StoreScanline( dptr + rowPitch*3, rowPitch, format, &temp[12], pw ) )
+ return E_FAIL;
+ }
}
}
@@ -425,6 +468,92 @@ static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result
}
+//-------------------------------------------------------------------------------------
+bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
+{
+ if ( !cImage.pixels )
+ return false;
+
+ // Promote "typeless" BC formats
+ DXGI_FORMAT cformat;
+ switch( cImage.format )
+ {
+ case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
+ case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break;
+ case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM; break;
+ case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM; break;
+ default: cformat = cImage.format; break;
+ }
+
+ // Determine BC format decoder
+ BC_DECODE pfDecode;
+ size_t sbpp;
+ switch(cformat)
+ {
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode = D3DXDecodeBC2; sbpp = 16; break;
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode = D3DXDecodeBC3; sbpp = 16; break;
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
+ default:
+ // BC4, BC5, and BC6 don't have alpha channels
+ return false;
+ }
+
+ // Scan blocks for non-opaque alpha
+ static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
+
+ XMVECTOR temp[16];
+ const uint8_t *pPixels = cImage.pixels;
+ for( size_t h = 0; h < cImage.height; h += 4 )
+ {
+ const uint8_t *ptr = pPixels;
+ size_t ph = std::min<size_t>( 4, cImage.height - h );
+ size_t w = 0;
+ for( size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4 )
+ {
+ pfDecode( temp, ptr );
+
+ size_t pw = std::min<size_t>( 4, cImage.width - w );
+ assert( pw > 0 && ph > 0 );
+
+ if ( pw == 4 && ph == 4 )
+ {
+ // Full blocks
+ for( size_t j = 0; j < 16; ++j )
+ {
+ XMVECTOR alpha = XMVectorSplatW( temp[j] );
+ if ( XMVector4Less( alpha, threshold ) )
+ return false;
+ }
+ }
+ else
+ {
+ // Handle partial blocks
+ for( size_t y = 0; y < ph; ++y )
+ {
+ for( size_t x = 0; x < pw; ++x )
+ {
+ XMVECTOR alpha = XMVectorSplatW( temp[ y * 4 + x ] );
+ if ( XMVector4Less( alpha, threshold ) )
+ return false;
+ }
+ }
+ }
+
+ ptr += sbpp;
+ }
+
+ pPixels += cImage.rowPitch;
+ }
+
+ return true;
+}
+
+
//=====================================================================================
// Entry-points
//=====================================================================================
@@ -432,34 +561,18 @@ static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result
//-------------------------------------------------------------------------------------
// Compression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& image )
{
- if ( IsCompressed(srcImage.format) || !IsCompressed(format) || IsTypeless(format) )
+ if ( IsCompressed(srcImage.format) || !IsCompressed(format) )
return E_INVALIDARG;
- // Image size must be a multiple of 4 (degenerate cases for mipmaps are allowed)
- bool degenerate = false;
-
- size_t width = srcImage.width;
- if ( (width % 4) != 0 )
- {
- if ( width != 1 && width != 2 )
- return E_INVALIDARG;
-
- degenerate = true;
- }
-
- size_t height = srcImage.height;
- if ( (height % 4) != 0 )
- {
- if ( height != 1 && height != 2 )
- return E_INVALIDARG;
-
- degenerate = true;
- }
+ if ( IsTypeless(format)
+ || IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
// Create compressed image
- HRESULT hr = image.Initialize2D( format, width, height, 1, 1 );
+ HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
return hr;
@@ -471,17 +584,17 @@ HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, flo
}
// Compress single image
- if ( (compress & TEX_COMPRESS_PARALLEL) && !degenerate )
+ if (compress & TEX_COMPRESS_PARALLEL)
{
#ifndef _OPENMP
return E_NOTIMPL;
#else
- hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), alphaRef );
+ hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
#endif // _OPENMP
}
else
{
- hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), alphaRef, degenerate );
+ hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
}
if ( FAILED(hr) )
@@ -490,29 +603,19 @@ HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, flo
return hr;
}
+_Use_decl_annotations_
HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages )
{
if ( !srcImages || !nimages )
return E_INVALIDARG;
- if ( !IsCompressed(format) || IsTypeless(format) )
+ if ( IsCompressed(metadata.format) || !IsCompressed(format) )
return E_INVALIDARG;
- // Image size must be a multiple of 4 (degenerate cases for mipmaps are allowed)
- size_t width = srcImages[0].width;
- if ( (width % 4) != 0 )
- {
- if ( width != 1 && width != 2 )
- return E_INVALIDARG;
- }
-
- size_t height = srcImages[0].height;
- if ( (height % 4) != 0 )
- {
- if ( height != 1 && height != 2 )
- return E_INVALIDARG;
- }
+ if ( IsTypeless(format)
+ || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
cImages.Release();
@@ -541,24 +644,20 @@ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& met
const Image& src = srcImages[ index ];
- height = src.height;
- width = src.width;
- if ( width != dest[ index ].width || height != dest[ index ].height )
+ if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
{
cImages.Release();
return E_FAIL;
}
- bool degenerate = ((height < 4) || (width < 4)) != 0;
-
- if ( (compress & TEX_COMPRESS_PARALLEL) && !degenerate)
+ if ( (compress & TEX_COMPRESS_PARALLEL) )
{
#ifndef _OPENMP
return E_NOTIMPL;
#else
if ( compress & TEX_COMPRESS_PARALLEL )
{
- hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), alphaRef );
+ hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
if ( FAILED(hr) )
{
cImages.Release();
@@ -569,7 +668,7 @@ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& met
}
else
{
- hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), alphaRef, degenerate );
+ hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
if ( FAILED(hr) )
{
cImages.Release();
@@ -585,9 +684,10 @@ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& met
//-------------------------------------------------------------------------------------
// Decompression
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image )
{
- if ( IsCompressed(format) || IsTypeless(format) )
+ if ( !IsCompressed(cImage.format) || IsCompressed(format) )
return E_INVALIDARG;
if ( format == DXGI_FORMAT_UNKNOWN )
@@ -600,8 +700,14 @@ HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image
return E_INVALIDARG;
}
}
- else if ( !IsCompressed(cImage.format) || !IsValid(format) )
- return E_INVALIDARG;
+ else
+ {
+ if ( !IsValid(format) )
+ return E_INVALIDARG;
+
+ if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
// Create decompressed image
HRESULT hr = image.Initialize2D( format, cImage.width, cImage.height, 1, 1 );
@@ -623,13 +729,14 @@ HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image
return hr;
}
+_Use_decl_annotations_
HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& metadata,
DXGI_FORMAT format, ScratchImage& images )
{
if ( !cImages || !nimages )
return E_INVALIDARG;
- if ( IsCompressed(format) || IsTypeless(format) )
+ if ( !IsCompressed(metadata.format) || IsCompressed(format) )
return E_INVALIDARG;
if ( format == DXGI_FORMAT_UNKNOWN )
@@ -642,8 +749,14 @@ HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& met
return E_FAIL;
}
}
- else if ( !IsValid(format) )
- return E_INVALIDARG;
+ else
+ {
+ if ( !IsValid(format) )
+ return E_INVALIDARG;
+
+ if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
+ HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
images.Release();
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexCompressGPU.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexCompressGPU.cpp
new file mode 100644
index 00000000..46b1a867
--- /dev/null
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexCompressGPU.cpp
@@ -0,0 +1,402 @@
+//-------------------------------------------------------------------------------------
+// DirectXTexCompressGPU.cpp
+//
+// DirectX Texture Library - DirectCompute-based texture compression
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// http://go.microsoft.com/fwlink/?LinkId=248926
+//-------------------------------------------------------------------------------------
+
+#include "directxtexp.h"
+
+#include "bcdirectcompute.h"
+
+namespace DirectX
+{
+
+inline static DWORD _GetSRGBFlags( _In_ DWORD compress )
+{
+ static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
+ static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
+ static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
+ return ( compress & TEX_COMPRESS_SRGB );
+}
+
+
+//-------------------------------------------------------------------------------------
+// Converts to R8G8B8A8_UNORM or R8G8B8A8_UNORM_SRGB doing any conversion logic needed
+//-------------------------------------------------------------------------------------
+static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage& image, bool srgb, _In_ DWORD filter )
+{
+ if ( !srcImage.pixels )
+ return E_POINTER;
+
+ DXGI_FORMAT format = srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
+ if ( FAILED(hr) )
+ return hr;
+
+ const Image *img = image.GetImage( 0, 0, 0 );
+ if ( !img )
+ {
+ image.Release();
+ return E_POINTER;
+ }
+
+ uint8_t* pDest = img->pixels;
+ if ( !pDest )
+ {
+ image.Release();
+ return E_POINTER;
+ }
+
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( ( sizeof(XMVECTOR) * srcImage.width ), 16 ) ) );
+ if ( !scanline )
+ {
+ image.Release();
+ return E_OUTOFMEMORY;
+ }
+
+ const uint8_t *pSrc = srcImage.pixels;
+ for( size_t h = 0; h < srcImage.height; ++h )
+ {
+ if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
+ {
+ image.Release();
+ return E_FAIL;
+ }
+
+ _ConvertScanline( scanline.get(), srcImage.width, format, srcImage.format, filter );
+
+ if ( !_StoreScanline( pDest, img->rowPitch, format, scanline.get(), srcImage.width ) )
+ {
+ image.Release();
+ return E_FAIL;
+ }
+
+ pSrc += srcImage.rowPitch;
+ pDest += img->rowPitch;
+ }
+
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------------------------
+// Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed
+//-------------------------------------------------------------------------------------
+static HRESULT _ConvertToRGBAF32( const Image& srcImage, ScratchImage& image, _In_ DWORD filter )
+{
+ if ( !srcImage.pixels )
+ return E_POINTER;
+
+ HRESULT hr = image.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
+ if ( FAILED(hr) )
+ return hr;
+
+ const Image *img = image.GetImage( 0, 0, 0 );
+ if ( !img )
+ {
+ image.Release();
+ return E_POINTER;
+ }
+
+ uint8_t* pDest = img->pixels;
+ if ( !pDest )
+ {
+ image.Release();
+ return E_POINTER;
+ }
+
+ const uint8_t *pSrc = srcImage.pixels;
+ for( size_t h = 0; h < srcImage.height; ++h )
+ {
+ if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
+ {
+ image.Release();
+ return E_FAIL;
+ }
+
+ _ConvertScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter );
+
+ pSrc += srcImage.rowPitch;
+ pDest += img->rowPitch;
+ }
+
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------------------------
+// Compress using GPU, converting to the proper input format for the shader if needed
+//-------------------------------------------------------------------------------------
+inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image& srcImage, _In_ const Image& destImage, _In_ DWORD compress )
+{
+ if ( !gpubc )
+ return E_POINTER;
+
+ assert( srcImage.pixels && destImage.pixels );
+
+ DXGI_FORMAT format = gpubc->GetSourceFormat();
+
+ if ( srcImage.format == format )
+ {
+ // Input is already in our required source format
+ return gpubc->Compress( srcImage, destImage );
+ }
+ else
+ {
+ // Convert format and then use as the source image
+ ScratchImage image;
+ HRESULT hr;
+
+ DWORD srgb = _GetSRGBFlags( compress );
+
+ switch( format )
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ hr = _ConvertToRGBA32( srcImage, image, false, srgb );
+ break;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ hr = _ConvertToRGBA32( srcImage, image, true, srgb );
+ break;
+
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ hr = _ConvertToRGBAF32( srcImage, image, srgb );
+ break;
+
+ default:
+ hr = E_UNEXPECTED;
+ break;
+ }
+
+ if ( FAILED(hr) )
+ return hr;
+
+ const Image *img = image.GetImage( 0, 0, 0 );
+ if ( !img )
+ return E_POINTER;
+
+ return gpubc->Compress( *img, destImage );
+ }
+}
+
+
+//=====================================================================================
+// Entry-points
+//=====================================================================================
+
+//-------------------------------------------------------------------------------------
+// Compression
+//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
+HRESULT Compress( ID3D11Device* pDevice, const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaWeight, ScratchImage& image )
+{
+ if ( !pDevice || IsCompressed(srcImage.format) || !IsCompressed(format) )
+ return E_INVALIDARG;
+
+ if ( IsTypeless(format)
+ || IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
+ // Setup GPU compressor
+ std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
+ if ( !gpubc )
+ return E_OUTOFMEMORY;
+
+ HRESULT hr = gpubc->Initialize( pDevice );
+ if ( FAILED(hr) )
+ return hr;
+
+ hr = gpubc->Prepare( srcImage.width, srcImage.height, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
+ if ( FAILED(hr) )
+ return hr;
+
+ // Create workspace for result
+ hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
+ if ( FAILED(hr) )
+ return hr;
+
+ const Image *img = image.GetImage( 0, 0, 0 );
+ if ( !img )
+ {
+ image.Release();
+ return E_POINTER;
+ }
+
+ hr = _GPUCompress( gpubc.get(), srcImage, *img, compress );
+ if ( FAILED(hr) )
+ image.Release();
+
+ return hr;
+}
+
+_Use_decl_annotations_
+HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
+ DXGI_FORMAT format, DWORD compress, float alphaWeight, ScratchImage& cImages )
+{
+ if ( !pDevice || !srcImages || !nimages )
+ return E_INVALIDARG;
+
+ if ( IsCompressed(metadata.format) || !IsCompressed(format) )
+ return E_INVALIDARG;
+
+ if ( IsTypeless(format)
+ || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
+ cImages.Release();
+
+ // Setup GPU compressor
+ std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
+ if ( !gpubc )
+ return E_OUTOFMEMORY;
+
+ HRESULT hr = gpubc->Initialize( pDevice );
+ if ( FAILED(hr) )
+ return hr;
+
+ // Create workspace for result
+ TexMetadata mdata2 = metadata;
+ mdata2.format = format;
+ hr = cImages.Initialize( mdata2 );
+ if ( FAILED(hr) )
+ return hr;
+
+ if ( nimages != cImages.GetImageCount() )
+ {
+ cImages.Release();
+ return E_FAIL;
+ }
+
+ const Image* dest = cImages.GetImages();
+ if ( !dest )
+ {
+ cImages.Release();
+ return E_POINTER;
+ }
+
+ // Process images (ordered by size)
+ switch( metadata.dimension )
+ {
+ case TEX_DIMENSION_TEXTURE1D:
+ case TEX_DIMENSION_TEXTURE2D:
+ {
+ size_t w = metadata.width;
+ size_t h = metadata.height;
+
+ for( size_t level=0; level < metadata.mipLevels; ++level )
+ {
+ hr = gpubc->Prepare( w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
+ if ( FAILED(hr) )
+ {
+ cImages.Release();
+ return hr;
+ }
+
+ for( size_t item = 0; item < metadata.arraySize; ++item )
+ {
+ size_t index = metadata.ComputeIndex( level, item, 0 );
+ if ( index >= nimages )
+ {
+ cImages.Release();
+ return E_FAIL;
+ }
+
+ assert( dest[ index ].format == format );
+
+ const Image& src = srcImages[ index ];
+
+ if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
+ {
+ cImages.Release();
+ return E_FAIL;
+ }
+
+ hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
+ if ( FAILED(hr) )
+ {
+ cImages.Release();
+ return hr;
+ }
+ }
+
+ if ( h > 1 )
+ h >>= 1;
+
+ if ( w > 1 )
+ w >>= 1;
+ }
+ }
+ break;
+
+ case TEX_DIMENSION_TEXTURE3D:
+ {
+ size_t w = metadata.width;
+ size_t h = metadata.height;
+ size_t d = metadata.depth;
+
+ for( size_t level=0; level < metadata.mipLevels; ++level )
+ {
+ hr = gpubc->Prepare( w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
+ if ( FAILED(hr) )
+ {
+ cImages.Release();
+ return hr;
+ }
+
+ for( size_t slice=0; slice < d; ++slice )
+ {
+ size_t index = metadata.ComputeIndex( level, 0, slice );
+ if ( index >= nimages )
+ {
+ cImages.Release();
+ return E_FAIL;
+ }
+
+ assert( dest[ index ].format == format );
+
+ const Image& src = srcImages[ index ];
+
+ if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
+ {
+ cImages.Release();
+ return E_FAIL;
+ }
+
+ hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
+ if ( FAILED(hr) )
+ {
+ cImages.Release();
+ return hr;
+ }
+ }
+
+ if ( h > 1 )
+ h >>= 1;
+
+ if ( w > 1 )
+ w >>= 1;
+
+ if ( d > 1 )
+ d >>= 1;
+ }
+ }
+ break;
+
+ default:
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
+
+ return S_OK;
+}
+
+}; // namespace
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexConvert.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexConvert.cpp
index 3496ce5b..c063213a 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexConvert.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexConvert.cpp
@@ -23,28 +23,196 @@
using namespace DirectX::PackedVector;
#endif
+using Microsoft::WRL::ComPtr;
+
+namespace
+{
+#if DIRECTX_MATH_VERSION < 306
+ inline float round_to_nearest( float x )
+ {
+ // Round to nearest (even)
+ float i = floorf(x);
+ x -= i;
+ if(x < 0.5f)
+ return i;
+ if(x > 0.5f)
+ return i + 1.f;
+
+ float int_part;
+ modff( i / 2.f, &int_part );
+ if ( (2.f*int_part) == i )
+ {
+ return i;
+ }
+
+ return i + 1.f;
+ }
+#endif
+
+ inline uint32_t FloatTo7e3(float Value)
+ {
+ uint32_t IValue = reinterpret_cast<uint32_t *>(&Value)[0];
+
+ if ( IValue & 0x80000000U )
+ {
+ // Positive only
+ return 0;
+ }
+ else if (IValue > 0x41FF73FFU)
+ {
+ // The number is too large to be represented as a 7e3. Saturate.
+ return 0x3FFU;
+ }
+ else
+ {
+ if (IValue < 0x3E800000U)
+ {
+ // The number is too small to be represented as a normalized 7e3.
+ // Convert it to a denormalized value.
+ uint32_t Shift = 125U - (IValue >> 23U);
+ IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift;
+ }
+ else
+ {
+ // Rebias the exponent to represent the value as a normalized 7e3.
+ IValue += 0xC2000000U;
+ }
+
+ return ((IValue + 0x7FFFU + ((IValue >> 16U) & 1U)) >> 16U)&0x3FFU;
+ }
+ }
+
+ inline float FloatFrom7e3( uint32_t Value )
+ {
+ uint32_t Mantissa = (uint32_t)(Value & 0x7F);
+
+ uint32_t Exponent = (Value & 0x380);
+ if (Exponent != 0) // The value is normalized
+ {
+ Exponent = (uint32_t)((Value >> 7) & 0x7);
+ }
+ else if (Mantissa != 0) // The value is denormalized
+ {
+ // Normalize the value in the resulting float
+ Exponent = 1;
+
+ do
+ {
+ Exponent--;
+ Mantissa <<= 1;
+ } while ((Mantissa & 0x80) == 0);
+
+ Mantissa &= 0x7F;
+ }
+ else // The value is zero
+ {
+ Exponent = (uint32_t)-124;
+ }
+
+ uint32_t Result = ((Exponent + 124) << 23) | // Exponent
+ (Mantissa << 16); // Mantissa
+
+ return reinterpret_cast<float*>(&Result)[0];
+ }
+
+ inline uint32_t FloatTo6e4(float Value)
+ {
+ uint32_t IValue = reinterpret_cast<uint32_t *>(&Value)[0];
+
+ if ( IValue & 0x80000000U )
+ {
+ // Positive only
+ return 0;
+ }
+ else if (IValue > 0x43FEFFFFU)
+ {
+ // The number is too large to be represented as a 6e4. Saturate.
+ return 0x3FFU;
+ }
+ else
+ {
+ if (IValue < 0x3C800000U)
+ {
+ // The number is too small to be represented as a normalized 6e4.
+ // Convert it to a denormalized value.
+ uint32_t Shift = 121U - (IValue >> 23U);
+ IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift;
+ }
+ else
+ {
+ // Rebias the exponent to represent the value as a normalized 6e4.
+ IValue += 0xC4000000U;
+ }
+
+ return ((IValue + 0xFFFFU + ((IValue >> 17U) & 1U)) >> 17U)&0x3FFU;
+ }
+ }
+
+ inline float FloatFrom6e4( uint32_t Value )
+ {
+ uint32_t Mantissa = (uint32_t)(Value & 0x3F);
+
+ uint32_t Exponent = (Value & 0x3C0);
+ if (Exponent != 0) // The value is normalized
+ {
+ Exponent = (uint32_t)((Value >> 6) & 0xF);
+ }
+ else if (Mantissa != 0) // The value is denormalized
+ {
+ // Normalize the value in the resulting float
+ Exponent = 1;
+
+ do
+ {
+ Exponent--;
+ Mantissa <<= 1;
+ } while ((Mantissa & 0x40) == 0);
+
+ Mantissa &= 0x3F;
+ }
+ else // The value is zero
+ {
+ Exponent = (uint32_t)-120;
+ }
+
+ uint32_t Result = ((Exponent + 120) << 23) | // Exponent
+ (Mantissa << 17); // Mantissa
+
+ return reinterpret_cast<float*>(&Result)[0];
+ }
+};
+
namespace DirectX
{
+static const XMVECTORF32 g_Grayscale = { 0.2125f, 0.7154f, 0.0721f, 0.0f };
+static const XMVECTORF32 g_HalfMin = { -65504.f, -65504.f, -65504.f, -65504.f };
+static const XMVECTORF32 g_HalfMax = { 65504.f, 65504.f, 65504.f, 65504.f };
+static const XMVECTORF32 g_8BitBias = { 0.5f/255.f, 0.5f/255.f, 0.5f/255.f, 0.5f/255.f };
//-------------------------------------------------------------------------------------
// Copies an image row with optional clearing of alpha value to 1.0
// (can be used in place as well) otherwise copies the image row unmodified.
//-------------------------------------------------------------------------------------
-void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t inSize, DXGI_FORMAT format, DWORD flags )
+void _CopyScanline(_When_(pDestination == pSource, _Inout_updates_bytes_(outSize))
+ _When_(pDestination != pSource, _Out_writes_bytes_(outSize))
+ LPVOID pDestination, _In_ size_t outSize,
+ _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
+ _In_ DXGI_FORMAT format, _In_ DWORD flags)
{
assert( pDestination && outSize > 0 );
assert( pSource && inSize > 0 );
- assert( IsValid(format) && !IsVideo(format) );
+ assert( IsValid(format) && !IsPalettized(format) );
if ( flags & TEXP_SCANLINE_SETALPHA )
{
- switch( format )
+ switch( static_cast<int>(format) )
{
//-----------------------------------------------------------------------------
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
case DXGI_FORMAT_R32G32B32A32_UINT:
case DXGI_FORMAT_R32G32B32A32_SINT:
+ if ( inSize >= 16 && outSize >= 16 )
{
uint32_t alpha;
if ( format == DXGI_FORMAT_R32G32B32A32_FLOAT )
@@ -56,8 +224,8 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
if ( pDestination == pSource )
{
- uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t count = 0; count < outSize; count += 16 )
+ uint32_t *dPtr = reinterpret_cast<uint32_t*> (pDestination);
+ for( size_t count = 0; count < ( outSize - 15 ); count += 16 )
{
dPtr += 3;
*(dPtr++) = alpha;
@@ -68,7 +236,7 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
size_t size = std::min<size_t>( outSize, inSize );
- for( size_t count = 0; count < size; count += 16 )
+ for( size_t count = 0; count < ( size - 15 ); count += 16 )
{
*(dPtr++) = *(sPtr++);
*(dPtr++) = *(sPtr++);
@@ -87,6 +255,8 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
case DXGI_FORMAT_R16G16B16A16_UINT:
case DXGI_FORMAT_R16G16B16A16_SNORM:
case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_Y416:
+ if ( inSize >= 8 && outSize >= 8 )
{
uint16_t alpha;
if ( format == DXGI_FORMAT_R16G16B16A16_FLOAT )
@@ -99,7 +269,7 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
if ( pDestination == pSource )
{
uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
- for( size_t count = 0; count < outSize; count += 8 )
+ for( size_t count = 0; count < ( outSize - 7 ); count += 8 )
{
dPtr += 3;
*(dPtr++) = alpha;
@@ -110,7 +280,7 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
size_t size = std::min<size_t>( outSize, inSize );
- for( size_t count = 0; count < size; count += 8 )
+ for( size_t count = 0; count < ( size - 7 ); count += 8 )
{
*(dPtr++) = *(sPtr++);
*(dPtr++) = *(sPtr++);
@@ -127,24 +297,29 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_R10G10B10A2_UINT:
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
- if ( pDestination == pSource )
+ case DXGI_FORMAT_Y410:
+ case 116 /* DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT */:
+ case 117 /* DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT */:
+ if ( inSize >= 4 && outSize >= 4 )
{
- uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t count = 0; count < outSize; count += 4 )
+ if ( pDestination == pSource )
{
-#pragma warning(suppress: 6001 6101) // PREFast doesn't properly understand the aliasing here.
- *dPtr |= 0xC0000000;
- ++dPtr;
+ uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
+ for( size_t count = 0; count < ( outSize - 3 ); count += 4 )
+ {
+ *dPtr |= 0xC0000000;
+ ++dPtr;
+ }
}
- }
- else
- {
- const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
- uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- size_t size = std::min<size_t>( outSize, inSize );
- for( size_t count = 0; count < size; count += 4 )
+ else
{
- *(dPtr++) = *(sPtr++) | 0xC0000000;
+ const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
+ uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
+ size_t size = std::min<size_t>( outSize, inSize );
+ for( size_t count = 0; count < ( size - 3 ); count += 4 )
+ {
+ *(dPtr++) = *(sPtr++) | 0xC0000000;
+ }
}
}
return;
@@ -159,13 +334,15 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_AYUV:
+ if ( inSize >= 4 && outSize >= 4 )
{
const uint32_t alpha = ( format == DXGI_FORMAT_R8G8B8A8_SNORM || format == DXGI_FORMAT_R8G8B8A8_SINT ) ? 0x7f000000 : 0xff000000;
if ( pDestination == pSource )
{
uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t count = 0; count < outSize; count += 4 )
+ for( size_t count = 0; count < ( outSize - 3 ); count += 4 )
{
uint32_t t = *dPtr & 0xFFFFFF;
t |= alpha;
@@ -177,7 +354,7 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
size_t size = std::min<size_t>( outSize, inSize );
- for( size_t count = 0; count < size; count += 4 )
+ for( size_t count = 0; count < ( size - 3 ); count += 4 )
{
uint32_t t = *(sPtr++) & 0xFFFFFF;
t |= alpha;
@@ -189,22 +366,25 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
//-----------------------------------------------------------------------------
case DXGI_FORMAT_B5G5R5A1_UNORM:
- if ( pDestination == pSource )
+ if ( inSize >= 2 && outSize >= 2 )
{
- uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
- for( size_t count = 0; count < outSize; count += 2 )
+ if ( pDestination == pSource )
{
- *(dPtr++) |= 0x8000;
+ uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
+ for( size_t count = 0; count < ( outSize - 1 ); count += 2 )
+ {
+ *(dPtr++) |= 0x8000;
+ }
}
- }
- else
- {
- const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
- uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
- size_t size = std::min<size_t>( outSize, inSize );
- for( size_t count = 0; count < size; count += 2 )
+ else
{
- *(dPtr++) = *(sPtr++) | 0x8000;
+ const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
+ uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
+ size_t size = std::min<size_t>( outSize, inSize );
+ for( size_t count = 0; count < ( size - 1 ); count += 2 )
+ {
+ *(dPtr++) = *(sPtr++) | 0x8000;
+ }
}
}
return;
@@ -214,29 +394,30 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
memset( pDestination, 0xff, outSize );
return;
-#ifdef DXGI_1_2_FORMATS
//-----------------------------------------------------------------------------
case DXGI_FORMAT_B4G4R4A4_UNORM:
- if ( pDestination == pSource )
+ if ( inSize >= 2 && outSize >= 2 )
{
- uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
- for( size_t count = 0; count < outSize; count += 2 )
+ if ( pDestination == pSource )
{
- *(dPtr++) |= 0xF000;
+ uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
+ for( size_t count = 0; count < ( outSize - 1 ); count += 2 )
+ {
+ *(dPtr++) |= 0xF000;
+ }
}
- }
- else
- {
- const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
- uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
- size_t size = std::min<size_t>( outSize, inSize );
- for( size_t count = 0; count < size; count += 2 )
+ else
{
- *(dPtr++) = *(sPtr++) | 0xF000;
+ const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
+ uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
+ size_t size = std::min<size_t>( outSize, inSize );
+ for( size_t count = 0; count < ( size - 1 ); count += 2 )
+ {
+ *(dPtr++) = *(sPtr++) | 0xF000;
+ }
}
}
return;
-#endif // DXGI_1_2_FORMATS
}
}
@@ -253,11 +434,12 @@ void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t
// Swizzles (RGB <-> BGR) an image row with optional clearing of alpha value to 1.0
// (can be used in place as well) otherwise copies the image row unmodified.
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void _SwizzleScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t inSize, DXGI_FORMAT format, DWORD flags )
{
assert( pDestination && outSize > 0 );
assert( pSource && inSize > 0 );
- assert( IsValid(format) && !IsVideo(format) );
+ assert( IsValid(format) && !IsPlanar(format) && !IsPalettized(format) );
switch( format )
{
@@ -266,43 +448,45 @@ void _SwizzleScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, siz
case DXGI_FORMAT_R10G10B10A2_UNORM:
case DXGI_FORMAT_R10G10B10A2_UINT:
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
- if ( flags & TEXP_SCANLINE_LEGACY )
+ if ( inSize >= 4 && outSize >= 4 )
{
- // Swap Red (R) and Blue (B) channel (used for D3DFMT_A2R10G10B10 legacy sources)
- if ( pDestination == pSource )
+ if ( flags & TEXP_SCANLINE_LEGACY )
{
- uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t count = 0; count < outSize; count += 4 )
+ // Swap Red (R) and Blue (B) channel (used for D3DFMT_A2R10G10B10 legacy sources)
+ if ( pDestination == pSource )
{
-#pragma warning(suppress: 6001 6101) // PREFast doesn't properly understand the aliasing here.
- uint32_t t = *dPtr;
+ uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
+ for( size_t count = 0; count < ( outSize - 3 ); count += 4 )
+ {
+ uint32_t t = *dPtr;
- uint32_t t1 = (t & 0x3ff00000) >> 20;
- uint32_t t2 = (t & 0x000003ff) << 20;
- uint32_t t3 = (t & 0x000ffc00);
- uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xC0000000 : (t & 0xC0000000);
+ uint32_t t1 = (t & 0x3ff00000) >> 20;
+ uint32_t t2 = (t & 0x000003ff) << 20;
+ uint32_t t3 = (t & 0x000ffc00);
+ uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xC0000000 : (t & 0xC0000000);
- *(dPtr++) = t1 | t2 | t3 | ta;
+ *(dPtr++) = t1 | t2 | t3 | ta;
+ }
}
- }
- else
- {
- const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
- uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- size_t size = std::min<size_t>( outSize, inSize );
- for( size_t count = 0; count < size; count += 4 )
+ else
{
- uint32_t t = *(sPtr++);
+ const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
+ uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
+ size_t size = std::min<size_t>( outSize, inSize );
+ for( size_t count = 0; count < ( size - 3 ); count += 4 )
+ {
+ uint32_t t = *(sPtr++);
- uint32_t t1 = (t & 0x3ff00000) >> 20;
- uint32_t t2 = (t & 0x000003ff) << 20;
- uint32_t t3 = (t & 0x000ffc00);
- uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xC0000000 : (t & 0xC0000000);
+ uint32_t t1 = (t & 0x3ff00000) >> 20;
+ uint32_t t2 = (t & 0x000003ff) << 20;
+ uint32_t t3 = (t & 0x000ffc00);
+ uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xC0000000 : (t & 0xC0000000);
- *(dPtr++) = t1 | t2 | t3 | ta;
+ *(dPtr++) = t1 | t2 | t3 | ta;
+ }
}
+ return;
}
- return;
}
break;
@@ -316,40 +500,88 @@ void _SwizzleScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, siz
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
- // Swap Red (R) and Blue (B) channels (used to convert from DXGI 1.1 BGR formats to DXGI 1.0 RGB)
- if ( pDestination == pSource )
+ if ( inSize >= 4 && outSize >= 4 )
{
- uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t count = 0; count < outSize; count += 4 )
+ // Swap Red (R) and Blue (B) channels (used to convert from DXGI 1.1 BGR formats to DXGI 1.0 RGB)
+ if ( pDestination == pSource )
{
- uint32_t t = *dPtr;
+ uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
+ for( size_t count = 0; count < ( outSize - 3 ); count += 4 )
+ {
+ uint32_t t = *dPtr;
- uint32_t t1 = (t & 0x00ff0000) >> 16;
- uint32_t t2 = (t & 0x000000ff) << 16;
- uint32_t t3 = (t & 0x0000ff00);
- uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : (t & 0xFF000000);
+ uint32_t t1 = (t & 0x00ff0000) >> 16;
+ uint32_t t2 = (t & 0x000000ff) << 16;
+ uint32_t t3 = (t & 0x0000ff00);
+ uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : (t & 0xFF000000);
- *(dPtr++) = t1 | t2 | t3 | ta;
+ *(dPtr++) = t1 | t2 | t3 | ta;
+ }
}
+ else
+ {
+ const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
+ uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
+ size_t size = std::min<size_t>( outSize, inSize );
+ for( size_t count = 0; count < ( size - 3 ); count += 4 )
+ {
+ uint32_t t = *(sPtr++);
+
+ uint32_t t1 = (t & 0x00ff0000) >> 16;
+ uint32_t t2 = (t & 0x000000ff) << 16;
+ uint32_t t3 = (t & 0x0000ff00);
+ uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : (t & 0xFF000000);
+
+ *(dPtr++) = t1 | t2 | t3 | ta;
+ }
+ }
+ return;
}
- else
+ break;
+
+ //---------------------------------------------------------------------------------
+ case DXGI_FORMAT_YUY2:
+ if ( inSize >= 4 && outSize >= 4 )
{
- const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
- uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- size_t size = std::min<size_t>( outSize, inSize );
- for( size_t count = 0; count < size; count += 4 )
+ if ( flags & TEXP_SCANLINE_LEGACY )
{
- uint32_t t = *(sPtr++);
+ // Reorder YUV components (used to convert legacy UYVY -> YUY2)
+ if ( pDestination == pSource )
+ {
+ uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
+ for( size_t count = 0; count < ( outSize - 3 ); count += 4 )
+ {
+ uint32_t t = *dPtr;
- uint32_t t1 = (t & 0x00ff0000) >> 16;
- uint32_t t2 = (t & 0x000000ff) << 16;
- uint32_t t3 = (t & 0x0000ff00);
- uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : (t & 0xFF000000);
+ uint32_t t1 = (t & 0x000000ff) << 8;
+ uint32_t t2 = (t & 0x0000ff00) >> 8;
+ uint32_t t3 = (t & 0x00ff0000) << 8;
+ uint32_t t4 = (t & 0xff000000) >> 8;
- *(dPtr++) = t1 | t2 | t3 | ta;
+ *(dPtr++) = t1 | t2 | t3 | t4;
+ }
+ }
+ else
+ {
+ const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
+ uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
+ size_t size = std::min<size_t>( outSize, inSize );
+ for( size_t count = 0; count < ( size - 3 ); count += 4 )
+ {
+ uint32_t t = *(sPtr++);
+
+ uint32_t t1 = (t & 0x000000ff) << 8;
+ uint32_t t2 = (t & 0x0000ff00) >> 8;
+ uint32_t t3 = (t & 0x00ff0000) << 8;
+ uint32_t t4 = (t & 0xff000000) >> 8;
+
+ *(dPtr++) = t1 | t2 | t3 | t4;
+ }
+ }
+ return;
}
}
- return;
+ break;
}
// Fall-through case is to just use memcpy (assuming this is not an in-place operation)
@@ -365,13 +597,14 @@ void _SwizzleScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, siz
// Converts an image row with optional clearing of alpha value to 1.0
// Returns true if supported, false if expansion case not supported
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat,
LPCVOID pSource, size_t inSize, DXGI_FORMAT inFormat, DWORD flags )
{
assert( pDestination && outSize > 0 );
assert( pSource && inSize > 0 );
- assert( IsValid(outFormat) && !IsVideo(outFormat) );
- assert( IsValid(inFormat) && !IsVideo(inFormat) );
+ assert( IsValid(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat) );
+ assert( IsValid(inFormat) && !IsPlanar(inFormat) && !IsPalettized(inFormat) );
switch( inFormat )
{
@@ -380,11 +613,12 @@ bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat
return false;
// DXGI_FORMAT_B5G6R5_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 2 && outSize >= 4 )
{
const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
{
uint16_t t = *(sPtr++);
@@ -394,19 +628,21 @@ bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat
*(dPtr++) = t1 | t2 | t3 | 0xff000000;
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_B5G5R5A1_UNORM:
if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
return false;
// DXGI_FORMAT_B5G5R5A1_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 2 && outSize >= 4 )
{
const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
{
uint16_t t = *(sPtr++);
@@ -417,20 +653,21 @@ bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat
*(dPtr++) = t1 | t2 | t3 | ta;
}
+ return true;
}
- return true;
+ return false;
-#ifdef DXGI_1_2_FORMATS
case DXGI_FORMAT_B4G4R4A4_UNORM:
if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
return false;
// DXGI_FORMAT_B4G4R4A4_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 2 && outSize >= 4 )
{
const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
{
uint16_t t = *(sPtr++);
@@ -441,9 +678,9 @@ bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat
*(dPtr++) = t1 | t2 | t3 | ta;
}
+ return true;
}
- return true;
-#endif // DXGI_1_2_FORMATS
+ return false;
}
return false;
@@ -457,7 +694,7 @@ bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat
if ( size >= sizeof(type) )\
{\
const type * __restrict sPtr = reinterpret_cast<const type*>(pSource);\
- for( size_t icount = 0; icount < size; icount += sizeof(type) )\
+ for( size_t icount = 0; icount < ( size - sizeof(type) + 1 ); icount += sizeof(type) )\
{\
if ( dPtr >= ePtr ) break;\
*(dPtr++) = func( sPtr++ );\
@@ -470,7 +707,7 @@ bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat
if ( size >= sizeof(type) )\
{\
const type * __restrict sPtr = reinterpret_cast<const type*>(pSource);\
- for( size_t icount = 0; icount < size; icount += sizeof(type) )\
+ for( size_t icount = 0; icount < ( size - sizeof(type) + 1 ); icount += sizeof(type) )\
{\
XMVECTOR v = func( sPtr++ );\
if ( dPtr >= ePtr ) break;\
@@ -484,7 +721,7 @@ bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat
if ( size >= sizeof(type) )\
{\
const type * __restrict sPtr = reinterpret_cast<const type*>(pSource);\
- for( size_t icount = 0; icount < size; icount += sizeof(type) )\
+ for( size_t icount = 0; icount < ( size - sizeof(type) + 1 ); icount += sizeof(type) )\
{\
XMVECTOR v = func( sPtr++ );\
if ( dPtr >= ePtr ) break;\
@@ -494,14 +731,15 @@ bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat
}\
return false;
-bool _LoadScanline( XMVECTOR* pDestination, size_t count,
+#pragma warning(suppress: 6101)
+_Use_decl_annotations_ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
LPCVOID pSource, size_t size, DXGI_FORMAT format )
{
#if !defined(_XM_NO_INTRINSICS_)
assert( pDestination && count > 0 && (((uintptr_t)pDestination & 0xF) == 0) );
#endif
assert( pSource && size > 0 );
- assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format) && !IsCompressed(format) );
+ assert( IsValid(format) && !IsTypeless(format, false) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format) );
XMVECTOR* __restrict dPtr = pDestination;
if ( !dPtr )
@@ -509,7 +747,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
const XMVECTOR* ePtr = pDestination + count;
- switch( format )
+ switch( static_cast<int>(format) )
{
case DXGI_FORMAT_R32G32B32A32_FLOAT:
{
@@ -558,24 +796,92 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
LOAD_SCANLINE2( XMINT2, XMLoadSInt2, g_XMIdentityR3 )
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
- if ( size >= (sizeof(float)+sizeof(uint32_t)) )
{
- const float * sPtr = reinterpret_cast<const float*>(pSource);
- for( size_t icount = 0; icount < size; icount += (sizeof(float)+sizeof(uint32_t)) )
+ const size_t psize = sizeof(float)+sizeof(uint32_t);
+ if ( size >= psize )
{
- const uint8_t* ps8 = reinterpret_cast<const uint8_t*>( &sPtr[1] );
- if ( dPtr >= ePtr ) break;
- *(dPtr++) = XMVectorSet( sPtr[0], static_cast<float>( *ps8 ), 0.f, 1.f );
- sPtr += 2;
+ const float * sPtr = reinterpret_cast<const float*>(pSource);
+ for( size_t icount = 0; icount < ( size - psize + 1 ); icount += psize )
+ {
+ const uint8_t* ps8 = reinterpret_cast<const uint8_t*>( &sPtr[1] );
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( sPtr[0], static_cast<float>( *ps8 ), 0.f, 1.f );
+ sPtr += 2;
+ }
+ return true;
+ }
+ }
+ return false;
+
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ {
+ const size_t psize = sizeof(float)+sizeof(uint32_t);
+ if ( size >= psize )
+ {
+ const float * sPtr = reinterpret_cast<const float*>(pSource);
+ for( size_t icount = 0; icount < ( size - psize + 1 ); icount += psize )
+ {
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( sPtr[0], 0.f /* typeless component assumed zero */, 0.f, 1.f );
+ sPtr += 2;
+ }
+ return true;
+ }
+ }
+ return false;
+
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ {
+ const size_t psize = sizeof(float)+sizeof(uint32_t);
+ if ( size >= psize )
+ {
+ const float * sPtr = reinterpret_cast<const float*>(pSource);
+ for( size_t icount = 0; icount < ( size - psize + 1 ); icount += psize )
+ {
+ const uint8_t* pg8 = reinterpret_cast<const uint8_t*>( &sPtr[1] );
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( 0.f /* typeless component assumed zero */, static_cast<float>( *pg8 ), 0.f, 1.f );
+ sPtr += 2;
+ }
+ return true;
}
- return true;
}
return false;
case DXGI_FORMAT_R10G10B10A2_UNORM:
- case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
LOAD_SCANLINE( XMUDECN4, XMLoadUDecN4 );
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+#if DIRECTX_MATH_VERSION >= 306
+ LOAD_SCANLINE( XMUDECN4, XMLoadUDecN4_XR );
+#else
+ if ( size >= sizeof(XMUDECN4) )
+ {
+ const XMUDECN4 * __restrict sPtr = reinterpret_cast<const XMUDECN4*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUDECN4) + 1 ); icount += sizeof(XMUDECN4) )
+ {
+ if ( dPtr >= ePtr ) break;
+
+ int32_t ElementX = sPtr->v & 0x3FF;
+ int32_t ElementY = (sPtr->v >> 10) & 0x3FF;
+ int32_t ElementZ = (sPtr->v >> 20) & 0x3FF;
+
+ XMVECTORF32 vResult = {
+ (float)(ElementX - 0x180) / 510.0f,
+ (float)(ElementY - 0x180) / 510.0f,
+ (float)(ElementZ - 0x180) / 510.0f,
+ (float)(sPtr->v >> 30) / 3.0f
+ };
+
+ ++sPtr;
+
+ *(dPtr++) = vResult.v;
+ }
+ return true;
+ }
+ return false;
+#endif
+
case DXGI_FORMAT_R10G10B10A2_UINT:
LOAD_SCANLINE( XMUDEC4, XMLoadUDec4 );
@@ -615,7 +921,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(float) )
{
const float* __restrict sPtr = reinterpret_cast<const float*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(float) )
+ for( size_t icount = 0; icount < ( size - sizeof(float) + 1 ); icount += sizeof(float) )
{
XMVECTOR v = XMLoadFloat( sPtr++ );
if ( dPtr >= ePtr ) break;
@@ -629,7 +935,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(uint32_t) )
{
const uint32_t* __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(uint32_t) + 1 ); icount += sizeof(uint32_t) )
{
XMVECTOR v = XMLoadInt( sPtr++ );
v = XMConvertVectorUIntToFloat( v, 0 );
@@ -644,7 +950,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(int32_t) )
{
const int32_t * __restrict sPtr = reinterpret_cast<const int32_t*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(int32_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(int32_t) + 1 ); icount += sizeof(int32_t) )
{
XMVECTOR v = XMLoadInt( reinterpret_cast<const uint32_t*> (sPtr++) );
v = XMConvertVectorIntToFloat( v, 0 );
@@ -659,7 +965,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(uint32_t) )
{
const uint32_t * sPtr = reinterpret_cast<const uint32_t*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(uint32_t) + 1 ); icount += sizeof(uint32_t) )
{
float d = static_cast<float>( *sPtr & 0xFFFFFF ) / 16777215.f;
float s = static_cast<float>( ( *sPtr & 0xFF000000 ) >> 24 );
@@ -671,6 +977,36 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
}
return false;
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ if ( size >= sizeof(uint32_t) )
+ {
+ const uint32_t * sPtr = reinterpret_cast<const uint32_t*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(uint32_t) + 1 ); icount += sizeof(uint32_t) )
+ {
+ float r = static_cast<float>( *sPtr & 0xFFFFFF ) / 16777215.f;
+ ++sPtr;
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( r, 0.f /* typeless component assumed zero */, 0.f, 1.f );
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ if ( size >= sizeof(uint32_t) )
+ {
+ const uint32_t * sPtr = reinterpret_cast<const uint32_t*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(uint32_t) + 1 ); icount += sizeof(uint32_t) )
+ {
+ float g = static_cast<float>( ( *sPtr & 0xFF000000 ) >> 24 );
+ ++sPtr;
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( 0.f /* typeless component assumed zero */, g, 0.f, 1.f );
+ }
+ return true;
+ }
+ return false;
+
case DXGI_FORMAT_R8G8_UNORM:
LOAD_SCANLINE2( XMUBYTEN2, XMLoadUByteN2, g_XMIdentityR3 )
@@ -687,7 +1023,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(HALF) )
{
const HALF * __restrict sPtr = reinterpret_cast<const HALF*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(HALF) )
+ for( size_t icount = 0; icount < ( size - sizeof(HALF) + 1 ); icount += sizeof(HALF) )
{
if ( dPtr >= ePtr ) break;
*(dPtr++) = XMVectorSet( XMConvertHalfToFloat(*sPtr++), 0.f, 0.f, 1.f );
@@ -701,7 +1037,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(uint16_t) )
{
const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(uint16_t) + 1 ); icount += sizeof(uint16_t) )
{
if ( dPtr >= ePtr ) break;
*(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 65535.f, 0.f, 0.f, 1.f );
@@ -714,7 +1050,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(uint16_t) )
{
const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(uint16_t) + 1 ); icount += sizeof(uint16_t) )
{
if ( dPtr >= ePtr ) break;
*(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
@@ -727,7 +1063,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(int16_t) )
{
const int16_t * __restrict sPtr = reinterpret_cast<const int16_t*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(int16_t) + 1 ); icount += sizeof(int16_t) )
{
if ( dPtr >= ePtr ) break;
*(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 32767.f, 0.f, 0.f, 1.f );
@@ -740,7 +1076,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(int16_t) )
{
const int16_t * __restrict sPtr = reinterpret_cast<const int16_t*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(int16_t) + 1 ); icount += sizeof(int16_t) )
{
if ( dPtr >= ePtr ) break;
*(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
@@ -776,10 +1112,10 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
return false;
case DXGI_FORMAT_R8_SNORM:
- if ( size >= sizeof(char) )
+ if ( size >= sizeof(int8_t) )
{
- const char * __restrict sPtr = reinterpret_cast<const char*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(char) )
+ const int8_t * __restrict sPtr = reinterpret_cast<const int8_t*>(pSource);
+ for( size_t icount = 0; icount < size; icount += sizeof(int8_t) )
{
if ( dPtr >= ePtr ) break;
*(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 127.f, 0.f, 0.f, 1.f );
@@ -789,10 +1125,10 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
return false;
case DXGI_FORMAT_R8_SINT:
- if ( size >= sizeof(char) )
+ if ( size >= sizeof(int8_t) )
{
- const char * __restrict sPtr = reinterpret_cast<const char*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(char) )
+ const int8_t * __restrict sPtr = reinterpret_cast<const int8_t*>(pSource);
+ for( size_t icount = 0; icount < size; icount += sizeof(int8_t) )
{
if ( dPtr >= ePtr ) break;
*(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
@@ -820,10 +1156,10 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
{
- for( size_t bcount = 0; bcount < 8; ++bcount )
+ for( size_t bcount = 8; bcount > 0; --bcount )
{
if ( dPtr >= ePtr ) break;
- *(dPtr++) = XMVectorSet( (((*sPtr >> bcount) & 0x1) ? 1.f : 0.f), 0.f, 0.f, 1.f );
+ *(dPtr++) = XMVectorSet( (((*sPtr >> (bcount-1)) & 0x1) ? 1.f : 0.f), 0.f, 0.f, 1.f );
}
++sPtr;
@@ -833,13 +1169,37 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
return false;
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+#if DIRECTX_MATH_VERSION >= 306
LOAD_SCANLINE3( XMFLOAT3SE, XMLoadFloat3SE, g_XMIdentityR3 )
+#else
+ if ( size >= sizeof(XMFLOAT3SE) )
+ {
+ const XMFLOAT3SE * __restrict sPtr = reinterpret_cast<const XMFLOAT3SE*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMFLOAT3SE) + 1 ); icount += sizeof(XMFLOAT3SE) )
+ {
+ union { float f; int32_t i; } fi;
+ fi.i = 0x33800000 + (sPtr->e << 23);
+ float Scale = fi.f;
+
+ XMVECTORF32 v = {
+ Scale * float( sPtr->xm ),
+ Scale * float( sPtr->ym ),
+ Scale * float( sPtr->zm ),
+ 1.0f };
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = v;
+ }
+ return true;
+ }
+ return false;
+#endif
case DXGI_FORMAT_R8G8_B8G8_UNORM:
if ( size >= sizeof(XMUBYTEN4) )
{
const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
{
XMVECTOR v = XMLoadUByteN4( sPtr++ );
XMVECTOR v1 = XMVectorSwizzle<0, 3, 2, 1>( v );
@@ -856,7 +1216,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(XMUBYTEN4) )
{
const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
{
XMVECTOR v = XMLoadUByteN4( sPtr++ );
XMVECTOR v0 = XMVectorSwizzle<1, 0, 3, 2>( v );
@@ -873,9 +1233,9 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
case DXGI_FORMAT_B5G6R5_UNORM:
if ( size >= sizeof(XMU565) )
{
- static XMVECTORF32 s_Scale = { 1.f/31.f, 1.f/63.f, 1.f/31.f, 1.f };
+ static const XMVECTORF32 s_Scale = { 1.f/31.f, 1.f/63.f, 1.f/31.f, 1.f };
const XMU565 * __restrict sPtr = reinterpret_cast<const XMU565*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(XMU565) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMU565) + 1 ); icount += sizeof(XMU565) )
{
XMVECTOR v = XMLoadU565( sPtr++ );
v = XMVectorMultiply( v, s_Scale );
@@ -890,9 +1250,9 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
case DXGI_FORMAT_B5G5R5A1_UNORM:
if ( size >= sizeof(XMU555) )
{
- static XMVECTORF32 s_Scale = { 1.f/31.f, 1.f/31.f, 1.f/31.f, 1.f };
+ static const XMVECTORF32 s_Scale = { 1.f/31.f, 1.f/31.f, 1.f/31.f, 1.f };
const XMU555 * __restrict sPtr = reinterpret_cast<const XMU555*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(XMU555) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMU555) + 1 ); icount += sizeof(XMU555) )
{
XMVECTOR v = XMLoadU555( sPtr++ );
v = XMVectorMultiply( v, s_Scale );
@@ -908,7 +1268,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(XMUBYTEN4) )
{
const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
{
XMVECTOR v = XMLoadUByteN4( sPtr++ );
if ( dPtr >= ePtr ) break;
@@ -923,7 +1283,7 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(XMUBYTEN4) )
{
const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
{
XMVECTOR v = XMLoadUByteN4( sPtr++ );
v = XMVectorSwizzle<2, 1, 0, 3>( v );
@@ -934,13 +1294,232 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
}
return false;
-#ifdef DXGI_1_2_FORMATS
+ case DXGI_FORMAT_AYUV:
+ if ( size >= sizeof(XMUBYTEN4) )
+ {
+ const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
+ {
+ int v = int(sPtr->x) - 128;
+ int u = int(sPtr->y) - 128;
+ int y = int(sPtr->z) - 16;
+ unsigned int a = sPtr->w;
+ ++sPtr;
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/dd206750.aspx
+
+ // Y’ = Y - 16
+ // Cb’ = Cb - 128
+ // Cr’ = Cr - 128
+
+ // R = 1.1644Y’ + 1.5960Cr’
+ // G = 1.1644Y’ - 0.3917Cb’ - 0.8128Cr’
+ // B = 1.1644Y’ + 2.0172Cb’
+
+ int r = (298 * y + 409 * v + 128) >> 8;
+ int g = (298 * y - 100 * u - 208 * v + 128) >> 8;
+ int b = (298 * y + 516 * u + 128) >> 8;
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( float( std::min<int>( std::max<int>( r, 0 ), 255 ) ) / 255.f,
+ float( std::min<int>( std::max<int>( g, 0 ), 255 ) ) / 255.f,
+ float( std::min<int>( std::max<int>( b, 0 ), 255 ) ) / 255.f,
+ float( a / 255.f ) );
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_Y410:
+ if ( size >= sizeof(XMUDECN4) )
+ {
+ const XMUDECN4 * __restrict sPtr = reinterpret_cast<const XMUDECN4*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUDECN4) + 1 ); icount += sizeof(XMUDECN4) )
+ {
+ int64_t u = int(sPtr->x) - 512;
+ int64_t y = int(sPtr->y) - 64;
+ int64_t v = int(sPtr->z) - 512;
+ unsigned int a = sPtr->w;
+ ++sPtr;
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/bb970578.aspx
+
+ // Y’ = Y - 64
+ // Cb’ = Cb - 512
+ // Cr’ = Cr - 512
+
+ // R = 1.1678Y’ + 1.6007Cr’
+ // G = 1.1678Y’ - 0.3929Cb’ - 0.8152Cr’
+ // B = 1.1678Y’ + 2.0232Cb’
+
+ int r = static_cast<int>( (76533 * y + 104905 * v + 32768) >> 16 );
+ int g = static_cast<int>( (76533 * y - 25747 * u - 53425 * v + 32768) >> 16 );
+ int b = static_cast<int>( (76533 * y + 132590 * u + 32768) >> 16 );
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( float( std::min<int>( std::max<int>( r, 0 ), 1023 ) ) / 1023.f,
+ float( std::min<int>( std::max<int>( g, 0 ), 1023 ) ) / 1023.f,
+ float( std::min<int>( std::max<int>( b, 0 ), 1023 ) ) / 1023.f,
+ float( a / 3.f ) );
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_Y416:
+ if ( size >= sizeof(XMUSHORTN4) )
+ {
+ const XMUSHORTN4 * __restrict sPtr = reinterpret_cast<const XMUSHORTN4*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUSHORTN4) + 1 ); icount += sizeof(XMUSHORTN4) )
+ {
+ int64_t u = int64_t(sPtr->x) - 32768;
+ int64_t y = int64_t(sPtr->y) - 4096;
+ int64_t v = int64_t(sPtr->z) - 32768;
+ unsigned int a = sPtr->w;
+ ++sPtr;
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/bb970578.aspx
+
+ // Y’ = Y - 4096
+ // Cb’ = Cb - 32768
+ // Cr’ = Cr - 32768
+
+ // R = 1.1689Y’ + 1.6023Cr’
+ // G = 1.1689Y’ - 0.3933Cb’ - 0.8160Cr’
+ // B = 1.1689Y’+ 2.0251Cb’
+
+ int r = static_cast<int>( (76607 * y + 105006 * v + 32768) >> 16 );
+ int g = static_cast<int>( (76607 * y - 25772 * u - 53477 * v + 32768) >> 16 );
+ int b = static_cast<int>( (76607 * y + 132718 * u + 32768) >> 16 );
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( float( std::min<int>( std::max<int>( r, 0 ), 65535 ) ) / 65535.f,
+ float( std::min<int>( std::max<int>( g, 0 ), 65535 ) ) / 65535.f,
+ float( std::min<int>( std::max<int>( b, 0 ), 65535 ) ) / 65535.f,
+ float( std::min<int>( std::max<int>( a, 0 ), 65535 ) ) / 65535.f );
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_YUY2:
+ if ( size >= sizeof(XMUBYTEN4) )
+ {
+ const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
+ {
+ int y0 = int(sPtr->x) - 16;
+ int u = int(sPtr->y) - 128;
+ int y1 = int(sPtr->z) - 16;
+ int v = int(sPtr->w) - 128;
+ ++sPtr;
+
+ // See AYUV
+ int r = (298 * y0 + 409 * v + 128) >> 8;
+ int g = (298 * y0 - 100 * u - 208 * v + 128) >> 8;
+ int b = (298 * y0 + 516 * u + 128) >> 8;
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( float( std::min<int>( std::max<int>( r, 0 ), 255 ) ) / 255.f,
+ float( std::min<int>( std::max<int>( g, 0 ), 255 ) ) / 255.f,
+ float( std::min<int>( std::max<int>( b, 0 ), 255 ) ) / 255.f,
+ 1.f );
+
+ r = (298 * y1 + 409 * v + 128) >> 8;
+ g = (298 * y1 - 100 * u - 208 * v + 128) >> 8;
+ b = (298 * y1 + 516 * u + 128) >> 8;
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( float( std::min<int>( std::max<int>( r, 0 ), 255 ) ) / 255.f,
+ float( std::min<int>( std::max<int>( g, 0 ), 255 ) ) / 255.f,
+ float( std::min<int>( std::max<int>( b, 0 ), 255 ) ) / 255.f,
+ 1.f );
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_Y210:
+ // Same as Y216 with least significant 6 bits set to zero
+ if ( size >= sizeof(XMUSHORTN4) )
+ {
+ const XMUSHORTN4 * __restrict sPtr = reinterpret_cast<const XMUSHORTN4*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUSHORTN4) + 1 ); icount += sizeof(XMUSHORTN4) )
+ {
+ int64_t y0 = int64_t(sPtr->x >> 6) - 64;
+ int64_t u = int64_t(sPtr->y >> 6) - 512;
+ int64_t y1 = int64_t(sPtr->z >> 6) - 64;
+ int64_t v = int64_t(sPtr->w >> 6) - 512;
+ ++sPtr;
+
+ // See Y410
+ int r = static_cast<int>( (76533 * y0 + 104905 * v + 32768) >> 16 );
+ int g = static_cast<int>( (76533 * y0 - 25747 * u - 53425 * v + 32768) >> 16 );
+ int b = static_cast<int>( (76533 * y0 + 132590 * u + 32768) >> 16 );
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( float( std::min<int>( std::max<int>( r, 0 ), 1023 ) ) / 1023.f,
+ float( std::min<int>( std::max<int>( g, 0 ), 1023 ) ) / 1023.f,
+ float( std::min<int>( std::max<int>( b, 0 ), 1023 ) ) / 1023.f,
+ 1.f );
+
+ r = static_cast<int>( (76533 * y1 + 104905 * v + 32768) >> 16 );
+ g = static_cast<int>( (76533 * y1 - 25747 * u - 53425 * v + 32768) >> 16 );
+ b = static_cast<int>( (76533 * y1 + 132590 * u + 32768) >> 16 );
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( float( std::min<int>( std::max<int>( r, 0 ), 1023 ) ) / 1023.f,
+ float( std::min<int>( std::max<int>( g, 0 ), 1023 ) ) / 1023.f,
+ float( std::min<int>( std::max<int>( b, 0 ), 1023 ) ) / 1023.f,
+ 1.f );
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_Y216:
+ if ( size >= sizeof(XMUSHORTN4) )
+ {
+ const XMUSHORTN4 * __restrict sPtr = reinterpret_cast<const XMUSHORTN4*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUSHORTN4) + 1 ); icount += sizeof(XMUSHORTN4) )
+ {
+ int64_t y0 = int64_t(sPtr->x) - 4096;
+ int64_t u = int64_t(sPtr->y) - 32768;
+ int64_t y1 = int64_t(sPtr->z) - 4096;
+ int64_t v = int64_t(sPtr->w) - 32768;
+ ++sPtr;
+
+ // See Y416
+ int r = static_cast<int>( (76607 * y0 + 105006 * v + 32768) >> 16 );
+ int g = static_cast<int>( (76607 * y0 - 25772 * u - 53477 * v + 32768) >> 16 );
+ int b = static_cast<int>( (76607 * y0 + 132718 * u + 32768) >> 16 );
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( float( std::min<int>( std::max<int>( r, 0 ), 65535 ) ) / 65535.f,
+ float( std::min<int>( std::max<int>( g, 0 ), 65535 ) ) / 65535.f,
+ float( std::min<int>( std::max<int>( b, 0 ), 65535 ) ) / 65535.f,
+ 1.f );
+
+ r = static_cast<int>( (76607 * y1 + 105006 * v + 32768) >> 16 );
+ g = static_cast<int>( (76607 * y1 - 25772 * u - 53477 * v + 32768) >> 16 );
+ b = static_cast<int>( (76607 * y1 + 132718 * u + 32768) >> 16 );
+
+ if ( dPtr >= ePtr ) break;
+ *(dPtr++) = XMVectorSet( float( std::min<int>( std::max<int>( r, 0 ), 65535 ) ) / 65535.f,
+ float( std::min<int>( std::max<int>( g, 0 ), 65535 ) ) / 65535.f,
+ float( std::min<int>( std::max<int>( b, 0 ), 65535 ) ) / 65535.f,
+ 1.f );
+ }
+ return true;
+ }
+ return false;
+
case DXGI_FORMAT_B4G4R4A4_UNORM:
if ( size >= sizeof(XMUNIBBLE4) )
{
- static XMVECTORF32 s_Scale = { 1.f/15.f, 1.f/15.f, 1.f/15.f, 1.f/15.f };
+ static const XMVECTORF32 s_Scale = { 1.f/15.f, 1.f/15.f, 1.f/15.f, 1.f/15.f };
const XMUNIBBLE4 * __restrict sPtr = reinterpret_cast<const XMUNIBBLE4*>(pSource);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUNIBBLE4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUNIBBLE4) + 1 ); icount += sizeof(XMUNIBBLE4) )
{
XMVECTOR v = XMLoadUNibble4( sPtr++ );
v = XMVectorMultiply( v, s_Scale );
@@ -951,14 +1530,65 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
}
return false;
- // we don't support the video formats ( see IsVideo function )
-#endif // DXGI_1_2_FORMATS
+ case 116 /* DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT */:
+ // Xbox One specific 7e3 format
+ if ( size >= sizeof(XMUDECN4) )
+ {
+ const XMUDECN4 * __restrict sPtr = reinterpret_cast<const XMUDECN4*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUDECN4) + 1 ); icount += sizeof(XMUDECN4) )
+ {
+ if ( dPtr >= ePtr ) break;
+
+ XMVECTORF32 vResult = {
+ FloatFrom7e3(sPtr->x),
+ FloatFrom7e3(sPtr->y),
+ FloatFrom7e3(sPtr->z),
+ (float)(sPtr->v >> 30) / 3.0f
+ };
+
+ ++sPtr;
+
+ *(dPtr++) = vResult.v;
+ }
+ return true;
+ }
+ return false;
+
+ case 117 /* DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT */:
+ // Xbox One specific 6e4 format
+ if ( size >= sizeof(XMUDECN4) )
+ {
+ const XMUDECN4 * __restrict sPtr = reinterpret_cast<const XMUDECN4*>(pSource);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUDECN4) + 1 ); icount += sizeof(XMUDECN4) )
+ {
+ if ( dPtr >= ePtr ) break;
+
+ XMVECTORF32 vResult = {
+ FloatFrom6e4(sPtr->x),
+ FloatFrom6e4(sPtr->y),
+ FloatFrom6e4(sPtr->z),
+ (float)(sPtr->v >> 30) / 3.0f
+ };
+
+ ++sPtr;
+
+ *(dPtr++) = vResult.v;
+ }
+ return true;
+ }
+ return false;
+
+ // We don't support the planar or palettized formats
default:
return false;
}
}
+#undef LOAD_SCANLINE
+#undef LOAD_SCANLINE3
+#undef LOAD_SCANLINE2
+
//-------------------------------------------------------------------------------------
// Stores an image row from standard RGBA XMVECTOR (aligned) array
@@ -967,22 +1597,24 @@ bool _LoadScanline( XMVECTOR* pDestination, size_t count,
if ( size >= sizeof(type) )\
{\
type * __restrict dPtr = reinterpret_cast<type*>(pDestination);\
- for( size_t icount = 0; icount < size; icount += sizeof(type) )\
+ for( size_t icount = 0; icount < ( size - sizeof(type) + 1 ); icount += sizeof(type) )\
{\
if ( sPtr >= ePtr ) break;\
func( dPtr++, *sPtr++ );\
}\
+ return true; \
}\
- return true;
+ return false;
+_Use_decl_annotations_
bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
- const XMVECTOR* pSource, size_t count )
+ const XMVECTOR* pSource, size_t count, float threshold )
{
assert( pDestination && size > 0 );
#if !defined(_XM_NO_INTRINSICS_)
assert( pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0) );
#endif
- assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format) && !IsCompressed(format) );
+ assert( IsValid(format) && !IsTypeless(format) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format) );
const XMVECTOR* __restrict sPtr = pSource;
if ( !sPtr )
@@ -990,7 +1622,7 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
const XMVECTOR* ePtr = pSource + count;
- switch( format )
+ switch( static_cast<int>(format) )
{
case DXGI_FORMAT_R32G32B32A32_FLOAT:
STORE_SCANLINE( XMFLOAT4, XMStoreFloat4 )
@@ -1011,7 +1643,19 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
STORE_SCANLINE( XMINT3, XMStoreSInt3 )
case DXGI_FORMAT_R16G16B16A16_FLOAT:
- STORE_SCANLINE( XMHALF4, XMStoreHalf4 )
+ if ( size >= sizeof(XMHALF4) )
+ {
+ XMHALF4* __restrict dPtr = reinterpret_cast<XMHALF4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMHALF4) + 1 ); icount += sizeof(XMHALF4) )
+ {
+ if ( sPtr >= ePtr ) break;
+ XMVECTOR v = *sPtr++;
+ v = XMVectorClamp( v, g_HalfMin, g_HalfMax );
+ XMStoreHalf4( dPtr++, v );
+ }
+ return true;
+ }
+ return false;
case DXGI_FORMAT_R16G16B16A16_UNORM:
STORE_SCANLINE( XMUSHORTN4, XMStoreUShortN4 )
@@ -1035,27 +1679,62 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
STORE_SCANLINE( XMINT2, XMStoreSInt2 )
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
- if ( size >= (sizeof(float)+sizeof(uint32_t)) )
{
- float *dPtr = reinterpret_cast<float*>(pDestination);
- for( size_t icount = 0; icount < size; icount += (sizeof(float)+sizeof(uint32_t)) )
+ const size_t psize = sizeof(float)+sizeof(uint32_t);
+ if ( size >= psize )
{
- if ( sPtr >= ePtr ) break;
- XMFLOAT4 f;
- XMStoreFloat4( &f, *sPtr++ );
- dPtr[0] = f.x;
- uint8_t* ps8 = reinterpret_cast<uint8_t*>( &dPtr[1] );
- ps8[0] = static_cast<uint8_t>( std::min<float>( 255.f, std::max<float>( 0.f, f.y ) ) );
- ps8[1] = ps8[2] = ps8[3] = 0;
- dPtr += 2;
+ float *dPtr = reinterpret_cast<float*>(pDestination);
+ for( size_t icount = 0; icount < ( size - psize + 1 ); icount += psize )
+ {
+ if ( sPtr >= ePtr ) break;
+ XMFLOAT4 f;
+ XMStoreFloat4( &f, *sPtr++ );
+ dPtr[0] = f.x;
+ uint8_t* ps8 = reinterpret_cast<uint8_t*>( &dPtr[1] );
+ ps8[0] = static_cast<uint8_t>( std::min<float>( 255.f, std::max<float>( 0.f, f.y ) ) );
+ ps8[1] = ps8[2] = ps8[3] = 0;
+ dPtr += 2;
+ }
+ return true;
}
}
- return true;
+ return false;
case DXGI_FORMAT_R10G10B10A2_UNORM:
- case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
STORE_SCANLINE( XMUDECN4, XMStoreUDecN4 );
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+#if DIRECTX_MATH_VERSION >= 306
+ STORE_SCANLINE( XMUDECN4, XMStoreUDecN4_XR );
+#else
+ if ( size >= sizeof(XMUDECN4) )
+ {
+ static const XMVECTORF32 Scale = { 510.0f, 510.0f, 510.0f, 3.0f };
+ static const XMVECTORF32 Bias = { 384.0f, 384.0f, 384.0f, 0.0f };
+ static const XMVECTORF32 C = { 1023.f, 1023.f, 1023.f, 3.f };
+
+ XMUDECN4 * __restrict dPtr = reinterpret_cast<XMUDECN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUDECN4) + 1 ); icount += sizeof(XMUDECN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMVECTOR N = XMVectorMultiplyAdd( *sPtr++, Scale, Bias );
+ N = XMVectorClamp( N, g_XMZero, C );
+
+ XMFLOAT4A tmp;
+ XMStoreFloat4A(&tmp, N );
+
+ dPtr->v = ((uint32_t)tmp.w << 30)
+ | (((uint32_t)tmp.z & 0x3FF) << 20)
+ | (((uint32_t)tmp.y & 0x3FF) << 10)
+ | (((uint32_t)tmp.x & 0x3FF));
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
+#endif
+
case DXGI_FORMAT_R10G10B10A2_UINT:
STORE_SCANLINE( XMUDEC4, XMStoreUDec4 );
@@ -1064,7 +1743,18 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- STORE_SCANLINE( XMUBYTEN4, XMStoreUByteN4 )
+ if ( size >= sizeof(XMUBYTEN4) )
+ {
+ XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+ XMVECTOR v = XMVectorAdd( *sPtr++, g_8BitBias );
+ XMStoreUByteN4( dPtr++, v );
+ }
+ return true;
+ }
+ return false;
case DXGI_FORMAT_R8G8B8A8_UINT:
STORE_SCANLINE( XMUBYTE4, XMStoreUByte4 )
@@ -1076,7 +1766,19 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
STORE_SCANLINE( XMBYTE4, XMStoreByte4 )
case DXGI_FORMAT_R16G16_FLOAT:
- STORE_SCANLINE( XMHALF2, XMStoreHalf2 )
+ if ( size >= sizeof(XMHALF2) )
+ {
+ XMHALF2* __restrict dPtr = reinterpret_cast<XMHALF2*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMHALF2) + 1 ); icount += sizeof(XMHALF2) )
+ {
+ if ( sPtr >= ePtr ) break;
+ XMVECTOR v = *sPtr++;
+ v = XMVectorClamp( v, g_HalfMin, g_HalfMax );
+ XMStoreHalf2( dPtr++, v );
+ }
+ return true;
+ }
+ return false;
case DXGI_FORMAT_R16G16_UNORM:
STORE_SCANLINE( XMUSHORTN2, XMStoreUShortN2 )
@@ -1095,39 +1797,42 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
if ( size >= sizeof(float) )
{
float * __restrict dPtr = reinterpret_cast<float*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(float) )
+ for( size_t icount = 0; icount < ( size - sizeof(float) + 1 ); icount += sizeof(float) )
{
if ( sPtr >= ePtr ) break;
XMStoreFloat( dPtr++, *(sPtr++) );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R32_UINT:
if ( size >= sizeof(uint32_t) )
{
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(uint32_t) + 1 ); icount += sizeof(uint32_t) )
{
if ( sPtr >= ePtr ) break;
XMVECTOR v = XMConvertVectorFloatToUInt( *(sPtr++), 0 );
XMStoreInt( dPtr++, v );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R32_SINT:
- if ( size >= sizeof(uint32_t) )
+ if ( size >= sizeof(int32_t) )
{
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(int32_t) + 1 ); icount += sizeof(int32_t) )
{
if ( sPtr >= ePtr ) break;
XMVECTOR v = XMConvertVectorFloatToInt( *(sPtr++), 0 );
XMStoreInt( dPtr++, v );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_D24_UNORM_S8_UINT:
if ( size >= sizeof(uint32_t) )
@@ -1135,7 +1840,7 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
static const XMVECTORF32 clamp = { 1.f, 255.f, 0.f, 0.f };
XMVECTOR zero = XMVectorZero();
uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(uint32_t) + 1 ); icount += sizeof(uint32_t) )
{
if ( sPtr >= ePtr ) break;
XMFLOAT4 f;
@@ -1143,8 +1848,9 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
*dPtr++ = (static_cast<uint32_t>( f.x * 16777215.f ) & 0xFFFFFF)
| ((static_cast<uint32_t>( f.y ) & 0xFF) << 24);
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R8G8_UNORM:
STORE_SCANLINE( XMUBYTEN2, XMStoreUByteN2 )
@@ -1162,71 +1868,77 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
if ( size >= sizeof(HALF) )
{
HALF * __restrict dPtr = reinterpret_cast<HALF*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(HALF) )
+ for( size_t icount = 0; icount < ( size - sizeof(HALF) + 1 ); icount += sizeof(HALF) )
{
if ( sPtr >= ePtr ) break;
float v = XMVectorGetX( *sPtr++ );
+ v = std::max<float>( std::min<float>( v, 65504.f ), -65504.f );
*(dPtr++) = XMConvertFloatToHalf(v);
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_D16_UNORM:
case DXGI_FORMAT_R16_UNORM:
- if ( size >= sizeof(int16_t) )
+ if ( size >= sizeof(uint16_t) )
{
- int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
+ uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(uint16_t) + 1 ); icount += sizeof(uint16_t) )
{
if ( sPtr >= ePtr ) break;
float v = XMVectorGetX( *sPtr++ );
v = std::max<float>( std::min<float>( v, 1.f ), 0.f );
*(dPtr++) = static_cast<uint16_t>( v*65535.f + 0.5f );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R16_UINT:
if ( size >= sizeof(uint16_t) )
{
uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(uint16_t) + 1 ); icount += sizeof(uint16_t) )
{
if ( sPtr >= ePtr ) break;
float v = XMVectorGetX( *sPtr++ );
v = std::max<float>( std::min<float>( v, 65535.f ), 0.f );
*(dPtr++) = static_cast<uint16_t>(v);
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R16_SNORM:
if ( size >= sizeof(int16_t) )
{
int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(int16_t) + 1 ); icount += sizeof(int16_t) )
{
if ( sPtr >= ePtr ) break;
float v = XMVectorGetX( *sPtr++ );
v = std::max<float>( std::min<float>( v, 1.f ), -1.f );
- *(dPtr++) = static_cast<uint16_t>( v * 32767.f );
+ *(dPtr++) = static_cast<int16_t>( v * 32767.f );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R16_SINT:
if ( size >= sizeof(int16_t) )
{
int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
+ for( size_t icount = 0; icount < ( size - sizeof(int16_t) + 1 ); icount += sizeof(int16_t) )
{
if ( sPtr >= ePtr ) break;
float v = XMVectorGetX( *sPtr++ );
v = std::max<float>( std::min<float>( v, 32767.f ), -32767.f );
*(dPtr++) = static_cast<int16_t>(v);
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R8_UNORM:
if ( size >= sizeof(uint8_t) )
@@ -1237,10 +1949,11 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
if ( sPtr >= ePtr ) break;
float v = XMVectorGetX( *sPtr++ );
v = std::max<float>( std::min<float>( v, 1.f ), 0.f );
- *(dPtr++) = static_cast<uint8_t>( v * 255.f);
+ *(dPtr++) = static_cast<uint8_t>( v * 255.f );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R8_UINT:
if ( size >= sizeof(uint8_t) )
@@ -1253,36 +1966,39 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
v = std::max<float>( std::min<float>( v, 255.f ), 0.f );
*(dPtr++) = static_cast<uint8_t>(v);
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R8_SNORM:
- if ( size >= sizeof(char) )
+ if ( size >= sizeof(int8_t) )
{
- char * __restrict dPtr = reinterpret_cast<char*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(char) )
+ int8_t * __restrict dPtr = reinterpret_cast<int8_t*>(pDestination);
+ for( size_t icount = 0; icount < size; icount += sizeof(int8_t) )
{
if ( sPtr >= ePtr ) break;
float v = XMVectorGetX( *sPtr++ );
v = std::max<float>( std::min<float>( v, 1.f ), -1.f );
- *(dPtr++) = static_cast<char>( v * 127.f );
+ *(dPtr++) = static_cast<int8_t>( v * 127.f );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R8_SINT:
- if ( size >= sizeof(char) )
+ if ( size >= sizeof(int8_t) )
{
- char * __restrict dPtr = reinterpret_cast<char*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(char) )
+ int8_t * __restrict dPtr = reinterpret_cast<int8_t*>(pDestination);
+ for( size_t icount = 0; icount < size; icount += sizeof(int8_t) )
{
if ( sPtr >= ePtr ) break;
float v = XMVectorGetX( *sPtr++ );
v = std::max<float>( std::min<float>( v, 127.f ), -127.f );
- *(dPtr++) = static_cast<char>( v );
+ *(dPtr++) = static_cast<int8_t>( v );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_A8_UNORM:
if ( size >= sizeof(uint8_t) )
@@ -1295,8 +2011,9 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
v = std::max<float>( std::min<float>( v, 1.f ), 0.f );
*(dPtr++) = static_cast<uint8_t>( v * 255.f);
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R1_UNORM:
if ( size >= sizeof(uint8_t) )
@@ -1305,139 +2022,494 @@ bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
{
uint8_t pixels = 0;
- for( size_t bcount = 0; bcount < 8; ++bcount )
+ for( size_t bcount = 8; bcount > 0; --bcount )
{
if ( sPtr >= ePtr ) break;
float v = XMVectorGetX( *sPtr++ );
- if ( v > 0.5f )
- pixels |= 1 << bcount;
+
+ // Absolute thresholding generally doesn't give good results for all images
+ // Picking the 'right' threshold automatically requires whole-image analysis
+
+ if ( v > 0.25f )
+ pixels |= 1 << (bcount-1);
}
*(dPtr++) = pixels;
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+#if DIRECTX_MATH_VERSION >= 306
STORE_SCANLINE( XMFLOAT3SE, XMStoreFloat3SE )
+#else
+ if ( size >= sizeof(XMFLOAT3SE) )
+ {
+ static const float maxf9 = float(0x1FF << 7);
+ static const float minf9 = float(1.f / (1 << 16));
+
+ XMFLOAT3SE * __restrict dPtr = reinterpret_cast<XMFLOAT3SE*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMFLOAT3SE) + 1 ); icount += sizeof(XMFLOAT3SE) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMFLOAT3 rgb;
+ XMStoreFloat3( &rgb, *(sPtr++) );
+
+ float r = (rgb.x >= 0.f) ? ( (rgb.x > maxf9) ? maxf9 : rgb.x ) : 0.f;
+ float g = (rgb.y >= 0.f) ? ( (rgb.y > maxf9) ? maxf9 : rgb.y ) : 0.f;
+ float b = (rgb.z >= 0.f) ? ( (rgb.z > maxf9) ? maxf9 : rgb.z ) : 0.f;
+
+ const float max_rg = (r > g) ? r : g;
+ const float max_rgb = (max_rg > b) ? max_rg : b;
+
+ const float maxColor = (max_rgb > minf9) ? max_rgb : minf9;
+
+ union { float f; INT32 i; } fi;
+ fi.f = maxColor;
+ fi.i &= 0xFF800000; // cut off fraction
+
+ dPtr->e = (fi.i - 0x37800000) >> 23;
+
+ fi.i = 0x83000000 - fi.i;
+ float ScaleR = fi.f;
+
+ dPtr->xm = static_cast<uint32_t>( round_to_nearest(r * ScaleR) );
+ dPtr->ym = static_cast<uint32_t>( round_to_nearest(g * ScaleR) );
+ dPtr->zm = static_cast<uint32_t>( round_to_nearest(b * ScaleR) );
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
+#endif
case DXGI_FORMAT_R8G8_B8G8_UNORM:
if ( size >= sizeof(XMUBYTEN4) )
{
XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
{
if ( sPtr >= ePtr ) break;
XMVECTOR v0 = *sPtr++;
XMVECTOR v1 = (sPtr < ePtr) ? XMVectorSplatY( *sPtr++ ) : XMVectorZero();
XMVECTOR v = XMVectorSelect( v1, v0, g_XMSelect1110 );
+ v = XMVectorAdd( v, g_8BitBias );
XMStoreUByteN4( dPtr++, v );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_G8R8_G8B8_UNORM:
if ( size >= sizeof(XMUBYTEN4) )
{
- static XMVECTORI32 select1101 = {XM_SELECT_1, XM_SELECT_1, XM_SELECT_0, XM_SELECT_1};
+ static XMVECTORU32 select1101 = {XM_SELECT_1, XM_SELECT_1, XM_SELECT_0, XM_SELECT_1};
XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
{
if ( sPtr >= ePtr ) break;
XMVECTOR v0 = XMVectorSwizzle<1, 0, 3, 2>( *sPtr++ );
XMVECTOR v1 = (sPtr < ePtr) ? XMVectorSplatY( *sPtr++ ) : XMVectorZero();
XMVECTOR v = XMVectorSelect( v1, v0, select1101 );
+ v = XMVectorAdd( v, g_8BitBias );
XMStoreUByteN4( dPtr++, v );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_B5G6R5_UNORM:
if ( size >= sizeof(XMU565) )
{
- static XMVECTORF32 s_Scale = { 31.f, 63.f, 31.f, 1.f };
+ static const XMVECTORF32 s_Scale = { 31.f, 63.f, 31.f, 1.f };
XMU565 * __restrict dPtr = reinterpret_cast<XMU565*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(XMU565) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMU565) + 1 ); icount += sizeof(XMU565) )
{
if ( sPtr >= ePtr ) break;
XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
v = XMVectorMultiply( v, s_Scale );
XMStoreU565( dPtr++, v );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_B5G5R5A1_UNORM:
if ( size >= sizeof(XMU555) )
{
- static XMVECTORF32 s_Scale = { 31.f, 31.f, 31.f, 1.f };
+ static const XMVECTORF32 s_Scale = { 31.f, 31.f, 31.f, 1.f };
XMU555 * __restrict dPtr = reinterpret_cast<XMU555*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(XMU555) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMU555) + 1 ); icount += sizeof(XMU555) )
{
if ( sPtr >= ePtr ) break;
XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
v = XMVectorMultiply( v, s_Scale );
- XMStoreU555( dPtr++, v );
+ XMStoreU555( dPtr, v );
+ dPtr->w = ( XMVectorGetW( v ) > threshold ) ? 1 : 0;
+ ++dPtr;
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
if ( size >= sizeof(XMUBYTEN4) )
{
XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
{
if ( sPtr >= ePtr ) break;
XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
+ v = XMVectorAdd( v, g_8BitBias );
XMStoreUByteN4( dPtr++, v );
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_B8G8R8X8_UNORM:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
if ( size >= sizeof(XMUBYTEN4) )
{
XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
{
if ( sPtr >= ePtr ) break;
XMVECTOR v = XMVectorPermute<2, 1, 0, 7>( *sPtr++, g_XMIdentityR3 );
+ v = XMVectorAdd( v, g_8BitBias );
XMStoreUByteN4( dPtr++, v );
}
+ return true;
}
- return true;
+ return false;
+
+ case DXGI_FORMAT_AYUV:
+ if ( size >= sizeof(XMUBYTEN4) )
+ {
+ XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMUBYTEN4 rgba;
+ XMStoreUByteN4( &rgba, *sPtr++ );
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/dd206750.aspx
+
+ // Y = 0.2568R + 0.5041G + 0.1001B + 16
+ // Cb = -0.1482R - 0.2910G + 0.4392B + 128
+ // Cr = 0.4392R - 0.3678G - 0.0714B + 128
+
+ int y = ( ( 66 * rgba.x + 129 * rgba.y + 25 * rgba.z + 128) >> 8) + 16;
+ int u = ( ( -38 * rgba.x - 74 * rgba.y + 112 * rgba.z + 128) >> 8) + 128;
+ int v = ( ( 112 * rgba.x - 94 * rgba.y - 18 * rgba.z + 128) >> 8) + 128;
+
+ dPtr->x = static_cast<uint8_t>( std::min<int>( std::max<int>( v, 0 ), 255 ) );
+ dPtr->y = static_cast<uint8_t>( std::min<int>( std::max<int>( u, 0 ), 255 ) );
+ dPtr->z = static_cast<uint8_t>( std::min<int>( std::max<int>( y, 0 ), 255 ) );
+ dPtr->w = rgba.w;
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_Y410:
+ if ( size >= sizeof(XMUDECN4) )
+ {
+ XMUDECN4 * __restrict dPtr = reinterpret_cast<XMUDECN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUDECN4) + 1 ); icount += sizeof(XMUDECN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMUDECN4 rgba;
+ XMStoreUDecN4( &rgba, *sPtr++ );
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/bb970578.aspx
+
+ // Y = 0.2560R + 0.5027G + 0.0998B + 64
+ // Cb = -0.1478R - 0.2902G + 0.4379B + 512
+ // Cr = 0.4379R - 0.3667G - 0.0712B + 512
+
+ int64_t r = rgba.x;
+ int64_t g = rgba.y;
+ int64_t b = rgba.z;
+
+ int y = static_cast<int>( ( 16780 * r + 32942 * g + 6544 * b + 32768) >> 16) + 64;
+ int u = static_cast<int>( ( -9683 * r - 19017 * g + 28700 * b + 32768) >> 16) + 512;
+ int v = static_cast<int>( ( 28700 * r - 24033 * g - 4667 * b + 32768) >> 16) + 512;
+
+ dPtr->x = static_cast<uint32_t>( std::min<int>( std::max<int>( u, 0 ), 1023 ) );
+ dPtr->y = static_cast<uint32_t>( std::min<int>( std::max<int>( y, 0 ), 1023 ) );
+ dPtr->z = static_cast<uint32_t>( std::min<int>( std::max<int>( v, 0 ), 1023 ) );
+ dPtr->w = rgba.w;
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_Y416:
+ if ( size >= sizeof(XMUSHORTN4) )
+ {
+ XMUSHORTN4 * __restrict dPtr = reinterpret_cast<XMUSHORTN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUSHORTN4) + 1 ); icount += sizeof(XMUSHORTN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMUSHORTN4 rgba;
+ XMStoreUShortN4( &rgba, *sPtr++ );
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/bb970578.aspx
+
+ // Y = 0.2558R + 0.5022G + 0.0998B + 4096
+ // Cb = -0.1476R - 0.2899G + 0.4375B + 32768
+ // Cr = 0.4375R - 0.3664G - 0.0711B + 32768
+
+ int64_t r = int64_t(rgba.x);
+ int64_t g = int64_t(rgba.y);
+ int64_t b = int64_t(rgba.z);
+
+ int y = static_cast<int>( ( 16763 * r + 32910 * g + 6537 * b + 32768) >> 16) + 4096;
+ int u = static_cast<int>( ( -9674 * r - 18998 * g + 28672 * b + 32768) >> 16) + 32768;
+ int v = static_cast<int>( ( 28672 * r - 24010 * g - 4662 * b + 32768) >> 16) + 32768;
+
+ dPtr->x = static_cast<uint16_t>( std::min<int>( std::max<int>( u, 0 ), 65535 ) );
+ dPtr->y = static_cast<uint16_t>( std::min<int>( std::max<int>( y, 0 ), 65535 ) );
+ dPtr->z = static_cast<uint16_t>( std::min<int>( std::max<int>( v, 0 ), 65535 ) );
+ dPtr->w = rgba.w;
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_YUY2:
+ if ( size >= sizeof(XMUBYTEN4) )
+ {
+ XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUBYTEN4) + 1 ); icount += sizeof(XMUBYTEN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMUBYTEN4 rgb1;
+ XMStoreUByteN4( &rgb1, *sPtr++ );
+
+ // See AYUV
+ int y0 = ( ( 66 * rgb1.x + 129 * rgb1.y + 25 * rgb1.z + 128) >> 8) + 16;
+ int u0 = ( ( -38 * rgb1.x - 74 * rgb1.y + 112 * rgb1.z + 128) >> 8) + 128;
+ int v0 = ( ( 112 * rgb1.x - 94 * rgb1.y - 18 * rgb1.z + 128) >> 8) + 128;
+
+ XMUBYTEN4 rgb2;
+ if(sPtr < ePtr)
+ {
+ XMStoreUByteN4( &rgb2, *sPtr++ );
+ }
+ else
+ {
+ rgb2.x = rgb2.y = rgb2.z = rgb2.w = 0;
+ }
+
+ int y1 = ( ( 66 * rgb2.x + 129 * rgb2.y + 25 * rgb2.z + 128) >> 8) + 16;
+ int u1 = ( ( -38 * rgb2.x - 74 * rgb2.y + 112 * rgb2.z + 128) >> 8) + 128;
+ int v1 = ( ( 112 * rgb2.x - 94 * rgb2.y - 18 * rgb2.z + 128) >> 8) + 128;
+
+ dPtr->x = static_cast<uint8_t>( std::min<int>( std::max<int>( y0, 0 ), 255 ) );
+ dPtr->y = static_cast<uint8_t>( std::min<int>( std::max<int>( (u0 + u1) >> 1, 0 ), 255 ) );
+ dPtr->z = static_cast<uint8_t>( std::min<int>( std::max<int>( y1, 0 ), 255 ) );
+ dPtr->w = static_cast<uint8_t>( std::min<int>( std::max<int>( (v0 + v1) >> 1, 0 ), 255 ) );
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_Y210:
+ // Same as Y216 with least significant 6 bits set to zero
+ if ( size >= sizeof(XMUSHORTN4) )
+ {
+ XMUSHORTN4 * __restrict dPtr = reinterpret_cast<XMUSHORTN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUSHORTN4) + 1 ); icount += sizeof(XMUSHORTN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMUDECN4 rgb1;
+ XMStoreUDecN4( &rgb1, *sPtr++ );
+
+ // See Y410
+ int64_t r = rgb1.x;
+ int64_t g = rgb1.y;
+ int64_t b = rgb1.z;
+
+ int y0 = static_cast<int>( ( 16780 * r + 32942 * g + 6544 * b + 32768) >> 16) + 64;
+ int u0 = static_cast<int>( ( -9683 * r - 19017 * g + 28700 * b + 32768) >> 16) + 512;
+ int v0 = static_cast<int>( ( 28700 * r - 24033 * g - 4667 * b + 32768) >> 16) + 512;
+
+ XMUDECN4 rgb2;
+ if(sPtr < ePtr)
+ {
+ XMStoreUDecN4( &rgb2, *sPtr++ );
+ }
+ else
+ {
+ rgb2.x = rgb2.y = rgb2.z = rgb2.w = 0;
+ }
+
+ r = rgb2.x;
+ g = rgb2.y;
+ b = rgb2.z;
+
+ int y1 = static_cast<int>( ( 16780 * r + 32942 * g + 6544 * b + 32768) >> 16) + 64;
+ int u1 = static_cast<int>( ( -9683 * r - 19017 * g + 28700 * b + 32768) >> 16) + 512;
+ int v1 = static_cast<int>( ( 28700 * r - 24033 * g - 4667 * b + 32768) >> 16) + 512;
+
+ dPtr->x = static_cast<uint16_t>( std::min<int>( std::max<int>( y0, 0 ), 1023 ) << 6 );
+ dPtr->y = static_cast<uint16_t>( std::min<int>( std::max<int>( (u0 + u1) >> 1, 0 ), 1023 ) << 6 );
+ dPtr->z = static_cast<uint16_t>( std::min<int>( std::max<int>( y1, 0 ), 1023 ) << 6 );
+ dPtr->w = static_cast<uint16_t>( std::min<int>( std::max<int>( (v0 + v1) >> 1, 0 ), 1023 ) << 6 );
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_Y216:
+ if ( size >= sizeof(XMUSHORTN4) )
+ {
+ XMUSHORTN4 * __restrict dPtr = reinterpret_cast<XMUSHORTN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUSHORTN4) + 1 ); icount += sizeof(XMUSHORTN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMUSHORTN4 rgb1;
+ XMStoreUShortN4( &rgb1, *sPtr++ );
+
+ // See Y416
+ int64_t r = int64_t(rgb1.x);
+ int64_t g = int64_t(rgb1.y);
+ int64_t b = int64_t(rgb1.z);
+
+ int y0 = static_cast<int>( ( 16763 * r + 32910 * g + 6537 * b + 32768) >> 16) + 4096;
+ int u0 = static_cast<int>( (-9674 * r - 18998 * g + 28672 * b + 32768) >> 16) + 32768;
+ int v0 = static_cast<int>( ( 28672 * r - 24010 * g - 4662 * b + 32768) >> 16) + 32768;
+
+ XMUSHORTN4 rgb2;
+ if(sPtr < ePtr)
+ {
+ XMStoreUShortN4( &rgb2, *sPtr++ );
+ }
+ else
+ {
+ rgb2.x = rgb2.y = rgb2.z = rgb2.w = 0;
+ }
+
+ r = int64_t(rgb2.x);
+ g = int64_t(rgb2.y);
+ b = int64_t(rgb2.z);
+
+ int y1 = static_cast<int>( ( 16763 * r + 32910 * g + 6537 * b + 32768) >> 16) + 4096;
+ int u1 = static_cast<int>( (-9674 * r - 18998 * g + 28672 * b + 32768) >> 16) + 32768;
+ int v1 = static_cast<int>( ( 28672 * r - 24010 * g - 4662 * b + 32768) >> 16) + 32768;
+
+ dPtr->x = static_cast<uint16_t>( std::min<int>( std::max<int>( y0, 0 ), 65535 ) );
+ dPtr->y = static_cast<uint16_t>( std::min<int>( std::max<int>( (u0 + u1) >> 1, 0 ), 65535 ) );
+ dPtr->z = static_cast<uint16_t>( std::min<int>( std::max<int>( y1, 0 ), 65535 ) );
+ dPtr->w = static_cast<uint16_t>( std::min<int>( std::max<int>( (v0 + v1) >> 1, 0 ), 65535 ) );
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
-#ifdef DXGI_1_2_FORMATS
case DXGI_FORMAT_B4G4R4A4_UNORM:
if ( size >= sizeof(XMUNIBBLE4) )
{
- static XMVECTORF32 s_Scale = { 15.f, 15.f, 15.f, 15.f };
+ static const XMVECTORF32 s_Scale = { 15.f, 15.f, 15.f, 15.f };
XMUNIBBLE4 * __restrict dPtr = reinterpret_cast<XMUNIBBLE4*>(pDestination);
- for( size_t icount = 0; icount < size; icount += sizeof(XMUNIBBLE4) )
+ for( size_t icount = 0; icount < ( size - sizeof(XMUNIBBLE4) + 1 ); icount += sizeof(XMUNIBBLE4) )
{
if ( sPtr >= ePtr ) break;
XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
v = XMVectorMultiply( v, s_Scale );
XMStoreUNibble4( dPtr++, v );
}
+ return true;
}
- return true;
+ return false;
+
+ case 116 /* DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT */:
+ // Xbox One specific 7e3 format with alpha
+ if ( size >= sizeof(XMUDECN4) )
+ {
+ static const XMVECTORF32 Scale = { 1.0f, 1.0f, 1.0f, 3.0f };
+ static const XMVECTORF32 C = { 31.875f, 31.875f, 31.875f, 3.f };
+
+ XMUDECN4 * __restrict dPtr = reinterpret_cast<XMUDECN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUDECN4) + 1 ); icount += sizeof(XMUDECN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMVECTOR V = XMVectorMultiply( *sPtr++, Scale );
+ V = XMVectorClamp( V, g_XMZero, C );
- // We don't support the video formats ( see IsVideo function )
-#endif // DXGI_1_2_FORMATS
+ XMFLOAT4A tmp;
+ XMStoreFloat4A( &tmp, V );
+
+ dPtr->x = FloatTo7e3( tmp.x );
+ dPtr->y = FloatTo7e3( tmp.y );
+ dPtr->z = FloatTo7e3( tmp.z );
+ dPtr->w = (uint32_t)tmp.w;
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
+
+ case 117 /* DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT */:
+ // Xbox One specific 6e4 format with alpha
+ if ( size >= sizeof(XMUDECN4) )
+ {
+ static const XMVECTORF32 Scale = { 1.0f, 1.0f, 1.0f, 3.0f };
+ static const XMVECTORF32 C = { 508.f, 508.f, 508.f, 3.f };
+
+ XMUDECN4 * __restrict dPtr = reinterpret_cast<XMUDECN4*>(pDestination);
+ for( size_t icount = 0; icount < ( size - sizeof(XMUDECN4) + 1 ); icount += sizeof(XMUDECN4) )
+ {
+ if ( sPtr >= ePtr ) break;
+
+ XMVECTOR V = XMVectorMultiply( *sPtr++, Scale );
+ V = XMVectorClamp( V, g_XMZero, C );
+
+ XMFLOAT4A tmp;
+ XMStoreFloat4A( &tmp, V );
+
+ dPtr->x = FloatTo6e4( tmp.x );
+ dPtr->y = FloatTo6e4( tmp.y );
+ dPtr->z = FloatTo6e4( tmp.z );
+ dPtr->w = (uint32_t)tmp.w;
+ ++dPtr;
+ }
+ return true;
+ }
+ return false;
+
+ // We don't support the planar or palettized formats
default:
return false;
}
}
+#undef STORE_SCANLINE
+
//-------------------------------------------------------------------------------------
// Convert DXGI image to/from GUID_WICPixelFormat128bppRGBAFloat (no range conversions)
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT _ConvertToR32G32B32A32( const Image& srcImage, ScratchImage& image )
{
if ( !srcImage.pixels )
@@ -1477,7 +2549,8 @@ HRESULT _ConvertToR32G32B32A32( const Image& srcImage, ScratchImage& image )
return S_OK;
}
-HRESULT _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ const Image& destImage )
+_Use_decl_annotations_
+HRESULT _ConvertFromR32G32B32A32( const Image& srcImage, const Image& destImage )
{
assert( srcImage.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
@@ -1502,6 +2575,7 @@ HRESULT _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ const Image&
return S_OK;
}
+_Use_decl_annotations_
HRESULT _ConvertFromR32G32B32A32( const Image& srcImage, DXGI_FORMAT format, ScratchImage& image )
{
if ( !srcImage.pixels )
@@ -1528,6 +2602,7 @@ HRESULT _ConvertFromR32G32B32A32( const Image& srcImage, DXGI_FORMAT format, Scr
return S_OK;
}
+_Use_decl_annotations_
HRESULT _ConvertFromR32G32B32A32( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, ScratchImage& result )
{
if ( !srcImages )
@@ -1596,128 +2671,181 @@ HRESULT _ConvertFromR32G32B32A32( const Image* srcImages, size_t nimages, const
//-------------------------------------------------------------------------------------
-// RGB -> sRGB
+// Convert from Linear RGB to sRGB
+//
+// if C_linear <= 0.0031308 -> C_srgb = 12.92 * C_linear
+// if C_linear > 0.0031308 -> C_srgb = ( 1 + a ) * pow( C_Linear, 1 / 2.4 ) - a
+// where a = 0.055
//-------------------------------------------------------------------------------------
-static const uint32_t g_fEncodeGamma22[] =
+#if DIRECTX_MATH_VERSION < 306
+static inline XMVECTOR XMColorRGBToSRGB( FXMVECTOR rgb )
{
- 0x00000000, 0x3bd56bd3, 0x3c486344, 0x3c90da15, 0x3cbc2677, 0x3ce67704, 0x3d080183, 0x3d1c7728,
- 0x3d30a8fb, 0x3d44a03c, 0x3d586400, 0x3d6bf9e7, 0x3d7f6679, 0x3d8956bd, 0x3d92e906, 0x3d9c6b70,
- 0x3da5df22, 0x3daf451b, 0x3db89e3e, 0x3dc1eb50, 0x3dcb2d04, 0x3dd463f7, 0x3ddd90b9, 0x3de6b3ca,
- 0x3defcda0, 0x3df8dea6, 0x3e00f3a0, 0x3e0573e3, 0x3e09f046, 0x3e0e68f0, 0x3e12de06, 0x3e174fa6,
- 0x3e1bbdf2, 0x3e202906, 0x3e2490fd, 0x3e28f5f1, 0x3e2d57fb, 0x3e31b72f, 0x3e3613a4, 0x3e3a6d6e,
- 0x3e3ec4a0, 0x3e43194d, 0x3e476b84, 0x3e4bbb57, 0x3e5008d7, 0x3e54540f, 0x3e589d0f, 0x3e5ce3e5,
- 0x3e61289d, 0x3e656b44, 0x3e69abe5, 0x3e6dea8d, 0x3e722745, 0x3e766217, 0x3e7a9b0e, 0x3e7ed235,
- 0x3e8183c9, 0x3e839d98, 0x3e85b68c, 0x3e87cea8, 0x3e89e5f2, 0x3e8bfc6b, 0x3e8e1219, 0x3e9026ff,
- 0x3e923b20, 0x3e944e7f, 0x3e966120, 0x3e987307, 0x3e9a8436, 0x3e9c94af, 0x3e9ea476, 0x3ea0b38e,
- 0x3ea2c1fb, 0x3ea4cfbb, 0x3ea6dcd5, 0x3ea8e94a, 0x3eaaf51c, 0x3ead004e, 0x3eaf0ae2, 0x3eb114d9,
- 0x3eb31e37, 0x3eb526fe, 0x3eb72f2f, 0x3eb936cd, 0x3ebb3dd8, 0x3ebd4454, 0x3ebf4a43, 0x3ec14fa5,
- 0x3ec3547e, 0x3ec558cd, 0x3ec75c95, 0x3ec95fd8, 0x3ecb6297, 0x3ecd64d4, 0x3ecf6690, 0x3ed167ce,
- 0x3ed3688e, 0x3ed568d1, 0x3ed76899, 0x3ed967e9, 0x3edb66bf, 0x3edd651f, 0x3edf630a, 0x3ee16080,
- 0x3ee35d84, 0x3ee55a16, 0x3ee75636, 0x3ee951e8, 0x3eeb4d2a, 0x3eed4800, 0x3eef4269, 0x3ef13c68,
- 0x3ef335fc, 0x3ef52f26, 0x3ef727ea, 0x3ef92046, 0x3efb183c, 0x3efd0fcd, 0x3eff06fa, 0x3f007ee2,
- 0x3f017a16, 0x3f027519, 0x3f036fec, 0x3f046a8f, 0x3f056502, 0x3f065f47, 0x3f07595d, 0x3f085344,
- 0x3f094cfe, 0x3f0a468b, 0x3f0b3feb, 0x3f0c391e, 0x3f0d3224, 0x3f0e2aff, 0x3f0f23af, 0x3f101c32,
- 0x3f11148c, 0x3f120cba, 0x3f1304bf, 0x3f13fc9a, 0x3f14f44b, 0x3f15ebd3, 0x3f16e333, 0x3f17da6b,
- 0x3f18d17a, 0x3f19c860, 0x3f1abf1f, 0x3f1bb5b7, 0x3f1cac28, 0x3f1da272, 0x3f1e9895, 0x3f1f8e92,
- 0x3f20846a, 0x3f217a1c, 0x3f226fa8, 0x3f23650f, 0x3f245a52, 0x3f254f70, 0x3f264469, 0x3f27393f,
- 0x3f282df1, 0x3f29227f, 0x3f2a16ea, 0x3f2b0b31, 0x3f2bff56, 0x3f2cf358, 0x3f2de738, 0x3f2edaf6,
- 0x3f2fce91, 0x3f30c20b, 0x3f31b564, 0x3f32a89b, 0x3f339bb1, 0x3f348ea6, 0x3f35817a, 0x3f36742f,
- 0x3f3766c3, 0x3f385936, 0x3f394b8a, 0x3f3a3dbe, 0x3f3b2fd3, 0x3f3c21c8, 0x3f3d139e, 0x3f3e0556,
- 0x3f3ef6ee, 0x3f3fe868, 0x3f40d9c4, 0x3f41cb01, 0x3f42bc20, 0x3f43ad22, 0x3f449e06, 0x3f458ecc,
- 0x3f467f75, 0x3f477001, 0x3f486071, 0x3f4950c2, 0x3f4a40f8, 0x3f4b3111, 0x3f4c210d, 0x3f4d10ed,
- 0x3f4e00b2, 0x3f4ef05a, 0x3f4fdfe7, 0x3f50cf58, 0x3f51beae, 0x3f52ade8, 0x3f539d07, 0x3f548c0c,
- 0x3f557af5, 0x3f5669c4, 0x3f575878, 0x3f584711, 0x3f593590, 0x3f5a23f6, 0x3f5b1241, 0x3f5c0072,
- 0x3f5cee89, 0x3f5ddc87, 0x3f5eca6b, 0x3f5fb835, 0x3f60a5e7, 0x3f619380, 0x3f6280ff, 0x3f636e65,
- 0x3f645bb3, 0x3f6548e8, 0x3f663604, 0x3f672309, 0x3f680ff4, 0x3f68fcc8, 0x3f69e983, 0x3f6ad627,
- 0x3f6bc2b3, 0x3f6caf27, 0x3f6d9b83, 0x3f6e87c8, 0x3f6f73f5, 0x3f70600c, 0x3f714c0b, 0x3f7237f4,
- 0x3f7323c4, 0x3f740f7f, 0x3f74fb22, 0x3f75e6af, 0x3f76d225, 0x3f77bd85, 0x3f78a8ce, 0x3f799401,
- 0x3f7a7f1e, 0x3f7b6a25, 0x3f7c5516, 0x3f7d3ff1, 0x3f7e2ab6, 0x3f7f1566, 0x3f800000, 0x3f800000
-};
+ static const XMVECTORF32 Cutoff = { 0.0031308f, 0.0031308f, 0.0031308f, 1.f };
+ static const XMVECTORF32 Linear = { 12.92f, 12.92f, 12.92f, 1.f };
+ static const XMVECTORF32 Scale = { 1.055f, 1.055f, 1.055f, 1.f };
+ static const XMVECTORF32 Bias = { 0.055f, 0.055f, 0.055f, 0.f };
+ static const XMVECTORF32 InvGamma = { 1.0f/2.4f, 1.0f/2.4f, 1.0f/2.4f, 1.f };
+
+ XMVECTOR V = XMVectorSaturate(rgb);
+ XMVECTOR V0 = XMVectorMultiply( V, Linear );
+ XMVECTOR V1 = Scale * XMVectorPow( V, InvGamma ) - Bias;
+ XMVECTOR select = XMVectorLess( V, Cutoff );
+ V = XMVectorSelect( V1, V0, select );
+ return XMVectorSelect( rgb, V, g_XMSelect1110 );
+}
+#endif
-#pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
-static inline XMVECTOR _TableEncodeGamma22( FXMVECTOR v )
+_Use_decl_annotations_
+bool _StoreScanlineLinear( LPVOID pDestination, size_t size, DXGI_FORMAT format,
+ XMVECTOR* pSource, size_t count, DWORD flags, float threshold )
{
- float f[4];
- XMStoreFloat4( (XMFLOAT4*)f, v );
+ assert( pDestination && size > 0 );
+ assert( pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0) );
+ assert( IsValid(format) && !IsTypeless(format) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format) );
- for( size_t i=0; i < 4; ++i )
+ switch ( format )
{
- float f2 = sqrtf(f[i]) * 254.0f;
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ flags |= TEX_FILTER_SRGB;
+ break;
- uint32_t i2 = static_cast<uint32_t>(f2);
- i2 = std::min<uint32_t>( i2, _countof( g_fEncodeGamma22 )-2 );
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ break;
- float fS = f2 - (float) i2;
- float fA = ((float *) g_fEncodeGamma22)[i2];
- float fB = ((float *) g_fEncodeGamma22)[i2 + 1];
+ default:
+ // can't treat A8, XR, Depth, SNORM, UINT, or SINT as sRGB
+ flags &= ~TEX_FILTER_SRGB;
+ break;
+ }
- f[i] = fA + fS * (fB - fA);
+ // sRGB output processing (Linear RGB -> sRGB)
+ if ( flags & TEX_FILTER_SRGB_OUT )
+ {
+ // To avoid the need for another temporary scanline buffer, we allow this function to overwrite the source buffer in-place
+ // Given the intended usage in the filtering routines, this is not a problem.
+ XMVECTOR* ptr = pSource;
+ for( size_t i=0; i < count; ++i, ++ptr )
+ {
+ *ptr = XMColorRGBToSRGB( *ptr );
+ }
}
- return XMLoadFloat4( (XMFLOAT4*)f );
+ return _StoreScanline( pDestination, size, format, pSource, count, threshold );
}
//-------------------------------------------------------------------------------------
-// sRGB -> RGB
+// Convert from sRGB to Linear RGB
+//
+// if C_srgb <= 0.04045 -> C_linear = C_srgb / 12.92
+// if C_srgb > 0.04045 -> C_linear = pow( ( C_srgb + a ) / ( 1 + a ), 2.4 )
+// where a = 0.055
//-------------------------------------------------------------------------------------
-static const uint32_t g_fDecodeGamma22[] =
+#if DIRECTX_MATH_VERSION < 306
+static inline XMVECTOR XMColorSRGBToRGB( FXMVECTOR srgb )
{
- 0x00000000, 0x3b144eb0, 0x3b9ef3b0, 0x3bf84b42, 0x3c2a5c46, 0x3c59c180, 0x3c850eb5, 0x3c9da52a,
- 0x3cb6967a, 0x3ccfd852, 0x3ce9628b, 0x3d01974b, 0x3d0e9b82, 0x3d1bbba3, 0x3d28f5bc, 0x3d364822,
- 0x3d43b159, 0x3d51301d, 0x3d5ec344, 0x3d6c69c9, 0x3d7a22c4, 0x3d83f6ad, 0x3d8ae465, 0x3d91da35,
- 0x3d98d7c7, 0x3d9fdcd2, 0x3da6e914, 0x3dadfc47, 0x3db51635, 0x3dbc36a3, 0x3dc35d62, 0x3dca8a3a,
- 0x3dd1bd02, 0x3dd8f591, 0x3de033bb, 0x3de7775d, 0x3deec050, 0x3df60e74, 0x3dfd61a6, 0x3e025ce5,
- 0x3e060b61, 0x3e09bc38, 0x3e0d6f5f, 0x3e1124c8, 0x3e14dc68, 0x3e189630, 0x3e1c521a, 0x3e201016,
- 0x3e23d01d, 0x3e279225, 0x3e2b5624, 0x3e2f1c10, 0x3e32e3e4, 0x3e36ad94, 0x3e3a7918, 0x3e3e4668,
- 0x3e42157f, 0x3e45e654, 0x3e49b8e0, 0x3e4d8d1d, 0x3e516304, 0x3e553a8d, 0x3e5913b4, 0x3e5cee70,
- 0x3e60cabf, 0x3e64a89b, 0x3e6887fb, 0x3e6c68db, 0x3e704b3a, 0x3e742f0e, 0x3e781454, 0x3e7bfb04,
- 0x3e7fe321, 0x3e81e650, 0x3e83dbc0, 0x3e85d1dc, 0x3e87c8a3, 0x3e89c015, 0x3e8bb830, 0x3e8db0ee,
- 0x3e8faa51, 0x3e91a454, 0x3e939ef9, 0x3e959a3b, 0x3e97961b, 0x3e999295, 0x3e9b8fa7, 0x3e9d8d52,
- 0x3e9f8b93, 0x3ea18a6a, 0x3ea389d2, 0x3ea589cb, 0x3ea78a56, 0x3ea98b6e, 0x3eab8d15, 0x3ead8f47,
- 0x3eaf9204, 0x3eb1954a, 0x3eb39917, 0x3eb59d6c, 0x3eb7a246, 0x3eb9a7a5, 0x3ebbad88, 0x3ebdb3ec,
- 0x3ebfbad3, 0x3ec1c237, 0x3ec3ca1a, 0x3ec5d27c, 0x3ec7db58, 0x3ec9e4b4, 0x3ecbee85, 0x3ecdf8d3,
- 0x3ed0039a, 0x3ed20ed8, 0x3ed41a8a, 0x3ed626b5, 0x3ed83351, 0x3eda4065, 0x3edc4de9, 0x3ede5be0,
- 0x3ee06a4a, 0x3ee27923, 0x3ee4886a, 0x3ee69821, 0x3ee8a845, 0x3eeab8d8, 0x3eecc9d6, 0x3eeedb3f,
- 0x3ef0ed13, 0x3ef2ff53, 0x3ef511fb, 0x3ef7250a, 0x3ef93883, 0x3efb4c61, 0x3efd60a7, 0x3eff7553,
- 0x3f00c531, 0x3f01cfeb, 0x3f02dad9, 0x3f03e5f5, 0x3f04f145, 0x3f05fcc4, 0x3f070875, 0x3f081456,
- 0x3f092067, 0x3f0a2ca8, 0x3f0b3917, 0x3f0c45b7, 0x3f0d5284, 0x3f0e5f7f, 0x3f0f6caa, 0x3f107a03,
- 0x3f118789, 0x3f12953b, 0x3f13a31d, 0x3f14b12b, 0x3f15bf64, 0x3f16cdca, 0x3f17dc5e, 0x3f18eb1b,
- 0x3f19fa05, 0x3f1b091b, 0x3f1c185c, 0x3f1d27c7, 0x3f1e375c, 0x3f1f471d, 0x3f205707, 0x3f21671b,
- 0x3f227759, 0x3f2387c2, 0x3f249852, 0x3f25a90c, 0x3f26b9ef, 0x3f27cafb, 0x3f28dc30, 0x3f29ed8b,
- 0x3f2aff11, 0x3f2c10bd, 0x3f2d2290, 0x3f2e348b, 0x3f2f46ad, 0x3f3058f7, 0x3f316b66, 0x3f327dfd,
- 0x3f3390ba, 0x3f34a39d, 0x3f35b6a7, 0x3f36c9d6, 0x3f37dd2b, 0x3f38f0a5, 0x3f3a0443, 0x3f3b1808,
- 0x3f3c2bf2, 0x3f3d4000, 0x3f3e5434, 0x3f3f688c, 0x3f407d07, 0x3f4191a8, 0x3f42a66c, 0x3f43bb54,
- 0x3f44d05f, 0x3f45e58e, 0x3f46fadf, 0x3f481054, 0x3f4925ed, 0x3f4a3ba8, 0x3f4b5186, 0x3f4c6789,
- 0x3f4d7daa, 0x3f4e93f0, 0x3f4faa57, 0x3f50c0e0, 0x3f51d78b, 0x3f52ee58, 0x3f540545, 0x3f551c55,
- 0x3f563386, 0x3f574ad7, 0x3f58624b, 0x3f5979de, 0x3f5a9191, 0x3f5ba965, 0x3f5cc15b, 0x3f5dd971,
- 0x3f5ef1a6, 0x3f6009fc, 0x3f612272, 0x3f623b08, 0x3f6353bc, 0x3f646c90, 0x3f658586, 0x3f669e98,
- 0x3f67b7cb, 0x3f68d11b, 0x3f69ea8d, 0x3f6b041b, 0x3f6c1dc9, 0x3f6d3795, 0x3f6e5180, 0x3f6f6b8b,
- 0x3f7085b2, 0x3f719ff7, 0x3f72ba5b, 0x3f73d4dc, 0x3f74ef7c, 0x3f760a38, 0x3f772512, 0x3f78400b,
- 0x3f795b20, 0x3f7a7651, 0x3f7b91a2, 0x3f7cad0e, 0x3f7dc896, 0x3f7ee43c, 0x3f800000, 0x3f800000
-};
-
+ static const XMVECTORF32 Cutoff = { 0.04045f, 0.04045f, 0.04045f, 1.f };
+ static const XMVECTORF32 ILinear = { 1.f/12.92f, 1.f/12.92f, 1.f/12.92f, 1.f };
+ static const XMVECTORF32 Scale = { 1.f/1.055f, 1.f/1.055f, 1.f/1.055f, 1.f };
+ static const XMVECTORF32 Bias = { 0.055f, 0.055f, 0.055f, 0.f };
+ static const XMVECTORF32 Gamma = { 2.4f, 2.4f, 2.4f, 1.f };
+
+ XMVECTOR V = XMVectorSaturate(srgb);
+ XMVECTOR V0 = XMVectorMultiply( V, ILinear );
+ XMVECTOR V1 = XMVectorPow( (V + Bias) * Scale, Gamma );
+ XMVECTOR select = XMVectorGreater( V, Cutoff );
+ V = XMVectorSelect( V0, V1, select );
+ return XMVectorSelect( srgb, V, g_XMSelect1110 );
+}
+#endif
-#pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
-static inline XMVECTOR _TableDecodeGamma22( FXMVECTOR v )
+_Use_decl_annotations_
+bool _LoadScanlineLinear( XMVECTOR* pDestination, size_t count,
+ LPCVOID pSource, size_t size, DXGI_FORMAT format, DWORD flags )
{
- float f[4];
- XMStoreFloat4( (XMFLOAT4*)f, v );
+ assert( pDestination && count > 0 && (((uintptr_t)pDestination & 0xF) == 0) );
+ assert( pSource && size > 0 );
+ assert( IsValid(format) && !IsTypeless(format,false) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format) );
- for( size_t i=0; i < 4; ++i )
+ switch ( format )
{
- float f2 = f[i] * f[i] * 254.0f;
- uint32_t i2 = static_cast<uint32_t>(f2);
- i2 = std::min<uint32_t>( i2, _countof(g_fDecodeGamma22)-2 );
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ flags |= TEX_FILTER_SRGB;
+ break;
- float fS = f2 - (float) i2;
- float fA = ((float *) g_fDecodeGamma22)[i2];
- float fB = ((float *) g_fDecodeGamma22)[i2 + 1];
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ break;
- f[i] = fA + fS * (fB - fA);
+ default:
+ // can't treat A8, XR, Depth, SNORM, UINT, or SINT as sRGB
+ flags &= ~TEX_FILTER_SRGB;
+ break;
}
- return XMLoadFloat4( (XMFLOAT4*)f );
+ if ( _LoadScanline( pDestination, count, pSource, size, format ) )
+ {
+ // sRGB input processing (sRGB -> Linear RGB)
+ if ( flags & TEX_FILTER_SRGB_IN )
+ {
+ XMVECTOR* ptr = pDestination;
+ for( size_t i=0; i < count; ++i, ++ptr )
+ {
+ *ptr = XMColorSRGBToRGB( *ptr );
+ }
+ }
+
+ return true;
+ }
+
+ return false;
}
@@ -1798,16 +2926,24 @@ static const ConvertData g_ConvertTable[] = {
{ DXGI_FORMAT_B5G5R5A1_UNORM, 5, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
{ DXGI_FORMAT_B8G8R8A8_UNORM, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
{ DXGI_FORMAT_B8G8R8X8_UNORM, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B },
- { DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, 10, CONVF_UNORM | CONVF_X2 | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
+ { DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, 10, CONVF_UNORM | CONVF_XR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
{ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
{ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B },
{ DXGI_FORMAT_BC6H_UF16, 16, CONVF_FLOAT | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
{ DXGI_FORMAT_BC6H_SF16, 16, CONVF_FLOAT | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
{ DXGI_FORMAT_BC7_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
{ DXGI_FORMAT_BC7_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
-#ifdef DXGI_1_2_FORMATS
+ { DXGI_FORMAT_AYUV, 8, CONVF_UNORM | CONVF_YUV | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
+ { DXGI_FORMAT_Y410, 10, CONVF_UNORM | CONVF_YUV | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
+ { DXGI_FORMAT_Y416, 16, CONVF_UNORM | CONVF_YUV | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
+ { DXGI_FORMAT_YUY2, 8, CONVF_UNORM | CONVF_YUV | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B },
+ { DXGI_FORMAT_Y210, 10, CONVF_UNORM | CONVF_YUV | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B },
+ { DXGI_FORMAT_Y216, 16, CONVF_UNORM | CONVF_YUV | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B },
{ DXGI_FORMAT_B4G4R4A4_UNORM, 4, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
-#endif
+ { DXGI_FORMAT(116)
+ /* DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT */, 10, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
+ { DXGI_FORMAT(117)
+ /* DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT */, 10, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
};
#pragma prefast( suppress : 25004, "Signature must match bsearch" );
@@ -1819,6 +2955,7 @@ static int __cdecl _ConvertCompare( const void* ptr1, const void *ptr2 )
else return (p1->format < p2->format ) ? -1 : 1;
}
+_Use_decl_annotations_
DWORD _GetConvertFlags( DXGI_FORMAT format )
{
#ifdef _DEBUG
@@ -1838,13 +2975,14 @@ DWORD _GetConvertFlags( DXGI_FORMAT format )
return (in) ? in->flags : 0;
}
+_Use_decl_annotations_
void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, DXGI_FORMAT inFormat, DWORD flags )
{
#if !defined(_XM_NO_INTRINSICS_)
assert( pBuffer && count > 0 && (((uintptr_t)pBuffer & 0xF) == 0) );
#endif
- assert( IsValid(outFormat) && !IsVideo(outFormat) && !IsTypeless(outFormat) );
- assert( IsValid(inFormat) && !IsVideo(inFormat) && !IsTypeless(inFormat) );
+ assert( IsValid(outFormat) && !IsTypeless(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat) );
+ assert( IsValid(inFormat) && !IsTypeless(inFormat) && !IsPlanar(inFormat) && !IsPalettized(inFormat) );
if ( !pBuffer )
return;
@@ -1877,44 +3015,332 @@ void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, D
assert( _GetConvertFlags( outFormat ) == out->flags );
// Handle SRGB filtering modes
- if ( IsSRGB( inFormat ) )
+ switch ( inFormat )
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
flags |= TEX_FILTER_SRGB_IN;
+ break;
- if ( IsSRGB( outFormat ) )
- flags |= TEX_FILTER_SRGB_OUT;
-
- if ( in->flags & CONVF_SNORM )
+ case DXGI_FORMAT_A8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
flags &= ~TEX_FILTER_SRGB_IN;
+ break;
+ }
+
+ switch ( outFormat )
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ flags |= TEX_FILTER_SRGB_OUT;
+ break;
- if ( out->flags & CONVF_SNORM )
+ case DXGI_FORMAT_A8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
flags &= ~TEX_FILTER_SRGB_OUT;
+ break;
+ }
if ( (flags & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
{
flags &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
}
- // sRGB input processing (sRGB -> RGB)
+ // sRGB input processing (sRGB -> Linear RGB)
if ( flags & TEX_FILTER_SRGB_IN )
{
- if ( (in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM) )
+ if ( !(in->flags & CONVF_DEPTH) && ( (in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM) ) )
{
XMVECTOR* ptr = pBuffer;
- for( size_t i=0; i < count; ++i )
+ for( size_t i=0; i < count; ++i, ++ptr )
{
- // rgb = rgb^(2.2); a=a
- XMVECTOR v = *ptr;
- XMVECTOR v1 = _TableDecodeGamma22( v );
- *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
+ *ptr = XMColorSRGBToRGB( *ptr );
}
}
}
// Handle conversion special cases
DWORD diffFlags = in->flags ^ out->flags;
- if ( diffFlags != 0)
+ if ( diffFlags != 0 )
{
- if ( out->flags & CONVF_UNORM )
+ static const XMVECTORF32 s_two = { 2.0f, 2.0f, 2.0f, 2.0f };
+
+ if ( diffFlags & CONVF_DEPTH )
+ {
+ if ( in->flags & CONVF_DEPTH )
+ {
+ // CONVF_DEPTH -> !CONVF_DEPTH
+ if ( in->flags & CONVF_STENCIL )
+ {
+ // Stencil -> Alpha
+ static const XMVECTORF32 S = { 1.f, 1.f, 1.f, 255.f };
+
+ if( out->flags & CONVF_UNORM )
+ {
+ // UINT -> UNORM
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatY( v );
+ v1 = XMVectorClamp( v1, g_XMZero, S );
+ v1 = XMVectorDivide( v1, S );
+ v = XMVectorSelect( v1, v, g_XMSelect1110 );
+ *ptr++ = v;
+ }
+ }
+ else if ( out->flags & CONVF_SNORM )
+ {
+ // UINT -> SNORM
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatY( v );
+ v1 = XMVectorClamp( v1, g_XMZero, S );
+ v1 = XMVectorDivide( v1, S );
+ v1 = XMVectorMultiplyAdd( v1, s_two, g_XMNegativeOne );
+ v = XMVectorSelect( v1, v, g_XMSelect1110 );
+ *ptr++ = v;
+ }
+ }
+ else
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatY( v );
+ v = XMVectorSelect( v1, v, g_XMSelect1110 );
+ *ptr++ = v;
+ }
+ }
+ }
+
+ // Depth -> RGB
+ if ( ( out->flags & CONVF_UNORM ) && ( in->flags & CONVF_FLOAT ) )
+ {
+ // Depth FLOAT -> UNORM
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSaturate( v );
+ v1 = XMVectorSplatX( v1 );
+ v = XMVectorSelect( v, v1, g_XMSelect1110 );
+ *ptr++ = v;
+ }
+ }
+ else if ( out->flags & CONVF_SNORM )
+ {
+ if ( in->flags & CONVF_UNORM )
+ {
+ // Depth UNORM -> SNORM
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorMultiplyAdd( v, s_two, g_XMNegativeOne );
+ v1 = XMVectorSplatX( v1 );
+ v = XMVectorSelect( v, v1, g_XMSelect1110 );
+ *ptr++ = v;
+ }
+ }
+ else
+ {
+ // Depth FLOAT -> SNORM
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorClamp( v, g_XMNegativeOne, g_XMOne );
+ v1 = XMVectorSplatX( v1 );
+ v = XMVectorSelect( v, v1, g_XMSelect1110 );
+ *ptr++ = v;
+ }
+ }
+ }
+ else
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatX( v );
+ v = XMVectorSelect( v, v1, g_XMSelect1110 );
+ *ptr++ = v;
+ }
+ }
+ }
+ else
+ {
+ // !CONVF_DEPTH -> CONVF_DEPTH
+
+ // RGB -> Depth (red channel)
+ switch( flags & ( TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE ) )
+ {
+ case TEX_FILTER_RGB_COPY_GREEN:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatY( v );
+ v = XMVectorSelect( v, v1, g_XMSelect1000 );
+ *ptr++ = v;
+ }
+ }
+ break;
+
+ case TEX_FILTER_RGB_COPY_BLUE:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatZ( v );
+ v = XMVectorSelect( v, v1, g_XMSelect1000 );
+ *ptr++ = v;
+ }
+ }
+ break;
+
+ default:
+ if ( (in->flags & CONVF_UNORM) && ( (in->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G|CONVF_B) ) )
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVector3Dot( v, g_Grayscale );
+ v = XMVectorSelect( v, v1, g_XMSelect1000 );
+ *ptr++ = v;
+ }
+ break;
+ }
+
+ // fall-through
+
+ case TEX_FILTER_RGB_COPY_RED:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatX( v );
+ v = XMVectorSelect( v, v1, g_XMSelect1000 );
+ *ptr++ = v;
+ }
+ }
+ break;
+ }
+
+ // Finialize type conversion for depth (red channel)
+ if ( out->flags & CONVF_UNORM )
+ {
+ if ( in->flags & CONVF_SNORM )
+ {
+ // SNORM -> UNORM
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorMultiplyAdd( v, g_XMOneHalf, g_XMOneHalf );
+ v = XMVectorSelect( v, v1, g_XMSelect1000 );
+ *ptr++ = v;
+ }
+ }
+ else if ( in->flags & CONVF_FLOAT )
+ {
+ // FLOAT -> UNORM
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSaturate( v );
+ v = XMVectorSelect( v, v1, g_XMSelect1000 );
+ *ptr++ = v;
+ }
+ }
+ }
+
+ if ( out->flags & CONVF_STENCIL )
+ {
+ // Alpha -> Stencil (green channel)
+ static const XMVECTORU32 select0100 = { XM_SELECT_0, XM_SELECT_1, XM_SELECT_0, XM_SELECT_0 };
+ static const XMVECTORF32 S = { 255.f, 255.f, 255.f, 255.f };
+
+ if ( in->flags & CONVF_UNORM )
+ {
+ // UNORM -> UINT
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorMultiply( v, S );
+ v1 = XMVectorSplatW( v1 );
+ v = XMVectorSelect( v, v1, select0100 );
+ *ptr++ = v;
+ }
+ }
+ else if ( in->flags & CONVF_SNORM )
+ {
+ // SNORM -> UINT
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorMultiplyAdd( v, g_XMOneHalf, g_XMOneHalf );
+ v1 = XMVectorMultiply( v1, S );
+ v1 = XMVectorSplatW( v1 );
+ v = XMVectorSelect( v, v1, select0100 );
+ *ptr++ = v;
+ }
+ }
+ else
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatW( v );
+ v = XMVectorSelect( v, v1, select0100 );
+ *ptr++ = v;
+ }
+ }
+ }
+ }
+ }
+ else if ( out->flags & CONVF_DEPTH )
+ {
+ // CONVF_DEPTH -> CONVF_DEPTH
+ if ( diffFlags & CONVF_FLOAT )
+ {
+ if ( in->flags & CONVF_FLOAT )
+ {
+ // FLOAT -> UNORM depth, preserve stencil
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSaturate( v );
+ v = XMVectorSelect( v, v1, g_XMSelect1000 );
+ *ptr++ = v;
+ }
+ }
+ }
+ }
+ else if ( out->flags & CONVF_UNORM )
{
if ( in->flags & CONVF_SNORM )
{
@@ -1942,12 +3368,11 @@ void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, D
if ( in->flags & CONVF_UNORM )
{
// UNORM -> SNORM
- static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
XMVECTOR* ptr = pBuffer;
for( size_t i=0; i < count; ++i )
{
XMVECTOR v = *ptr;
- *ptr++ = XMVectorMultiplyAdd( v, two, g_XMNegativeOne );
+ *ptr++ = XMVectorMultiplyAdd( v, s_two, g_XMNegativeOne );
}
}
else if ( in->flags & CONVF_FLOAT )
@@ -1969,11 +3394,54 @@ void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, D
if ( ((out->flags & CONVF_RGBA_MASK) == CONVF_A) && !(in->flags & CONVF_A) )
{
// !CONVF_A -> A format
- XMVECTOR* ptr = pBuffer;
- for( size_t i=0; i < count; ++i )
+ switch( flags & ( TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE ) )
{
- XMVECTOR v = *ptr;
- *ptr++ = XMVectorSplatX( v );
+ case TEX_FILTER_RGB_COPY_GREEN:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ *ptr++ = XMVectorSplatY( v );
+ }
+ }
+ break;
+
+ case TEX_FILTER_RGB_COPY_BLUE:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ *ptr++ = XMVectorSplatZ( v );
+ }
+ }
+ break;
+
+ default:
+ if ( (in->flags & CONVF_UNORM) && ( (in->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G|CONVF_B) ) )
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ *ptr++ = XMVector3Dot( v, g_Grayscale );
+ }
+ break;
+ }
+
+ // fall-through
+
+ case TEX_FILTER_RGB_COPY_RED:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ *ptr++ = XMVectorSplatX( v );
+ }
+ }
+ break;
}
}
else if ( ((in->flags & CONVF_RGBA_MASK) == CONVF_A) && !(out->flags & CONVF_A) )
@@ -1986,31 +3454,129 @@ void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, D
*ptr++ = XMVectorSplatW( v );
}
}
- else if ( ((in->flags & CONVF_RGB_MASK) == CONVF_R) && ((out->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G|CONVF_B)) )
+ else if ( (in->flags & CONVF_RGB_MASK) == CONVF_R )
{
- // R format -> RGB format
- XMVECTOR* ptr = pBuffer;
- for( size_t i=0; i < count; ++i )
+ if ( (out->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G|CONVF_B) )
{
- XMVECTOR v = *ptr;
- XMVECTOR v1 = XMVectorSplatX( v );
- *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
+ // R format -> RGB format
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatX( v );
+ *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
+ }
+ }
+ else if ( (out->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G) )
+ {
+ // R format -> RG format
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatX( v );
+ *ptr++ = XMVectorSelect( v, v1, g_XMSelect1100 );
+ }
+ }
+ }
+ else if ( (in->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G|CONVF_B) )
+ {
+ if ( (out->flags & CONVF_RGB_MASK) == CONVF_R )
+ {
+ // RGB format -> R format
+ switch( flags & ( TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE ) )
+ {
+ case TEX_FILTER_RGB_COPY_GREEN:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatY( v );
+ *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
+ }
+ }
+ break;
+
+ case TEX_FILTER_RGB_COPY_BLUE:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSplatZ( v );
+ *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
+ }
+ }
+ break;
+
+ default:
+ if ( in->flags & CONVF_UNORM )
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVector3Dot( v, g_Grayscale );
+ *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
+ }
+ break;
+ }
+
+ // fall-through
+
+ case TEX_FILTER_RGB_COPY_RED:
+ // Leave data unchanged and the store will handle this...
+ break;
+ }
+ }
+ else if ( (out->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G) )
+ {
+ // RGB format -> RG format
+ switch( flags & ( TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE ) )
+ {
+ case TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_BLUE:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSwizzle<0,2,0,2>( v );
+ *ptr++ = XMVectorSelect( v, v1, g_XMSelect1100 );
+ }
+ }
+ break;
+
+ case TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE:
+ {
+ XMVECTOR* ptr = pBuffer;
+ for( size_t i=0; i < count; ++i )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR v1 = XMVectorSwizzle<1,2,3,0>( v );
+ *ptr++ = XMVectorSelect( v, v1, g_XMSelect1100 );
+ }
+ }
+ break;
+
+ case TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN:
+ default:
+ // Leave data unchanged and the store will handle this...
+ break;
+ }
}
}
}
- // sRGB output processing (RGB -> sRGB)
+ // sRGB output processing (Linear RGB -> sRGB)
if ( flags & TEX_FILTER_SRGB_OUT )
{
- if ( (out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM) )
+ if ( !(out->flags & CONVF_DEPTH) && ( (out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM) ) )
{
XMVECTOR* ptr = pBuffer;
- for( size_t i=0; i < count; ++i )
+ for( size_t i=0; i < count; ++i, ++ptr )
{
- // rgb = rgb^(1/2.2); a=a
- XMVECTOR v = *ptr;
- XMVECTOR v1 = _TableEncodeGamma22( v );
- *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
+ *ptr = XMColorRGBToSRGB( *ptr );
}
}
}
@@ -2018,129 +3584,706 @@ void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, D
//-------------------------------------------------------------------------------------
-// Convert the source image using WIC
+// Dithering
//-------------------------------------------------------------------------------------
-static HRESULT _ConvertUsingWIC( _In_ const Image& srcImage, _In_ const WICPixelFormatGUID& pfGUID,
- _In_ const WICPixelFormatGUID& targetGUID,
- _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
+
+// 4X4X4 ordered dithering matrix
+static const float g_Dither[] =
{
- assert( srcImage.width == destImage.width );
- assert( srcImage.height == destImage.height );
+ // (z & 3) + ( (y & 3) * 8) + (x & 3)
+ 0.468750f, -0.031250f, 0.343750f, -0.156250f, 0.468750f, -0.031250f, 0.343750f, -0.156250f,
+ -0.281250f, 0.218750f, -0.406250f, 0.093750f, -0.281250f, 0.218750f, -0.406250f, 0.093750f,
+ 0.281250f, -0.218750f, 0.406250f, -0.093750f, 0.281250f, -0.218750f, 0.406250f, -0.093750f,
+ -0.468750f, 0.031250f, -0.343750f, 0.156250f, -0.468750f, 0.031250f, -0.343750f, 0.156250f,
+};
- IWICImagingFactory* pWIC = _GetWIC();
- if ( !pWIC )
- return E_NOINTERFACE;
+static const XMVECTORF32 g_Scale16pc = { 65535.f, 65535.f, 65535.f, 65535.f };
+static const XMVECTORF32 g_Scale15pc = { 32767.f, 32767.f, 32767.f, 32767.f };
+static const XMVECTORF32 g_Scale10pc = { 1023.f, 1023.f, 1023.f, 3.f };
+static const XMVECTORF32 g_Scale8pc = { 255.f, 255.f, 255.f, 255.f };
+static const XMVECTORF32 g_Scale7pc = { 127.f, 127.f, 127.f, 127.f };
+static const XMVECTORF32 g_Scale565pc = { 31.f, 63.f, 31.f, 1.f };
+static const XMVECTORF32 g_Scale5551pc = { 31.f, 31.f, 31.f, 1.f };
+static const XMVECTORF32 g_Scale4pc = { 15.f, 15.f, 15.f, 15.f };
+
+static const XMVECTORF32 g_ErrorWeight3 = { 3.f/16.f, 3.f/16.f, 3.f/16.f, 3.f/16.f };
+static const XMVECTORF32 g_ErrorWeight5 = { 5.f/16.f, 5.f/16.f, 5.f/16.f, 5.f/16.f };
+static const XMVECTORF32 g_ErrorWeight1 = { 1.f/16.f, 1.f/16.f, 1.f/16.f, 1.f/16.f };
+static const XMVECTORF32 g_ErrorWeight7 = { 7.f/16.f, 7.f/16.f, 7.f/16.f, 7.f/16.f };
+
+#define STORE_SCANLINE( type, scalev, clampzero, norm, itype, mask, row, bgr ) \
+ if ( size >= sizeof(type) ) \
+ { \
+ type * __restrict dest = reinterpret_cast<type*>(pDestination); \
+ for( size_t i = 0; i < count; ++i ) \
+ { \
+ ptrdiff_t index = static_cast<ptrdiff_t>( ( row & 1 ) ? ( count - i - 1 ) : i ); \
+ ptrdiff_t delta = ( row & 1 ) ? -2 : 0; \
+ \
+ XMVECTOR v = sPtr[ index ]; \
+ if ( bgr ) { v = XMVectorSwizzle<2, 1, 0, 3>( v ); } \
+ if ( norm && clampzero ) v = XMVectorSaturate( v ) ; \
+ else if ( clampzero ) v = XMVectorClamp( v, g_XMZero, scalev ); \
+ else if ( norm ) v = XMVectorClamp( v, g_XMNegativeOne, g_XMOne ); \
+ else v = XMVectorClamp( v, -scalev + g_XMOne, scalev ); \
+ v = XMVectorAdd( v, vError ); \
+ if ( norm ) v = XMVectorMultiply( v, scalev ); \
+ \
+ XMVECTOR target; \
+ if ( pDiffusionErrors ) \
+ { \
+ target = XMVectorRound( v ); \
+ vError = XMVectorSubtract( v, target ); \
+ if (norm) vError = XMVectorDivide( vError, scalev ); \
+ \
+ /* Distribute error to next scanline and next pixel */ \
+ pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError ); \
+ pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError ); \
+ pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError ); \
+ vError = XMVectorMultiply( vError, g_ErrorWeight7 ); \
+ } \
+ else \
+ { \
+ /* Applied ordered dither */ \
+ target = XMVectorAdd( v, ordered[ index & 3 ] ); \
+ target = XMVectorRound( target ); \
+ } \
+ \
+ target = XMVectorMin( scalev, target ); \
+ target = XMVectorMax( (clampzero) ? g_XMZero : ( -scalev + g_XMOne ), target ); \
+ \
+ XMFLOAT4A tmp; \
+ XMStoreFloat4A( &tmp, target ); \
+ \
+ auto dPtr = &dest[ index ]; \
+ dPtr->x = static_cast<itype>( tmp.x ) & mask; \
+ dPtr->y = static_cast<itype>( tmp.y ) & mask; \
+ dPtr->z = static_cast<itype>( tmp.z ) & mask; \
+ dPtr->w = static_cast<itype>( tmp.w ) & mask; \
+ } \
+ return true; \
+ } \
+ return false;
- ScopedObject<IWICFormatConverter> FC;
- HRESULT hr = pWIC->CreateFormatConverter( &FC );
- if ( FAILED(hr) )
- return hr;
+#define STORE_SCANLINE2( type, scalev, clampzero, norm, itype, mask, row ) \
+ /* The 2 component cases are always bgr=false */ \
+ if ( size >= sizeof(type) ) \
+ { \
+ type * __restrict dest = reinterpret_cast<type*>(pDestination); \
+ for( size_t i = 0; i < count; ++i ) \
+ { \
+ ptrdiff_t index = static_cast<ptrdiff_t>( ( row & 1 ) ? ( count - i - 1 ) : i ); \
+ ptrdiff_t delta = ( row & 1 ) ? -2 : 0; \
+ \
+ XMVECTOR v = sPtr[ index ]; \
+ if ( norm && clampzero ) v = XMVectorSaturate( v ) ; \
+ else if ( clampzero ) v = XMVectorClamp( v, g_XMZero, scalev ); \
+ else if ( norm ) v = XMVectorClamp( v, g_XMNegativeOne, g_XMOne ); \
+ else v = XMVectorClamp( v, -scalev + g_XMOne, scalev ); \
+ v = XMVectorAdd( v, vError ); \
+ if ( norm ) v = XMVectorMultiply( v, scalev ); \
+ \
+ XMVECTOR target; \
+ if ( pDiffusionErrors ) \
+ { \
+ target = XMVectorRound( v ); \
+ vError = XMVectorSubtract( v, target ); \
+ if (norm) vError = XMVectorDivide( vError, scalev ); \
+ \
+ /* Distribute error to next scanline and next pixel */ \
+ pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError ); \
+ pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError ); \
+ pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError ); \
+ vError = XMVectorMultiply( vError, g_ErrorWeight7 ); \
+ } \
+ else \
+ { \
+ /* Applied ordered dither */ \
+ target = XMVectorAdd( v, ordered[ index & 3 ] ); \
+ target = XMVectorRound( target ); \
+ } \
+ \
+ target = XMVectorMin( scalev, target ); \
+ target = XMVectorMax( (clampzero) ? g_XMZero : ( -scalev + g_XMOne ), target ); \
+ \
+ XMFLOAT4A tmp; \
+ XMStoreFloat4A( &tmp, target ); \
+ \
+ auto dPtr = &dest[ index ]; \
+ dPtr->x = static_cast<itype>( tmp.x ) & mask; \
+ dPtr->y = static_cast<itype>( tmp.y ) & mask; \
+ } \
+ return true; \
+ } \
+ return false;
- // Need to implement usage of TEX_FILTER_SRGB_IN/TEX_FILTER_SRGB_OUT
+#define STORE_SCANLINE1( type, scalev, clampzero, norm, mask, row, selectw ) \
+ /* The 1 component cases are always bgr=false */ \
+ if ( size >= sizeof(type) ) \
+ { \
+ type * __restrict dest = reinterpret_cast<type*>(pDestination); \
+ for( size_t i = 0; i < count; ++i ) \
+ { \
+ ptrdiff_t index = static_cast<ptrdiff_t>( ( row & 1 ) ? ( count - i - 1 ) : i ); \
+ ptrdiff_t delta = ( row & 1 ) ? -2 : 0; \
+ \
+ XMVECTOR v = sPtr[ index ]; \
+ if ( norm && clampzero ) v = XMVectorSaturate( v ) ; \
+ else if ( clampzero ) v = XMVectorClamp( v, g_XMZero, scalev ); \
+ else if ( norm ) v = XMVectorClamp( v, g_XMNegativeOne, g_XMOne ); \
+ else v = XMVectorClamp( v, -scalev + g_XMOne, scalev ); \
+ v = XMVectorAdd( v, vError ); \
+ if ( norm ) v = XMVectorMultiply( v, scalev ); \
+ \
+ XMVECTOR target; \
+ if ( pDiffusionErrors ) \
+ { \
+ target = XMVectorRound( v ); \
+ vError = XMVectorSubtract( v, target ); \
+ if (norm) vError = XMVectorDivide( vError, scalev ); \
+ \
+ /* Distribute error to next scanline and next pixel */ \
+ pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError ); \
+ pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError ); \
+ pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError ); \
+ vError = XMVectorMultiply( vError, g_ErrorWeight7 ); \
+ } \
+ else \
+ { \
+ /* Applied ordered dither */ \
+ target = XMVectorAdd( v, ordered[ index & 3 ] ); \
+ target = XMVectorRound( target ); \
+ } \
+ \
+ target = XMVectorMin( scalev, target ); \
+ target = XMVectorMax( (clampzero) ? g_XMZero : ( -scalev + g_XMOne ), target ); \
+ \
+ dest[ index ] = static_cast<type>( (selectw) ? XMVectorGetW( target ) : XMVectorGetX( target ) ) & mask; \
+ } \
+ return true; \
+ } \
+ return false;
- BOOL canConvert = FALSE;
- hr = FC->CanConvert( pfGUID, targetGUID, &canConvert );
- if ( FAILED(hr) || !canConvert )
+#pragma warning(push)
+#pragma warning( disable : 4127 )
+
+_Use_decl_annotations_
+bool _StoreScanlineDither( LPVOID pDestination, size_t size, DXGI_FORMAT format,
+ XMVECTOR* pSource, size_t count, float threshold, size_t y, size_t z, XMVECTOR* pDiffusionErrors )
+{
+ assert( pDestination && size > 0 );
+ assert( pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0) );
+ assert( IsValid(format) && !IsTypeless(format) && !IsCompressed(format) && !IsPlanar(format) && !IsPalettized(format) );
+
+ XMVECTOR ordered[4];
+ if ( pDiffusionErrors )
{
- // This case is not an issue for the subset of WIC formats that map directly to DXGI
- return E_UNEXPECTED;
+ // If pDiffusionErrors != 0, then this function performs error diffusion dithering (aka Floyd-Steinberg dithering)
+
+ // To avoid the need for another temporary scanline buffer, we allow this function to overwrite the source buffer in-place
+ // Given the intended usage in the conversion routines, this is not a problem.
+
+ XMVECTOR* ptr = pSource;
+ const XMVECTOR* err = pDiffusionErrors + 1;
+ for( size_t i=0; i < count; ++i )
+ {
+ // Add contribution from previous scanline
+ XMVECTOR v = XMVectorAdd( *ptr, *err++ );
+ *ptr++ = v;
+ }
+
+ // Reset errors for next scanline
+ memset( pDiffusionErrors, 0, sizeof(XMVECTOR)*(count+2) );
}
+ else
+ {
+ // If pDiffusionErrors == 0, then this function performs ordered dithering
- ScopedObject<IWICBitmap> source;
- hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
- static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
- srcImage.pixels, &source );
- if ( FAILED(hr) )
- return hr;
+ XMVECTOR dither = XMLoadFloat4( reinterpret_cast<const XMFLOAT4*>( g_Dither + (z & 3) + ( (y & 3) * 8 ) ) );
- hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
- if ( FAILED(hr) )
- return hr;
+ ordered[0] = XMVectorSplatX( dither );
+ ordered[1] = XMVectorSplatY( dither );
+ ordered[2] = XMVectorSplatZ( dither );
+ ordered[3] = XMVectorSplatW( dither );
+ }
- hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
- if ( FAILED(hr) )
- return hr;
+ const XMVECTOR* __restrict sPtr = pSource;
+ if ( !sPtr )
+ return false;
- return S_OK;
+ XMVECTOR vError = XMVectorZero();
+
+ switch( format )
+ {
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ STORE_SCANLINE( XMUSHORTN4, g_Scale16pc, true, true, uint16_t, 0xFFFF, y, false )
+
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ STORE_SCANLINE( XMUSHORT4, g_Scale16pc, true, false, uint16_t, 0xFFFF, y, false )
+
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ STORE_SCANLINE( XMSHORTN4, g_Scale15pc, false, true, int16_t, 0xFFFF, y, false )
+
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ STORE_SCANLINE( XMSHORT4, g_Scale15pc, false, false, int16_t, 0xFFFF, y, false )
+
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ STORE_SCANLINE( XMUDECN4, g_Scale10pc, true, true, uint16_t, 0x3FF, y, false )
+
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ STORE_SCANLINE( XMUDEC4, g_Scale10pc, true, false, uint16_t, 0x3FF, y, false )
+
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ if ( size >= sizeof(XMUDEC4) )
+ {
+ static const XMVECTORF32 Scale = { 510.0f, 510.0f, 510.0f, 3.0f };
+ static const XMVECTORF32 Bias = { 384.0f, 384.0f, 384.0f, 0.0f };
+ static const XMVECTORF32 MinXR = { -0.7529f, -0.7529f, -0.7529f, 0.f };
+ static const XMVECTORF32 MaxXR = { 1.2529f, 1.2529f, 1.2529f, 1.0f };
+
+ XMUDEC4 * __restrict dest = reinterpret_cast<XMUDEC4*>(pDestination);
+ for( size_t i = 0; i < count; ++i )
+ {
+ ptrdiff_t index = static_cast<ptrdiff_t>( ( y & 1 ) ? ( count - i - 1 ) : i );
+ ptrdiff_t delta = ( y & 1 ) ? -2 : 0;
+
+ XMVECTOR v = XMVectorClamp( sPtr[ index ], MinXR, MaxXR );
+ v = XMVectorMultiplyAdd( v, Scale, vError );
+
+ XMVECTOR target;
+ if ( pDiffusionErrors )
+ {
+ target = XMVectorRound( v );
+ vError = XMVectorSubtract( v, target );
+ vError = XMVectorDivide( vError, Scale );
+
+ // Distribute error to next scanline and next pixel
+ pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError );
+ pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError );
+ pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError );
+ vError = XMVectorMultiply( vError, g_ErrorWeight7 );
+ }
+ else
+ {
+ // Applied ordered dither
+ target = XMVectorAdd( v, ordered[ index & 3 ] );
+ target = XMVectorRound( target );
+ }
+
+ target = XMVectorAdd( target, Bias );
+ target = XMVectorClamp( target, g_XMZero, g_Scale10pc );
+
+ XMFLOAT4A tmp;
+ XMStoreFloat4A( &tmp, target );
+
+ auto dPtr = &dest[ index ];
+ dPtr->x = static_cast<uint16_t>( tmp.x ) & 0x3FF;
+ dPtr->y = static_cast<uint16_t>( tmp.y ) & 0x3FF;
+ dPtr->z = static_cast<uint16_t>( tmp.z ) & 0x3FF;
+ dPtr->w = static_cast<uint16_t>( tmp.w );
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ STORE_SCANLINE( XMUBYTEN4, g_Scale8pc, true, true, uint8_t, 0xFF, y, false )
+
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ STORE_SCANLINE( XMUBYTE4, g_Scale8pc, true, false, uint8_t, 0xFF, y, false )
+
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ STORE_SCANLINE( XMBYTEN4, g_Scale7pc, false, true, int8_t, 0xFF, y, false )
+
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ STORE_SCANLINE( XMBYTE4, g_Scale7pc, false, false, int8_t, 0xFF, y, false )
+
+ case DXGI_FORMAT_R16G16_UNORM:
+ STORE_SCANLINE2( XMUSHORTN2, g_Scale16pc, true, true, uint16_t, 0xFFFF, y )
+
+ case DXGI_FORMAT_R16G16_UINT:
+ STORE_SCANLINE2( XMUSHORT2, g_Scale16pc, true, false, uint16_t, 0xFFFF, y )
+
+ case DXGI_FORMAT_R16G16_SNORM:
+ STORE_SCANLINE2( XMSHORTN2, g_Scale15pc, false, true, int16_t, 0xFFFF, y )
+
+ case DXGI_FORMAT_R16G16_SINT:
+ STORE_SCANLINE2( XMSHORT2, g_Scale15pc, false, false, int16_t, 0xFFFF, y )
+
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ if ( size >= sizeof(uint32_t) )
+ {
+ static const XMVECTORF32 Clamp = { 1.f, 255.f, 0.f, 0.f };
+ static const XMVECTORF32 Scale = { 16777215.f, 1.f, 0.f, 0.f };
+ static const XMVECTORF32 Scale2 = { 16777215.f, 255.f, 0.f, 0.f };
+
+ uint32_t * __restrict dest = reinterpret_cast<uint32_t*>(pDestination);
+ for( size_t i = 0; i < count; ++i )
+ {
+ ptrdiff_t index = static_cast<ptrdiff_t>( ( y & 1 ) ? ( count - i - 1 ) : i );
+ ptrdiff_t delta = ( y & 1 ) ? -2 : 0;
+
+ XMVECTOR v = XMVectorClamp( sPtr[ index ], g_XMZero, Clamp );
+ v = XMVectorAdd( v, vError );
+ v = XMVectorMultiply( v, Scale );
+
+ XMVECTOR target;
+ if ( pDiffusionErrors )
+ {
+ target = XMVectorRound( v );
+ vError = XMVectorSubtract( v, target );
+ vError = XMVectorDivide( vError, Scale );
+
+ // Distribute error to next scanline and next pixel
+ pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError );
+ pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError );
+ pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError );
+ vError = XMVectorMultiply( vError, g_ErrorWeight7 );
+ }
+ else
+ {
+ // Applied ordered dither
+ target = XMVectorAdd( v, ordered[ index & 3 ] );
+ target = XMVectorRound( target );
+ }
+
+ target = XMVectorClamp( target, g_XMZero, Scale2 );
+
+ XMFLOAT4A tmp;
+ XMStoreFloat4A( &tmp, target );
+
+ auto dPtr = &dest[ index ];
+ *dPtr = (static_cast<uint32_t>( tmp.x ) & 0xFFFFFF)
+ | ((static_cast<uint32_t>( tmp.y ) & 0xFF) << 24);
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_R8G8_UNORM:
+ STORE_SCANLINE2( XMUBYTEN2, g_Scale8pc, true, true, uint8_t, 0xFF, y )
+
+ case DXGI_FORMAT_R8G8_UINT:
+ STORE_SCANLINE2( XMUBYTE2, g_Scale8pc, true, false, uint8_t, 0xFF, y )
+
+ case DXGI_FORMAT_R8G8_SNORM:
+ STORE_SCANLINE2( XMBYTEN2, g_Scale7pc, false, true, int8_t, 0xFF, y )
+
+ case DXGI_FORMAT_R8G8_SINT:
+ STORE_SCANLINE2( XMBYTE2, g_Scale7pc, false, false, int8_t, 0xFF, y )
+
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ STORE_SCANLINE1( uint16_t, g_Scale16pc, true, true, 0xFFFF, y, false )
+
+ case DXGI_FORMAT_R16_UINT:
+ STORE_SCANLINE1( uint16_t, g_Scale16pc, true, false, 0xFFFF, y, false )
+
+ case DXGI_FORMAT_R16_SNORM:
+ STORE_SCANLINE1( int16_t, g_Scale15pc, false, true, 0xFFFF, y, false )
+
+ case DXGI_FORMAT_R16_SINT:
+ STORE_SCANLINE1( int16_t, g_Scale15pc, false, false, 0xFFFF, y, false )
+
+ case DXGI_FORMAT_R8_UNORM:
+ STORE_SCANLINE1( uint8_t, g_Scale8pc, true, true, 0xFF, y, false )
+
+ case DXGI_FORMAT_R8_UINT:
+ STORE_SCANLINE1( uint8_t, g_Scale8pc, true, false, 0xFF, y, false )
+
+ case DXGI_FORMAT_R8_SNORM:
+ STORE_SCANLINE1( int8_t, g_Scale7pc, false, true, 0xFF, y, false )
+
+ case DXGI_FORMAT_R8_SINT:
+ STORE_SCANLINE1( int8_t, g_Scale7pc, false, false, 0xFF, y, false )
+
+ case DXGI_FORMAT_A8_UNORM:
+ STORE_SCANLINE1( uint8_t, g_Scale8pc, true, true, 0xFF, y, true )
+
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ if ( size >= sizeof(XMU565) )
+ {
+ XMU565 * __restrict dest = reinterpret_cast<XMU565*>(pDestination);
+ for( size_t i = 0; i < count; ++i )
+ {
+ ptrdiff_t index = static_cast<ptrdiff_t>( ( y & 1 ) ? ( count - i - 1 ) : i );
+ ptrdiff_t delta = ( y & 1 ) ? -2 : 0;
+
+ XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( sPtr[ index ] );
+ v = XMVectorSaturate( v );
+ v = XMVectorAdd( v, vError );
+ v = XMVectorMultiply( v, g_Scale565pc );
+
+ XMVECTOR target;
+ if ( pDiffusionErrors )
+ {
+ target = XMVectorRound( v );
+ vError = XMVectorSubtract( v, target );
+ vError = XMVectorDivide( vError, g_Scale565pc );
+
+ // Distribute error to next scanline and next pixel
+ pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError );
+ pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError );
+ pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError );
+ vError = XMVectorMultiply( vError, g_ErrorWeight7 );
+ }
+ else
+ {
+ // Applied ordered dither
+ target = XMVectorAdd( v, ordered[ index & 3 ] );
+ target = XMVectorRound( target );
+ }
+
+ target = XMVectorClamp( target, g_XMZero, g_Scale565pc );
+
+ XMFLOAT4A tmp;
+ XMStoreFloat4A( &tmp, target );
+
+ auto dPtr = &dest[ index ];
+ dPtr->x = static_cast<uint16_t>( tmp.x ) & 0x1F;
+ dPtr->y = static_cast<uint16_t>( tmp.y ) & 0x3F;
+ dPtr->z = static_cast<uint16_t>( tmp.z ) & 0x1F;
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ if ( size >= sizeof(XMU555) )
+ {
+ XMU555 * __restrict dest = reinterpret_cast<XMU555*>(pDestination);
+ for( size_t i = 0; i < count; ++i )
+ {
+ ptrdiff_t index = static_cast<ptrdiff_t>( ( y & 1 ) ? ( count - i - 1 ) : i );
+ ptrdiff_t delta = ( y & 1 ) ? -2 : 0;
+
+ XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( sPtr[ index ] );
+ v = XMVectorSaturate( v );
+ v = XMVectorAdd( v, vError );
+ v = XMVectorMultiply( v, g_Scale5551pc );
+
+ XMVECTOR target;
+ if ( pDiffusionErrors )
+ {
+ target = XMVectorRound( v );
+ vError = XMVectorSubtract( v, target );
+ vError = XMVectorDivide( vError, g_Scale5551pc );
+
+ // Distribute error to next scanline and next pixel
+ pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError );
+ pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError );
+ pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError );
+ vError = XMVectorMultiply( vError, g_ErrorWeight7 );
+ }
+ else
+ {
+ // Applied ordered dither
+ target = XMVectorAdd( v, ordered[ index & 3 ] );
+ target = XMVectorRound( target );
+ }
+
+ target = XMVectorClamp( target, g_XMZero, g_Scale5551pc );
+
+ XMFLOAT4A tmp;
+ XMStoreFloat4A( &tmp, target );
+
+ auto dPtr = &dest[ index ];
+ dPtr->x = static_cast<uint16_t>( tmp.x ) & 0x1F;
+ dPtr->y = static_cast<uint16_t>( tmp.y ) & 0x1F;
+ dPtr->z = static_cast<uint16_t>( tmp.z ) & 0x1F;
+ dPtr->w = ( XMVectorGetW( target ) > threshold ) ? 1 : 0;
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ STORE_SCANLINE( XMUBYTEN4, g_Scale8pc, true, true, uint8_t, 0xFF, y, true )
+
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ if ( size >= sizeof(XMUBYTEN4) )
+ {
+ XMUBYTEN4 * __restrict dest = reinterpret_cast<XMUBYTEN4*>(pDestination);
+ for( size_t i = 0; i < count; ++i )
+ {
+ ptrdiff_t index = static_cast<ptrdiff_t>( ( y & 1 ) ? ( count - i - 1 ) : i );
+ ptrdiff_t delta = ( y & 1 ) ? -2 : 0;
+
+ XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( sPtr[ index ] );
+ v = XMVectorSaturate( v );
+ v = XMVectorAdd( v, vError );
+ v = XMVectorMultiply( v, g_Scale8pc );
+
+ XMVECTOR target;
+ if ( pDiffusionErrors )
+ {
+ target = XMVectorRound( v );
+ vError = XMVectorSubtract( v, target );
+ vError = XMVectorDivide( vError, g_Scale8pc );
+
+ // Distribute error to next scanline and next pixel
+ pDiffusionErrors[ index-delta ] += XMVectorMultiply( g_ErrorWeight3, vError );
+ pDiffusionErrors[ index+1 ] += XMVectorMultiply( g_ErrorWeight5, vError );
+ pDiffusionErrors[ index+2+delta ] += XMVectorMultiply( g_ErrorWeight1, vError );
+ vError = XMVectorMultiply( vError, g_ErrorWeight7 );
+ }
+ else
+ {
+ // Applied ordered dither
+ target = XMVectorAdd( v, ordered[ index & 3 ] );
+ target = XMVectorRound( target );
+ }
+
+ target = XMVectorClamp( target, g_XMZero, g_Scale8pc );
+
+ XMFLOAT4A tmp;
+ XMStoreFloat4A( &tmp, target );
+
+ auto dPtr = &dest[ index ];
+ dPtr->x = static_cast<uint8_t>( tmp.x ) & 0xFF;
+ dPtr->y = static_cast<uint8_t>( tmp.y ) & 0xFF;
+ dPtr->z = static_cast<uint8_t>( tmp.z ) & 0xFF;
+ dPtr->w = 0;
+ }
+ return true;
+ }
+ return false;
+
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ STORE_SCANLINE( XMUNIBBLE4, g_Scale4pc, true, true, uint8_t, 0xF, y, true )
+
+ default:
+ return _StoreScanline( pDestination, size, format, pSource, count, threshold );
+ }
}
+#pragma warning(pop)
+
+#undef STORE_SCANLINE
+#undef STORE_SCANLINE2
+#undef STORE_SCANLINE1
+
//-------------------------------------------------------------------------------------
-// Convert the source using WIC and then convert to DXGI format from there
+// Selection logic for using WIC vs. our own routines
//-------------------------------------------------------------------------------------
-static HRESULT _ConvertFromWIC( _In_ const Image& srcImage, _In_ const WICPixelFormatGUID& pfGUID,
- _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
+static inline bool _UseWICConversion( _In_ DWORD filter, _In_ DXGI_FORMAT sformat, _In_ DXGI_FORMAT tformat,
+ _Out_ WICPixelFormatGUID& pfGUID, _Out_ WICPixelFormatGUID& targetGUID )
{
- assert( srcImage.width == destImage.width );
- assert( srcImage.height == destImage.height );
+ memcpy( &pfGUID, &GUID_NULL, sizeof(GUID) );
+ memcpy( &targetGUID, &GUID_NULL, sizeof(GUID) );
- IWICImagingFactory* pWIC = _GetWIC();
- if ( !pWIC )
- return E_NOINTERFACE;
+ if ( filter & TEX_FILTER_FORCE_NON_WIC )
+ {
+ // Explicit flag indicates use of non-WIC code paths
+ return false;
+ }
- ScopedObject<IWICFormatConverter> FC;
- HRESULT hr = pWIC->CreateFormatConverter( &FC );
- if ( FAILED(hr) )
- return hr;
+ if ( !_DXGIToWIC( sformat, pfGUID ) || !_DXGIToWIC( tformat, targetGUID ) )
+ {
+ // Source or target format are not WIC supported native pixel formats
+ return false;
+ }
- BOOL canConvert = FALSE;
- hr = FC->CanConvert( pfGUID, GUID_WICPixelFormat128bppRGBAFloat, &canConvert );
- if ( FAILED(hr) || !canConvert )
+ if ( filter & TEX_FILTER_FORCE_WIC )
{
- // This case is not an issue for the subset of WIC formats that map directly to DXGI
- return E_UNEXPECTED;
+ // Explicit flag to use WIC code paths, skips all the case checks below
+ return true;
}
- ScratchImage temp;
- hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
- if ( FAILED(hr) )
- return hr;
+ if ( filter & TEX_FILTER_SEPARATE_ALPHA )
+ {
+ // Alpha is not premultiplied, so use non-WIC code paths
+ return false;
+ }
- const Image *timg = temp.GetImage( 0, 0, 0 );
- if ( !timg )
- return E_POINTER;
+#if defined(_XBOX_ONE) && defined(_TITLE)
+ if ( sformat == DXGI_FORMAT_R16G16B16A16_FLOAT
+ || sformat == DXGI_FORMAT_R16_FLOAT
+ || tformat == DXGI_FORMAT_R16G16B16A16_FLOAT
+ || tformat == DXGI_FORMAT_R16_FLOAT )
+ {
+ // Use non-WIC code paths as these conversions are not supported by Xbox One XDK
+ return false;
+ }
+#endif
- ScopedObject<IWICBitmap> source;
- hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
- static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
- srcImage.pixels, &source );
- if ( FAILED(hr) )
- return hr;
+ // Check for special cases
+ switch ( sformat )
+ {
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ switch( tformat )
+ {
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_D32_FLOAT:
+ // WIC converts via UNORM formats and ends up converting colorspaces for these cases
+ case DXGI_FORMAT_A8_UNORM:
+ // Conversion logic for these kinds of textures is unintuitive for WIC code paths
+ return false;
+ }
+ break;
+
+ case DXGI_FORMAT_R16_FLOAT:
+ switch( tformat )
+ {
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_D32_FLOAT:
+ // WIC converts via UNORM formats and ends up converting colorspaces for these cases
+ case DXGI_FORMAT_A8_UNORM:
+ // Conversion logic for these kinds of textures is unintuitive for WIC code paths
+ return false;
+ }
+ break;
- hr = FC->Initialize( source.Get(), GUID_WICPixelFormat128bppRGBAFloat, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
- if ( FAILED(hr) )
- return hr;
+ case DXGI_FORMAT_A8_UNORM:
+ // Conversion logic for these kinds of textures is unintuitive for WIC code paths
+ return false;
- hr = FC->CopyPixels( 0, static_cast<UINT>( timg->rowPitch ), static_cast<UINT>( timg->slicePitch ), timg->pixels );
- if ( FAILED(hr) )
- return hr;
+ default:
+ switch( tformat )
+ {
+ case DXGI_FORMAT_A8_UNORM:
+ // Conversion logic for these kinds of textures is unintuitive for WIC code paths
+ return false;
+ }
+ }
+
+ // Check for implicit color space changes
+ if ( IsSRGB( sformat ) )
+ filter |= TEX_FILTER_SRGB_IN;
- // Perform conversion on temp image which is now in R32G32B32A32_FLOAT format to final image
- uint8_t *pSrc = timg->pixels;
- uint8_t *pDest = destImage.pixels;
- if ( !pSrc || !pDest )
- return E_POINTER;
+ if ( IsSRGB( tformat ) )
+ filter |= TEX_FILTER_SRGB_OUT;
- for( size_t h = 0; h < srcImage.height; ++h )
+ if ( (filter & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
{
- _ConvertScanline( reinterpret_cast<XMVECTOR*>(pSrc), srcImage.width, destImage.format, DXGI_FORMAT_R32G32B32A32_FLOAT, filter );
+ filter &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
+ }
- if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, reinterpret_cast<const XMVECTOR*>(pSrc), srcImage.width ) )
- return E_FAIL;
+ DWORD wicsrgb = _CheckWICColorSpace( pfGUID, targetGUID );
- pSrc += timg->rowPitch;
- pDest += destImage.rowPitch;
+ if ( wicsrgb != (filter & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) )
+ {
+ // WIC will perform a colorspace conversion we didn't request
+ return false;
}
- return S_OK;
+ return true;
}
//-------------------------------------------------------------------------------------
-// Convert the source from DXGI format then use WIC to convert to final format
+// Convert the source image using WIC
//-------------------------------------------------------------------------------------
-static HRESULT _ConvertToWIC( _In_ const Image& srcImage,
- _In_ const WICPixelFormatGUID& targetGUID, _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
+static HRESULT _ConvertUsingWIC( _In_ const Image& srcImage, _In_ const WICPixelFormatGUID& pfGUID,
+ _In_ const WICPixelFormatGUID& targetGUID,
+ _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
{
assert( srcImage.width == destImage.width );
assert( srcImage.height == destImage.height );
@@ -2149,101 +4292,275 @@ static HRESULT _ConvertToWIC( _In_ const Image& srcImage,
if ( !pWIC )
return E_NOINTERFACE;
- ScopedObject<IWICFormatConverter> FC;
- HRESULT hr = pWIC->CreateFormatConverter( &FC );
+ ComPtr<IWICFormatConverter> FC;
+ HRESULT hr = pWIC->CreateFormatConverter( FC.GetAddressOf() );
if ( FAILED(hr) )
return hr;
+ // Note that WIC conversion ignores the TEX_FILTER_SRGB_IN and TEX_FILTER_SRGB_OUT flags,
+ // but also always assumes UNORM <-> FLOAT conversions are changing color spaces sRGB <-> scRGB
+
BOOL canConvert = FALSE;
- hr = FC->CanConvert( GUID_WICPixelFormat128bppRGBAFloat, targetGUID, &canConvert );
+ hr = FC->CanConvert( pfGUID, targetGUID, &canConvert );
if ( FAILED(hr) || !canConvert )
{
// This case is not an issue for the subset of WIC formats that map directly to DXGI
return E_UNEXPECTED;
}
- ScratchImage temp;
- hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
+ ComPtr<IWICBitmap> source;
+ hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
+ static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
+ srcImage.pixels, source.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- const Image *timg = temp.GetImage( 0, 0, 0 );
- if ( !timg )
- return E_POINTER;
+ hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold * 100.f, WICBitmapPaletteTypeCustom );
+ if ( FAILED(hr) )
+ return hr;
+
+ hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
+ if ( FAILED(hr) )
+ return hr;
+
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------------------------
+// Convert the source image (not using WIC)
+//-------------------------------------------------------------------------------------
+static HRESULT _Convert( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage, _In_ float threshold, _In_ size_t z )
+{
+ assert( srcImage.width == destImage.width );
+ assert( srcImage.height == destImage.height );
const uint8_t *pSrc = srcImage.pixels;
- if ( !pSrc )
+ uint8_t *pDest = destImage.pixels;
+ if ( !pSrc || !pDest )
return E_POINTER;
- uint8_t *pDest = timg->pixels;
- if ( !pDest )
- return E_POINTER;
+ size_t width = srcImage.width;
- for( size_t h = 0; h < srcImage.height; ++h )
+ if ( filter & TEX_FILTER_DITHER_DIFFUSION )
{
- if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
- return E_FAIL;
+ // Error diffusion dithering (aka Floyd-Steinberg dithering)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*(width*2 + 2)), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
- _ConvertScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter );
+ XMVECTOR* pDiffusionErrors = scanline.get() + width;
+ memset( pDiffusionErrors, 0, sizeof(XMVECTOR)*(width+2) );
- pSrc += srcImage.rowPitch;
- pDest += timg->rowPitch;
+ for( size_t h = 0; h < srcImage.height; ++h )
+ {
+ if ( !_LoadScanline( scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format ) )
+ return E_FAIL;
+
+ _ConvertScanline( scanline.get(), width, destImage.format, srcImage.format, filter );
+
+ if ( !_StoreScanlineDither( pDest, destImage.rowPitch, destImage.format, scanline.get(), width, threshold, h, z, pDiffusionErrors ) )
+ return E_FAIL;
+
+ pSrc += srcImage.rowPitch;
+ pDest += destImage.rowPitch;
+ }
}
+ else
+ {
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
- // Perform conversion on temp image which is now in R32G32B32A32_FLOAT format
- ScopedObject<IWICBitmap> source;
- hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( timg->width ), static_cast<UINT>( timg->height ), GUID_WICPixelFormat128bppRGBAFloat,
- static_cast<UINT>( timg->rowPitch ), static_cast<UINT>( timg->slicePitch ),
- timg->pixels, &source );
- if ( FAILED(hr) )
- return hr;
+ if ( filter & TEX_FILTER_DITHER )
+ {
+ // Ordered dithering
+ for( size_t h = 0; h < srcImage.height; ++h )
+ {
+ if ( !_LoadScanline( scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format ) )
+ return E_FAIL;
- hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
- if ( FAILED(hr) )
- return hr;
+ _ConvertScanline( scanline.get(), width, destImage.format, srcImage.format, filter );
- hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
- if ( FAILED(hr) )
- return hr;
+ if ( !_StoreScanlineDither( pDest, destImage.rowPitch, destImage.format, scanline.get(), width, threshold, h, z, nullptr ) )
+ return E_FAIL;
+
+ pSrc += srcImage.rowPitch;
+ pDest += destImage.rowPitch;
+ }
+ }
+ else
+ {
+ // No dithering
+ for( size_t h = 0; h < srcImage.height; ++h )
+ {
+ if ( !_LoadScanline( scanline.get(), width, pSrc, srcImage.rowPitch, srcImage.format ) )
+ return E_FAIL;
+
+ _ConvertScanline( scanline.get(), width, destImage.format, srcImage.format, filter );
+
+ if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), width, threshold ) )
+ return E_FAIL;
+
+ pSrc += srcImage.rowPitch;
+ pDest += destImage.rowPitch;
+ }
+ }
+ }
return S_OK;
}
//-------------------------------------------------------------------------------------
-// Convert the source image (not using WIC)
+static DXGI_FORMAT _PlanarToSingle( _In_ DXGI_FORMAT format )
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_NV12:
+ case DXGI_FORMAT_NV11:
+ return DXGI_FORMAT_YUY2;
+
+ case DXGI_FORMAT_P010:
+ return DXGI_FORMAT_Y210;
+
+ case DXGI_FORMAT_P016:
+ return DXGI_FORMAT_Y216;
+
+ // We currently do not support conversion for Xbox One specific depth formats
+
+ // We can't do anything with DXGI_FORMAT_420_OPAQUE because it's an opaque blob of bits
+
+ default:
+ return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+
+//-------------------------------------------------------------------------------------
+// Convert the image from a planar to non-planar image
//-------------------------------------------------------------------------------------
-static HRESULT _Convert( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
+#define CONVERT_420_TO_422( srcType, destType )\
+ {\
+ size_t rowPitch = srcImage.rowPitch;\
+ \
+ auto sourceE = reinterpret_cast<const srcType*>( pSrc + srcImage.slicePitch );\
+ auto pSrcUV = pSrc + ( srcImage.height * rowPitch );\
+ \
+ for( size_t y = 0; y < srcImage.height; y+= 2 )\
+ {\
+ auto sPtrY0 = reinterpret_cast<const srcType*>( pSrc );\
+ auto sPtrY2 = reinterpret_cast<const srcType*>( pSrc + rowPitch );\
+ auto sPtrUV = reinterpret_cast<const srcType*>( pSrcUV );\
+ \
+ destType * __restrict dPtr0 = reinterpret_cast<destType*>(pDest);\
+ destType * __restrict dPtr1 = reinterpret_cast<destType*>(pDest + destImage.rowPitch);\
+ \
+ for( size_t x = 0; x < srcImage.width; x+= 2 )\
+ {\
+ if ( (sPtrUV+1) >= sourceE ) break;\
+ \
+ srcType u = *(sPtrUV++);\
+ srcType v = *(sPtrUV++);\
+ \
+ dPtr0->x = *(sPtrY0++);\
+ dPtr0->y = u;\
+ dPtr0->z = *(sPtrY0++);\
+ dPtr0->w = v;\
+ ++dPtr0;\
+ \
+ dPtr1->x = *(sPtrY2++);\
+ dPtr1->y = u;\
+ dPtr1->z = *(sPtrY2++);\
+ dPtr1->w = v;\
+ ++dPtr1;\
+ }\
+ \
+ pSrc += rowPitch * 2;\
+ pSrcUV += rowPitch;\
+ \
+ pDest += destImage.rowPitch * 2;\
+ }\
+ }
+
+static HRESULT _ConvertToSinglePlane( _In_ const Image& srcImage, _In_ const Image& destImage )
{
assert( srcImage.width == destImage.width );
assert( srcImage.height == destImage.height );
- ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
- if ( !scanline )
- return E_OUTOFMEMORY;
-
const uint8_t *pSrc = srcImage.pixels;
uint8_t *pDest = destImage.pixels;
if ( !pSrc || !pDest )
return E_POINTER;
- for( size_t h = 0; h < srcImage.height; ++h )
+ switch ( srcImage.format )
{
- if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
- return E_FAIL;
-
- _ConvertScanline( scanline.get(), srcImage.width, destImage.format, srcImage.format, filter );
-
- if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
- return E_FAIL;
+ case DXGI_FORMAT_NV12:
+ assert( destImage.format == DXGI_FORMAT_YUY2 );
+ CONVERT_420_TO_422( uint8_t, XMUBYTEN4 );
+ return S_OK;
+
+ case DXGI_FORMAT_P010:
+ assert( destImage.format == DXGI_FORMAT_Y210 );
+ CONVERT_420_TO_422( uint16_t, XMUSHORTN4 );
+ return S_OK;
+
+ case DXGI_FORMAT_P016:
+ assert( destImage.format == DXGI_FORMAT_Y216 );
+ CONVERT_420_TO_422( uint16_t, XMUSHORTN4 );
+ return S_OK;
+
+ case DXGI_FORMAT_NV11:
+ assert( destImage.format == DXGI_FORMAT_YUY2 );
+ // Convert 4:1:1 to 4:2:2
+ {
+ size_t rowPitch = srcImage.rowPitch;
+
+ const uint8_t* sourceE = pSrc + srcImage.slicePitch;
+ const uint8_t* pSrcUV = pSrc + ( srcImage.height * rowPitch );
+
+ for( size_t y = 0; y < srcImage.height; ++y )
+ {
+ const uint8_t* sPtrY = pSrc;
+ const uint8_t* sPtrUV = pSrcUV;
+
+ XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDest);
+
+ for( size_t x = 0; x < srcImage.width; x+= 4 )
+ {
+ if ( (sPtrUV+1) >= sourceE ) break;
+
+ uint8_t u = *(sPtrUV++);
+ uint8_t v = *(sPtrUV++);
+
+ dPtr->x = *(sPtrY++);
+ dPtr->y = u;
+ dPtr->z = *(sPtrY++);
+ dPtr->w = v;
+ ++dPtr;
+
+ dPtr->x = *(sPtrY++);
+ dPtr->y = u;
+ dPtr->z = *(sPtrY++);
+ dPtr->w = v;
+ ++dPtr;
+ }
+
+ pSrc += rowPitch;
+ pSrcUV += (rowPitch >> 1);
+
+ pDest += destImage.rowPitch;
+ }
+ }
+ return S_OK;
- pSrc += srcImage.rowPitch;
- pDest += destImage.rowPitch;
+ default:
+ return E_UNEXPECTED;
}
-
- return S_OK;
}
+#undef CONVERT_420_TO_422
+
//=====================================================================================
// Entry-points
@@ -2252,6 +4569,7 @@ static HRESULT _Convert( _In_ const Image& srcImage, _In_ DWORD filter, _In_ con
//-------------------------------------------------------------------------------------
// Convert image
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT Convert( const Image& srcImage, DXGI_FORMAT format, DWORD filter, float threshold, ScratchImage& image )
{
if ( (srcImage.format == format) || !IsValid( format ) )
@@ -2261,11 +4579,12 @@ HRESULT Convert( const Image& srcImage, DXGI_FORMAT format, DWORD filter, float
return E_POINTER;
if ( IsCompressed(srcImage.format) || IsCompressed(format)
- || IsVideo(srcImage.format) || IsVideo(format)
+ || IsPlanar(srcImage.format) || IsPlanar(format)
+ || IsPalettized(srcImage.format) || IsPalettized(format)
|| IsTypeless(srcImage.format) || IsTypeless(format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
return E_INVALIDARG;
#endif
@@ -2281,34 +4600,14 @@ HRESULT Convert( const Image& srcImage, DXGI_FORMAT format, DWORD filter, float
return E_POINTER;
}
- WICPixelFormatGUID pfGUID;
- if ( _DXGIToWIC( srcImage.format, pfGUID ) )
+ WICPixelFormatGUID pfGUID, targetGUID;
+ if ( _UseWICConversion( filter, srcImage.format, format, pfGUID, targetGUID ) )
{
- WICPixelFormatGUID targetGUID;
- if ( _DXGIToWIC( format, targetGUID ) )
- {
- // Case 1: Both source and target formats are WIC supported
- hr = _ConvertUsingWIC( srcImage, pfGUID, targetGUID, filter, threshold, *rimage );
- }
- else
- {
- // Case 2: Source format is supported by WIC, but not the target format
- hr = _ConvertFromWIC( srcImage, pfGUID, filter, threshold, *rimage );
- }
+ hr = _ConvertUsingWIC( srcImage, pfGUID, targetGUID, filter, threshold, *rimage );
}
else
{
- WICPixelFormatGUID targetGUID;
- if ( _DXGIToWIC( format, targetGUID ) )
- {
- // Case 3: Source format is not supported by WIC, but does support the target format
- hr = _ConvertToWIC( srcImage, targetGUID, filter, threshold, *rimage );
- }
- else
- {
- // Case 4: Both source and target format are not supported by WIC
- hr = _Convert( srcImage, filter, *rimage );
- }
+ hr = _Convert( srcImage, filter, *rimage, threshold, 0 );
}
if ( FAILED(hr) )
@@ -2324,6 +4623,7 @@ HRESULT Convert( const Image& srcImage, DXGI_FORMAT format, DWORD filter, float
//-------------------------------------------------------------------------------------
// Convert image (complex)
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT Convert( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DXGI_FORMAT format, DWORD filter, float threshold, ScratchImage& result )
{
@@ -2331,11 +4631,12 @@ HRESULT Convert( const Image* srcImages, size_t nimages, const TexMetadata& meta
return E_INVALIDARG;
if ( IsCompressed(metadata.format) || IsCompressed(format)
- || IsVideo(metadata.format) || IsVideo(format)
+ || IsPlanar(metadata.format) || IsPlanar(format)
+ || IsPalettized(metadata.format) || IsPalettized(format)
|| IsTypeless(metadata.format) || IsTypeless(format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) )
return E_INVALIDARG;
#endif
@@ -2360,8 +4661,200 @@ HRESULT Convert( const Image* srcImages, size_t nimages, const TexMetadata& meta
}
WICPixelFormatGUID pfGUID, targetGUID;
- bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
- bool wictargetpf = _DXGIToWIC( format, targetGUID );
+ bool usewic = _UseWICConversion( filter, metadata.format, format, pfGUID, targetGUID );
+
+ switch (metadata.dimension)
+ {
+ case TEX_DIMENSION_TEXTURE1D:
+ case TEX_DIMENSION_TEXTURE2D:
+ for( size_t index=0; index < nimages; ++index )
+ {
+ const Image& src = srcImages[ index ];
+ if ( src.format != metadata.format )
+ {
+ result.Release();
+ return E_FAIL;
+ }
+
+#ifdef _M_X64
+ if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
+ return E_FAIL;
+#endif
+
+ const Image& dst = dest[ index ];
+ assert( dst.format == format );
+
+ if ( src.width != dst.width || src.height != dst.height )
+ {
+ result.Release();
+ return E_FAIL;
+ }
+
+ if ( usewic )
+ {
+ hr = _ConvertUsingWIC( src, pfGUID, targetGUID, filter, threshold, dst );
+ }
+ else
+ {
+ hr = _Convert( src, filter, dst, threshold, 0 );
+ }
+
+ if ( FAILED(hr) )
+ {
+ result.Release();
+ return hr;
+ }
+ }
+ break;
+
+ case TEX_DIMENSION_TEXTURE3D:
+ {
+ size_t index = 0;
+ size_t d = metadata.depth;
+ for( size_t level = 0; level < metadata.mipLevels; ++level )
+ {
+ for( size_t slice = 0; slice < d; ++slice, ++index )
+ {
+ if ( index >= nimages )
+ return E_FAIL;
+
+ const Image& src = srcImages[ index ];
+ if ( src.format != metadata.format )
+ {
+ result.Release();
+ return E_FAIL;
+ }
+
+#ifdef _M_X64
+ if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
+ return E_FAIL;
+#endif
+
+ const Image& dst = dest[ index ];
+ assert( dst.format == format );
+
+ if ( src.width != dst.width || src.height != dst.height )
+ {
+ result.Release();
+ return E_FAIL;
+ }
+
+ if ( usewic )
+ {
+ hr = _ConvertUsingWIC( src, pfGUID, targetGUID, filter, threshold, dst );
+ }
+ else
+ {
+ hr = _Convert( src, filter, dst, threshold, slice );
+ }
+
+ if ( FAILED(hr) )
+ {
+ result.Release();
+ return hr;
+ }
+ }
+
+ if ( d > 1 )
+ d >>= 1;
+ }
+ }
+ break;
+
+ default:
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------------------------
+// Convert image from planar to single plane (image)
+//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
+HRESULT ConvertToSinglePlane( const Image& srcImage, ScratchImage& image )
+{
+ if ( !IsPlanar(srcImage.format) )
+ return E_INVALIDARG;
+
+ if ( !srcImage.pixels )
+ return E_POINTER;
+
+ DXGI_FORMAT format = _PlanarToSingle( srcImage.format );
+ if ( format == DXGI_FORMAT_UNKNOWN )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
+#ifdef _M_X64
+ if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
+ return E_INVALIDARG;
+#endif
+
+ HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
+ if ( FAILED(hr) )
+ return hr;
+
+ const Image *rimage = image.GetImage( 0, 0, 0 );
+ if ( !rimage )
+ {
+ image.Release();
+ return E_POINTER;
+ }
+
+ hr = _ConvertToSinglePlane( srcImage, *rimage );
+ if ( FAILED(hr) )
+ {
+ image.Release();
+ return hr;
+ }
+
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------------------------
+// Convert image from planar to single plane (complex)
+//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
+HRESULT ConvertToSinglePlane( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
+ ScratchImage& result )
+{
+ if ( !srcImages || !nimages )
+ return E_INVALIDARG;
+
+ if ( metadata.IsVolumemap() )
+ {
+ // Direct3D does not support any planar formats for Texture3D
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
+
+ DXGI_FORMAT format = _PlanarToSingle( metadata.format );
+ if ( format == DXGI_FORMAT_UNKNOWN )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
+#ifdef _M_X64
+ if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) )
+ return E_INVALIDARG;
+#endif
+
+ TexMetadata mdata2 = metadata;
+ mdata2.format = format;
+ HRESULT hr = result.Initialize( mdata2 );
+ if ( FAILED(hr) )
+ return hr;
+
+ if ( nimages != result.GetImageCount() )
+ {
+ result.Release();
+ return E_FAIL;
+ }
+
+ const Image* dest = result.GetImages();
+ if ( !dest )
+ {
+ result.Release();
+ return E_POINTER;
+ }
for( size_t index=0; index < nimages; ++index )
{
@@ -2372,7 +4865,7 @@ HRESULT Convert( const Image* srcImages, size_t nimages, const TexMetadata& meta
return E_FAIL;
}
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
return E_FAIL;
#endif
@@ -2386,33 +4879,7 @@ HRESULT Convert( const Image* srcImages, size_t nimages, const TexMetadata& meta
return E_FAIL;
}
- if ( wicpf )
- {
- if ( wictargetpf )
- {
- // Case 1: Both source and target formats are WIC supported
- hr = _ConvertUsingWIC( src, pfGUID, targetGUID, filter, threshold, dst );
- }
- else
- {
- // Case 2: Source format is supported by WIC, but not the target format
- hr = _ConvertFromWIC( src, pfGUID, filter, threshold, dst );
- }
- }
- else
- {
- if ( wictargetpf )
- {
- // Case 3: Source format is not supported by WIC, but does support the target format
- hr = _ConvertToWIC( src, targetGUID, filter, threshold, dst );
- }
- else
- {
- // Case 4: Both source and target format are not supported by WIC
- hr = _Convert( src, filter, dst );
- }
- }
-
+ hr = _ConvertToSinglePlane( src, dst );
if ( FAILED(hr) )
{
result.Release();
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexD3D11.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexD3D11.cpp
index e640dfd0..38e4fcc7 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexD3D11.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexD3D11.cpp
@@ -15,7 +15,11 @@
#include "DirectXTexP.h"
+#if !defined(_XBOX_ONE) || !defined(_TITLE)
#include <d3d10.h>
+#endif
+
+using Microsoft::WRL::ComPtr;
namespace DirectX
{
@@ -26,7 +30,34 @@ static HRESULT _Capture( _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource
if ( !pContext || !pSource || !result.GetPixels() )
return E_POINTER;
- if ( metadata.dimension == TEX_DIMENSION_TEXTURE3D )
+#if defined(_XBOX_ONE) && defined(_TITLE)
+
+ ComPtr<ID3D11Device> d3dDevice;
+ pContext->GetDevice( d3dDevice.GetAddressOf() );
+
+ if ( d3dDevice->GetCreationFlags() & D3D11_CREATE_DEVICE_IMMEDIATE_CONTEXT_FAST_SEMANTICS )
+ {
+ ComPtr<ID3D11DeviceX> d3dDeviceX;
+ HRESULT hr = d3dDevice.As( &d3dDeviceX );
+ if ( FAILED(hr) )
+ return hr;
+
+ ComPtr<ID3D11DeviceContextX> d3dContextX;
+ hr = pContext->QueryInterface( __uuidof(ID3D11DeviceContextX), reinterpret_cast<void**>( d3dContextX.GetAddressOf() ) );
+ if ( FAILED(hr) )
+ return hr;
+
+ UINT64 copyFence = d3dContextX->InsertFence(0);
+
+ while ( d3dDeviceX->IsFencePending( copyFence ) )
+ {
+ SwitchToThread();
+ }
+ }
+
+#endif
+
+ if ( metadata.IsVolumemap() )
{
//--- Volume texture ----------------------------------------------------------
assert( metadata.arraySize == 1 );
@@ -43,7 +74,7 @@ static HRESULT _Capture( _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource
if ( FAILED(hr) )
return hr;
- const uint8_t* pslice = reinterpret_cast<const uint8_t*>( mapped.pData );
+ auto pslice = reinterpret_cast<const uint8_t*>( mapped.pData );
if ( !pslice )
{
pContext->Unmap( pSource, dindex );
@@ -51,6 +82,11 @@ static HRESULT _Capture( _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource
}
size_t lines = ComputeScanlines( metadata.format, height );
+ if ( !lines )
+ {
+ pContext->Unmap( pSource, dindex );
+ return E_UNEXPECTED;
+ }
for( size_t slice = 0; slice < depth; ++slice )
{
@@ -120,8 +156,13 @@ static HRESULT _Capture( _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource
}
size_t lines = ComputeScanlines( metadata.format, height );
+ if ( !lines )
+ {
+ pContext->Unmap( pSource, dindex );
+ return E_UNEXPECTED;
+ }
- const uint8_t* sptr = reinterpret_cast<const uint8_t*>( mapped.pData );
+ auto sptr = reinterpret_cast<const uint8_t*>( mapped.pData );
uint8_t* dptr = img->pixels;
for( size_t h = 0; h < lines; ++h )
{
@@ -150,6 +191,7 @@ static HRESULT _Capture( _In_ ID3D11DeviceContext* pContext, _In_ ID3D11Resource
//-------------------------------------------------------------------------------------
// Determine if given texture metadata is supported on the given device
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
{
if ( !pDevice )
@@ -163,9 +205,6 @@ bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
if ( !IsValid( fmt ) )
return false;
- if ( IsVideo(fmt) )
- return false;
-
switch( fmt )
{
case DXGI_FORMAT_BC4_TYPELESS:
@@ -201,7 +240,11 @@ bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
// Most cases are known apriori based on feature level, but we use this for robustness to handle the few optional cases
UINT formatSupport = 0;
- pDevice->CheckFormatSupport( fmt, &formatSupport );
+ HRESULT hr = pDevice->CheckFormatSupport( fmt, &formatSupport );
+ if ( FAILED(hr) )
+ {
+ formatSupport = 0;
+ }
switch ( metadata.dimension )
{
@@ -221,17 +264,17 @@ bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
if ( fl < D3D_FEATURE_LEVEL_10_0 )
{
- if ( (arraySize > 1) || (iWidth > 4096 /*D3D_FL9_3_REQ_TEXTURE1D_U_DIMENSION*/) )
+ if ( (arraySize > 1) || (iWidth > D3D_FL9_3_REQ_TEXTURE1D_U_DIMENSION) )
return false;
- if ( (fl < D3D_FEATURE_LEVEL_9_3) && (iWidth > 2048 /*D3D_FL9_1_REQ_TEXTURE1D_U_DIMENSION*/ ) )
+ if ( (fl < D3D_FEATURE_LEVEL_9_3) && (iWidth > D3D_FL9_1_REQ_TEXTURE1D_U_DIMENSION ) )
return false;
}
}
break;
case TEX_DIMENSION_TEXTURE2D:
- if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE )
+ if ( metadata.IsCubemap() )
{
if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) )
return false;
@@ -253,13 +296,13 @@ bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
if ( fl < D3D_FEATURE_LEVEL_10_0 )
{
- if ( (iWidth > 4096 /*D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION*/ )
- || (iHeight > 4096 /*D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION*/ ) )
+ if ( (iWidth > D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION )
+ || (iHeight > D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION ) )
return false;
if ( (fl < D3D_FEATURE_LEVEL_9_3)
- && ( (iWidth > 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/)
- || (iHeight > 512 /*D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION*/) ) )
+ && ( (iWidth > D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION)
+ || (iHeight > D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION) ) )
return false;
}
}
@@ -284,13 +327,13 @@ bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
if ( fl < D3D_FEATURE_LEVEL_10_0 )
{
if ( (arraySize > 1)
- || (iWidth > 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/)
- || (iHeight > 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/) )
+ || (iWidth > D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION)
+ || (iHeight > D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION) )
return false;
if ( (fl < D3D_FEATURE_LEVEL_9_3)
- && ( (iWidth > 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/)
- || (iHeight > 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/) ) )
+ && ( (iWidth > D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION)
+ || (iHeight > D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION) ) )
return false;
}
}
@@ -316,9 +359,9 @@ bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
if ( fl < D3D_FEATURE_LEVEL_10_0 )
{
- if ( (iWidth > 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/)
- || (iHeight > 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/)
- || (iDepth > 256 /*D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION*/) )
+ if ( (iWidth > D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)
+ || (iHeight > D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION)
+ || (iDepth > D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) )
return false;
}
}
@@ -336,33 +379,46 @@ bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
//-------------------------------------------------------------------------------------
// Create a texture resource
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT CreateTexture( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
ID3D11Resource** ppResource )
{
+ return CreateTextureEx( pDevice, srcImages, nimages, metadata,
+ D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false,
+ ppResource );
+}
+
+_Use_decl_annotations_
+HRESULT CreateTextureEx( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
+ D3D11_USAGE usage, unsigned int bindFlags, unsigned int cpuAccessFlags, unsigned int miscFlags, bool forceSRGB,
+ ID3D11Resource** ppResource )
+{
if ( !pDevice || !srcImages || !nimages || !ppResource )
return E_INVALIDARG;
+ *ppResource = nullptr;
+
if ( !metadata.mipLevels || !metadata.arraySize )
return E_INVALIDARG;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF)
|| (metadata.mipLevels > 0xFFFFFFFF) || (metadata.arraySize > 0xFFFFFFFF) )
return E_INVALIDARG;
#endif
- std::unique_ptr<D3D11_SUBRESOURCE_DATA[]> initData( new D3D11_SUBRESOURCE_DATA[ metadata.mipLevels * metadata.arraySize ] );
+ std::unique_ptr<D3D11_SUBRESOURCE_DATA[]> initData( new (std::nothrow) D3D11_SUBRESOURCE_DATA[ metadata.mipLevels * metadata.arraySize ] );
if ( !initData )
return E_OUTOFMEMORY;
// Fill out subresource array
- if ( metadata.dimension == TEX_DIMENSION_TEXTURE3D )
+ if ( metadata.IsVolumemap() )
{
//--- Volume case -------------------------------------------------------------
if ( !metadata.depth )
return E_INVALIDARG;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( metadata.depth > 0xFFFFFFFF )
return E_INVALIDARG;
#endif
@@ -456,6 +512,8 @@ HRESULT CreateTexture( ID3D11Device* pDevice, const Image* srcImages, size_t nim
// Create texture using static initialization data
HRESULT hr = E_FAIL;
+ DXGI_FORMAT tformat = ( forceSRGB ) ? MakeSRGB( metadata.format ) : metadata.format;
+
switch ( metadata.dimension )
{
case TEX_DIMENSION_TEXTURE1D:
@@ -464,11 +522,11 @@ HRESULT CreateTexture( ID3D11Device* pDevice, const Image* srcImages, size_t nim
desc.Width = static_cast<UINT>( metadata.width );
desc.MipLevels = static_cast<UINT>( metadata.mipLevels );
desc.ArraySize = static_cast<UINT>( metadata.arraySize );
- desc.Format = metadata.format;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = 0;
+ desc.Format = tformat;
+ desc.Usage = usage;
+ desc.BindFlags = bindFlags;
+ desc.CPUAccessFlags = cpuAccessFlags;
+ desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
hr = pDevice->CreateTexture1D( &desc, initData.get(), reinterpret_cast<ID3D11Texture1D**>(ppResource) );
}
@@ -481,13 +539,16 @@ HRESULT CreateTexture( ID3D11Device* pDevice, const Image* srcImages, size_t nim
desc.Height = static_cast<UINT>( metadata.height );
desc.MipLevels = static_cast<UINT>( metadata.mipLevels );
desc.ArraySize = static_cast<UINT>( metadata.arraySize );
- desc.Format = metadata.format;
+ desc.Format = tformat;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = (metadata.miscFlags & TEX_MISC_TEXTURECUBE) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
+ desc.Usage = usage;
+ desc.BindFlags = bindFlags;
+ desc.CPUAccessFlags = cpuAccessFlags;
+ if ( metadata.IsCubemap() )
+ desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE;
+ else
+ desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
hr = pDevice->CreateTexture2D( &desc, initData.get(), reinterpret_cast<ID3D11Texture2D**>(ppResource) );
}
@@ -500,11 +561,11 @@ HRESULT CreateTexture( ID3D11Device* pDevice, const Image* srcImages, size_t nim
desc.Height = static_cast<UINT>( metadata.height );
desc.Depth = static_cast<UINT>( metadata.depth );
desc.MipLevels = static_cast<UINT>( metadata.mipLevels );
- desc.Format = metadata.format;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = 0;
+ desc.Format = tformat;
+ desc.Usage = usage;
+ desc.BindFlags = bindFlags;
+ desc.CPUAccessFlags = cpuAccessFlags;
+ desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
hr = pDevice->CreateTexture3D( &desc, initData.get(), reinterpret_cast<ID3D11Texture3D**>(ppResource) );
}
@@ -518,71 +579,89 @@ HRESULT CreateTexture( ID3D11Device* pDevice, const Image* srcImages, size_t nim
//-------------------------------------------------------------------------------------
// Create a shader resource view and associated texture
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT CreateShaderResourceView( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
ID3D11ShaderResourceView** ppSRV )
{
+ return CreateShaderResourceViewEx( pDevice, srcImages, nimages, metadata,
+ D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, false,
+ ppSRV );
+}
+
+_Use_decl_annotations_
+HRESULT CreateShaderResourceViewEx( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
+ D3D11_USAGE usage, unsigned int bindFlags, unsigned int cpuAccessFlags, unsigned int miscFlags, bool forceSRGB,
+ ID3D11ShaderResourceView** ppSRV )
+{
if ( !ppSRV )
return E_INVALIDARG;
- ScopedObject<ID3D11Resource> resource;
- HRESULT hr = CreateTexture( pDevice, srcImages, nimages, metadata, &resource );
+ *ppSRV = nullptr;
+
+ ComPtr<ID3D11Resource> resource;
+ HRESULT hr = CreateTextureEx( pDevice, srcImages, nimages, metadata,
+ usage, bindFlags, cpuAccessFlags, miscFlags, forceSRGB,
+ resource.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- assert( !resource.IsNull() );
+ assert( resource );
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
memset( &SRVDesc, 0, sizeof(SRVDesc) );
- SRVDesc.Format = metadata.format;
+ if ( forceSRGB )
+ SRVDesc.Format = MakeSRGB( metadata.format );
+ else
+ SRVDesc.Format = metadata.format;
switch ( metadata.dimension )
{
case TEX_DIMENSION_TEXTURE1D:
if ( metadata.arraySize > 1 )
{
- SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1DARRAY;
SRVDesc.Texture1DArray.MipLevels = static_cast<UINT>( metadata.mipLevels );
SRVDesc.Texture1DArray.ArraySize = static_cast<UINT>( metadata.arraySize );
}
else
{
- SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE1D;
SRVDesc.Texture1D.MipLevels = static_cast<UINT>( metadata.mipLevels );
}
break;
case TEX_DIMENSION_TEXTURE2D:
- if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE )
+ if ( metadata.IsCubemap() )
{
if (metadata.arraySize > 6)
{
assert( (metadata.arraySize % 6) == 0 );
- SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBEARRAY;
SRVDesc.TextureCubeArray.MipLevels = static_cast<UINT>( metadata.mipLevels );
SRVDesc.TextureCubeArray.NumCubes = static_cast<UINT>( metadata.arraySize / 6 );
}
else
{
- SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURECUBE;
SRVDesc.TextureCube.MipLevels = static_cast<UINT>( metadata.mipLevels );
}
}
else if ( metadata.arraySize > 1 )
{
- SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2DARRAY;
SRVDesc.Texture2DArray.MipLevels = static_cast<UINT>( metadata.mipLevels );
SRVDesc.Texture2DArray.ArraySize = static_cast<UINT>( metadata.arraySize );
}
else
{
- SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
SRVDesc.Texture2D.MipLevels = static_cast<UINT>( metadata.mipLevels );
}
break;
case TEX_DIMENSION_TEXTURE3D:
assert( metadata.arraySize == 1 );
- SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE3D;
SRVDesc.Texture3D.MipLevels = static_cast<UINT>( metadata.mipLevels );
break;
@@ -603,6 +682,7 @@ HRESULT CreateShaderResourceView( ID3D11Device* pDevice, const Image* srcImages,
//-------------------------------------------------------------------------------------
// Save a texture resource to a DDS file in memory/on disk
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID3D11Resource* pSource, ScratchImage& result )
{
if ( !pDevice || !pContext || !pSource )
@@ -617,12 +697,12 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
{
case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
{
- ScopedObject<ID3D11Texture1D> pTexture;
- hr = pSource->QueryInterface( __uuidof(ID3D11Texture1D), (void**) &pTexture );
+ ComPtr<ID3D11Texture1D> pTexture;
+ hr = pSource->QueryInterface( __uuidof(ID3D11Texture1D), reinterpret_cast<void**>( pTexture.GetAddressOf() ) );
if ( FAILED(hr) )
break;
- assert( pTexture.Get() );
+ assert( pTexture );
D3D11_TEXTURE1D_DESC desc;
pTexture->GetDesc( &desc );
@@ -632,12 +712,12 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.Usage = D3D11_USAGE_STAGING;
- ScopedObject<ID3D11Texture1D> pStaging;
- hr = pDevice->CreateTexture1D( &desc, 0, &pStaging );
+ ComPtr<ID3D11Texture1D> pStaging;
+ hr = pDevice->CreateTexture1D( &desc, 0, pStaging.GetAddressOf() );
if ( FAILED(hr) )
break;
- assert( pStaging.Get() );
+ assert( pStaging );
pContext->CopyResource( pStaging.Get(), pSource );
@@ -647,6 +727,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
mdata.arraySize = desc.ArraySize;
mdata.mipLevels = desc.MipLevels;
mdata.miscFlags = 0;
+ mdata.miscFlags2 = 0;
mdata.format = desc.Format;
mdata.dimension = TEX_DIMENSION_TEXTURE1D;
@@ -660,28 +741,28 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
{
- ScopedObject<ID3D11Texture2D> pTexture;
- hr = pSource->QueryInterface( __uuidof(ID3D11Texture2D), (void**) &pTexture );
+ ComPtr<ID3D11Texture2D> pTexture;
+ hr = pSource->QueryInterface( __uuidof(ID3D11Texture2D), reinterpret_cast<void**>( pTexture.GetAddressOf() ) );
if ( FAILED(hr) )
break;
- assert( pTexture.Get() );
+ assert( pTexture );
D3D11_TEXTURE2D_DESC desc;
pTexture->GetDesc( &desc );
- ScopedObject<ID3D11Texture2D> pStaging;
+ ComPtr<ID3D11Texture2D> pStaging;
if ( desc.SampleDesc.Count > 1 )
{
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
- ScopedObject<ID3D11Texture2D> pTemp;
- hr = pDevice->CreateTexture2D( &desc, 0, &pTemp );
+ ComPtr<ID3D11Texture2D> pTemp;
+ hr = pDevice->CreateTexture2D( &desc, 0, pTemp.GetAddressOf() );
if ( FAILED(hr) )
break;
- assert( pTemp.Get() );
+ assert( pTemp );
DXGI_FORMAT fmt = desc.Format;
if ( IsTypeless(fmt) )
@@ -707,7 +788,6 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
for( UINT level = 0; level < desc.MipLevels; ++level )
{
UINT index = D3D11CalcSubresource( level, item, desc.MipLevels );
-
pContext->ResolveSubresource( pTemp.Get(), index, pSource, index, fmt );
}
}
@@ -717,11 +797,11 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.Usage = D3D11_USAGE_STAGING;
- hr = pDevice->CreateTexture2D( &desc, 0, &pStaging );
+ hr = pDevice->CreateTexture2D( &desc, 0, pStaging.GetAddressOf() );
if ( FAILED(hr) )
break;
- assert( pStaging.Get() );
+ assert( pStaging );
pContext->CopyResource( pStaging.Get(), pTemp.Get() );
}
@@ -736,7 +816,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
if ( FAILED(hr) )
break;
- assert( pStaging.Get() );
+ assert( pStaging );
pContext->CopyResource( pStaging.Get(), pSource );
}
@@ -748,6 +828,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
mdata.arraySize = desc.ArraySize;
mdata.mipLevels = desc.MipLevels;
mdata.miscFlags = (desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) ? TEX_MISC_TEXTURECUBE : 0;
+ mdata.miscFlags2 = 0;
mdata.format = desc.Format;
mdata.dimension = TEX_DIMENSION_TEXTURE2D;
@@ -761,12 +842,12 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
{
- ScopedObject<ID3D11Texture3D> pTexture;
- hr = pSource->QueryInterface( __uuidof(ID3D11Texture3D), (void**) &pTexture );
+ ComPtr<ID3D11Texture3D> pTexture;
+ hr = pSource->QueryInterface( __uuidof(ID3D11Texture3D), reinterpret_cast<void**>( pTexture.GetAddressOf() ) );
if ( FAILED(hr) )
break;
- assert( pTexture.Get() );
+ assert( pTexture );
D3D11_TEXTURE3D_DESC desc;
pTexture->GetDesc( &desc );
@@ -776,12 +857,12 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.Usage = D3D11_USAGE_STAGING;
- ScopedObject<ID3D11Texture3D> pStaging;
- hr = pDevice->CreateTexture3D( &desc, 0, &pStaging );
+ ComPtr<ID3D11Texture3D> pStaging;
+ hr = pDevice->CreateTexture3D( &desc, 0, pStaging.GetAddressOf() );
if ( FAILED(hr) )
break;
- assert( pStaging.Get() );
+ assert( pStaging );
pContext->CopyResource( pStaging.Get(), pSource );
@@ -792,6 +873,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
mdata.arraySize = 1;
mdata.mipLevels = desc.MipLevels;
mdata.miscFlags = 0;
+ mdata.miscFlags2 = 0;
mdata.format = desc.Format;
mdata.dimension = TEX_DIMENSION_TEXTURE3D;
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexDDS.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexDDS.cpp
index d249b4fe..67d2e825 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexDDS.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexDDS.cpp
@@ -39,6 +39,10 @@ enum CONVERSION_FLAGS
CONV_FLAGS_8332 = 0x400, // Source is a 8:3:3:2 (16bpp) format
CONV_FLAGS_A8P8 = 0x800, // Has an 8-bit palette with an alpha channel
CONV_FLAGS_DX10 = 0x10000, // Has the 'DX10' extension header
+ CONV_FLAGS_PMALPHA = 0x20000, // Contains premultiplied alpha data
+ CONV_FLAGS_L8 = 0x40000, // Source is a 8 luminance format
+ CONV_FLAGS_L16 = 0x80000, // Source is a 16 luminance format
+ CONV_FLAGS_A8L8 = 0x100000, // Source is a 8:8 luminance format
};
struct LegacyDDS
@@ -54,8 +58,8 @@ const LegacyDDS g_LegacyDDSMap[] =
{ DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_NONE, DDSPF_DXT3 }, // D3DFMT_DXT3
{ DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, DDSPF_DXT5 }, // D3DFMT_DXT5
- { DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_NONE, DDSPF_DXT2 }, // D3DFMT_DXT2 (ignore premultiply)
- { DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_NONE, DDSPF_DXT4 }, // D3DFMT_DXT4 (ignore premultiply)
+ { DXGI_FORMAT_BC2_UNORM, CONV_FLAGS_PMALPHA, DDSPF_DXT2 }, // D3DFMT_DXT2
+ { DXGI_FORMAT_BC3_UNORM, CONV_FLAGS_PMALPHA, DDSPF_DXT4 }, // D3DFMT_DXT4
{ DXGI_FORMAT_BC4_UNORM, CONV_FLAGS_NONE, DDSPF_BC4_UNORM },
{ DXGI_FORMAT_BC4_SNORM, CONV_FLAGS_NONE, DDSPF_BC4_SNORM },
@@ -114,21 +118,14 @@ const LegacyDDS g_LegacyDDSMap[] =
{ DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND
| CONV_FLAGS_PAL8, { sizeof(DDS_PIXELFORMAT), DDS_PAL8, 0, 8, 0, 0, 0, 0 } }, // D3DFMT_P8
-#ifdef DXGI_1_2_FORMATS
{ DXGI_FORMAT_B4G4R4A4_UNORM, CONV_FLAGS_4444, DDSPF_A4R4G4B4 }, // D3DFMT_A4R4G4B4 (uses DXGI 1.2 format)
{ DXGI_FORMAT_B4G4R4A4_UNORM, CONV_FLAGS_NOALPHA
| CONV_FLAGS_4444, { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0f00, 0x00f0, 0x000f, 0x0000 } }, // D3DFMT_X4R4G4B4 (uses DXGI 1.2 format)
{ DXGI_FORMAT_B4G4R4A4_UNORM, CONV_FLAGS_EXPAND
| CONV_FLAGS_44, { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0x0f, 0x00, 0x00, 0xf0 } }, // D3DFMT_A4L4 (uses DXGI 1.2 format)
-#else // !DXGI_1_2_FORMATS
- { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND
- | CONV_FLAGS_4444, DDSPF_A4R4G4B4 }, // D3DFMT_A4R4G4B4
- { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND
- | CONV_FLAGS_NOALPHA
- | CONV_FLAGS_4444, { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0f00, 0x00f0, 0x000f, 0x0000 } }, // D3DFMT_X4R4G4B4
- { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND
- | CONV_FLAGS_44, { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0x0f, 0x00, 0x00, 0xf0 } }, // D3DFMT_A4L4
-#endif
+
+ { DXGI_FORMAT_YUY2, CONV_FLAGS_NONE, DDSPF_YUY2 }, // D3DFMT_YUY2 (uses DXGI 1.2 format)
+ { DXGI_FORMAT_YUY2, CONV_FLAGS_SWIZZLE, { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('U','Y','V','Y'), 0, 0, 0, 0, 0 } }, // D3DFMT_UYVY (uses DXGI 1.2 format)
};
// Note that many common DDS reader/writers (including D3DX) swap the
@@ -140,13 +137,11 @@ const LegacyDDS g_LegacyDDSMap[] =
// We do not support the following legacy Direct3D 9 formats:
// BumpDuDv D3DFMT_V8U8, D3DFMT_Q8W8V8U8, D3DFMT_V16U16, D3DFMT_A2W10V10U10
// BumpLuminance D3DFMT_L6V5U5, D3DFMT_X8L8V8U8
-// FourCC "UYVY" D3DFMT_UYVY
-// FourCC "YUY2" D3DFMT_YUY2
// FourCC 117 D3DFMT_CxV8U8
// ZBuffer D3DFMT_D16_LOCKABLE
// FourCC 82 D3DFMT_D32F_LOCKABLE
-static DXGI_FORMAT _GetDXGIFormat( const DDS_PIXELFORMAT& ddpf, DWORD flags, _Inout_opt_ DWORD* convFlags )
+static DXGI_FORMAT _GetDXGIFormat( const DDS_PIXELFORMAT& ddpf, DWORD flags, _Inout_ DWORD& convFlags )
{
const size_t MAP_SIZE = sizeof(g_LegacyDDSMap) / sizeof(LegacyDDS);
size_t index = 0;
@@ -192,8 +187,7 @@ static DXGI_FORMAT _GetDXGIFormat( const DDS_PIXELFORMAT& ddpf, DWORD flags, _In
cflags ^= CONV_FLAGS_SWIZZLE;
}
- if ( convFlags )
- *convFlags = cflags;
+ convFlags = cflags;
return format;
}
@@ -202,8 +196,8 @@ static DXGI_FORMAT _GetDXGIFormat( const DDS_PIXELFORMAT& ddpf, DWORD flags, _In
//-------------------------------------------------------------------------------------
// Decodes DDS header including optional DX10 extended header
//-------------------------------------------------------------------------------------
-static HRESULT _DecodeDDSHeader( _In_bytecount_(size) LPCVOID pSource, size_t size, DWORD flags, _Out_ TexMetadata& metadata,
- _Inout_opt_ DWORD* convFlags )
+static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t size, DWORD flags, _Out_ TexMetadata& metadata,
+ _Inout_ DWORD& convFlags )
{
if ( !pSource )
return E_INVALIDARG;
@@ -222,8 +216,7 @@ static HRESULT _DecodeDDSHeader( _In_bytecount_(size) LPCVOID pSource, size_t si
return E_FAIL;
}
- const DDS_HEADER* pHeader = reinterpret_cast<const DDS_HEADER*>( (const uint8_t*)pSource + sizeof( uint32_t ) );
- assert( pHeader );
+ auto pHeader = reinterpret_cast<const DDS_HEADER*>( (const uint8_t*)pSource + sizeof( uint32_t ) );
// Verify header to validate DDS file
if ( pHeader->dwSize != sizeof(DDS_HEADER)
@@ -241,14 +234,13 @@ static HRESULT _DecodeDDSHeader( _In_bytecount_(size) LPCVOID pSource, size_t si
&& (MAKEFOURCC( 'D', 'X', '1', '0' ) == pHeader->ddspf.dwFourCC) )
{
// Buffer must be big enough for both headers and magic value
- if ( size < (sizeof(DDS_HEADER)+sizeof(uint32_t)+sizeof(DDS_HEADER_DXT10)) )
+ if ( size < ( sizeof(DDS_HEADER) + sizeof(uint32_t) + sizeof(DDS_HEADER_DXT10) ) )
{
return E_FAIL;
}
- const DDS_HEADER_DXT10* d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( (const uint8_t*)pSource + sizeof( uint32_t ) + sizeof(DDS_HEADER) );
- if ( convFlags )
- *convFlags |= CONV_FLAGS_DX10;
+ auto d3d10ext = reinterpret_cast<const DDS_HEADER_DXT10*>( (const uint8_t*)pSource + sizeof( uint32_t ) + sizeof(DDS_HEADER) );
+ convFlags |= CONV_FLAGS_DX10;
metadata.arraySize = d3d10ext->arraySize;
if ( metadata.arraySize == 0 )
@@ -257,11 +249,15 @@ static HRESULT _DecodeDDSHeader( _In_bytecount_(size) LPCVOID pSource, size_t si
}
metadata.format = d3d10ext->dxgiFormat;
- if ( !IsValid( metadata.format ) )
+ if ( !IsValid( metadata.format ) || IsPalettized( metadata.format ) )
{
- HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
+ static_assert( TEX_MISC_TEXTURECUBE == DDS_RESOURCE_MISC_TEXTURECUBE, "DDS header mismatch");
+
+ metadata.miscFlags = d3d10ext->miscFlag & ~TEX_MISC_TEXTURECUBE;
+
switch ( d3d10ext->resourceDimension )
{
case DDS_DIMENSION_TEXTURE1D:
@@ -309,6 +305,16 @@ static HRESULT _DecodeDDSHeader( _In_bytecount_(size) LPCVOID pSource, size_t si
default:
return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
}
+
+ static_assert( TEX_MISC2_ALPHA_MODE_MASK == DDS_MISC_FLAGS2_ALPHA_MODE_MASK, "DDS header mismatch");
+
+ static_assert( TEX_ALPHA_MODE_UNKNOWN == DDS_ALPHA_MODE_UNKNOWN, "DDS header mismatch");
+ static_assert( TEX_ALPHA_MODE_STRAIGHT == DDS_ALPHA_MODE_STRAIGHT, "DDS header mismatch");
+ static_assert( TEX_ALPHA_MODE_PREMULTIPLIED == DDS_ALPHA_MODE_PREMULTIPLIED, "DDS header mismatch");
+ static_assert( TEX_ALPHA_MODE_OPAQUE == DDS_ALPHA_MODE_OPAQUE, "DDS header mismatch");
+ static_assert( TEX_ALPHA_MODE_CUSTOM == DDS_ALPHA_MODE_CUSTOM, "DDS header mismatch");
+
+ metadata.miscFlags2 = d3d10ext->miscFlags2;
}
else
{
@@ -345,6 +351,31 @@ static HRESULT _DecodeDDSHeader( _In_bytecount_(size) LPCVOID pSource, size_t si
if ( metadata.format == DXGI_FORMAT_UNKNOWN )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
+ if ( convFlags & CONV_FLAGS_PMALPHA )
+ metadata.miscFlags2 |= TEX_ALPHA_MODE_PREMULTIPLIED;
+
+ // Special flag for handling LUMINANCE legacy formats
+ if ( flags & DDS_FLAGS_EXPAND_LUMINANCE )
+ {
+ switch ( metadata.format )
+ {
+ case DXGI_FORMAT_R8_UNORM:
+ metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ convFlags |= CONV_FLAGS_L8 | CONV_FLAGS_EXPAND;
+ break;
+
+ case DXGI_FORMAT_R8G8_UNORM:
+ metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ convFlags |= CONV_FLAGS_A8L8 | CONV_FLAGS_EXPAND;
+ break;
+
+ case DXGI_FORMAT_R16_UNORM:
+ metadata.format = DXGI_FORMAT_R16G16B16A16_UNORM;
+ convFlags |= CONV_FLAGS_L16 | CONV_FLAGS_EXPAND;
+ break;
+ }
+ }
}
// Special flag for handling BGR DXGI 1.1 formats
@@ -354,38 +385,32 @@ static HRESULT _DecodeDDSHeader( _In_bytecount_(size) LPCVOID pSource, size_t si
{
case DXGI_FORMAT_B8G8R8A8_UNORM:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
- if ( convFlags )
- *convFlags |= CONV_FLAGS_SWIZZLE;
+ convFlags |= CONV_FLAGS_SWIZZLE;
break;
case DXGI_FORMAT_B8G8R8X8_UNORM:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
- if ( convFlags )
- *convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
+ convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
break;
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
- if ( convFlags )
- *convFlags |= CONV_FLAGS_SWIZZLE;
+ convFlags |= CONV_FLAGS_SWIZZLE;
break;
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
- if ( convFlags )
- *convFlags |= CONV_FLAGS_SWIZZLE;
+ convFlags |= CONV_FLAGS_SWIZZLE;
break;
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
- if ( convFlags )
- *convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
+ convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
break;
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
- if ( convFlags )
- *convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
+ convFlags |= CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA;
break;
}
}
@@ -397,16 +422,11 @@ static HRESULT _DecodeDDSHeader( _In_bytecount_(size) LPCVOID pSource, size_t si
{
case DXGI_FORMAT_B5G6R5_UNORM:
case DXGI_FORMAT_B5G5R5A1_UNORM:
-#ifdef DXGI_1_2_FORMATS
case DXGI_FORMAT_B4G4R4A4_UNORM:
-#endif
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
- if ( convFlags )
- {
- *convFlags |= CONV_FLAGS_EXPAND;
- if ( metadata.format == DXGI_FORMAT_B5G6R5_UNORM )
- *convFlags |= CONV_FLAGS_NOALPHA;
- }
+ convFlags |= CONV_FLAGS_EXPAND;
+ if ( metadata.format == DXGI_FORMAT_B5G6R5_UNORM )
+ convFlags |= CONV_FLAGS_NOALPHA;
}
}
@@ -417,19 +437,30 @@ static HRESULT _DecodeDDSHeader( _In_bytecount_(size) LPCVOID pSource, size_t si
//-------------------------------------------------------------------------------------
// Encodes DDS file header (magic value, header, optional DX10 extended header)
//-------------------------------------------------------------------------------------
-HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
- _Out_opt_cap_x_(maxsize) LPVOID pDestination, _In_ size_t maxsize, _Out_ size_t& required )
+_Use_decl_annotations_
+HRESULT _EncodeDDSHeader( const TexMetadata& metadata, DWORD flags,
+ LPVOID pDestination, size_t maxsize, size_t& required )
{
- assert( IsValid( metadata.format ) && !IsVideo( metadata.format ) );
+ if ( !IsValid( metadata.format ) )
+ return E_INVALIDARG;
+
+ if ( IsPalettized( metadata.format ) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if ( metadata.arraySize > 1 )
{
- if ( (metadata.arraySize != 6) || (metadata.dimension != TEX_DIMENSION_TEXTURE2D) || !(metadata.miscFlags & TEX_MISC_TEXTURECUBE) )
+ if ( (metadata.arraySize != 6) || (metadata.dimension != TEX_DIMENSION_TEXTURE2D) || !(metadata.IsCubemap()) )
{
+ // Texture1D arrays, Texture2D arrays, and Cubemap arrays must be stored using 'DX10' extended header
flags |= DDS_FLAGS_FORCE_DX10_EXT;
}
}
+ if ( flags & DDS_FLAGS_FORCE_DX10_EXT_MISC2 )
+ {
+ flags |= DDS_FLAGS_FORCE_DX10_EXT;
+ }
+
DDS_PIXELFORMAT ddpf = { 0 };
if ( !(flags & DDS_FLAGS_FORCE_DX10_EXT) )
{
@@ -444,8 +475,8 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
case DXGI_FORMAT_R8G8_B8G8_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_R8G8_B8G8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_G8R8_G8B8_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_G8R8_G8B8, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC1_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_DXT1, sizeof(DDS_PIXELFORMAT) ); break;
- case DXGI_FORMAT_BC2_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_DXT3, sizeof(DDS_PIXELFORMAT) ); break;
- case DXGI_FORMAT_BC3_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_DXT5, sizeof(DDS_PIXELFORMAT) ); break;
+ case DXGI_FORMAT_BC2_UNORM: memcpy_s( &ddpf, sizeof(ddpf), metadata.IsPMAlpha() ? (&DDSPF_DXT2) : (&DDSPF_DXT3), sizeof(DDS_PIXELFORMAT) ); break;
+ case DXGI_FORMAT_BC3_UNORM: memcpy_s( &ddpf, sizeof(ddpf), metadata.IsPMAlpha() ? (&DDSPF_DXT4) : (&DDSPF_DXT5), sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC4_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_BC4_UNORM, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC4_SNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_BC4_SNORM, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_BC5_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_BC5_UNORM, sizeof(DDS_PIXELFORMAT) ); break;
@@ -454,10 +485,8 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
case DXGI_FORMAT_B5G5R5A1_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_A1R5G5B5, sizeof(DDS_PIXELFORMAT) ); break;
case DXGI_FORMAT_B8G8R8A8_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_A8R8G8B8, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.1
case DXGI_FORMAT_B8G8R8X8_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_X8R8G8B8, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.1
-
-#ifdef DXGI_1_2_FORMATS
- case DXGI_FORMAT_B4G4R4A4_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_A4R4G4B4, sizeof(DDS_PIXELFORMAT) ); break;
-#endif
+ case DXGI_FORMAT_B4G4R4A4_UNORM: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_A4R4G4B4, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.2
+ case DXGI_FORMAT_YUY2: memcpy_s( &ddpf, sizeof(ddpf), &DDSPF_YUY2, sizeof(DDS_PIXELFORMAT) ); break; // DXGI 1.2
// Legacy D3DX formats using D3DFMT enum value as FourCC
case DXGI_FORMAT_R32G32B32A32_FLOAT:
@@ -500,7 +529,7 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
*reinterpret_cast<uint32_t*>(pDestination) = DDS_MAGIC;
- DDS_HEADER* header = reinterpret_cast<DDS_HEADER*>( reinterpret_cast<uint8_t*>(pDestination) + sizeof(uint32_t) );
+ auto header = reinterpret_cast<DDS_HEADER*>( reinterpret_cast<uint8_t*>(pDestination) + sizeof(uint32_t) );
assert( header );
memset( header, 0, sizeof(DDS_HEADER ) );
@@ -512,7 +541,7 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
{
header->dwFlags |= DDS_HEADER_FLAGS_MIPMAP;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( metadata.mipLevels > 0xFFFFFFFF )
return E_INVALIDARG;
#endif
@@ -526,8 +555,8 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
switch( metadata.dimension )
{
case TEX_DIMENSION_TEXTURE1D:
-#ifdef _AMD64_
- if ( metadata.height > 0xFFFFFFFF )
+#ifdef _M_X64
+ if ( metadata.width > 0xFFFFFFFF )
return E_INVALIDARG;
#endif
@@ -536,7 +565,7 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
break;
case TEX_DIMENSION_TEXTURE2D:
-#ifdef _AMD64_
+#ifdef _M_X64
if ( metadata.height > 0xFFFFFFFF
|| metadata.width > 0xFFFFFFFF)
return E_INVALIDARG;
@@ -546,7 +575,7 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
header->dwWidth = static_cast<uint32_t>( metadata.width );
header->dwDepth = 1;
- if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE )
+ if ( metadata.IsCubemap() )
{
header->dwCaps |= DDS_SURFACE_FLAGS_CUBEMAP;
header->dwCaps2 |= DDS_CUBEMAP_ALLFACES;
@@ -554,7 +583,7 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
break;
case TEX_DIMENSION_TEXTURE3D:
-#ifdef _AMD64_
+#ifdef _M_X64
if ( metadata.height > 0xFFFFFFFF
|| metadata.width > 0xFFFFFFFF
|| metadata.depth > 0xFFFFFFFF )
@@ -575,7 +604,7 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
size_t rowPitch, slicePitch;
ComputePitch( metadata.format, metadata.width, metadata.height, rowPitch, slicePitch, CP_FLAGS_NONE );
-#ifdef _AMD64_
+#ifdef _M_X64
if ( slicePitch > 0xFFFFFFFF
|| rowPitch > 0xFFFFFFFF )
return E_FAIL;
@@ -596,18 +625,22 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
{
memcpy_s( &header->ddspf, sizeof(header->ddspf), &DDSPF_DX10, sizeof(DDS_PIXELFORMAT) );
- DDS_HEADER_DXT10* ext = reinterpret_cast<DDS_HEADER_DXT10*>( reinterpret_cast<uint8_t*>(header) + sizeof(DDS_HEADER) );
+ auto ext = reinterpret_cast<DDS_HEADER_DXT10*>( reinterpret_cast<uint8_t*>(header) + sizeof(DDS_HEADER) );
assert( ext );
memset( ext, 0, sizeof(DDS_HEADER_DXT10) );
ext->dxgiFormat = metadata.format;
ext->resourceDimension = metadata.dimension;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( metadata.arraySize > 0xFFFFFFFF )
return E_INVALIDARG;
#endif
+ static_assert( TEX_MISC_TEXTURECUBE == DDS_RESOURCE_MISC_TEXTURECUBE, "DDS header mismatch");
+
+ ext->miscFlag = metadata.miscFlags & ~TEX_MISC_TEXTURECUBE;
+
if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE )
{
ext->miscFlag |= TEX_MISC_TEXTURECUBE;
@@ -618,6 +651,20 @@ HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
{
ext->arraySize = static_cast<UINT>( metadata.arraySize );
}
+
+ static_assert( TEX_MISC2_ALPHA_MODE_MASK == DDS_MISC_FLAGS2_ALPHA_MODE_MASK, "DDS header mismatch");
+
+ static_assert( TEX_ALPHA_MODE_UNKNOWN == DDS_ALPHA_MODE_UNKNOWN, "DDS header mismatch");
+ static_assert( TEX_ALPHA_MODE_STRAIGHT == DDS_ALPHA_MODE_STRAIGHT, "DDS header mismatch");
+ static_assert( TEX_ALPHA_MODE_PREMULTIPLIED == DDS_ALPHA_MODE_PREMULTIPLIED, "DDS header mismatch");
+ static_assert( TEX_ALPHA_MODE_OPAQUE == DDS_ALPHA_MODE_OPAQUE, "DDS header mismatch");
+ static_assert( TEX_ALPHA_MODE_CUSTOM == DDS_ALPHA_MODE_CUSTOM, "DDS header mismatch");
+
+ if ( flags & DDS_FLAGS_FORCE_DX10_EXT_MISC2 )
+ {
+ // This was formerly 'reserved'. D3DX10 and D3DX11 will fail if this value is anything other than 0
+ ext->miscFlags2 = metadata.miscFlags2;
+ }
}
else
{
@@ -642,6 +689,9 @@ enum TEXP_LEGACY_FORMAT
TEXP_LEGACY_A8P8,
TEXP_LEGACY_A4L4,
TEXP_LEGACY_B4G4R4A4,
+ TEXP_LEGACY_L8,
+ TEXP_LEGACY_L16,
+ TEXP_LEGACY_A8L8
};
inline static TEXP_LEGACY_FORMAT _FindLegacyFormat( DWORD flags )
@@ -660,21 +710,26 @@ inline static TEXP_LEGACY_FORMAT _FindLegacyFormat( DWORD flags )
lformat = TEXP_LEGACY_A8R3G3B2;
else if ( flags & CONV_FLAGS_44 )
lformat = TEXP_LEGACY_A4L4;
-#ifndef DXGI_1_2_FORMATS
else if ( flags & CONV_FLAGS_4444 )
lformat = TEXP_LEGACY_B4G4R4A4;
-#endif
+ else if ( flags & CONV_FLAGS_L8 )
+ lformat = TEXP_LEGACY_L8;
+ else if ( flags & CONV_FLAGS_L16 )
+ lformat = TEXP_LEGACY_L16;
+ else if ( flags & CONV_FLAGS_A8L8 )
+ lformat = TEXP_LEGACY_A8L8;
return lformat;
}
-static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, size_t outSize, _In_ DXGI_FORMAT outFormat,
- _In_bytecount_(inSize) LPCVOID pSource, size_t inSize, _In_ TEXP_LEGACY_FORMAT inFormat,
- _In_opt_count_c_(256) const uint32_t* pal8, _In_ DWORD flags )
+_Success_(return != false)
+static bool _LegacyExpandScanline( _Out_writes_bytes_(outSize) LPVOID pDestination, size_t outSize, _In_ DXGI_FORMAT outFormat,
+ _In_reads_bytes_(inSize) LPCVOID pSource, size_t inSize, _In_ TEXP_LEGACY_FORMAT inFormat,
+ _In_reads_opt_(256) const uint32_t* pal8, _In_ DWORD flags )
{
assert( pDestination && outSize > 0 );
assert( pSource && inSize > 0 );
- assert( IsValid(outFormat) && !IsVideo(outFormat) );
+ assert( IsValid(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat) );
switch( inFormat )
{
@@ -683,11 +738,12 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
return false;
// D3DFMT_R8G8B8 -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 3 && outSize >= 4 )
{
const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 3, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 2 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 3, ocount += 4 )
{
// 24bpp Direct3D 9 files are actually BGR, so need to swizzle as well
uint32_t t1 = ( *(sPtr) << 16 );
@@ -697,19 +753,21 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
*(dPtr++) = t1 | t2 | t3 | 0xff000000;
sPtr += 3;
}
+ return true;
}
- return true;
+ return false;
case TEXP_LEGACY_R3G3B2:
switch( outFormat )
{
case DXGI_FORMAT_R8G8B8A8_UNORM:
// D3DFMT_R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 1 && outSize >= 4 )
{
const uint8_t* __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < inSize ) && ( ocount < ( outSize - 3 ) ) ); ++icount, ocount += 4 )
{
uint8_t t = *(sPtr++);
@@ -719,16 +777,18 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
*(dPtr++) = t1 | t2 | t3 | 0xff000000;
}
+ return true;
}
- return true;
+ return false;
case DXGI_FORMAT_B5G6R5_UNORM:
// D3DFMT_R3G3B2 -> DXGI_FORMAT_B5G6R5_UNORM
+ if ( inSize >= 1 && outSize >= 2 )
{
const uint8_t* __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 2 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < inSize ) && ( ocount < ( outSize - 1 ) ) ); ++icount, ocount += 2 )
{
uint8_t t = *(sPtr++);
@@ -738,8 +798,9 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
*(dPtr++) = t1 | t2 | t3;
}
+ return true;
}
- return true;
+ return false;
}
break;
@@ -748,11 +809,12 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
return false;
// D3DFMT_A8R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 2 && outSize >= 4 )
{
const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
{
uint16_t t = *(sPtr++);
@@ -763,37 +825,41 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
*(dPtr++) = t1 | t2 | t3 | ta;
}
+ return true;
}
- return true;
+ return false;
case TEXP_LEGACY_P8:
if ( (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8 )
return false;
// D3DFMT_P8 -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 1 && outSize >= 4 )
{
const uint8_t* __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < inSize ) && ( ocount < ( outSize - 3 ) ) ); ++icount, ocount += 4 )
{
uint8_t t = *(sPtr++);
*(dPtr++) = pal8[ t ];
}
+ return true;
}
- return true;
+ return false;
case TEXP_LEGACY_A8P8:
if ( (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8 )
return false;
// D3DFMT_A8P8 -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 2 && outSize >= 4 )
{
const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
{
uint16_t t = *(sPtr++);
@@ -802,20 +868,21 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
*(dPtr++) = t1 | ta;
}
+ return true;
}
- return true;
+ return false;
case TEXP_LEGACY_A4L4:
switch( outFormat )
{
-#ifdef DXGI_1_2_FORMATS
case DXGI_FORMAT_B4G4R4A4_UNORM :
// D3DFMT_A4L4 -> DXGI_FORMAT_B4G4R4A4_UNORM
+ if ( inSize >= 1 && outSize >= 2 )
{
const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 2 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < inSize ) && ( ocount < ( outSize - 1 ) ) ); ++icount, ocount += 2 )
{
uint8_t t = *(sPtr++);
@@ -824,17 +891,18 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
*(dPtr++) = t1 | (t1 << 4) | (t1 << 8) | ta;
}
+ return true;
}
- return true;
-#endif // DXGI_1_2_FORMATS
+ return false;
case DXGI_FORMAT_R8G8B8A8_UNORM:
// D3DFMT_A4L4 -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 1 && outSize >= 4 )
{
const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < inSize ) && ( ocount < ( outSize - 3 ) ) ); ++icount, ocount += 4 )
{
uint8_t t = *(sPtr++);
@@ -843,22 +911,23 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
*(dPtr++) = t1 | (t1 << 8) | (t1 << 16) | ta;
}
+ return true;
}
- return true;
+ return false;
}
break;
-#ifndef DXGI_1_2_FORMATS
case TEXP_LEGACY_B4G4R4A4:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
// D3DFMT_A4R4G4B4 -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 2 && outSize >= 4 )
{
const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
- for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
+ for( size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
{
uint16_t t = *(sPtr++);
@@ -869,9 +938,80 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
*(dPtr++) = t1 | t2 | t3 | ta;
}
+ return true;
}
- return true;
-#endif
+ return false;
+
+ case TEXP_LEGACY_L8:
+ if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
+ return false;
+
+ // D3DFMT_L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 1 && outSize >= 4 )
+ {
+ const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
+ uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
+
+ for( size_t ocount = 0, icount = 0; ( ( icount < inSize ) && ( ocount < ( outSize - 3 ) ) ); ++icount, ocount += 4 )
+ {
+ uint32_t t1 = *(sPtr++);
+ uint32_t t2 = (t1 << 8);
+ uint32_t t3 = (t1 << 16);
+
+ *(dPtr++) = t1 | t2 | t3 | 0xff000000;
+ }
+ return true;
+ }
+ return false;
+
+ case TEXP_LEGACY_L16:
+ if (outFormat != DXGI_FORMAT_R16G16B16A16_UNORM)
+ return false;
+
+ // D3DFMT_L16 -> DXGI_FORMAT_R16G16B16A16_UNORM
+ if ( inSize >= 2 && outSize >= 8 )
+ {
+ const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
+ uint64_t * __restrict dPtr = reinterpret_cast<uint64_t*>(pDestination);
+
+ for( size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 7 ) ) ); icount += 2, ocount += 8 )
+ {
+ uint16_t t = *(sPtr++);
+
+ uint64_t t1 = t;
+ uint64_t t2 = (t1 << 16);
+ uint64_t t3 = (t1 << 32);
+
+ *(dPtr++) = t1 | t2 | t3 | 0xffff000000000000;
+ }
+ return true;
+ }
+ return false;
+
+ case TEXP_LEGACY_A8L8:
+ if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
+ return false;
+
+ // D3DFMT_A8L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
+ if ( inSize >= 2 && outSize >= 4 )
+ {
+ const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
+ uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
+
+ for( size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
+ {
+ uint16_t t = *(sPtr++);
+
+ uint32_t t1 = (t & 0xff);
+ uint32_t t2 = (t1 << 8);
+ uint32_t t3 = (t1 << 16);
+ uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : ((t & 0xff00) << 16);
+
+ *(dPtr++) = t1 | t2 | t3 | ta;
+ }
+ return true;
+ }
+ return false;
}
return false;
@@ -881,22 +1021,22 @@ static bool _LegacyExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, s
//-------------------------------------------------------------------------------------
// Converts or copies image data from pPixels into scratch image data
//-------------------------------------------------------------------------------------
-static HRESULT _CopyImage( _In_bytecount_(size) const void* pPixels, _In_ size_t size,
- _In_ const TexMetadata& metadata, _In_ DWORD cpFlags, _In_ DWORD convFlags, _In_opt_count_c_(256) const uint32_t *pal8, _In_ const ScratchImage& image )
+static HRESULT _CopyImage( _In_reads_bytes_(size) const void* pPixels, _In_ size_t size,
+ _In_ const TexMetadata& metadata, _In_ DWORD cpFlags, _In_ DWORD convFlags, _In_reads_opt_(256) const uint32_t *pal8, _In_ const ScratchImage& image )
{
assert( pPixels );
assert( image.GetPixels() );
if ( !size )
return E_FAIL;
-
+
if ( convFlags & CONV_FLAGS_EXPAND )
{
if ( convFlags & CONV_FLAGS_888 )
cpFlags |= CP_FLAGS_24BPP;
- else if ( convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444 | CONV_FLAGS_8332 | CONV_FLAGS_A8P8 ) )
+ else if ( convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444 | CONV_FLAGS_8332 | CONV_FLAGS_A8P8 | CONV_FLAGS_L16 | CONV_FLAGS_A8L8) )
cpFlags |= CP_FLAGS_16BPP;
- else if ( convFlags & (CONV_FLAGS_44 | CONV_FLAGS_332 | CONV_FLAGS_PAL8) )
+ else if ( convFlags & (CONV_FLAGS_44 | CONV_FLAGS_332 | CONV_FLAGS_PAL8 | CONV_FLAGS_L8) )
cpFlags |= CP_FLAGS_8BPP;
}
@@ -909,7 +1049,12 @@ static HRESULT _CopyImage( _In_bytecount_(size) const void* pPixels, _In_ size_t
assert( pixelSize <= size );
- std::unique_ptr<Image[]> timages( new Image[nimages] );
+ std::unique_ptr<Image[]> timages( new (std::nothrow) Image[nimages] );
+ if ( !timages )
+ {
+ return E_OUTOFMEMORY;
+ }
+
if ( !_SetupImageArray( (uint8_t*)pPixels, size, metadata, cpFlags, timages.get(), nimages ) )
{
return E_FAIL;
@@ -962,17 +1107,27 @@ static HRESULT _CopyImage( _In_bytecount_(size) const void* pPixels, _In_ size_t
size_t csize = std::min<size_t>( images[ index ].slicePitch, timages[ index ].slicePitch );
memcpy_s( pDest, images[ index ].slicePitch, pSrc, csize );
}
+ else if ( IsPlanar( metadata.format ) )
+ {
+ size_t count = ComputeScanlines( metadata.format, images[ index ].height );
+ if ( !count )
+ return E_UNEXPECTED;
+
+ size_t csize = std::min<size_t>( dpitch, spitch );
+ for( size_t h = 0; h < count; ++h )
+ {
+ memcpy_s( pDest, dpitch, pSrc, csize );
+ pSrc += spitch;
+ pDest += dpitch;
+ }
+ }
else
{
for( size_t h = 0; h < images[ index ].height; ++h )
{
if ( convFlags & CONV_FLAGS_EXPAND )
{
-#ifdef DXGI_1_2_FORMATS
if ( convFlags & (CONV_FLAGS_565|CONV_FLAGS_5551|CONV_FLAGS_4444) )
-#else
- if ( convFlags & (CONV_FLAGS_565|CONV_FLAGS_5551) )
-#endif
{
if ( !_ExpandScanline( pDest, dpitch, DXGI_FORMAT_R8G8B8A8_UNORM,
pSrc, spitch,
@@ -1040,17 +1195,18 @@ static HRESULT _CopyImage( _In_bytecount_(size) const void* pPixels, _In_ size_t
size_t csize = std::min<size_t>( images[ index ].slicePitch, timages[ index ].slicePitch );
memcpy_s( pDest, images[ index ].slicePitch, pSrc, csize );
}
+ else if ( IsPlanar( metadata.format ) )
+ {
+ // Direct3D does not support any planar formats for Texture3D
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
else
{
for( size_t h = 0; h < images[ index ].height; ++h )
{
if ( convFlags & CONV_FLAGS_EXPAND )
{
-#ifdef DXGI_1_2_FORMATS
if ( convFlags & (CONV_FLAGS_565|CONV_FLAGS_5551|CONV_FLAGS_4444) )
-#else
- if ( convFlags & (CONV_FLAGS_565|CONV_FLAGS_5551) )
-#endif
{
if ( !_ExpandScanline( pDest, dpitch, DXGI_FORMAT_R8G8B8A8_UNORM,
pSrc, spitch,
@@ -1106,6 +1262,9 @@ static HRESULT _CopyImageInPlace( DWORD convFlags, _In_ const ScratchImage& imag
const TexMetadata& metadata = image.GetMetadata();
+ if ( IsPlanar( metadata.format ) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
DWORD tflags = (convFlags & CONV_FLAGS_NOALPHA) ? TEXP_SCANLINE_SETALPHA : 0;
if ( convFlags & CONV_FLAGS_SWIZZLE )
tflags |= TEXP_SCANLINE_LEGACY;
@@ -1146,20 +1305,23 @@ static HRESULT _CopyImageInPlace( DWORD convFlags, _In_ const ScratchImage& imag
// Obtain metadata from DDS file in memory/on disk
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT GetMetadataFromDDSMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadata& metadata )
{
if ( !pSource || size == 0 )
return E_INVALIDARG;
- return _DecodeDDSHeader( pSource, size, flags, metadata, 0 );
+ DWORD convFlags = 0;
+ return _DecodeDDSHeader( pSource, size, flags, metadata, convFlags );
}
+_Use_decl_annotations_
HRESULT GetMetadataFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata& metadata )
{
if ( !szFile )
return E_INVALIDARG;
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0 ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( szFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
@@ -1209,13 +1371,15 @@ HRESULT GetMetadataFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata& metada
return HRESULT_FROM_WIN32( GetLastError() );
}
- return _DecodeDDSHeader( header, bytesRead, flags, metadata, 0 );
+ DWORD convFlags = 0;
+ return _DecodeDDSHeader( header, bytesRead, flags, metadata, convFlags );
}
//-------------------------------------------------------------------------------------
// Load a DDS file in memory
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT LoadFromDDSMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadata* metadata, ScratchImage& image )
{
if ( !pSource || size == 0 )
@@ -1225,7 +1389,7 @@ HRESULT LoadFromDDSMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadat
DWORD convFlags = 0;
TexMetadata mdata;
- HRESULT hr = _DecodeDDSHeader( pSource, size, flags, mdata, &convFlags );
+ HRESULT hr = _DecodeDDSHeader( pSource, size, flags, mdata, convFlags );
if ( FAILED(hr) )
return hr;
@@ -1249,7 +1413,7 @@ HRESULT LoadFromDDSMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadat
if ( FAILED(hr) )
return hr;
- LPCVOID pPixels = reinterpret_cast<LPCVOID>( reinterpret_cast<const uint8_t*>(pSource) + offset );
+ auto pPixels = reinterpret_cast<LPCVOID>( reinterpret_cast<const uint8_t*>(pSource) + offset );
assert( pPixels );
hr = _CopyImage( pPixels, size - offset, mdata,
(flags & DDS_FLAGS_LEGACY_DWORD) ? CP_FLAGS_LEGACY_DWORD : CP_FLAGS_NONE, convFlags, pal8, image );
@@ -1268,6 +1432,7 @@ HRESULT LoadFromDDSMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadat
//-------------------------------------------------------------------------------------
// Load a DDS file from disk
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT LoadFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, ScratchImage& image )
{
if ( !szFile )
@@ -1275,7 +1440,7 @@ HRESULT LoadFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
image.Release();
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle ( CreateFile2( szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0 ) ) );
#else
ScopedHandle hFile( safe_handle ( CreateFileW( szFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
@@ -1328,7 +1493,7 @@ HRESULT LoadFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
DWORD convFlags = 0;
TexMetadata mdata;
- HRESULT hr = _DecodeDDSHeader( header, bytesRead, flags, mdata, &convFlags );
+ HRESULT hr = _DecodeDDSHeader( header, bytesRead, flags, mdata, convFlags );
if ( FAILED(hr) )
return hr;
@@ -1349,7 +1514,7 @@ HRESULT LoadFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
std::unique_ptr<uint32_t[]> pal8;
if ( convFlags & CONV_FLAGS_PAL8 )
{
- pal8.reset( new uint32_t[256] );
+ pal8.reset( new (std::nothrow) uint32_t[256] );
if ( !pal8 )
{
return E_OUTOFMEMORY;
@@ -1378,7 +1543,7 @@ HRESULT LoadFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
if ( (convFlags & CONV_FLAGS_EXPAND) || (flags & DDS_FLAGS_LEGACY_DWORD) )
{
- std::unique_ptr<uint8_t[]> temp( new uint8_t[ remaining ] );
+ std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ remaining ] );
if ( !temp )
{
image.Release();
@@ -1408,7 +1573,7 @@ HRESULT LoadFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
}
else
{
- if ( remaining > image.GetPixelsSize() )
+ if ( remaining < image.GetPixelsSize() )
{
image.Release();
return E_FAIL;
@@ -1442,6 +1607,7 @@ HRESULT LoadFromDDSFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
//-------------------------------------------------------------------------------------
// Save a DDS file to memory
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT SaveToDDSMemory( const Image* images, size_t nimages, const TexMetadata& metadata, DWORD flags, Blob& blob )
{
if ( !images || (nimages == 0) )
@@ -1453,11 +1619,28 @@ HRESULT SaveToDDSMemory( const Image* images, size_t nimages, const TexMetadata&
if ( FAILED(hr) )
return hr;
+ bool fastpath = true;
+
for( size_t i = 0; i < nimages; ++i )
{
- required += images[ i ].slicePitch;
if ( !images[ i ].pixels )
return E_POINTER;
+
+ if ( images[ i ].format != metadata.format )
+ return E_FAIL;
+
+ size_t ddsRowPitch, ddsSlicePitch;
+ ComputePitch( metadata.format, images[ i ].width, images[ i ].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE );
+
+ assert( images[ i ].rowPitch > 0 );
+ assert( images[ i ].slicePitch > 0 );
+
+ if ( ( images[ i ].rowPitch != ddsRowPitch ) || ( images[ i ].slicePitch != ddsSlicePitch ) )
+ {
+ fastpath = false;
+ }
+
+ required += ddsSlicePitch;
}
assert( required > 0 );
@@ -1468,7 +1651,7 @@ HRESULT SaveToDDSMemory( const Image* images, size_t nimages, const TexMetadata&
if ( FAILED(hr) )
return hr;
- uint8_t* pDestination = reinterpret_cast<uint8_t*>( blob.GetBufferPointer() );
+ auto pDestination = reinterpret_cast<uint8_t*>( blob.GetBufferPointer() );
assert( pDestination );
hr = _EncodeDDSHeader( metadata, flags, pDestination, blob.GetBufferSize(), required );
@@ -1503,14 +1686,47 @@ HRESULT SaveToDDSMemory( const Image* images, size_t nimages, const TexMetadata&
return E_FAIL;
}
- size_t pixsize = images[ index ].slicePitch;
- if ( memcpy_s( pDestination, remaining, images[ index ].pixels, pixsize ) )
+ if ( fastpath )
{
- blob.Release();
- return E_FAIL;
+ size_t pixsize = images[ index ].slicePitch;
+ if ( memcpy_s( pDestination, remaining, images[ index ].pixels, pixsize ) )
+ {
+ blob.Release();
+ return E_FAIL;
+ }
+
+ pDestination += pixsize;
+ remaining -= pixsize;
+ }
+ else
+ {
+ size_t ddsRowPitch, ddsSlicePitch;
+ ComputePitch( metadata.format, images[ index ].width, images[ index ].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE );
+
+ size_t rowPitch = images[ index ].rowPitch;
+
+ const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(images[ index ].pixels);
+ uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
+
+ size_t lines = ComputeScanlines( metadata.format, images[ index ].height );
+ size_t csize = std::min<size_t>( rowPitch, ddsRowPitch );
+ size_t tremaining = remaining;
+ for( size_t j = 0; j < lines; ++j )
+ {
+ if ( memcpy_s( dPtr, tremaining, sPtr, csize ) )
+ {
+ blob.Release();
+ return E_FAIL;
+ }
+
+ sPtr += rowPitch;
+ dPtr += ddsRowPitch;
+ tremaining -= ddsRowPitch;
+ }
+
+ pDestination += ddsSlicePitch;
+ remaining -= ddsSlicePitch;
}
- pDestination += pixsize;
- remaining -= pixsize;
++index;
}
@@ -1539,14 +1755,47 @@ HRESULT SaveToDDSMemory( const Image* images, size_t nimages, const TexMetadata&
return E_FAIL;
}
- size_t pixsize = images[ index ].slicePitch;
- if ( memcpy_s( pDestination, remaining, images[ index ].pixels, pixsize ) )
+ if ( fastpath )
{
- blob.Release();
- return E_FAIL;
+ size_t pixsize = images[ index ].slicePitch;
+ if ( memcpy_s( pDestination, remaining, images[ index ].pixels, pixsize ) )
+ {
+ blob.Release();
+ return E_FAIL;
+ }
+
+ pDestination += pixsize;
+ remaining -= pixsize;
+ }
+ else
+ {
+ size_t ddsRowPitch, ddsSlicePitch;
+ ComputePitch( metadata.format, images[ index ].width, images[ index ].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE );
+
+ size_t rowPitch = images[ index ].rowPitch;
+
+ const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(images[ index ].pixels);
+ uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
+
+ size_t lines = ComputeScanlines( metadata.format, images[ index ].height );
+ size_t csize = std::min<size_t>( rowPitch, ddsRowPitch );
+ size_t tremaining = remaining;
+ for( size_t j = 0; j < lines; ++j )
+ {
+ if ( memcpy_s( dPtr, tremaining, sPtr, csize ) )
+ {
+ blob.Release();
+ return E_FAIL;
+ }
+
+ sPtr += rowPitch;
+ dPtr += ddsRowPitch;
+ tremaining -= ddsRowPitch;
+ }
+
+ pDestination += ddsSlicePitch;
+ remaining -= ddsSlicePitch;
}
- pDestination += pixsize;
- remaining -= pixsize;
++index;
}
@@ -1569,6 +1818,7 @@ HRESULT SaveToDDSMemory( const Image* images, size_t nimages, const TexMetadata&
//-------------------------------------------------------------------------------------
// Save a DDS file to disk
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT SaveToDDSFile( const Image* images, size_t nimages, const TexMetadata& metadata, DWORD flags, LPCWSTR szFile )
{
if ( !szFile )
@@ -1583,7 +1833,7 @@ HRESULT SaveToDDSFile( const Image* images, size_t nimages, const TexMetadata& m
return hr;
// Create file and write header
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( szFile, GENERIC_WRITE, 0, CREATE_ALWAYS, 0 ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( szFile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) );
@@ -1621,16 +1871,50 @@ HRESULT SaveToDDSFile( const Image* images, size_t nimages, const TexMetadata& m
if ( !images[ index ].pixels )
return E_POINTER;
- size_t pixsize = images[ index ].slicePitch;
+ assert( images[ index ].rowPitch > 0 );
+ assert( images[ index ].slicePitch > 0 );
+
+ size_t ddsRowPitch, ddsSlicePitch;
+ ComputePitch( metadata.format, images[ index ].width, images[ index ].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE );
- if ( !WriteFile( hFile.get(), images[ index ].pixels, static_cast<DWORD>( pixsize ), &bytesWritten, 0 ) )
+ if ( images[ index ].slicePitch == ddsSlicePitch )
{
- return HRESULT_FROM_WIN32( GetLastError() );
- }
+ if ( !WriteFile( hFile.get(), images[ index ].pixels, static_cast<DWORD>( ddsSlicePitch ), &bytesWritten, 0 ) )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
- if ( bytesWritten != pixsize )
+ if ( bytesWritten != ddsSlicePitch )
+ {
+ return E_FAIL;
+ }
+ }
+ else
{
- return E_FAIL;
+ size_t rowPitch = images[ index ].rowPitch;
+ if ( rowPitch < ddsRowPitch )
+ {
+ // DDS uses 1-byte alignment, so if this is happening then the input pitch isn't actually a full line of data
+ return E_FAIL;
+ }
+
+ const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(images[ index ].pixels);
+
+ size_t lines = ComputeScanlines( metadata.format, images[ index ].height );
+ for( size_t j = 0; j < lines; ++j )
+ {
+ if ( !WriteFile( hFile.get(), sPtr, static_cast<DWORD>( ddsRowPitch ), &bytesWritten, 0 ) )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ if ( bytesWritten != ddsRowPitch )
+ {
+ return E_FAIL;
+ }
+
+ sPtr += rowPitch;
+ }
}
}
}
@@ -1655,16 +1939,50 @@ HRESULT SaveToDDSFile( const Image* images, size_t nimages, const TexMetadata& m
if ( !images[ index ].pixels )
return E_POINTER;
- size_t pixsize = images[ index ].slicePitch;
+ assert( images[ index ].rowPitch > 0 );
+ assert( images[ index ].slicePitch > 0 );
- if ( !WriteFile( hFile.get(), images[ index ].pixels, static_cast<DWORD>( pixsize ), &bytesWritten, 0 ) )
+ size_t ddsRowPitch, ddsSlicePitch;
+ ComputePitch( metadata.format, images[ index ].width, images[ index ].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE );
+
+ if ( images[ index ].slicePitch == ddsSlicePitch )
{
- return HRESULT_FROM_WIN32( GetLastError() );
- }
+ if ( !WriteFile( hFile.get(), images[ index ].pixels, static_cast<DWORD>( ddsSlicePitch ), &bytesWritten, 0 ) )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
- if ( bytesWritten != pixsize )
+ if ( bytesWritten != ddsSlicePitch )
+ {
+ return E_FAIL;
+ }
+ }
+ else
{
- return E_FAIL;
+ size_t rowPitch = images[ index ].rowPitch;
+ if ( rowPitch < ddsRowPitch )
+ {
+ // DDS uses 1-byte alignment, so if this is happening then the input pitch isn't actually a full line of data
+ return E_FAIL;
+ }
+
+ const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(images[ index ].pixels);
+
+ size_t lines = ComputeScanlines( metadata.format, images[ index ].height );
+ for( size_t j = 0; j < lines; ++j )
+ {
+ if ( !WriteFile( hFile.get(), sPtr, static_cast<DWORD>( ddsRowPitch ), &bytesWritten, 0 ) )
+ {
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ if ( bytesWritten != ddsRowPitch )
+ {
+ return E_FAIL;
+ }
+
+ sPtr += rowPitch;
+ }
}
}
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp
index c90ea090..4459e7f3 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexFlipRotate.cpp
@@ -15,6 +15,8 @@
#include "DirectXTexP.h"
+using Microsoft::WRL::ComPtr;
+
namespace DirectX
{
@@ -33,15 +35,15 @@ static HRESULT _PerformFlipRotateUsingWIC( _In_ const Image& srcImage, _In_ DWOR
if ( !pWIC )
return E_NOINTERFACE;
- ScopedObject<IWICBitmap> source;
+ ComPtr<IWICBitmap> source;
HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
- srcImage.pixels, &source );
+ srcImage.pixels, source.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICBitmapFlipRotator> FR;
- hr = pWIC->CreateBitmapFlipRotator( &FR );
+ ComPtr<IWICBitmapFlipRotator> FR;
+ hr = pWIC->CreateBitmapFlipRotator( FR.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -126,6 +128,7 @@ static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD
//-------------------------------------------------------------------------------------
// Flip/rotate image
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
{
if ( !srcImage.pixels )
@@ -134,7 +137,7 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
if ( !flags )
return E_INVALIDARG;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
return E_INVALIDARG;
#endif
@@ -207,6 +210,7 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
//-------------------------------------------------------------------------------------
// Flip/rotate image (complex)
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DWORD flags, ScratchImage& result )
{
@@ -278,7 +282,7 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
return E_FAIL;
}
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
return E_FAIL;
#endif
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexImage.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexImage.cpp
index 95d54267..28f433ec 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexImage.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexImage.cpp
@@ -20,10 +20,12 @@ namespace DirectX
extern bool _CalculateMipLevels( _In_ size_t width, _In_ size_t height, _Inout_ size_t& mipLevels );
extern bool _CalculateMipLevels3D( _In_ size_t width, _In_ size_t height, _In_ size_t depth, _Inout_ size_t& mipLevels );
+extern bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage );
//-------------------------------------------------------------------------------------
// Determines number of image array entries and pixel size
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
size_t& nImages, size_t& pixelSize )
{
@@ -102,6 +104,7 @@ void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
//-------------------------------------------------------------------------------------
// Fills in the image array entries
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
const TexMetadata& metadata, DWORD cpFlags,
Image* images, size_t nImages )
@@ -226,14 +229,39 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
// ScratchImage - Bitmap image container
//=====================================================================================
+ScratchImage& ScratchImage::operator= (ScratchImage&& moveFrom)
+{
+ if ( this != &moveFrom )
+ {
+ Release();
+
+ _nimages = moveFrom._nimages;
+ _size = moveFrom._size;
+ _metadata = moveFrom._metadata;
+ _image = moveFrom._image;
+ _memory = moveFrom._memory;
+
+ moveFrom._nimages = 0;
+ moveFrom._size = 0;
+ moveFrom._image = nullptr;
+ moveFrom._memory = nullptr;
+ }
+ return *this;
+}
+
+
//-------------------------------------------------------------------------------------
// Methods
//-------------------------------------------------------------------------------------
-HRESULT ScratchImage::Initialize( const TexMetadata& mdata )
+_Use_decl_annotations_
+HRESULT ScratchImage::Initialize( const TexMetadata& mdata, DWORD flags )
{
- if ( !IsValid(mdata.format) || IsVideo(mdata.format) )
+ if ( !IsValid(mdata.format) )
return E_INVALIDARG;
+ if ( IsPalettized(mdata.format) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
size_t mipLevels = mdata.mipLevels;
switch( mdata.dimension )
@@ -250,7 +278,7 @@ HRESULT ScratchImage::Initialize( const TexMetadata& mdata )
if ( !mdata.width || !mdata.height || mdata.depth != 1 || !mdata.arraySize )
return E_INVALIDARG;
- if ( mdata.miscFlags & TEX_MISC_TEXTURECUBE )
+ if ( mdata.IsCubemap() )
{
if ( (mdata.arraySize % 6) != 0 )
return E_INVALIDARG;
@@ -263,7 +291,7 @@ HRESULT ScratchImage::Initialize( const TexMetadata& mdata )
case TEX_DIMENSION_TEXTURE3D:
if ( !mdata.width || !mdata.height || !mdata.depth || mdata.arraySize != 1 )
return E_INVALIDARG;
-
+
if ( !_CalculateMipLevels3D(mdata.width,mdata.height,mdata.depth,mipLevels) )
return E_INVALIDARG;
break;
@@ -279,14 +307,15 @@ HRESULT ScratchImage::Initialize( const TexMetadata& mdata )
_metadata.depth = mdata.depth;
_metadata.arraySize = mdata.arraySize;
_metadata.mipLevels = mipLevels;
- _metadata.miscFlags = mdata.miscFlags & TEX_MISC_TEXTURECUBE;
+ _metadata.miscFlags = mdata.miscFlags;
+ _metadata.miscFlags2 = mdata.miscFlags2;
_metadata.format = mdata.format;
_metadata.dimension = mdata.dimension;
size_t pixelSize, nimages;
- _DetermineImageArray( _metadata, CP_FLAGS_NONE, nimages, pixelSize );
+ _DetermineImageArray( _metadata, flags, nimages, pixelSize );
- _image = new Image[ nimages ];
+ _image = new (std::nothrow) Image[ nimages ];
if ( !_image )
return E_OUTOFMEMORY;
@@ -300,7 +329,7 @@ HRESULT ScratchImage::Initialize( const TexMetadata& mdata )
return E_OUTOFMEMORY;
}
_size = pixelSize;
- if ( !_SetupImageArray( _memory, pixelSize, _metadata, CP_FLAGS_NONE, _image, nimages ) )
+ if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
{
Release();
return E_FAIL;
@@ -309,13 +338,14 @@ HRESULT ScratchImage::Initialize( const TexMetadata& mdata )
return S_OK;
}
-HRESULT ScratchImage::Initialize1D( DXGI_FORMAT fmt, size_t length, size_t arraySize, size_t mipLevels )
+_Use_decl_annotations_
+HRESULT ScratchImage::Initialize1D( DXGI_FORMAT fmt, size_t length, size_t arraySize, size_t mipLevels, DWORD flags )
{
- if ( !IsValid(fmt) || IsVideo(fmt) || !length || !arraySize )
+ if ( !length || !arraySize )
return E_INVALIDARG;
// 1D is a special case of the 2D case
- HRESULT hr = Initialize2D( fmt, length, 1, arraySize, mipLevels );
+ HRESULT hr = Initialize2D( fmt, length, 1, arraySize, mipLevels, flags );
if ( FAILED(hr) )
return hr;
@@ -324,11 +354,15 @@ HRESULT ScratchImage::Initialize1D( DXGI_FORMAT fmt, size_t length, size_t array
return S_OK;
}
-HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height, size_t arraySize, size_t mipLevels )
+_Use_decl_annotations_
+HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height, size_t arraySize, size_t mipLevels, DWORD flags )
{
- if ( !IsValid(fmt) || IsVideo(fmt) || !width || !height || !arraySize )
+ if ( !IsValid(fmt) || !width || !height || !arraySize )
return E_INVALIDARG;
+ if ( IsPalettized(fmt) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
if ( !_CalculateMipLevels(width,height,mipLevels) )
return E_INVALIDARG;
@@ -340,13 +374,14 @@ HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height
_metadata.arraySize = arraySize;
_metadata.mipLevels = mipLevels;
_metadata.miscFlags = 0;
+ _metadata.miscFlags2 = 0;
_metadata.format = fmt;
_metadata.dimension = TEX_DIMENSION_TEXTURE2D;
size_t pixelSize, nimages;
- _DetermineImageArray( _metadata, CP_FLAGS_NONE, nimages, pixelSize );
+ _DetermineImageArray( _metadata, flags, nimages, pixelSize );
- _image = new Image[ nimages ];
+ _image = new (std::nothrow) Image[ nimages ];
if ( !_image )
return E_OUTOFMEMORY;
@@ -360,7 +395,7 @@ HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height
return E_OUTOFMEMORY;
}
_size = pixelSize;
- if ( !_SetupImageArray( _memory, pixelSize, _metadata, CP_FLAGS_NONE, _image, nimages ) )
+ if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
{
Release();
return E_FAIL;
@@ -369,11 +404,15 @@ HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height
return S_OK;
}
-HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height, size_t depth, size_t mipLevels )
+_Use_decl_annotations_
+HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height, size_t depth, size_t mipLevels, DWORD flags )
{
- if ( !IsValid(fmt) || IsVideo(fmt) || !width || !height || !depth )
+ if ( !IsValid(fmt) || !width || !height || !depth )
return E_INVALIDARG;
+ if ( IsPalettized(fmt) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
if ( !_CalculateMipLevels3D(width,height,depth,mipLevels) )
return E_INVALIDARG;
@@ -385,13 +424,14 @@ HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height
_metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures
_metadata.mipLevels = mipLevels;
_metadata.miscFlags = 0;
+ _metadata.miscFlags2 = 0;
_metadata.format = fmt;
_metadata.dimension = TEX_DIMENSION_TEXTURE3D;
size_t pixelSize, nimages;
- _DetermineImageArray( _metadata, CP_FLAGS_NONE, nimages, pixelSize );
+ _DetermineImageArray( _metadata, flags, nimages, pixelSize );
- _image = new Image[ nimages ];
+ _image = new (std::nothrow) Image[ nimages ];
if ( !_image )
{
Release();
@@ -408,7 +448,7 @@ HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height
}
_size = pixelSize;
- if ( !_SetupImageArray( _memory, pixelSize, _metadata, CP_FLAGS_NONE, _image, nimages ) )
+ if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
{
Release();
return E_FAIL;
@@ -417,13 +457,14 @@ HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height
return S_OK;
}
-HRESULT ScratchImage::InitializeCube( DXGI_FORMAT fmt, size_t width, size_t height, size_t nCubes, size_t mipLevels )
+_Use_decl_annotations_
+HRESULT ScratchImage::InitializeCube( DXGI_FORMAT fmt, size_t width, size_t height, size_t nCubes, size_t mipLevels, DWORD flags )
{
- if ( !IsValid(fmt) || IsVideo(fmt) || !width || !height || !nCubes )
+ if ( !width || !height || !nCubes )
return E_INVALIDARG;
-
+
// A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube
- HRESULT hr = Initialize2D( fmt, width, height, nCubes * 6, mipLevels );
+ HRESULT hr = Initialize2D( fmt, width, height, nCubes * 6, mipLevels, flags );
if ( FAILED(hr) )
return hr;
@@ -432,34 +473,45 @@ HRESULT ScratchImage::InitializeCube( DXGI_FORMAT fmt, size_t width, size_t heig
return S_OK;
}
-HRESULT ScratchImage::InitializeFromImage( const Image& srcImage, bool allow1D )
+_Use_decl_annotations_
+HRESULT ScratchImage::InitializeFromImage( const Image& srcImage, bool allow1D, DWORD flags )
{
HRESULT hr = ( srcImage.height > 1 || !allow1D )
- ? Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1 )
- : Initialize1D( srcImage.format, srcImage.width, 1, 1 );
+ ? Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1, flags )
+ : Initialize1D( srcImage.format, srcImage.width, 1, 1, flags );
if ( FAILED(hr) )
return hr;
+ size_t rowCount = ComputeScanlines( srcImage.format, srcImage.height );
+ if ( !rowCount )
+ return E_UNEXPECTED;
+
const uint8_t* sptr = reinterpret_cast<const uint8_t*>( srcImage.pixels );
if ( !sptr )
return E_POINTER;
- uint8_t* dptr = reinterpret_cast<uint8_t*>( _image[0].pixels );
+ auto dptr = reinterpret_cast<uint8_t*>( _image[0].pixels );
if ( !dptr )
return E_POINTER;
- for( size_t y = 0; y < srcImage.height; ++y )
+ size_t spitch = srcImage.rowPitch;
+ size_t dpitch = _image[0].rowPitch;
+
+ size_t size = std::min<size_t>( dpitch, spitch );
+
+ for( size_t y = 0; y < rowCount; ++y )
{
- _CopyScanline( dptr, _image[0].rowPitch, sptr, srcImage.rowPitch, srcImage.format, TEXP_SCANLINE_NONE );
- sptr += srcImage.rowPitch;
- dptr += _image[0].rowPitch;
+ memcpy_s( dptr, dpitch, sptr, size );
+ sptr += spitch;
+ dptr += dpitch;
}
return S_OK;
}
-HRESULT ScratchImage::InitializeArrayFromImages( const Image* images, size_t nImages, bool allow1D )
+_Use_decl_annotations_
+HRESULT ScratchImage::InitializeArrayFromImages( const Image* images, size_t nImages, bool allow1D, DWORD flags )
{
if ( !images || !nImages )
return E_INVALIDARG;
@@ -481,35 +533,45 @@ HRESULT ScratchImage::InitializeArrayFromImages( const Image* images, size_t nIm
}
HRESULT hr = ( height > 1 || !allow1D )
- ? Initialize2D( format, width, height, nImages, 1 )
- : Initialize1D( format, width, nImages, 1 );
+ ? Initialize2D( format, width, height, nImages, 1, flags )
+ : Initialize1D( format, width, nImages, 1, flags );
if ( FAILED(hr) )
return hr;
+ size_t rowCount = ComputeScanlines( format, height );
+ if ( !rowCount )
+ return E_UNEXPECTED;
+
for( size_t index=0; index < nImages; ++index )
{
- const uint8_t* sptr = reinterpret_cast<const uint8_t*>( images[index].pixels );
+ auto sptr = reinterpret_cast<const uint8_t*>( images[index].pixels );
if ( !sptr )
return E_POINTER;
assert( index < _nimages );
- uint8_t* dptr = reinterpret_cast<uint8_t*>( _image[index].pixels );
+ auto dptr = reinterpret_cast<uint8_t*>( _image[index].pixels );
if ( !dptr )
return E_POINTER;
- for( size_t y = 0; y < height; ++y )
+ size_t spitch = images[index].rowPitch;
+ size_t dpitch = _image[index].rowPitch;
+
+ size_t size = std::min<size_t>( dpitch, spitch );
+
+ for( size_t y = 0; y < rowCount; ++y )
{
- _CopyScanline( dptr, _image[index].rowPitch, sptr, images[index].rowPitch, format, TEXP_SCANLINE_NONE );
- sptr += images[index].rowPitch;
- dptr += _image[index].rowPitch;
+ memcpy_s( dptr, dpitch, sptr, size );
+ sptr += spitch;
+ dptr += dpitch;
}
}
return S_OK;
}
-HRESULT ScratchImage::InitializeCubeFromImages( const Image* images, size_t nImages )
+_Use_decl_annotations_
+HRESULT ScratchImage::InitializeCubeFromImages( const Image* images, size_t nImages, DWORD flags )
{
if ( !images || !nImages )
return E_INVALIDARG;
@@ -518,7 +580,7 @@ HRESULT ScratchImage::InitializeCubeFromImages( const Image* images, size_t nIma
if ( ( nImages % 6 ) != 0 )
return E_INVALIDARG;
- HRESULT hr = InitializeArrayFromImages( images, nImages, false );
+ HRESULT hr = InitializeArrayFromImages( images, nImages, false, flags );
if ( FAILED(hr) )
return hr;
@@ -527,7 +589,8 @@ HRESULT ScratchImage::InitializeCubeFromImages( const Image* images, size_t nIma
return S_OK;
}
-HRESULT ScratchImage::Initialize3DFromImages( const Image* images, size_t depth )
+_Use_decl_annotations_
+HRESULT ScratchImage::Initialize3DFromImages( const Image* images, size_t depth, DWORD flags )
{
if ( !images || !depth )
return E_INVALIDARG;
@@ -548,26 +611,35 @@ HRESULT ScratchImage::Initialize3DFromImages( const Image* images, size_t depth
}
}
- HRESULT hr = Initialize3D( format, width, height, depth, 1 );
+ HRESULT hr = Initialize3D( format, width, height, depth, 1, flags );
if ( FAILED(hr) )
return hr;
+ size_t rowCount = ComputeScanlines( format, height );
+ if ( !rowCount )
+ return E_UNEXPECTED;
+
for( size_t slice=0; slice < depth; ++slice )
{
- const uint8_t* sptr = reinterpret_cast<const uint8_t*>( images[slice].pixels );
+ auto sptr = reinterpret_cast<const uint8_t*>( images[slice].pixels );
if ( !sptr )
return E_POINTER;
assert( slice < _nimages );
- uint8_t* dptr = reinterpret_cast<uint8_t*>( _image[slice].pixels );
+ auto dptr = reinterpret_cast<uint8_t*>( _image[slice].pixels );
if ( !dptr )
return E_POINTER;
- for( size_t y = 0; y < height; ++y )
+ size_t spitch = images[slice].rowPitch;
+ size_t dpitch = _image[slice].rowPitch;
+
+ size_t size = std::min<size_t>( dpitch, spitch );
+
+ for( size_t y = 0; y < rowCount; ++y )
{
- _CopyScanline( dptr, _image[slice].rowPitch, sptr, images[slice].rowPitch, format, TEXP_SCANLINE_NONE );
- sptr += images[slice].rowPitch;
- dptr += _image[slice].rowPitch;
+ memcpy_s( dptr, dpitch, sptr, size );
+ sptr += spitch;
+ dptr += dpitch;
}
}
@@ -594,22 +666,15 @@ void ScratchImage::Release()
memset(&_metadata, 0, sizeof(_metadata));
}
+_Use_decl_annotations_
bool ScratchImage::OverrideFormat( DXGI_FORMAT f )
{
if ( !_image )
return false;
- if ( !IsValid( f ) || IsVideo( f ) )
+ if ( !IsValid( f ) || IsPlanar( f ) || IsPalettized( f ) )
return false;
- if ( ( BitsPerPixel( f ) != BitsPerPixel( _metadata.format ) )
- || ( IsCompressed( f ) != IsCompressed( _metadata.format ) )
- || ( IsPacked( f ) != IsPacked( _metadata.format ) ) )
- {
- // Can't change the effective pitch of the format this way
- return false;
- }
-
for( size_t index = 0; index < _nimages; ++index )
{
_image[ index ].format = f;
@@ -620,6 +685,7 @@ bool ScratchImage::OverrideFormat( DXGI_FORMAT f )
return true;
}
+_Use_decl_annotations_
const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const
{
if ( mip >= _metadata.mipLevels )
@@ -671,4 +737,58 @@ const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const
return &_image[index];
}
+bool ScratchImage::IsAlphaAllOpaque() const
+{
+ if ( !_image )
+ return false;
+
+ if ( !HasAlpha( _metadata.format ) )
+ return true;
+
+ if ( IsCompressed( _metadata.format ) )
+ {
+ for( size_t index = 0; index < _nimages; ++index )
+ {
+ if ( !_IsAlphaAllOpaqueBC( _image[ index ] ) )
+ return false;
+ }
+ }
+ else
+ {
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*_metadata.width), 16 ) ) );
+ if ( !scanline )
+ return false;
+
+ static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
+
+ for( size_t index = 0; index < _nimages; ++index )
+ {
+#pragma warning( suppress : 6011 )
+ const Image& img = _image[ index ];
+
+ const uint8_t *pPixels = img.pixels;
+ assert( pPixels );
+
+ for( size_t h = 0; h < img.height; ++h )
+ {
+ if ( !_LoadScanline( scanline.get(), img.width, pPixels, img.rowPitch, img.format ) )
+ return false;
+
+ XMVECTOR* ptr = scanline.get();
+ for( size_t w = 0; w < img.width; ++w )
+ {
+ XMVECTOR alpha = XMVectorSplatW( *ptr );
+ if ( XMVector4Less( alpha, threshold ) )
+ return false;
+ ++ptr;
+ }
+
+ pPixels += img.rowPitch;
+ }
+ }
+ }
+
+ return true;
+}
+
}; // namespace
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexMipmaps.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexMipmaps.cpp
index 1e7e27cd..1599d5c0 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexMipmaps.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexMipmaps.cpp
@@ -15,12 +15,13 @@
#include "DirectXTexP.h"
+#include "filters.h"
+
+using Microsoft::WRL::ComPtr;
+
namespace DirectX
{
-static const XMVECTORF32 s_boxScale = { 0.25f, 0.25f, 0.25f, 0.25f };
-static const XMVECTORF32 s_boxScale3D = { 0.125f, 0.125f, 0.125f, 0.125f };
-
//-------------------------------------------------------------------------------------
// Mipmap helper functions
//-------------------------------------------------------------------------------------
@@ -29,7 +30,9 @@ inline static bool ispow2( _In_ size_t x )
return ((x != 0) && !(x & (x - 1)));
}
-static size_t _CountMips( _In_ size_t width, _In_ size_t height)
+
+//--- mipmap (1D/2D) levels computation ---
+static size_t _CountMips( _In_ size_t width, _In_ size_t height )
{
size_t mipLevels = 1;
@@ -66,7 +69,9 @@ bool _CalculateMipLevels( _In_ size_t width, _In_ size_t height, _Inout_ size_t&
return true;
}
-static size_t _CountMips3D( _In_ size_t width, _In_ size_t height, _In_ size_t depth)
+
+//--- volume mipmap (3D) levels computation ---
+static size_t _CountMips3D( _In_ size_t width, _In_ size_t height, _In_ size_t depth )
{
size_t mipLevels = 1;
@@ -91,14 +96,11 @@ bool _CalculateMipLevels3D( _In_ size_t width, _In_ size_t height, _In_ size_t d
{
if ( mipLevels > 1 )
{
- if ( !ispow2(width) || !ispow2(height) || !ispow2(depth) )
- return false;
-
size_t maxMips = _CountMips3D(width,height,depth);
if ( mipLevels > maxMips )
return false;
}
- else if ( mipLevels == 0 && ispow2(width) && ispow2(height) && ispow2(depth) )
+ else if ( mipLevels == 0 )
{
mipLevels = _CountMips3D(width,height,depth);
}
@@ -109,8 +111,12 @@ bool _CalculateMipLevels3D( _In_ size_t width, _In_ size_t height, _In_ size_t d
return true;
}
+
#ifndef __MINGW32__
+//-------------------------------------------------------------------------------------
+// WIC related helper functions
+//-------------------------------------------------------------------------------------
static HRESULT _EnsureWicBitmapPixelFormat( _In_ IWICImagingFactory* pWIC, _In_ IWICBitmap* src, _In_ DWORD filter,
_In_ const WICPixelFormatGUID& desiredPixelFormat,
_Deref_out_ IWICBitmap** dest )
@@ -132,8 +138,19 @@ static HRESULT _EnsureWicBitmapPixelFormat( _In_ IWICImagingFactory* pWIC, _In_
}
else
{
- ScopedObject<IWICFormatConverter> converter;
- hr = pWIC->CreateFormatConverter( &converter );
+ ComPtr<IWICFormatConverter> converter;
+ hr = pWIC->CreateFormatConverter( converter.GetAddressOf() );
+
+ if ( SUCCEEDED(hr) )
+ {
+ BOOL canConvert = FALSE;
+ hr = converter->CanConvert( actualPixelFormat, desiredPixelFormat, &canConvert );
+ if ( FAILED(hr) || !canConvert )
+ {
+ return E_UNEXPECTED;
+ }
+ }
+
if ( SUCCEEDED(hr) )
{
hr = converter->Initialize( src, desiredPixelFormat, _GetWICDither(filter), 0, 0, WICBitmapPaletteTypeCustom );
@@ -149,6 +166,8 @@ static HRESULT _EnsureWicBitmapPixelFormat( _In_ IWICImagingFactory* pWIC, _In_
return hr;
}
+
+//--- Resizing color and alpha channels separately using WIC ---
HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBitmap* original,
_In_ size_t newWidth, _In_ size_t newHeight, _In_ DWORD filter, _Inout_ const Image* img )
{
@@ -168,13 +187,13 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi
if ( SUCCEEDED(hr) )
{
- ScopedObject<IWICComponentInfo> componentInfo;
- hr = pWIC->CreateComponentInfo( desiredPixelFormat, &componentInfo );
+ ComPtr<IWICComponentInfo> componentInfo;
+ hr = pWIC->CreateComponentInfo( desiredPixelFormat, componentInfo.GetAddressOf() );
- ScopedObject<IWICPixelFormatInfo> pixelFormatInfo;
+ ComPtr<IWICPixelFormatInfo> pixelFormatInfo;
if ( SUCCEEDED(hr) )
{
- hr = componentInfo->QueryInterface( __uuidof(IWICPixelFormatInfo), (void**)&pixelFormatInfo );
+ hr = componentInfo.As( &pixelFormatInfo );
}
UINT bitsPerPixel = 0;
@@ -195,7 +214,7 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi
}
else
{
-#if(_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
+#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
if ( _IsWIC2() )
{
colorBytesInPixel = colorBytesPerPixel = 12;
@@ -216,17 +235,15 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi
}
// Resize color only image (no alpha channel)
- ScopedObject<IWICBitmap> resizedColor;
+ ComPtr<IWICBitmap> resizedColor;
if ( SUCCEEDED(hr) )
{
- ScopedObject<IWICBitmapScaler> colorScaler;
-
- hr = pWIC->CreateBitmapScaler(&colorScaler);
+ ComPtr<IWICBitmapScaler> colorScaler;
+ hr = pWIC->CreateBitmapScaler( colorScaler.GetAddressOf() );
if ( SUCCEEDED(hr) )
{
- ScopedObject<IWICBitmap> converted;
-
- hr = _EnsureWicBitmapPixelFormat( pWIC, original, filter, colorPixelFormat, &converted );
+ ComPtr<IWICBitmap> converted;
+ hr = _EnsureWicBitmapPixelFormat( pWIC, original, filter, colorPixelFormat, converted.GetAddressOf() );
if ( SUCCEEDED(hr) )
{
hr = colorScaler->Initialize( converted.Get(), static_cast<UINT>(newWidth), static_cast<UINT>(newHeight), interpolationMode );
@@ -235,28 +252,25 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi
if ( SUCCEEDED(hr) )
{
- ScopedObject<IWICBitmap> resized;
-
- hr = pWIC->CreateBitmapFromSource( colorScaler.Get(), WICBitmapCacheOnDemand, &resized );
+ ComPtr<IWICBitmap> resized;
+ hr = pWIC->CreateBitmapFromSource( colorScaler.Get(), WICBitmapCacheOnDemand, resized.GetAddressOf() );
if ( SUCCEEDED(hr) )
{
- hr = _EnsureWicBitmapPixelFormat( pWIC, resized.Get(), filter, colorPixelFormat, &resizedColor );
+ hr = _EnsureWicBitmapPixelFormat( pWIC, resized.Get(), filter, colorPixelFormat, resizedColor.GetAddressOf() );
}
}
}
// Resize color+alpha image
- ScopedObject<IWICBitmap> resizedColorWithAlpha;
+ ComPtr<IWICBitmap> resizedColorWithAlpha;
if ( SUCCEEDED(hr) )
{
- ScopedObject<IWICBitmapScaler> colorWithAlphaScaler;
-
- hr = pWIC->CreateBitmapScaler( &colorWithAlphaScaler );
+ ComPtr<IWICBitmapScaler> colorWithAlphaScaler;
+ hr = pWIC->CreateBitmapScaler( colorWithAlphaScaler.GetAddressOf() );
if ( SUCCEEDED(hr) )
{
- ScopedObject<IWICBitmap> converted;
-
- hr = _EnsureWicBitmapPixelFormat( pWIC, original, filter, colorWithAlphaPixelFormat, &converted );
+ ComPtr<IWICBitmap> converted;
+ hr = _EnsureWicBitmapPixelFormat( pWIC, original, filter, colorWithAlphaPixelFormat, converted.GetAddressOf() );
if ( SUCCEEDED(hr) )
{
hr = colorWithAlphaScaler->Initialize( converted.Get(), static_cast<UINT>(newWidth), static_cast<UINT>(newHeight), interpolationMode );
@@ -265,12 +279,11 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi
if ( SUCCEEDED(hr) )
{
- ScopedObject<IWICBitmap> resized;
-
- hr = pWIC->CreateBitmapFromSource( colorWithAlphaScaler.Get(), WICBitmapCacheOnDemand, &resized );
+ ComPtr<IWICBitmap> resized;
+ hr = pWIC->CreateBitmapFromSource( colorWithAlphaScaler.Get(), WICBitmapCacheOnDemand, resized.GetAddressOf() );
if ( SUCCEEDED(hr) )
{
- hr = _EnsureWicBitmapPixelFormat( pWIC, resized.Get(), filter, colorWithAlphaPixelFormat, &resizedColorWithAlpha );
+ hr = _EnsureWicBitmapPixelFormat( pWIC, resized.Get(), filter, colorWithAlphaPixelFormat, resizedColorWithAlpha.GetAddressOf() );
}
}
}
@@ -278,13 +291,12 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi
// Merge pixels (copying color channels from color only image to color+alpha image)
if ( SUCCEEDED(hr) )
{
- ScopedObject<IWICBitmapLock> colorLock;
- ScopedObject<IWICBitmapLock> colorWithAlphaLock;
-
- hr = resizedColor->Lock( nullptr, WICBitmapLockRead, &colorLock );
+ ComPtr<IWICBitmapLock> colorLock;
+ ComPtr<IWICBitmapLock> colorWithAlphaLock;
+ hr = resizedColor->Lock( nullptr, WICBitmapLockRead, colorLock.GetAddressOf() );
if ( SUCCEEDED(hr) )
{
- hr = resizedColorWithAlpha->Lock( nullptr, WICBitmapLockWrite, &colorWithAlphaLock );
+ hr = resizedColorWithAlpha->Lock( nullptr, WICBitmapLockWrite, colorWithAlphaLock.GetAddressOf() );
}
if ( SUCCEEDED(hr) )
@@ -339,6 +351,7 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi
}
else
{
+#pragma warning( suppress : 26014 6386 ) // No overflow possible here
memcpy_s( colorWithAlphaData + colorWithAlphaIndex, colorWithAlphaBytesPerPixel, colorData + colorIndex, colorBytesInPixel );
}
}
@@ -348,8 +361,8 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi
if ( SUCCEEDED(hr) )
{
- ScopedObject<IWICBitmap> wicBitmap;
- hr = _EnsureWicBitmapPixelFormat( pWIC, resizedColorWithAlpha.Get(), filter, desiredPixelFormat, &wicBitmap );
+ ComPtr<IWICBitmap> wicBitmap;
+ hr = _EnsureWicBitmapPixelFormat( pWIC, resizedColorWithAlpha.Get(), filter, desiredPixelFormat, wicBitmap.GetAddressOf() );
if ( SUCCEEDED(hr) )
{
hr = wicBitmap->CopyPixels( nullptr, static_cast<UINT>(img->rowPitch), static_cast<UINT>(img->slicePitch), img->pixels );
@@ -360,9 +373,78 @@ HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBi
}
-//-------------------------------------------------------------------------------------
-// Generate a (2D) mip-map chain from a base image using WIC's image scaler
-//-------------------------------------------------------------------------------------
+//--- determine when to use WIC vs. non-WIC paths ---
+static bool _UseWICFiltering( _In_ DXGI_FORMAT format, _In_ DWORD filter )
+{
+ if ( filter & TEX_FILTER_FORCE_NON_WIC )
+ {
+ // Explicit flag indicates use of non-WIC code paths
+ return false;
+ }
+
+ if ( filter & TEX_FILTER_FORCE_WIC )
+ {
+ // Explicit flag to use WIC code paths, skips all the case checks below
+ return true;
+ }
+
+ if ( IsSRGB(format) || (filter & TEX_FILTER_SRGB) )
+ {
+ // Use non-WIC code paths for sRGB correct filtering
+ return false;
+ }
+
+#if defined(_XBOX_ONE) && defined(_TITLE)
+ if ( format == DXGI_FORMAT_R16G16B16A16_FLOAT
+ || format == DXGI_FORMAT_R16_FLOAT )
+ {
+ // Use non-WIC code paths as these conversions are not supported by Xbox One XDK
+ return false;
+ }
+#endif
+
+ static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
+
+ switch ( filter & TEX_FILTER_MASK )
+ {
+ case TEX_FILTER_LINEAR:
+ if ( filter & TEX_FILTER_WRAP )
+ {
+ // WIC only supports 'clamp' semantics (MIRROR is equivalent to clamp for linear)
+ return false;
+ }
+
+ if ( BitsPerColor(format) > 8 )
+ {
+ // Avoid the WIC bitmap scaler when doing Linear filtering of XR/HDR formats
+ return false;
+ }
+ break;
+
+ case TEX_FILTER_CUBIC:
+ if ( filter & ( TEX_FILTER_WRAP | TEX_FILTER_MIRROR ) )
+ {
+ // WIC only supports 'clamp' semantics
+ return false;
+ }
+
+ if ( BitsPerColor(format) > 8 )
+ {
+ // Avoid the WIC bitmap scaler when doing Cubic filtering of XR/HDR formats
+ return false;
+ }
+ break;
+
+ case TEX_FILTER_TRIANGLE:
+ // WIC does not implement this filter
+ return false;
+ }
+
+ return true;
+}
+
+
+//--- mipmap (1D/2D) generation using WIC image scalar ---
static HRESULT _GenerateMipMapsUsingWIC( _In_ const Image& baseImage, _In_ DWORD filter, _In_ size_t levels,
_In_ const WICPixelFormatGUID& pfGUID, _In_ const ScratchImage& mipChain, _In_ size_t item )
{
@@ -378,10 +460,10 @@ static HRESULT _GenerateMipMapsUsingWIC( _In_ const Image& baseImage, _In_ DWORD
size_t width = baseImage.width;
size_t height = baseImage.height;
- ScopedObject<IWICBitmap> source;
+ ComPtr<IWICBitmap> source;
HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( width ), static_cast<UINT>( height ), pfGUID,
static_cast<UINT>( baseImage.rowPitch ), static_cast<UINT>( baseImage.slicePitch ),
- baseImage.pixels, &source );
+ baseImage.pixels, source.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -403,13 +485,13 @@ static HRESULT _GenerateMipMapsUsingWIC( _In_ const Image& baseImage, _In_ DWORD
pDest += img0->rowPitch;
}
- ScopedObject<IWICComponentInfo> componentInfo;
- hr = pWIC->CreateComponentInfo( pfGUID, &componentInfo );
+ ComPtr<IWICComponentInfo> componentInfo;
+ hr = pWIC->CreateComponentInfo( pfGUID, componentInfo.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICPixelFormatInfo2> pixelFormatInfo;
- hr = componentInfo->QueryInterface( __uuidof(IWICPixelFormatInfo2), (void**)&pixelFormatInfo );
+ ComPtr<IWICPixelFormatInfo2> pixelFormatInfo;
+ hr = componentInfo.As( &pixelFormatInfo );
if ( FAILED(hr) )
return hr;
@@ -441,8 +523,8 @@ static HRESULT _GenerateMipMapsUsingWIC( _In_ const Image& baseImage, _In_ DWORD
}
else
{
- ScopedObject<IWICBitmapScaler> scaler;
- hr = pWIC->CreateBitmapScaler( &scaler );
+ ComPtr<IWICBitmapScaler> scaler;
+ hr = pWIC->CreateBitmapScaler( scaler.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -465,11 +547,18 @@ static HRESULT _GenerateMipMapsUsingWIC( _In_ const Image& baseImage, _In_ DWORD
{
// The WIC bitmap scaler is free to return a different pixel format than the source image, so here we
// convert it back
- ScopedObject<IWICFormatConverter> FC;
- hr = pWIC->CreateFormatConverter( &FC );
+ ComPtr<IWICFormatConverter> FC;
+ hr = pWIC->CreateFormatConverter( FC.GetAddressOf() );
if ( FAILED(hr) )
return hr;
+ BOOL canConvert = FALSE;
+ hr = FC->CanConvert( pfScaler, pfGUID, &canConvert );
+ if ( FAILED(hr) || !canConvert )
+ {
+ return E_UNEXPECTED;
+ }
+
hr = FC->Initialize( scaler.Get(), pfGUID, _GetWICDither( filter ), 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
@@ -486,9 +575,750 @@ static HRESULT _GenerateMipMapsUsingWIC( _In_ const Image& baseImage, _In_ DWORD
//-------------------------------------------------------------------------------------
+// Generate (1D/2D) mip-map helpers (custom filtering)
+//-------------------------------------------------------------------------------------
+static HRESULT _Setup2DMips( _In_reads_(nimages) const Image* baseImages, _In_ size_t nimages, _In_ const TexMetadata& mdata,
+ _Out_ ScratchImage& mipChain )
+{
+ if ( !baseImages || !nimages )
+ return E_INVALIDARG;
+
+ assert( mdata.mipLevels > 1 );
+ assert( mdata.arraySize == nimages );
+ assert( mdata.depth == 1 && mdata.dimension != TEX_DIMENSION_TEXTURE3D );
+ assert( mdata.width == baseImages[0].width );
+ assert( mdata.height == baseImages[0].height );
+ assert( mdata.format == baseImages[0].format );
+
+ HRESULT hr = mipChain.Initialize( mdata );
+ if ( FAILED(hr) )
+ return hr;
+
+ // Copy base image(s) to top of mip chain
+ for( size_t item=0; item < nimages; ++item )
+ {
+ const Image& src = baseImages[item];
+
+ const Image *dest = mipChain.GetImage( 0, item, 0 );
+ if ( !dest )
+ {
+ mipChain.Release();
+ return E_POINTER;
+ }
+
+ assert( src.format == dest->format );
+
+ uint8_t* pDest = dest->pixels;
+ if ( !pDest )
+ {
+ mipChain.Release();
+ return E_POINTER;
+ }
+
+ const uint8_t *pSrc = src.pixels;
+ size_t rowPitch = src.rowPitch;
+ for( size_t h=0; h < mdata.height; ++h )
+ {
+ size_t msize = std::min<size_t>( dest->rowPitch, rowPitch );
+ memcpy_s( pDest, dest->rowPitch, pSrc, msize );
+ pSrc += rowPitch;
+ pDest += dest->rowPitch;
+ }
+ }
+
+ return S_OK;
+}
+
+//--- 2D Point Filter ---
+static HRESULT _Generate2DMipsPointFilter( _In_ size_t levels, _In_ const ScratchImage& mipChain, _In_ size_t item )
+{
+ if ( !mipChain.GetImages() )
+ return E_INVALIDARG;
+
+ // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips)
+
+ assert( levels > 1 );
+
+ size_t width = mipChain.GetMetadata().width;
+ size_t height = mipChain.GetMetadata().height;
+
+ // Allocate temporary space (2 scanlines)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*2), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* row = target + width;
+
+ // Resize base image to each target mip level
+ for( size_t level=1; level < levels; ++level )
+ {
+#ifdef _DEBUG
+ memset( row, 0xCD, sizeof(XMVECTOR)*width );
+#endif
+
+ // 2D point filter
+ const Image* src = mipChain.GetImage( level-1, item, 0 );
+ const Image* dest = mipChain.GetImage( level, item, 0 );
+
+ if ( !src || !dest )
+ return E_POINTER;
+
+ const uint8_t* pSrc = src->pixels;
+ uint8_t* pDest = dest->pixels;
+
+ size_t rowPitch = src->rowPitch;
+
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+
+ size_t xinc = ( width << 16 ) / nwidth;
+ size_t yinc = ( height << 16 ) / nheight;
+
+ size_t lasty = size_t(-1);
+
+ size_t sy = 0;
+ for( size_t y = 0; y < nheight; ++y )
+ {
+ if ( (lasty ^ sy) >> 16 )
+ {
+ if ( !_LoadScanline( row, width, pSrc + ( rowPitch * (sy >> 16) ), rowPitch, src->format ) )
+ return E_FAIL;
+ lasty = sy;
+ }
+
+ size_t sx = 0;
+ for( size_t x = 0; x < nwidth; ++x )
+ {
+ target[ x ] = row[ sx >> 16 ];
+ sx += xinc;
+ }
+
+ if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) )
+ return E_FAIL;
+ pDest += dest->rowPitch;
+
+ sy += yinc;
+ }
+
+ if ( height > 1 )
+ height >>= 1;
+
+ if ( width > 1 )
+ width >>= 1;
+ }
+
+ return S_OK;
+}
+
+
+//--- 2D Box Filter ---
+static HRESULT _Generate2DMipsBoxFilter( _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain, _In_ size_t item )
+{
+ if ( !mipChain.GetImages() )
+ return E_INVALIDARG;
+
+ // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips)
+
+ assert( levels > 1 );
+
+ size_t width = mipChain.GetMetadata().width;
+ size_t height = mipChain.GetMetadata().height;
+
+ if ( !ispow2(width) || !ispow2(height) )
+ return E_FAIL;
+
+ // Allocate temporary space (3 scanlines)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*3), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* urow0 = target + width;
+ XMVECTOR* urow1 = target + width*2;
+
+ const XMVECTOR* urow2 = urow0 + 1;
+ const XMVECTOR* urow3 = urow1 + 1;
+
+ // Resize base image to each target mip level
+ for( size_t level=1; level < levels; ++level )
+ {
+ if ( height <= 1 )
+ {
+ urow1 = urow0;
+ }
+
+ if ( width <= 1 )
+ {
+ urow2 = urow0;
+ urow3 = urow1;
+ }
+
+ // 2D box filter
+ const Image* src = mipChain.GetImage( level-1, item, 0 );
+ const Image* dest = mipChain.GetImage( level, item, 0 );
+
+ if ( !src || !dest )
+ return E_POINTER;
+
+ const uint8_t* pSrc = src->pixels;
+ uint8_t* pDest = dest->pixels;
+
+ size_t rowPitch = src->rowPitch;
+
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+
+ for( size_t y = 0; y < nheight; ++y )
+ {
+ if ( !_LoadScanlineLinear( urow0, width, pSrc, rowPitch, src->format, filter ) )
+ return E_FAIL;
+ pSrc += rowPitch;
+
+ if ( urow0 != urow1 )
+ {
+ if ( !_LoadScanlineLinear( urow1, width, pSrc, rowPitch, src->format, filter ) )
+ return E_FAIL;
+ pSrc += rowPitch;
+ }
+
+ for( size_t x = 0; x < nwidth; ++x )
+ {
+ size_t x2 = x << 1;
+
+ AVERAGE4( target[ x ], urow0[ x2 ], urow1[ x2 ], urow2[ x2 ], urow3[ x2 ] );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) )
+ return E_FAIL;
+ pDest += dest->rowPitch;
+ }
+
+ if ( height > 1 )
+ height >>= 1;
+
+ if ( width > 1 )
+ width >>= 1;
+ }
+
+ return S_OK;
+}
+
+
+//--- 2D Linear Filter ---
+static HRESULT _Generate2DMipsLinearFilter( _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain, _In_ size_t item )
+{
+ if ( !mipChain.GetImages() )
+ return E_INVALIDARG;
+
+ // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips)
+
+ assert( levels > 1 );
+
+ size_t width = mipChain.GetMetadata().width;
+ size_t height = mipChain.GetMetadata().height;
+
+ // Allocate temporary space (3 scanlines, plus X and Y filters)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*3), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ std::unique_ptr<LinearFilter[]> lf( new (std::nothrow) LinearFilter[ width+height ] );
+ if ( !lf )
+ return E_OUTOFMEMORY;
+
+ LinearFilter* lfX = lf.get();
+ LinearFilter* lfY = lf.get() + width;
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* row0 = target + width;
+ XMVECTOR* row1 = target + width*2;
+
+ // Resize base image to each target mip level
+ for( size_t level=1; level < levels; ++level )
+ {
+ // 2D linear filter
+ const Image* src = mipChain.GetImage( level-1, item, 0 );
+ const Image* dest = mipChain.GetImage( level, item, 0 );
+
+ if ( !src || !dest )
+ return E_POINTER;
+
+ const uint8_t* pSrc = src->pixels;
+ uint8_t* pDest = dest->pixels;
+
+ size_t rowPitch = src->rowPitch;
+
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ _CreateLinearFilter( width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, lfX );
+
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+ _CreateLinearFilter( height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, lfY );
+
+#ifdef _DEBUG
+ memset( row0, 0xCD, sizeof(XMVECTOR)*width );
+ memset( row1, 0xDD, sizeof(XMVECTOR)*width );
+#endif
+
+ size_t u0 = size_t(-1);
+ size_t u1 = size_t(-1);
+
+ for( size_t y = 0; y < nheight; ++y )
+ {
+ auto& toY = lfY[ y ];
+
+ if ( toY.u0 != u0 )
+ {
+ if ( toY.u0 != u1 )
+ {
+ u0 = toY.u0;
+
+ if ( !_LoadScanlineLinear( row0, width, pSrc + (rowPitch * u0), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+ else
+ {
+ u0 = u1;
+ u1 = size_t(-1);
+
+ std::swap( row0, row1 );
+ }
+ }
+
+ if ( toY.u1 != u1 )
+ {
+ u1 = toY.u1;
+
+ if ( !_LoadScanlineLinear( row1, width, pSrc + (rowPitch * u1), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+
+ for( size_t x = 0; x < nwidth; ++x )
+ {
+ auto& toX = lfX[ x ];
+
+ BILINEAR_INTERPOLATE( target[x], toX, toY, row0, row1 );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) )
+ return E_FAIL;
+ pDest += dest->rowPitch;
+ }
+
+ if ( height > 1 )
+ height >>= 1;
+
+ if ( width > 1 )
+ width >>= 1;
+ }
+
+ return S_OK;
+}
+
+
+//--- 2D Cubic Filter ---
+static HRESULT _Generate2DMipsCubicFilter( _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain, _In_ size_t item )
+{
+ if ( !mipChain.GetImages() )
+ return E_INVALIDARG;
+
+ // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips)
+
+ assert( levels > 1 );
+
+ size_t width = mipChain.GetMetadata().width;
+ size_t height = mipChain.GetMetadata().height;
+
+ // Allocate temporary space (5 scanlines, plus X and Y filters)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*5), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ std::unique_ptr<CubicFilter[]> cf( new (std::nothrow) CubicFilter[ width+height ] );
+ if ( !cf )
+ return E_OUTOFMEMORY;
+
+ CubicFilter* cfX = cf.get();
+ CubicFilter* cfY = cf.get() + width;
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* row0 = target + width;
+ XMVECTOR* row1 = target + width*2;
+ XMVECTOR* row2 = target + width*3;
+ XMVECTOR* row3 = target + width*4;
+
+ // Resize base image to each target mip level
+ for( size_t level=1; level < levels; ++level )
+ {
+ // 2D cubic filter
+ const Image* src = mipChain.GetImage( level-1, item, 0 );
+ const Image* dest = mipChain.GetImage( level, item, 0 );
+
+ if ( !src || !dest )
+ return E_POINTER;
+
+ const uint8_t* pSrc = src->pixels;
+ uint8_t* pDest = dest->pixels;
+
+ size_t rowPitch = src->rowPitch;
+
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ _CreateCubicFilter( width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, (filter & TEX_FILTER_MIRROR_U) != 0, cfX );
+
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+ _CreateCubicFilter( height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, (filter & TEX_FILTER_MIRROR_V) != 0, cfY );
+
+#ifdef _DEBUG
+ memset( row0, 0xCD, sizeof(XMVECTOR)*width );
+ memset( row1, 0xDD, sizeof(XMVECTOR)*width );
+ memset( row2, 0xED, sizeof(XMVECTOR)*width );
+ memset( row3, 0xFD, sizeof(XMVECTOR)*width );
+#endif
+
+ size_t u0 = size_t(-1);
+ size_t u1 = size_t(-1);
+ size_t u2 = size_t(-1);
+ size_t u3 = size_t(-1);
+
+ for( size_t y = 0; y < nheight; ++y )
+ {
+ auto& toY = cfY[ y ];
+
+ // Scanline 1
+ if ( toY.u0 != u0 )
+ {
+ if ( toY.u0 != u1 && toY.u0 != u2 && toY.u0 != u3 )
+ {
+ u0 = toY.u0;
+
+ if ( !_LoadScanlineLinear( row0, width, pSrc + (rowPitch * u0), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+ else if ( toY.u0 == u1 )
+ {
+ u0 = u1;
+ u1 = size_t(-1);
+
+ std::swap( row0, row1 );
+ }
+ else if ( toY.u0 == u2 )
+ {
+ u0 = u2;
+ u2 = size_t(-1);
+
+ std::swap( row0, row2 );
+ }
+ else if ( toY.u0 == u3 )
+ {
+ u0 = u3;
+ u3 = size_t(-1);
+
+ std::swap( row0, row3 );
+ }
+ }
+
+ // Scanline 2
+ if ( toY.u1 != u1 )
+ {
+ if ( toY.u1 != u2 && toY.u1 != u3 )
+ {
+ u1 = toY.u1;
+
+ if ( !_LoadScanlineLinear( row1, width, pSrc + (rowPitch * u1), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+ else if ( toY.u1 == u2 )
+ {
+ u1 = u2;
+ u2 = size_t(-1);
+
+ std::swap( row1, row2 );
+ }
+ else if ( toY.u1 == u3 )
+ {
+ u1 = u3;
+ u3 = size_t(-1);
+
+ std::swap( row1, row3 );
+ }
+ }
+
+ // Scanline 3
+ if ( toY.u2 != u2 )
+ {
+ if ( toY.u2 != u3 )
+ {
+ u2 = toY.u2;
+
+ if ( !_LoadScanlineLinear( row2, width, pSrc + (rowPitch * u2), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+ else
+ {
+ u2 = u3;
+ u3 = size_t(-1);
+
+ std::swap( row2, row3 );
+ }
+ }
+
+ // Scanline 4
+ if ( toY.u3 != u3 )
+ {
+ u3 = toY.u3;
+
+ if ( !_LoadScanlineLinear( row3, width, pSrc + (rowPitch * u3), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+
+ for( size_t x = 0; x < nwidth; ++x )
+ {
+ auto& toX = cfX[ x ];
+
+ XMVECTOR C0, C1, C2, C3;
+
+ CUBIC_INTERPOLATE( C0, toX.x, row0[ toX.u0 ], row0[ toX.u1 ], row0[ toX.u2 ], row0[ toX.u3 ] );
+ CUBIC_INTERPOLATE( C1, toX.x, row1[ toX.u0 ], row1[ toX.u1 ], row1[ toX.u2 ], row1[ toX.u3 ] );
+ CUBIC_INTERPOLATE( C2, toX.x, row2[ toX.u0 ], row2[ toX.u1 ], row2[ toX.u2 ], row2[ toX.u3 ] );
+ CUBIC_INTERPOLATE( C3, toX.x, row3[ toX.u0 ], row3[ toX.u1 ], row3[ toX.u2 ], row3[ toX.u3 ] );
+
+ CUBIC_INTERPOLATE( target[x], toY.x, C0, C1, C2, C3 );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) )
+ return E_FAIL;
+ pDest += dest->rowPitch;
+ }
+
+ if ( height > 1 )
+ height >>= 1;
+
+ if ( width > 1 )
+ width >>= 1;
+ }
+
+ return S_OK;
+}
+
+
+//--- 2D Triangle Filter ---
+static HRESULT _Generate2DMipsTriangleFilter( _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain, _In_ size_t item )
+{
+ if ( !mipChain.GetImages() )
+ return E_INVALIDARG;
+
+ using namespace TriangleFilter;
+
+ // This assumes that the base image is already placed into the mipChain at the top level... (see _Setup2DMips)
+
+ assert( levels > 1 );
+
+ size_t width = mipChain.GetMetadata().width;
+ size_t height = mipChain.GetMetadata().height;
+
+ // Allocate initial temporary space (1 scanline, accumulation rows, plus X and Y filters)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( sizeof(XMVECTOR) * width, 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ std::unique_ptr<TriangleRow[]> rowActive( new (std::nothrow) TriangleRow[ height ] );
+ if ( !rowActive )
+ return E_OUTOFMEMORY;
+
+ TriangleRow * rowFree = nullptr;
+
+ std::unique_ptr<Filter> tfX, tfY;
+
+ XMVECTOR* row = scanline.get();
+
+ // Resize base image to each target mip level
+ for( size_t level=1; level < levels; ++level )
+ {
+ // 2D triangle filter
+ const Image* src = mipChain.GetImage( level-1, item, 0 );
+ const Image* dest = mipChain.GetImage( level, item, 0 );
+
+ if ( !src || !dest )
+ return E_POINTER;
+
+ const uint8_t* pSrc = src->pixels;
+ size_t rowPitch = src->rowPitch;
+ const uint8_t* pEndSrc = pSrc + rowPitch * height;
+
+ uint8_t* pDest = dest->pixels;
+
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ HRESULT hr = _Create( width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, tfX );
+ if ( FAILED(hr) )
+ return hr;
+
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+ hr = _Create( height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, tfY );
+ if ( FAILED(hr) )
+ return hr;
+
+#ifdef _DEBUG
+ memset( row, 0xCD, sizeof(XMVECTOR)*width );
+#endif
+
+ auto xFromEnd = reinterpret_cast<const FilterFrom*>( reinterpret_cast<const uint8_t*>( tfX.get() ) + tfX->sizeInBytes );
+ auto yFromEnd = reinterpret_cast<const FilterFrom*>( reinterpret_cast<const uint8_t*>( tfY.get() ) + tfY->sizeInBytes );
+
+ // Count times rows get written (and clear out any leftover accumulation rows from last miplevel)
+ for( FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; )
+ {
+ for ( size_t j = 0; j < yFrom->count; ++j )
+ {
+ size_t v = yFrom->to[ j ].u;
+ assert( v < nheight );
+ TriangleRow* rowAcc = &rowActive[ v ];
+
+ ++rowAcc->remaining;
+
+ if ( rowAcc->scanline )
+ {
+ memset( rowAcc->scanline.get(), 0, sizeof(XMVECTOR) * nwidth );
+ }
+ }
+
+ yFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( yFrom ) + yFrom->sizeInBytes );
+ }
+
+ // Filter image
+ for( FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; )
+ {
+ // Create accumulation rows as needed
+ for ( size_t j = 0; j < yFrom->count; ++j )
+ {
+ size_t v = yFrom->to[ j ].u;
+ assert( v < nheight );
+ TriangleRow* rowAcc = &rowActive[ v ];
+
+ if ( !rowAcc->scanline )
+ {
+ if ( rowFree )
+ {
+ // Steal and reuse scanline from 'free row' list
+ // (it will always be at least as wide as nwidth due to loop decending order)
+ assert( rowFree->scanline != 0 );
+ rowAcc->scanline.reset( rowFree->scanline.release() );
+ rowFree = rowFree->next;
+ }
+ else
+ {
+ rowAcc->scanline.reset( reinterpret_cast<XMVECTOR*>( _aligned_malloc( sizeof(XMVECTOR) * nwidth, 16 ) ) );
+ if ( !rowAcc->scanline )
+ return E_OUTOFMEMORY;
+ }
+
+ memset( rowAcc->scanline.get(), 0, sizeof(XMVECTOR) * nwidth );
+ }
+ }
+
+ // Load source scanline
+ if ( (pSrc + rowPitch) > pEndSrc )
+ return E_FAIL;
+
+ if ( !_LoadScanlineLinear( row, width, pSrc, rowPitch, src->format, filter ) )
+ return E_FAIL;
+
+ pSrc += rowPitch;
+
+ // Process row
+ size_t x = 0;
+ for( FilterFrom* xFrom = tfX->from; xFrom < xFromEnd; ++x )
+ {
+ for ( size_t j = 0; j < yFrom->count; ++j )
+ {
+ size_t v = yFrom->to[ j ].u;
+ assert( v < nheight );
+ float yweight = yFrom->to[ j ].weight;
+
+ XMVECTOR* accPtr = rowActive[ v ].scanline.get();
+ if ( !accPtr )
+ return E_POINTER;
+
+ for ( size_t k = 0; k < xFrom->count; ++k )
+ {
+ size_t u = xFrom->to[ k ].u;
+ assert( u < nwidth );
+
+ XMVECTOR weight = XMVectorReplicate( yweight * xFrom->to[ k ].weight );
+
+ assert( x < width );
+ accPtr[ u ] = XMVectorMultiplyAdd( row[ x ], weight, accPtr[ u ] );
+ }
+ }
+
+ xFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( xFrom ) + xFrom->sizeInBytes );
+ }
+
+ // Write completed accumulation rows
+ for ( size_t j = 0; j < yFrom->count; ++j )
+ {
+ size_t v = yFrom->to[ j ].u;
+ assert( v < nheight );
+ TriangleRow* rowAcc = &rowActive[ v ];
+
+ assert( rowAcc->remaining > 0 );
+ --rowAcc->remaining;
+
+ if ( !rowAcc->remaining )
+ {
+ XMVECTOR* pAccSrc = rowAcc->scanline.get();
+ if ( !pAccSrc )
+ return E_POINTER;
+
+ switch( dest->format )
+ {
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ // Need to slightly bias results for floating-point error accumulation which can
+ // be visible with harshly quantized values
+ static const XMVECTORF32 Bias = { 0.f, 0.f, 0.f, 0.1f };
+
+ XMVECTOR* ptr = pAccSrc;
+ for( size_t i=0; i < dest->width; ++i, ++ptr )
+ {
+ *ptr = XMVectorAdd( *ptr, Bias );
+ }
+ }
+ break;
+ }
+
+ // This performs any required clamping
+ if ( !_StoreScanlineLinear( pDest + (dest->rowPitch * v), dest->rowPitch, dest->format, pAccSrc, dest->width, filter ) )
+ return E_FAIL;
+
+ // Put row on freelist to reuse it's allocated scanline
+ rowAcc->next = rowFree;
+ rowFree = rowAcc;
+ }
+ }
+
+ yFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( yFrom ) + yFrom->sizeInBytes );
+ }
+
+ if ( height > 1 )
+ height >>= 1;
+
+ if ( width > 1 )
+ width >>= 1;
+ }
+
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------------------------
// Generate volume mip-map helpers
//-------------------------------------------------------------------------------------
-static HRESULT _Setup3DMips( _In_count_(depth) const Image* baseImages, _In_ size_t depth, size_t levels,
+static HRESULT _Setup3DMips( _In_reads_(depth) const Image* baseImages, _In_ size_t depth, size_t levels,
_Out_ ScratchImage& mipChain )
{
if ( !baseImages || !depth )
@@ -538,6 +1368,8 @@ static HRESULT _Setup3DMips( _In_count_(depth) const Image* baseImages, _In_ siz
return S_OK;
}
+
+//--- 3D Point Filter ---
static HRESULT _Generate3DMipsPointFilter( _In_ size_t depth, _In_ size_t levels, _In_ const ScratchImage& mipChain )
{
if ( !depth || !mipChain.GetImages() )
@@ -550,8 +1382,6 @@ static HRESULT _Generate3DMipsPointFilter( _In_ size_t depth, _In_ size_t levels
size_t width = mipChain.GetMetadata().width;
size_t height = mipChain.GetMetadata().height;
- assert( ispow2(width) && ispow2(height) && ispow2(depth) );
-
// Allocate temporary space (2 scanlines)
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*2), 16 ) ) );
if ( !scanline )
@@ -564,13 +1394,22 @@ static HRESULT _Generate3DMipsPointFilter( _In_ size_t depth, _In_ size_t levels
// Resize base image to each target mip level
for( size_t level=1; level < levels; ++level )
{
+#ifdef _DEBUG
+ memset( row, 0xCD, sizeof(XMVECTOR)*width );
+#endif
+
if ( depth > 1 )
{
// 3D point filter
- for( size_t slice=0; slice < depth; slice += 2 )
+ size_t ndepth = depth >> 1;
+
+ size_t zinc = ( depth << 16 ) / ndepth;
+
+ size_t sz = 0;
+ for( size_t slice=0; slice < ndepth; ++slice )
{
- const Image* src = mipChain.GetImage( level-1, 0, slice );
- const Image* dest = mipChain.GetImage( level, 0, slice >> 1 );
+ const Image* src = mipChain.GetImage( level-1, 0, (sz >> 16) );
+ const Image* dest = mipChain.GetImage( level, 0, slice );
if ( !src || !dest )
return E_POINTER;
@@ -580,25 +1419,39 @@ static HRESULT _Generate3DMipsPointFilter( _In_ size_t depth, _In_ size_t levels
size_t rowPitch = src->rowPitch;
- size_t nheight = height >> 1;
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+ size_t xinc = ( width << 16 ) / nwidth;
+ size_t yinc = ( height << 16 ) / nheight;
+
+ size_t lasty = size_t(-1);
+
+ size_t sy = 0;
for( size_t y = 0; y < nheight; ++y )
{
- if ( !_LoadScanline( row, width, pSrc, rowPitch, src->format ) )
- return E_FAIL;
- pSrc += rowPitch*2;
-
- size_t nwidth = width >> 1;
+ if ( (lasty ^ sy) >> 16 )
+ {
+ if ( !_LoadScanline( row, width, pSrc + ( rowPitch * (sy >> 16) ), rowPitch, src->format ) )
+ return E_FAIL;
+ lasty = sy;
+ }
+ size_t sx = 0;
for( size_t x = 0; x < nwidth; ++x )
{
- target[ x ] = row[ x*2 ];
+ target[ x ] = row[ sx >> 16 ];
+ sx += xinc;
}
if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) )
return E_FAIL;
pDest += dest->rowPitch;
+
+ sy += yinc;
}
+
+ sz += zinc;
}
}
else
@@ -615,24 +1468,36 @@ static HRESULT _Generate3DMipsPointFilter( _In_ size_t depth, _In_ size_t levels
size_t rowPitch = src->rowPitch;
- size_t nheight = height >> 1;
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+ size_t xinc = ( width << 16 ) / nwidth;
+ size_t yinc = ( height << 16 ) / nheight;
+
+ size_t lasty = size_t(-1);
+
+ size_t sy = 0;
for( size_t y = 0; y < nheight; ++y )
{
- if ( !_LoadScanline( row, width, pSrc, rowPitch, src->format ) )
- return E_FAIL;
- pSrc += rowPitch*2;
-
- size_t nwidth = width >> 1;
+ if ( (lasty ^ sy) >> 16 )
+ {
+ if ( !_LoadScanline( row, width, pSrc + ( rowPitch * (sy >> 16) ), rowPitch, src->format ) )
+ return E_FAIL;
+ lasty = sy;
+ }
+ size_t sx = 0;
for( size_t x = 0; x < nwidth; ++x )
{
- target[ x ] = row[ x*2 ];
+ target[ x ] = row[ sx >> 16 ];
+ sx += xinc;
}
if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) )
return E_FAIL;
pDest += dest->rowPitch;
+
+ sy += yinc;
}
}
@@ -646,12 +1511,12 @@ static HRESULT _Generate3DMipsPointFilter( _In_ size_t depth, _In_ size_t levels
depth >>= 1;
}
- assert( height == 1 && width == 1 && depth == 1 );
-
return S_OK;
}
-static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels, _In_ const ScratchImage& mipChain )
+
+//--- 3D Box Filter ---
+static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain )
{
if ( !depth || !mipChain.GetImages() )
return E_INVALIDARG;
@@ -663,7 +1528,8 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels,
size_t width = mipChain.GetMetadata().width;
size_t height = mipChain.GetMetadata().height;
- assert( ispow2(width) && ispow2(height) && ispow2(depth) );
+ if ( !ispow2(width) || !ispow2(height) || !ispow2(depth) )
+ return E_FAIL;
// Allocate temporary space (5 scanlines)
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*5), 16 ) ) );
@@ -685,13 +1551,13 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels,
// Resize base image to each target mip level
for( size_t level=1; level < levels; ++level )
{
- if ( height == 1)
+ if ( height <= 1 )
{
- urow0 = vrow0;
- urow1 = vrow1;
+ urow1 = urow0;
+ vrow1 = vrow0;
}
- if ( width == 1 )
+ if ( width <= 1 )
{
urow2 = urow0;
urow3 = urow1;
@@ -702,11 +1568,16 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels,
if ( depth > 1 )
{
// 3D box filter
- for( size_t slice=0; slice < depth; slice += 2 )
+ size_t ndepth = depth >> 1;
+
+ for( size_t slice=0; slice < ndepth; ++slice )
{
- const Image* srca = mipChain.GetImage( level-1, 0, slice );
- const Image* srcb = mipChain.GetImage( level-1, 0, slice+1 );
- const Image* dest = mipChain.GetImage( level, 0, slice >> 1 );
+ size_t slicea = std::min<size_t>( slice * 2, depth-1 );
+ size_t sliceb = std::min<size_t>( slicea + 1, depth-1 );
+
+ const Image* srca = mipChain.GetImage( level-1, 0, slicea );
+ const Image* srcb = mipChain.GetImage( level-1, 0, sliceb );
+ const Image* dest = mipChain.GetImage( level, 0, slice );
if ( !srca || !srcb || !dest )
return E_POINTER;
@@ -718,54 +1589,42 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels,
size_t aRowPitch = srca->rowPitch;
size_t bRowPitch = srcb->rowPitch;
- size_t nheight = height >> 1;
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
for( size_t y = 0; y < nheight; ++y )
{
- if ( !_LoadScanline( urow0, width, pSrc1, aRowPitch, srca->format ) )
+ if ( !_LoadScanlineLinear( urow0, width, pSrc1, aRowPitch, srca->format, filter ) )
return E_FAIL;
pSrc1 += aRowPitch;
if ( urow0 != urow1 )
{
- if ( !_LoadScanline( urow1, width, pSrc1, aRowPitch, srca->format ) )
+ if ( !_LoadScanlineLinear( urow1, width, pSrc1, aRowPitch, srca->format, filter ) )
return E_FAIL;
pSrc1 += aRowPitch;
}
- if ( urow0 != vrow0 )
- {
- if ( !_LoadScanline( vrow0, width, pSrc2, bRowPitch, srcb->format ) )
- return E_FAIL;
- pSrc2 += bRowPitch;
- }
+ if ( !_LoadScanlineLinear( vrow0, width, pSrc2, bRowPitch, srcb->format, filter ) )
+ return E_FAIL;
+ pSrc2 += bRowPitch;
- if ( urow0 != vrow1 && vrow0 != vrow1 )
+ if ( vrow0 != vrow1 )
{
- if ( !_LoadScanline( vrow1, width, pSrc2, bRowPitch, srcb->format ) )
+ if ( !_LoadScanlineLinear( vrow1, width, pSrc2, bRowPitch, srcb->format, filter ) )
return E_FAIL;
pSrc2 += bRowPitch;
}
- size_t nwidth = width >> 1;
-
for( size_t x = 0; x < nwidth; ++x )
{
- size_t x2 = x*2;
-
- // Box filter: Average 2x2x2 pixels
- XMVECTOR v = XMVectorAdd( urow0[ x2 ], urow1[ x2 ] );
- v = XMVectorAdd( v, urow2[ x2 ] );
- v = XMVectorAdd( v, urow3[ x2 ] );
- v = XMVectorAdd( v, vrow0[ x2 ] );
- v = XMVectorAdd( v, vrow1[ x2 ] );
- v = XMVectorAdd( v, vrow2[ x2 ] );
- v = XMVectorAdd( v, vrow3[ x2 ] );
-
- target[ x ] = XMVectorMultiply( v, s_boxScale3D );
+ size_t x2 = x << 1;
+
+ AVERAGE8( target[x], urow0[ x2 ], urow1[ x2 ], urow2[ x2 ], urow3[ x2 ],
+ vrow0[ x2 ], vrow1[ x2 ], vrow2[ x2 ], vrow3[ x2 ] );
}
- if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) )
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) )
return E_FAIL;
pDest += dest->rowPitch;
}
@@ -785,36 +1644,602 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels,
size_t rowPitch = src->rowPitch;
- size_t nheight = height >> 1;
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
for( size_t y = 0; y < nheight; ++y )
{
- if ( !_LoadScanline( urow0, width, pSrc, rowPitch, src->format ) )
+ if ( !_LoadScanlineLinear( urow0, width, pSrc, rowPitch, src->format, filter ) )
return E_FAIL;
pSrc += rowPitch;
if ( urow0 != urow1 )
{
- if ( !_LoadScanline( urow1, width, pSrc, rowPitch, src->format ) )
+ if ( !_LoadScanlineLinear( urow1, width, pSrc, rowPitch, src->format, filter ) )
return E_FAIL;
pSrc += rowPitch;
}
- size_t nwidth = width >> 1;
+ for( size_t x = 0; x < nwidth; ++x )
+ {
+ size_t x2 = x << 1;
+
+ AVERAGE4( target[ x ], urow0[ x2 ], urow1[ x2 ], urow2[ x2 ], urow3[ x2 ] );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) )
+ return E_FAIL;
+ pDest += dest->rowPitch;
+ }
+ }
+
+ if ( height > 1 )
+ height >>= 1;
+
+ if ( width > 1 )
+ width >>= 1;
+
+ if ( depth > 1 )
+ depth >>= 1;
+ }
+
+ return S_OK;
+}
+
+
+//--- 3D Linear Filter ---
+static HRESULT _Generate3DMipsLinearFilter( _In_ size_t depth, _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain )
+{
+ if ( !depth || !mipChain.GetImages() )
+ return E_INVALIDARG;
+
+ // This assumes that the base images are already placed into the mipChain at the top level... (see _Setup3DMips)
+
+ assert( levels > 1 );
+
+ size_t width = mipChain.GetMetadata().width;
+ size_t height = mipChain.GetMetadata().height;
+
+ // Allocate temporary space (5 scanlines, plus X/Y/Z filters)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*5), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ std::unique_ptr<LinearFilter[]> lf( new (std::nothrow) LinearFilter[ width+height+depth ] );
+ if ( !lf )
+ return E_OUTOFMEMORY;
+
+ LinearFilter* lfX = lf.get();
+ LinearFilter* lfY = lf.get() + width;
+ LinearFilter* lfZ = lf.get() + width + height;
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* urow0 = target + width;
+ XMVECTOR* urow1 = target + width*2;
+ XMVECTOR* vrow0 = target + width*3;
+ XMVECTOR* vrow1 = target + width*4;
+
+ // Resize base image to each target mip level
+ for( size_t level=1; level < levels; ++level )
+ {
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ _CreateLinearFilter( width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, lfX );
+
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+ _CreateLinearFilter( height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, lfY );
+
+#ifdef _DEBUG
+ memset( urow0, 0xCD, sizeof(XMVECTOR)*width );
+ memset( urow1, 0xDD, sizeof(XMVECTOR)*width );
+ memset( vrow0, 0xED, sizeof(XMVECTOR)*width );
+ memset( vrow1, 0xFD, sizeof(XMVECTOR)*width );
+#endif
+
+ if ( depth > 1 )
+ {
+ // 3D linear filter
+ size_t ndepth = depth >> 1;
+ _CreateLinearFilter( depth, ndepth, (filter & TEX_FILTER_WRAP_W) != 0, lfZ );
+
+ for( size_t slice=0; slice < ndepth; ++slice )
+ {
+ auto& toZ = lfZ[ slice ];
+
+ const Image* srca = mipChain.GetImage( level-1, 0, toZ.u0 );
+ const Image* srcb = mipChain.GetImage( level-1, 0, toZ.u1 );
+ if ( !srca || !srcb )
+ return E_POINTER;
+
+ size_t u0 = size_t(-1);
+ size_t u1 = size_t(-1);
+
+ const Image* dest = mipChain.GetImage( level, 0, slice );
+ if ( !dest )
+ return E_POINTER;
+
+ uint8_t* pDest = dest->pixels;
+
+ for( size_t y = 0; y < nheight; ++y )
+ {
+ auto& toY = lfY[ y ];
+
+ if ( toY.u0 != u0 )
+ {
+ if ( toY.u0 != u1 )
+ {
+ u0 = toY.u0;
+
+ if ( !_LoadScanlineLinear( urow0, width, srca->pixels + (srca->rowPitch * u0), srca->rowPitch, srca->format, filter )
+ || !_LoadScanlineLinear( vrow0, width, srcb->pixels + (srcb->rowPitch * u0), srcb->rowPitch, srcb->format, filter ) )
+ return E_FAIL;
+ }
+ else
+ {
+ u0 = u1;
+ u1 = size_t(-1);
+
+ std::swap( urow0, urow1 );
+ std::swap( vrow0, vrow1 );
+ }
+ }
+
+ if ( toY.u1 != u1 )
+ {
+ u1 = toY.u1;
+
+ if ( !_LoadScanlineLinear( urow1, width, srca->pixels + (srca->rowPitch * u1), srca->rowPitch, srca->format, filter )
+ || !_LoadScanlineLinear( vrow1, width, srcb->pixels + (srcb->rowPitch * u1), srcb->rowPitch, srcb->format, filter ) )
+ return E_FAIL;
+ }
+
+ for( size_t x = 0; x < nwidth; ++x )
+ {
+ auto& toX = lfX[ x ];
+
+ TRILINEAR_INTERPOLATE( target[x], toX, toY, toZ, urow0, urow1, vrow0, vrow1 );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) )
+ return E_FAIL;
+ pDest += dest->rowPitch;
+ }
+ }
+ }
+ else
+ {
+ // 2D linear filter
+ const Image* src = mipChain.GetImage( level-1, 0, 0 );
+ const Image* dest = mipChain.GetImage( level, 0, 0 );
+
+ if ( !src || !dest )
+ return E_POINTER;
+
+ const uint8_t* pSrc = src->pixels;
+ uint8_t* pDest = dest->pixels;
+
+ size_t rowPitch = src->rowPitch;
+
+ size_t u0 = size_t(-1);
+ size_t u1 = size_t(-1);
+
+ for( size_t y = 0; y < nheight; ++y )
+ {
+ auto& toY = lfY[ y ];
+
+ if ( toY.u0 != u0 )
+ {
+ if ( toY.u0 != u1 )
+ {
+ u0 = toY.u0;
+
+ if ( !_LoadScanlineLinear( urow0, width, pSrc + (rowPitch * u0), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+ else
+ {
+ u0 = u1;
+ u1 = size_t(-1);
+
+ std::swap( urow0, urow1 );
+ }
+ }
+
+ if ( toY.u1 != u1 )
+ {
+ u1 = toY.u1;
+
+ if ( !_LoadScanlineLinear( urow1, width, pSrc + (rowPitch * u1), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+
+ for( size_t x = 0; x < nwidth; ++x )
+ {
+ auto& toX = lfX[ x ];
+
+ BILINEAR_INTERPOLATE( target[x], toX, toY, urow0, urow1 );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) )
+ return E_FAIL;
+ pDest += dest->rowPitch;
+ }
+ }
+
+ if ( height > 1 )
+ height >>= 1;
+
+ if ( width > 1 )
+ width >>= 1;
+
+ if ( depth > 1 )
+ depth >>= 1;
+ }
+
+ return S_OK;
+}
+
+
+//--- 3D Cubic Filter ---
+static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain )
+{
+ if ( !depth || !mipChain.GetImages() )
+ return E_INVALIDARG;
+
+ // This assumes that the base images are already placed into the mipChain at the top level... (see _Setup3DMips)
+
+ assert( levels > 1 );
+
+ size_t width = mipChain.GetMetadata().width;
+ size_t height = mipChain.GetMetadata().height;
+
+ // Allocate temporary space (17 scanlines, plus X/Y/Z filters)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*17), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ std::unique_ptr<CubicFilter[]> cf( new (std::nothrow) CubicFilter[ width+height+depth ] );
+ if ( !cf )
+ return E_OUTOFMEMORY;
+
+ CubicFilter* cfX = cf.get();
+ CubicFilter* cfY = cf.get() + width;
+ CubicFilter* cfZ = cf.get() + width + height;
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* urow[4];
+ XMVECTOR* vrow[4];
+ XMVECTOR* srow[4];
+ XMVECTOR* trow[4];
+
+ XMVECTOR *ptr = scanline.get() + width;
+ for( size_t j = 0; j < 4; ++j )
+ {
+ urow[j] = ptr; ptr += width;
+ vrow[j] = ptr; ptr += width;
+ srow[j] = ptr; ptr += width;
+ trow[j] = ptr; ptr += width;
+ }
+
+ // Resize base image to each target mip level
+ for( size_t level=1; level < levels; ++level )
+ {
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ _CreateCubicFilter( width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, (filter & TEX_FILTER_MIRROR_U) != 0, cfX );
+
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+ _CreateCubicFilter( height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, (filter & TEX_FILTER_MIRROR_V) != 0, cfY );
+
+#ifdef _DEBUG
+ for( size_t j = 0; j < 4; ++j )
+ {
+ memset( urow[j], 0xCD, sizeof(XMVECTOR)*width );
+ memset( vrow[j], 0xDD, sizeof(XMVECTOR)*width );
+ memset( srow[j], 0xED, sizeof(XMVECTOR)*width );
+ memset( trow[j], 0xFD, sizeof(XMVECTOR)*width );
+ }
+#endif
+
+ if ( depth > 1 )
+ {
+ // 3D cubic filter
+ size_t ndepth = depth >> 1;
+ _CreateCubicFilter( depth, ndepth, (filter & TEX_FILTER_WRAP_W) != 0, (filter & TEX_FILTER_MIRROR_W) != 0, cfZ );
+
+ for( size_t slice=0; slice < ndepth; ++slice )
+ {
+ auto& toZ = cfZ[ slice ];
+
+ const Image* srca = mipChain.GetImage( level-1, 0, toZ.u0 );
+ const Image* srcb = mipChain.GetImage( level-1, 0, toZ.u1 );
+ const Image* srcc = mipChain.GetImage( level-1, 0, toZ.u2 );
+ const Image* srcd = mipChain.GetImage( level-1, 0, toZ.u3 );
+ if ( !srca || !srcb || !srcc || !srcd )
+ return E_POINTER;
+
+ size_t u0 = size_t(-1);
+ size_t u1 = size_t(-1);
+ size_t u2 = size_t(-1);
+ size_t u3 = size_t(-1);
+
+ const Image* dest = mipChain.GetImage( level, 0, slice );
+ if ( !dest )
+ return E_POINTER;
+
+ uint8_t* pDest = dest->pixels;
+
+ for( size_t y = 0; y < nheight; ++y )
+ {
+ auto& toY = cfY[ y ];
+
+ // Scanline 1
+ if ( toY.u0 != u0 )
+ {
+ if ( toY.u0 != u1 && toY.u0 != u2 && toY.u0 != u3 )
+ {
+ u0 = toY.u0;
+
+ if ( !_LoadScanlineLinear( urow[0], width, srca->pixels + (srca->rowPitch * u0), srca->rowPitch, srca->format, filter )
+ || !_LoadScanlineLinear( urow[1], width, srcb->pixels + (srcb->rowPitch * u0), srcb->rowPitch, srcb->format, filter )
+ || !_LoadScanlineLinear( urow[2], width, srcc->pixels + (srcc->rowPitch * u0), srcc->rowPitch, srcc->format, filter )
+ || !_LoadScanlineLinear( urow[3], width, srcd->pixels + (srcd->rowPitch * u0), srcd->rowPitch, srcd->format, filter ) )
+ return E_FAIL;
+ }
+ else if ( toY.u0 == u1 )
+ {
+ u0 = u1;
+ u1 = size_t(-1);
+
+ std::swap( urow[0], vrow[0] );
+ std::swap( urow[1], vrow[1] );
+ std::swap( urow[2], vrow[2] );
+ std::swap( urow[3], vrow[3] );
+ }
+ else if ( toY.u0 == u2 )
+ {
+ u0 = u2;
+ u2 = size_t(-1);
+
+ std::swap( urow[0], srow[0] );
+ std::swap( urow[1], srow[1] );
+ std::swap( urow[2], srow[2] );
+ std::swap( urow[3], srow[3] );
+ }
+ else if ( toY.u0 == u3 )
+ {
+ u0 = u3;
+ u3 = size_t(-1);
+
+ std::swap( urow[0], trow[0] );
+ std::swap( urow[1], trow[1] );
+ std::swap( urow[2], trow[2] );
+ std::swap( urow[3], trow[3] );
+ }
+ }
+
+ // Scanline 2
+ if ( toY.u1 != u1 )
+ {
+ if ( toY.u1 != u2 && toY.u1 != u3 )
+ {
+ u1 = toY.u1;
+
+ if ( !_LoadScanlineLinear( vrow[0], width, srca->pixels + (srca->rowPitch * u1), srca->rowPitch, srca->format, filter )
+ || !_LoadScanlineLinear( vrow[1], width, srcb->pixels + (srcb->rowPitch * u1), srcb->rowPitch, srcb->format, filter )
+ || !_LoadScanlineLinear( vrow[2], width, srcc->pixels + (srcc->rowPitch * u1), srcc->rowPitch, srcc->format, filter )
+ || !_LoadScanlineLinear( vrow[3], width, srcd->pixels + (srcd->rowPitch * u1), srcd->rowPitch, srcd->format, filter ) )
+ return E_FAIL;
+ }
+ else if ( toY.u1 == u2 )
+ {
+ u1 = u2;
+ u2 = size_t(-1);
+
+ std::swap( vrow[0], srow[0] );
+ std::swap( vrow[1], srow[1] );
+ std::swap( vrow[2], srow[2] );
+ std::swap( vrow[3], srow[3] );
+ }
+ else if ( toY.u1 == u3 )
+ {
+ u1 = u3;
+ u3 = size_t(-1);
+
+ std::swap( vrow[0], trow[0] );
+ std::swap( vrow[1], trow[1] );
+ std::swap( vrow[2], trow[2] );
+ std::swap( vrow[3], trow[3] );
+ }
+ }
+
+ // Scanline 3
+ if ( toY.u2 != u2 )
+ {
+ if ( toY.u2 != u3 )
+ {
+ u2 = toY.u2;
+
+ if ( !_LoadScanlineLinear( srow[0], width, srca->pixels + (srca->rowPitch * u2), srca->rowPitch, srca->format, filter )
+ || !_LoadScanlineLinear( srow[1], width, srcb->pixels + (srcb->rowPitch * u2), srcb->rowPitch, srcb->format, filter )
+ || !_LoadScanlineLinear( srow[2], width, srcc->pixels + (srcc->rowPitch * u2), srcc->rowPitch, srcc->format, filter )
+ || !_LoadScanlineLinear( srow[3], width, srcd->pixels + (srcd->rowPitch * u2), srcd->rowPitch, srcd->format, filter ) )
+ return E_FAIL;
+ }
+ else
+ {
+ u2 = u3;
+ u3 = size_t(-1);
+
+ std::swap( srow[0], trow[0] );
+ std::swap( srow[1], trow[1] );
+ std::swap( srow[2], trow[2] );
+ std::swap( srow[3], trow[3] );
+ }
+ }
+
+ // Scanline 4
+ if ( toY.u3 != u3 )
+ {
+ u3 = toY.u3;
+
+ if ( !_LoadScanlineLinear( trow[0], width, srca->pixels + (srca->rowPitch * u3), srca->rowPitch, srca->format, filter )
+ || !_LoadScanlineLinear( trow[1], width, srcb->pixels + (srcb->rowPitch * u3), srcb->rowPitch, srcb->format, filter )
+ || !_LoadScanlineLinear( trow[2], width, srcc->pixels + (srcc->rowPitch * u3), srcc->rowPitch, srcc->format, filter )
+ || !_LoadScanlineLinear( trow[3], width, srcd->pixels + (srcd->rowPitch * u3), srcd->rowPitch, srcd->format, filter ) )
+ return E_FAIL;
+ }
+
+ for( size_t x = 0; x < nwidth; ++x )
+ {
+ auto& toX = cfX[ x ];
+
+ XMVECTOR D[4];
+
+ for( size_t j=0; j < 4; ++j )
+ {
+ XMVECTOR C0, C1, C2, C3;
+ CUBIC_INTERPOLATE( C0, toX.x, urow[j][ toX.u0 ], urow[j][ toX.u1 ], urow[j][ toX.u2 ], urow[j][ toX.u3 ] );
+ CUBIC_INTERPOLATE( C1, toX.x, vrow[j][ toX.u0 ], vrow[j][ toX.u1 ], vrow[j][ toX.u2 ], vrow[j][ toX.u3 ] );
+ CUBIC_INTERPOLATE( C2, toX.x, srow[j][ toX.u0 ], srow[j][ toX.u1 ], srow[j][ toX.u2 ], srow[j][ toX.u3 ] );
+ CUBIC_INTERPOLATE( C3, toX.x, trow[j][ toX.u0 ], trow[j][ toX.u1 ], trow[j][ toX.u2 ], trow[j][ toX.u3 ] );
+
+ CUBIC_INTERPOLATE( D[j], toY.x, C0, C1, C2, C3 );
+ }
+
+ CUBIC_INTERPOLATE( target[x], toZ.x, D[0], D[1], D[2], D[3] );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) )
+ return E_FAIL;
+ pDest += dest->rowPitch;
+ }
+ }
+ }
+ else
+ {
+ // 2D cubic filter
+ const Image* src = mipChain.GetImage( level-1, 0, 0 );
+ const Image* dest = mipChain.GetImage( level, 0, 0 );
+
+ if ( !src || !dest )
+ return E_POINTER;
+
+ const uint8_t* pSrc = src->pixels;
+ uint8_t* pDest = dest->pixels;
+
+ size_t rowPitch = src->rowPitch;
+
+ size_t u0 = size_t(-1);
+ size_t u1 = size_t(-1);
+ size_t u2 = size_t(-1);
+ size_t u3 = size_t(-1);
+
+ for( size_t y = 0; y < nheight; ++y )
+ {
+ auto& toY = cfY[ y ];
+
+ // Scanline 1
+ if ( toY.u0 != u0 )
+ {
+ if ( toY.u0 != u1 && toY.u0 != u2 && toY.u0 != u3 )
+ {
+ u0 = toY.u0;
+
+ if ( !_LoadScanlineLinear( urow[0], width, pSrc + (rowPitch * u0), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+ else if ( toY.u0 == u1 )
+ {
+ u0 = u1;
+ u1 = size_t(-1);
+
+ std::swap( urow[0], vrow[0] );
+ }
+ else if ( toY.u0 == u2 )
+ {
+ u0 = u2;
+ u2 = size_t(-1);
+
+ std::swap( urow[0], srow[0] );
+ }
+ else if ( toY.u0 == u3 )
+ {
+ u0 = u3;
+ u3 = size_t(-1);
+
+ std::swap( urow[0], trow[0] );
+ }
+ }
+
+ // Scanline 2
+ if ( toY.u1 != u1 )
+ {
+ if ( toY.u1 != u2 && toY.u1 != u3 )
+ {
+ u1 = toY.u1;
+
+ if ( !_LoadScanlineLinear( vrow[0], width, pSrc + (rowPitch * u1), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+ else if ( toY.u1 == u2 )
+ {
+ u1 = u2;
+ u2 = size_t(-1);
+
+ std::swap( vrow[0], srow[0] );
+ }
+ else if ( toY.u1 == u3 )
+ {
+ u1 = u3;
+ u3 = size_t(-1);
+
+ std::swap( vrow[0], trow[0] );
+ }
+ }
+
+ // Scanline 3
+ if ( toY.u2 != u2 )
+ {
+ if ( toY.u2 != u3 )
+ {
+ u2 = toY.u2;
+
+ if ( !_LoadScanlineLinear( srow[0], width, pSrc + (rowPitch * u2), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
+ else
+ {
+ u2 = u3;
+ u3 = size_t(-1);
+
+ std::swap( srow[0], trow[0] );
+ }
+ }
+
+ // Scanline 4
+ if ( toY.u3 != u3 )
+ {
+ u3 = toY.u3;
+
+ if ( !_LoadScanlineLinear( trow[0], width, pSrc + (rowPitch * u3), rowPitch, src->format, filter ) )
+ return E_FAIL;
+ }
for( size_t x = 0; x < nwidth; ++x )
{
- size_t x2 = x*2;
+ auto& toX = cfX[ x ];
- // Box filter: Average 2x2 pixels
- XMVECTOR v = XMVectorAdd( urow0[ x2 ], urow1[ x2 ] );
- v = XMVectorAdd( v, urow2[ x2 ] );
- v = XMVectorAdd( v, urow3[ x2 ] );
+ XMVECTOR C0, C1, C2, C3;
+ CUBIC_INTERPOLATE( C0, toX.x, urow[0][ toX.u0 ], urow[0][ toX.u1 ], urow[0][ toX.u2 ], urow[0][ toX.u3 ] );
+ CUBIC_INTERPOLATE( C1, toX.x, vrow[0][ toX.u0 ], vrow[0][ toX.u1 ], vrow[0][ toX.u2 ], vrow[0][ toX.u3 ] );
+ CUBIC_INTERPOLATE( C2, toX.x, srow[0][ toX.u0 ], srow[0][ toX.u1 ], srow[0][ toX.u2 ], srow[0][ toX.u3 ] );
+ CUBIC_INTERPOLATE( C3, toX.x, trow[0][ toX.u0 ], trow[0][ toX.u1 ], trow[0][ toX.u2 ], trow[0][ toX.u3 ] );
- target[ x ] = XMVectorMultiply( v, s_boxScale );
+ CUBIC_INTERPOLATE( target[x], toY.x, C0, C1, C2, C3 );
}
- if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) )
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) )
return E_FAIL;
pDest += dest->rowPitch;
}
@@ -830,7 +2255,245 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels,
depth >>= 1;
}
- assert( height == 1 && width == 1 && depth == 1 );
+ return S_OK;
+}
+
+
+//--- 3D Triangle Filter ---
+static HRESULT _Generate3DMipsTriangleFilter( _In_ size_t depth, _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain )
+{
+ if ( !depth || !mipChain.GetImages() )
+ return E_INVALIDARG;
+
+ using namespace TriangleFilter;
+
+ // This assumes that the base images are already placed into the mipChain at the top level... (see _Setup3DMips)
+
+ assert( levels > 1 );
+
+ size_t width = mipChain.GetMetadata().width;
+ size_t height = mipChain.GetMetadata().height;
+
+ // Allocate initial temporary space (1 scanline, accumulation rows, plus X/Y/Z filters)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( sizeof(XMVECTOR) * width, 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ std::unique_ptr<TriangleRow[]> sliceActive( new (std::nothrow) TriangleRow[ depth ] );
+ if ( !sliceActive )
+ return E_OUTOFMEMORY;
+
+ TriangleRow * sliceFree = nullptr;
+
+ std::unique_ptr<Filter> tfX, tfY, tfZ;
+
+ XMVECTOR* row = scanline.get();
+
+ // Resize base image to each target mip level
+ for( size_t level=1; level < levels; ++level )
+ {
+ size_t nwidth = (width > 1) ? (width >> 1) : 1;
+ HRESULT hr = _Create( width, nwidth, (filter & TEX_FILTER_WRAP_U) != 0, tfX );
+ if ( FAILED(hr) )
+ return hr;
+
+ size_t nheight = (height > 1) ? (height >> 1) : 1;
+ hr = _Create( height, nheight, (filter & TEX_FILTER_WRAP_V) != 0, tfY );
+ if ( FAILED(hr) )
+ return hr;
+
+ size_t ndepth = (depth > 1 ) ? (depth >> 1) : 1;
+ hr = _Create( depth, ndepth, (filter & TEX_FILTER_WRAP_W) != 0, tfZ );
+ if ( FAILED(hr) )
+ return hr;
+
+#ifdef _DEBUG
+ memset( row, 0xCD, sizeof(XMVECTOR)*width );
+#endif
+
+ auto xFromEnd = reinterpret_cast<const FilterFrom*>( reinterpret_cast<const uint8_t*>( tfX.get() ) + tfX->sizeInBytes );
+ auto yFromEnd = reinterpret_cast<const FilterFrom*>( reinterpret_cast<const uint8_t*>( tfY.get() ) + tfY->sizeInBytes );
+ auto zFromEnd = reinterpret_cast<const FilterFrom*>( reinterpret_cast<const uint8_t*>( tfZ.get() ) + tfZ->sizeInBytes );
+
+ // Count times slices get written (and clear out any leftover accumulation slices from last miplevel)
+ for( FilterFrom* zFrom = tfZ->from; zFrom < zFromEnd; )
+ {
+ for ( size_t j = 0; j < zFrom->count; ++j )
+ {
+ size_t w = zFrom->to[ j ].u;
+ assert( w < ndepth );
+ TriangleRow* sliceAcc = &sliceActive[ w ];
+
+ ++sliceAcc->remaining;
+
+ if ( sliceAcc->scanline )
+ {
+ memset( sliceAcc->scanline.get(), 0, sizeof(XMVECTOR) * nwidth * nheight );
+ }
+ }
+
+ zFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( zFrom ) + zFrom->sizeInBytes );
+ }
+
+ // Filter image
+ size_t z = 0;
+ for( FilterFrom* zFrom = tfZ->from; zFrom < zFromEnd; ++z )
+ {
+ // Create accumulation slices as needed
+ for ( size_t j = 0; j < zFrom->count; ++j )
+ {
+ size_t w = zFrom->to[ j ].u;
+ assert( w < ndepth );
+ TriangleRow* sliceAcc = &sliceActive[ w ];
+
+ if ( !sliceAcc->scanline )
+ {
+ if ( sliceFree )
+ {
+ // Steal and reuse scanline from 'free slice' list
+ // (it will always be at least as large as nwidth*nheight due to loop decending order)
+ assert( sliceFree->scanline != 0 );
+ sliceAcc->scanline.reset( sliceFree->scanline.release() );
+ sliceFree = sliceFree->next;
+ }
+ else
+ {
+ size_t bytes = sizeof(XMVECTOR) * nwidth * nheight;
+ sliceAcc->scanline.reset( reinterpret_cast<XMVECTOR*>( _aligned_malloc( bytes, 16 ) ) );
+ if ( !sliceAcc->scanline )
+ return E_OUTOFMEMORY;
+ }
+
+ memset( sliceAcc->scanline.get(), 0, sizeof(XMVECTOR) * nwidth * nheight );
+ }
+ }
+
+ assert( z < depth );
+ const Image* src = mipChain.GetImage( level-1, 0, z );
+ if ( !src )
+ return E_POINTER;
+
+ const uint8_t* pSrc = src->pixels;
+ size_t rowPitch = src->rowPitch;
+ const uint8_t* pEndSrc = pSrc + rowPitch * height;
+
+ for( FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; )
+ {
+ // Load source scanline
+ if ( (pSrc + rowPitch) > pEndSrc )
+ return E_FAIL;
+
+ if ( !_LoadScanlineLinear( row, width, pSrc, rowPitch, src->format, filter ) )
+ return E_FAIL;
+
+ pSrc += rowPitch;
+
+ // Process row
+ size_t x = 0;
+ for( FilterFrom* xFrom = tfX->from; xFrom < xFromEnd; ++x )
+ {
+ for ( size_t j = 0; j < zFrom->count; ++j )
+ {
+ size_t w = zFrom->to[ j ].u;
+ assert( w < ndepth );
+ float zweight = zFrom->to[ j ].weight;
+
+ XMVECTOR* accSlice = sliceActive[ w ].scanline.get();
+ if ( !accSlice )
+ return E_POINTER;
+
+ for ( size_t k = 0; k < yFrom->count; ++k )
+ {
+ size_t v = yFrom->to[ k ].u;
+ assert( v < nheight );
+ float yweight = yFrom->to[ k ].weight;
+
+ XMVECTOR * accPtr = accSlice + v * nwidth;
+
+ for ( size_t l = 0; l < xFrom->count; ++l )
+ {
+ size_t u = xFrom->to[ l ].u;
+ assert( u < nwidth );
+
+ XMVECTOR weight = XMVectorReplicate( zweight * yweight * xFrom->to[ l ].weight );
+
+ assert( x < width );
+ accPtr[ u ] = XMVectorMultiplyAdd( row[ x ], weight, accPtr[ u ] );
+ }
+ }
+ }
+
+ xFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( xFrom ) + xFrom->sizeInBytes );
+ }
+
+ yFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( yFrom ) + yFrom->sizeInBytes );
+ }
+
+ // Write completed accumulation slices
+ for ( size_t j = 0; j < zFrom->count; ++j )
+ {
+ size_t w = zFrom->to[ j ].u;
+ assert( w < ndepth );
+ TriangleRow* sliceAcc = &sliceActive[ w ];
+
+ assert( sliceAcc->remaining > 0 );
+ --sliceAcc->remaining;
+
+ if ( !sliceAcc->remaining )
+ {
+ const Image* dest = mipChain.GetImage( level, 0, w );
+ XMVECTOR* pAccSrc = sliceAcc->scanline.get();
+ if ( !dest || !pAccSrc )
+ return E_POINTER;
+
+ uint8_t* pDest = dest->pixels;
+
+ for( size_t h = 0; h < nheight; ++h )
+ {
+ switch( dest->format )
+ {
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ // Need to slightly bias results for floating-point error accumulation which can
+ // be visible with harshly quantized values
+ static const XMVECTORF32 Bias = { 0.f, 0.f, 0.f, 0.1f };
+
+ XMVECTOR* ptr = pAccSrc;
+ for( size_t i=0; i < dest->width; ++i, ++ptr )
+ {
+ *ptr = XMVectorAdd( *ptr, Bias );
+ }
+ }
+ break;
+ }
+
+ // This performs any required clamping
+ if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, pAccSrc, dest->width, filter ) )
+ return E_FAIL;
+
+ pDest += dest->rowPitch;
+ pAccSrc += nwidth;
+ }
+
+ // Put slice on freelist to reuse it's allocated scanline
+ sliceAcc->next = sliceFree;
+ sliceFree = sliceAcc;
+ }
+ }
+
+ zFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( zFrom ) + zFrom->sizeInBytes );
+ }
+
+ if ( height > 1 )
+ height >>= 1;
+
+ if ( width > 1 )
+ width >>= 1;
+
+ if ( depth > 1 )
+ depth >>= 1;
+ }
return S_OK;
}
@@ -843,6 +2506,7 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels,
//-------------------------------------------------------------------------------------
// Generate mipmap chain
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT GenerateMipMaps( const Image& baseImage, DWORD filter, size_t levels, ScratchImage& mipChain, bool allow1D )
{
if ( !IsValid( baseImage.format ) )
@@ -854,157 +2518,363 @@ HRESULT GenerateMipMaps( const Image& baseImage, DWORD filter, size_t levels, Sc
if ( !_CalculateMipLevels(baseImage.width, baseImage.height, levels) )
return E_INVALIDARG;
- if ( IsCompressed( baseImage.format ) || IsVideo( baseImage.format ) )
+ if ( levels <= 1 )
+ return E_INVALIDARG;
+
+ if ( IsCompressed(baseImage.format) || IsTypeless(baseImage.format) || IsPlanar(baseImage.format) || IsPalettized(baseImage.format) )
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
+ HRESULT hr;
+
static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
- switch(filter & TEX_FILTER_MASK)
+
+ if ( _UseWICFiltering( baseImage.format, filter ) )
{
- case 0:
- case TEX_FILTER_POINT:
- case TEX_FILTER_FANT: // Equivalent to Box filter
- case TEX_FILTER_LINEAR:
- case TEX_FILTER_CUBIC:
+ //--- Use WIC filtering to generate mipmaps -----------------------------------
+ switch(filter & TEX_FILTER_MASK)
{
- WICPixelFormatGUID pfGUID;
- if ( _DXGIToWIC( baseImage.format, pfGUID ) )
- {
- // Case 1: Base image format is supported by Windows Imaging Component
- HRESULT hr = (baseImage.height > 1 || !allow1D)
+ case 0:
+ case TEX_FILTER_POINT:
+ case TEX_FILTER_FANT: // Equivalent to Box filter
+ case TEX_FILTER_LINEAR:
+ case TEX_FILTER_CUBIC:
+ {
+ static_assert( TEX_FILTER_FANT == TEX_FILTER_BOX, "TEX_FILTER_ flag alias mismatch" );
+
+ WICPixelFormatGUID pfGUID;
+ if ( _DXGIToWIC( baseImage.format, pfGUID, true ) )
+ {
+ // Case 1: Base image format is supported by Windows Imaging Component
+ hr = (baseImage.height > 1 || !allow1D)
? mipChain.Initialize2D( baseImage.format, baseImage.width, baseImage.height, 1, levels )
: mipChain.Initialize1D( baseImage.format, baseImage.width, 1, levels );
+ if ( FAILED(hr) )
+ return hr;
+
+ return _GenerateMipMapsUsingWIC( baseImage, filter, levels, pfGUID, mipChain, 0 );
+ }
+ else
+ {
+ // Case 2: Base image format is not supported by WIC, so we have to convert, generate, and convert back
+ assert( baseImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
+ ScratchImage temp;
+ hr = _ConvertToR32G32B32A32( baseImage, temp );
+ if ( FAILED(hr) )
+ return hr;
+
+ const Image *timg = temp.GetImage( 0, 0, 0 );
+ if ( !timg )
+ return E_POINTER;
+
+ ScratchImage tMipChain;
+ hr = (baseImage.height > 1 || !allow1D)
+ ? tMipChain.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, baseImage.width, baseImage.height, 1, levels )
+ : tMipChain.Initialize1D( DXGI_FORMAT_R32G32B32A32_FLOAT, baseImage.width, 1, levels );
+ if ( FAILED(hr) )
+ return hr;
+
+ hr = _GenerateMipMapsUsingWIC( *timg, filter, levels, GUID_WICPixelFormat128bppRGBAFloat, tMipChain, 0 );
+ if ( FAILED(hr) )
+ return hr;
+
+ temp.Release();
+
+ return _ConvertFromR32G32B32A32( tMipChain.GetImages(), tMipChain.GetImageCount(), tMipChain.GetMetadata(), baseImage.format, mipChain );
+ }
+ }
+ break;
+
+ default:
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
+ }
+ else
+ {
+ //--- Use custom filters to generate mipmaps ----------------------------------
+ TexMetadata mdata;
+ memset( &mdata, 0, sizeof(mdata) );
+ mdata.width = baseImage.width;
+ if ( baseImage.height > 1 || !allow1D )
+ {
+ mdata.height = baseImage.height;
+ mdata.dimension = TEX_DIMENSION_TEXTURE2D;
+ }
+ else
+ {
+ mdata.height = 1;
+ mdata.dimension= TEX_DIMENSION_TEXTURE1D;
+ }
+ mdata.depth = mdata.arraySize = 1;
+ mdata.mipLevels = levels;
+ mdata.format = baseImage.format;
+
+ DWORD filter_select = ( filter & TEX_FILTER_MASK );
+ if ( !filter_select )
+ {
+ // Default filter choice
+ filter_select = ( ispow2(baseImage.width) && ispow2(baseImage.height) ) ? TEX_FILTER_BOX : TEX_FILTER_LINEAR;
+ }
+
+ switch( filter_select )
+ {
+ case TEX_FILTER_BOX:
+ hr = _Setup2DMips( &baseImage, 1, mdata, mipChain );
if ( FAILED(hr) )
return hr;
- return _GenerateMipMapsUsingWIC( baseImage, filter, levels, pfGUID, mipChain, 0 );
- }
- else
- {
- // Case 2: Base image format is not supported by WIC, so we have to convert, generate, and convert back
- assert( baseImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
- ScratchImage temp;
- HRESULT hr = _ConvertToR32G32B32A32( baseImage, temp );
+ hr = _Generate2DMipsBoxFilter( levels, filter, mipChain, 0 );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
+
+ case TEX_FILTER_POINT:
+ hr = _Setup2DMips( &baseImage, 1, mdata, mipChain );
if ( FAILED(hr) )
return hr;
- const Image *timg = temp.GetImage( 0, 0, 0 );
- if ( !timg )
- return E_POINTER;
+ hr = _Generate2DMipsPointFilter( levels, mipChain, 0 );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
- ScratchImage tMipChain;
- hr = _GenerateMipMapsUsingWIC( *timg, filter, levels, GUID_WICPixelFormat128bppRGBAFloat, tMipChain, 0 );
+ case TEX_FILTER_LINEAR:
+ hr = _Setup2DMips( &baseImage, 1, mdata, mipChain );
if ( FAILED(hr) )
return hr;
- temp.Release();
+ hr = _Generate2DMipsLinearFilter( levels, filter, mipChain, 0 );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
- return _ConvertFromR32G32B32A32( tMipChain.GetImages(), tMipChain.GetImageCount(), tMipChain.GetMetadata(), baseImage.format, mipChain );
- }
- }
- break;
+ case TEX_FILTER_CUBIC:
+ hr = _Setup2DMips( &baseImage, 1, mdata, mipChain );
+ if ( FAILED(hr) )
+ return hr;
- default:
- return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ hr = _Generate2DMipsCubicFilter( levels, filter, mipChain, 0 );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
+
+ case TEX_FILTER_TRIANGLE:
+ hr = _Setup2DMips( &baseImage, 1, mdata, mipChain );
+ if ( FAILED(hr) )
+ return hr;
+
+ hr = _Generate2DMipsTriangleFilter( levels, filter, mipChain, 0 );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
+
+ default:
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
}
}
+_Use_decl_annotations_
HRESULT GenerateMipMaps( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DWORD filter, size_t levels, ScratchImage& mipChain )
{
if ( !srcImages || !nimages || !IsValid(metadata.format) )
return E_INVALIDARG;
- if ( metadata.dimension == TEX_DIMENSION_TEXTURE3D
- || IsCompressed( metadata.format ) || IsVideo( metadata.format ) )
+ if ( metadata.IsVolumemap()
+ || IsCompressed(metadata.format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if ( !_CalculateMipLevels(metadata.width, metadata.height, levels) )
return E_INVALIDARG;
+ if ( levels <= 1 )
+ return E_INVALIDARG;
+
+ std::vector<Image> baseImages;
+ baseImages.reserve( metadata.arraySize );
+ for( size_t item=0; item < metadata.arraySize; ++item )
+ {
+ size_t index = metadata.ComputeIndex( 0, item, 0);
+ if ( index >= nimages )
+ return E_FAIL;
+
+ const Image& src = srcImages[ index ];
+ if ( !src.pixels )
+ return E_POINTER;
+
+ if ( src.format != metadata.format || src.width != metadata.width || src.height != metadata.height )
+ {
+ // All base images must be the same format, width, and height
+ return E_FAIL;
+ }
+
+ baseImages.push_back( src );
+ }
+
+ assert( baseImages.size() == metadata.arraySize );
+
+ HRESULT hr;
+
static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
- switch(filter & TEX_FILTER_MASK)
+
+ if ( _UseWICFiltering( metadata.format, filter ) )
{
- case 0:
- case TEX_FILTER_POINT:
- case TEX_FILTER_FANT: // Equivalent to Box filter
- case TEX_FILTER_LINEAR:
- case TEX_FILTER_CUBIC:
+ //--- Use WIC filtering to generate mipmaps -----------------------------------
+ switch(filter & TEX_FILTER_MASK)
{
- WICPixelFormatGUID pfGUID;
- if ( _DXGIToWIC( metadata.format, pfGUID ) )
+ case 0:
+ case TEX_FILTER_POINT:
+ case TEX_FILTER_FANT: // Equivalent to Box filter
+ case TEX_FILTER_LINEAR:
+ case TEX_FILTER_CUBIC:
{
- // Case 1: Base image format is supported by Windows Imaging Component
- TexMetadata mdata2 = metadata;
- mdata2.mipLevels = levels;
- HRESULT hr = mipChain.Initialize( mdata2 );
+ static_assert( TEX_FILTER_FANT == TEX_FILTER_BOX, "TEX_FILTER_ flag alias mismatch" );
+
+ WICPixelFormatGUID pfGUID;
+ if ( _DXGIToWIC( metadata.format, pfGUID, true ) )
+ {
+ // Case 1: Base image format is supported by Windows Imaging Component
+ TexMetadata mdata2 = metadata;
+ mdata2.mipLevels = levels;
+ hr = mipChain.Initialize( mdata2 );
+ if ( FAILED(hr) )
+ return hr;
+
+ for( size_t item = 0; item < metadata.arraySize; ++item )
+ {
+ hr = _GenerateMipMapsUsingWIC( baseImages[item], filter, levels, pfGUID, mipChain, item );
+ if ( FAILED(hr) )
+ {
+ mipChain.Release();
+ return hr;
+ }
+ }
+
+ return S_OK;
+ }
+ else
+ {
+ // Case 2: Base image format is not supported by WIC, so we have to convert, generate, and convert back
+ assert( metadata.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
+
+ TexMetadata mdata2 = metadata;
+ mdata2.mipLevels = levels;
+ mdata2.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ ScratchImage tMipChain;
+ hr = tMipChain.Initialize( mdata2 );
+ if ( FAILED(hr) )
+ return hr;
+
+ for( size_t item = 0; item < metadata.arraySize; ++item )
+ {
+ ScratchImage temp;
+ hr = _ConvertToR32G32B32A32( baseImages[item], temp );
+ if ( FAILED(hr) )
+ return hr;
+
+ const Image *timg = temp.GetImage( 0, 0, 0 );
+ if ( !timg )
+ return E_POINTER;
+
+ hr = _GenerateMipMapsUsingWIC( *timg, filter, levels, GUID_WICPixelFormat128bppRGBAFloat, tMipChain, item );
+ if ( FAILED(hr) )
+ return hr;
+ }
+
+ return _ConvertFromR32G32B32A32( tMipChain.GetImages(), tMipChain.GetImageCount(), tMipChain.GetMetadata(), metadata.format, mipChain );
+ }
+ }
+ break;
+
+ default:
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
+ }
+ else
+ {
+ //--- Use custom filters to generate mipmaps ----------------------------------
+ TexMetadata mdata2 = metadata;
+ mdata2.mipLevels = levels;
+
+ DWORD filter_select = ( filter & TEX_FILTER_MASK );
+ if ( !filter_select )
+ {
+ // Default filter choice
+ filter_select = ( ispow2(metadata.width) && ispow2(metadata.height) ) ? TEX_FILTER_BOX : TEX_FILTER_LINEAR;
+ }
+
+ switch( filter_select )
+ {
+ case TEX_FILTER_BOX:
+ hr = _Setup2DMips( &baseImages[0], metadata.arraySize, mdata2, mipChain );
if ( FAILED(hr) )
return hr;
for( size_t item = 0; item < metadata.arraySize; ++item )
{
- size_t index = metadata.ComputeIndex( 0, item, 0 );
- if ( index >= nimages )
- {
+ hr = _Generate2DMipsBoxFilter( levels, filter, mipChain, item );
+ if ( FAILED(hr) )
mipChain.Release();
- return E_FAIL;
- }
+ }
+ return hr;
- const Image& baseImage = srcImages[ index ];
+ case TEX_FILTER_POINT:
+ hr = _Setup2DMips( &baseImages[0], metadata.arraySize, mdata2, mipChain );
+ if ( FAILED(hr) )
+ return hr;
- hr = _GenerateMipMapsUsingWIC( baseImage, filter, levels, pfGUID, mipChain, item );
+ for( size_t item = 0; item < metadata.arraySize; ++item )
+ {
+ hr = _Generate2DMipsPointFilter( levels, mipChain, item );
if ( FAILED(hr) )
- {
mipChain.Release();
- return hr;
- }
}
+ return hr;
- return S_OK;
- }
- else
- {
- // Case 2: Base image format is not supported by WIC, so we have to convert, generate, and convert back
- assert( metadata.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
-
- TexMetadata mdata2 = metadata;
- mdata2.mipLevels = levels;
- mdata2.format = DXGI_FORMAT_R32G32B32A32_FLOAT;
- ScratchImage tMipChain;
- HRESULT hr = tMipChain.Initialize( mdata2 );
+ case TEX_FILTER_LINEAR:
+ hr = _Setup2DMips( &baseImages[0], metadata.arraySize, mdata2, mipChain );
if ( FAILED(hr) )
return hr;
for( size_t item = 0; item < metadata.arraySize; ++item )
{
- size_t index = metadata.ComputeIndex( 0, item, 0 );
- if ( index >= nimages )
- return E_FAIL;
+ hr = _Generate2DMipsLinearFilter( levels, filter, mipChain, item );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ }
+ return hr;
- const Image& baseImage = srcImages[ index ];
+ case TEX_FILTER_CUBIC:
+ hr = _Setup2DMips( &baseImages[0], metadata.arraySize, mdata2, mipChain );
+ if ( FAILED(hr) )
+ return hr;
- ScratchImage temp;
- hr = _ConvertToR32G32B32A32( baseImage, temp );
+ for( size_t item = 0; item < metadata.arraySize; ++item )
+ {
+ hr = _Generate2DMipsCubicFilter( levels, filter, mipChain, item );
if ( FAILED(hr) )
- return hr;
+ mipChain.Release();
+ }
+ return hr;
- const Image *timg = temp.GetImage( 0, 0, 0 );
- if ( !timg )
- return E_POINTER;
+ case TEX_FILTER_TRIANGLE:
+ hr = _Setup2DMips( &baseImages[0], metadata.arraySize, mdata2, mipChain );
+ if ( FAILED(hr) )
+ return hr;
- hr = _GenerateMipMapsUsingWIC( *timg, filter, levels, GUID_WICPixelFormat128bppRGBAFloat, tMipChain, item );
+ for( size_t item = 0; item < metadata.arraySize; ++item )
+ {
+ hr = _Generate2DMipsTriangleFilter( levels, filter, mipChain, item );
if ( FAILED(hr) )
- return hr;
+ mipChain.Release();
}
+ return hr;
- return _ConvertFromR32G32B32A32( tMipChain.GetImages(), tMipChain.GetImageCount(), tMipChain.GetMetadata(), metadata.format, mipChain );
- }
+ default:
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
- break;
-
- default:
- return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );;
}
}
@@ -1012,19 +2882,23 @@ HRESULT GenerateMipMaps( const Image* srcImages, size_t nimages, const TexMetada
//-------------------------------------------------------------------------------------
// Generate mipmap chain for volume texture
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT GenerateMipMaps3D( const Image* baseImages, size_t depth, DWORD filter, size_t levels, ScratchImage& mipChain )
{
if ( !baseImages || !depth )
return E_INVALIDARG;
+ if ( filter & TEX_FILTER_FORCE_WIC )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
DXGI_FORMAT format = baseImages[0].format;
size_t width = baseImages[0].width;
size_t height = baseImages[0].height;
- if ( !ispow2(width) || !ispow2(height) || !ispow2(depth) )
+ if ( !_CalculateMipLevels3D(width, height, depth, levels) )
return E_INVALIDARG;
- if ( !_CalculateMipLevels3D(width, height, depth, levels) )
+ if ( levels <= 1 )
return E_INVALIDARG;
for( size_t slice=0; slice < depth; ++slice )
@@ -1039,30 +2913,33 @@ HRESULT GenerateMipMaps3D( const Image* baseImages, size_t depth, DWORD filter,
}
}
- if ( IsCompressed( format ) )
- {
- // We don't support generating mipmaps from compressed images, as those should be generated before compression
+ if ( IsCompressed(format) || IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
- }
+
+ static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
HRESULT hr;
- static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
- switch( filter & TEX_FILTER_MASK )
+ DWORD filter_select = ( filter & TEX_FILTER_MASK );
+ if ( !filter_select )
+ {
+ // Default filter choice
+ filter_select = ( ispow2(width) && ispow2(height) && ispow2(depth) ) ? TEX_FILTER_BOX : TEX_FILTER_TRIANGLE;
+ }
+
+ switch( filter_select )
{
- case 0:
- case TEX_FILTER_FANT:
+ case TEX_FILTER_BOX:
hr = _Setup3DMips( baseImages, depth, levels, mipChain );
if ( FAILED(hr) )
return hr;
- // For decimation, Fant is equivalent to a Box filter
- hr = _Generate3DMipsBoxFilter( depth, levels, mipChain );
+ hr = _Generate3DMipsBoxFilter( depth, levels, filter, mipChain );
if ( FAILED(hr) )
mipChain.Release();
return hr;
- case WIC_FLAGS_FILTER_POINT:
+ case TEX_FILTER_POINT:
hr = _Setup3DMips( baseImages, depth, levels, mipChain );
if ( FAILED(hr) )
return hr;
@@ -1072,34 +2949,62 @@ HRESULT GenerateMipMaps3D( const Image* baseImages, size_t depth, DWORD filter,
mipChain.Release();
return hr;
- case WIC_FLAGS_FILTER_LINEAR:
- // Need to implement a 3D bi-linear filter (2x2x2)
- return E_NOTIMPL;
+ case TEX_FILTER_LINEAR:
+ hr = _Setup3DMips( baseImages, depth, levels, mipChain );
+ if ( FAILED(hr) )
+ return hr;
+
+ hr = _Generate3DMipsLinearFilter( depth, levels, filter, mipChain );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
+
+ case TEX_FILTER_CUBIC:
+ hr = _Setup3DMips( baseImages, depth, levels, mipChain );
+ if ( FAILED(hr) )
+ return hr;
+
+ hr = _Generate3DMipsCubicFilter( depth, levels, filter, mipChain );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
+
+ case TEX_FILTER_TRIANGLE:
+ hr = _Setup3DMips( baseImages, depth, levels, mipChain );
+ if ( FAILED(hr) )
+ return hr;
- case WIC_FLAGS_FILTER_CUBIC:
- // Need to implement a 3D bi-cubic filter (3x3x3)
- return E_NOTIMPL;
+ hr = _Generate3DMipsTriangleFilter( depth, levels, filter, mipChain );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
default:
- return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );;
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
}
+_Use_decl_annotations_
HRESULT GenerateMipMaps3D( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DWORD filter, size_t levels, ScratchImage& mipChain )
{
- if ( !srcImages || !nimages || !IsValid(metadata.format)
- || !ispow2(metadata.width) || !ispow2(metadata.height) || !ispow2(metadata.depth) )
+ if ( !srcImages || !nimages || !IsValid(metadata.format) )
return E_INVALIDARG;
- if ( metadata.dimension != TEX_DIMENSION_TEXTURE3D
- || IsCompressed( metadata.format ) || IsVideo( metadata.format ) )
+ if ( filter & TEX_FILTER_FORCE_WIC )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
+ if ( !metadata.IsVolumemap()
+ || IsCompressed(metadata.format) || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if ( !_CalculateMipLevels3D(metadata.width, metadata.height, metadata.depth, levels) )
return E_INVALIDARG;
-
- std::vector<const Image> baseImages;
+
+ if ( levels <= 1 )
+ return E_INVALIDARG;
+
+ std::vector<Image> baseImages;
baseImages.reserve( metadata.depth );
for( size_t slice=0; slice < metadata.depth; ++slice )
{
@@ -1125,21 +3030,27 @@ HRESULT GenerateMipMaps3D( const Image* srcImages, size_t nimages, const TexMeta
HRESULT hr;
static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
- switch( filter & TEX_FILTER_MASK )
+
+ DWORD filter_select = ( filter & TEX_FILTER_MASK );
+ if ( !filter_select )
+ {
+ // Default filter choice
+ filter_select = ( ispow2(metadata.width) && ispow2(metadata.height) && ispow2(metadata.depth) ) ? TEX_FILTER_BOX : TEX_FILTER_TRIANGLE;
+ }
+
+ switch( filter_select )
{
- case 0:
- case TEX_FILTER_FANT:
+ case TEX_FILTER_BOX:
hr = _Setup3DMips( &baseImages[0], metadata.depth, levels, mipChain );
if ( FAILED(hr) )
return hr;
- // For decimation, Fant is equivalent to a Box filter
- hr = _Generate3DMipsBoxFilter( metadata.depth, levels, mipChain );
+ hr = _Generate3DMipsBoxFilter( metadata.depth, levels, filter, mipChain );
if ( FAILED(hr) )
mipChain.Release();
return hr;
- case WIC_FLAGS_FILTER_POINT:
+ case TEX_FILTER_POINT:
hr = _Setup3DMips( &baseImages[0], metadata.depth, levels, mipChain );
if ( FAILED(hr) )
return hr;
@@ -1149,16 +3060,38 @@ HRESULT GenerateMipMaps3D( const Image* srcImages, size_t nimages, const TexMeta
mipChain.Release();
return hr;
- case WIC_FLAGS_FILTER_LINEAR:
- // Need to implement a 3D bi-linear filter (2x2x2)
- return E_NOTIMPL;
+ case TEX_FILTER_LINEAR:
+ hr = _Setup3DMips( &baseImages[0], metadata.depth, levels, mipChain );
+ if ( FAILED(hr) )
+ return hr;
+
+ hr = _Generate3DMipsLinearFilter( metadata.depth, levels, filter, mipChain );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
+
+ case TEX_FILTER_CUBIC:
+ hr = _Setup3DMips( &baseImages[0], metadata.depth, levels, mipChain );
+ if ( FAILED(hr) )
+ return hr;
+
+ hr = _Generate3DMipsCubicFilter( metadata.depth, levels, filter, mipChain );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
+
+ case TEX_FILTER_TRIANGLE:
+ hr = _Setup3DMips( &baseImages[0], metadata.depth, levels, mipChain );
+ if ( FAILED(hr) )
+ return hr;
- case WIC_FLAGS_FILTER_CUBIC:
- // Need to implement a 3D bi-cubic filter (3x3x3)
- return E_NOTIMPL;
+ hr = _Generate3DMipsTriangleFilter( metadata.depth, levels, filter, mipChain );
+ if ( FAILED(hr) )
+ mipChain.Release();
+ return hr;
default:
- return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );;
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
}
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexMisc.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexMisc.cpp
index 988fb1fb..3285ba5d 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexMisc.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexMisc.cpp
@@ -17,10 +17,12 @@
namespace DirectX
{
+static const XMVECTORF32 g_Gamma22 = { 2.2f, 2.2f, 2.2f, 1.f };
//-------------------------------------------------------------------------------------
static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
- _Out_ float& mse, _Out_opt_cap_c_(4) float* mseV )
+ _Out_ float& mse, _Out_writes_opt_(4) float* mseV,
+ _In_ DWORD flags )
{
if ( !image1.pixels || !image2.pixels )
return E_POINTER;
@@ -34,13 +36,55 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
if ( !scanline )
return E_OUTOFMEMORY;
+ // Flags implied from image formats
+ switch( image1.format )
+ {
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ flags |= CMSE_IGNORE_ALPHA;
+ break;
+
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ flags |= CMSE_IMAGE1_SRGB | CMSE_IGNORE_ALPHA;
+ break;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ flags |= CMSE_IMAGE1_SRGB;
+ break;
+ }
+
+ switch( image2.format )
+ {
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ flags |= CMSE_IGNORE_ALPHA;
+ break;
+
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ flags |= CMSE_IMAGE2_SRGB | CMSE_IGNORE_ALPHA;
+ break;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ flags |= CMSE_IMAGE2_SRGB;
+ break;
+ }
+
const uint8_t *pSrc1 = image1.pixels;
const size_t rowPitch1 = image1.rowPitch;
const uint8_t *pSrc2 = image2.pixels;
const size_t rowPitch2 = image2.rowPitch;
- XMVECTOR acc = XMVectorZero();
+ XMVECTOR acc = g_XMZero;
+ static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
for( size_t h = 0; h < image1.height; ++h )
{
@@ -52,10 +96,47 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
if ( !_LoadScanline( ptr2, width, pSrc2, rowPitch2, image2.format ) )
return E_FAIL;
- for( size_t i = 0; i < width; ++i, ++ptr1, ++ptr2 )
+ for( size_t i = 0; i < width; ++i )
{
+ XMVECTOR v1 = *(ptr1++);
+ if ( flags & CMSE_IMAGE1_SRGB )
+ {
+ v1 = XMVectorPow( v1, g_Gamma22 );
+ }
+ if ( flags & CMSE_IMAGE1_X2_BIAS )
+ {
+ v1 = XMVectorMultiplyAdd( v1, two, g_XMNegativeOne );
+ }
+
+ XMVECTOR v2 = *(ptr2++);
+ if ( flags & CMSE_IMAGE2_SRGB )
+ {
+ v2 = XMVectorPow( v2, g_Gamma22 );
+ }
+ if ( flags & CMSE_IMAGE2_X2_BIAS )
+ {
+ v1 = XMVectorMultiplyAdd( v2, two, g_XMNegativeOne );
+ }
+
// sum[ (I1 - I2)^2 ]
- XMVECTOR v = XMVectorSubtract( *ptr1, *ptr2 );
+ XMVECTOR v = XMVectorSubtract( v1, v2 );
+ if ( flags & CMSE_IGNORE_RED )
+ {
+ v = XMVectorSelect( v, g_XMZero, g_XMMaskX );
+ }
+ if ( flags & CMSE_IGNORE_GREEN )
+ {
+ v = XMVectorSelect( v, g_XMZero, g_XMMaskY );
+ }
+ if ( flags & CMSE_IGNORE_BLUE )
+ {
+ v = XMVectorSelect( v, g_XMZero, g_XMMaskZ );
+ }
+ if ( flags & CMSE_IGNORE_ALPHA )
+ {
+ v = XMVectorSelect( v, g_XMZero, g_XMMaskW );
+ }
+
acc = XMVectorMultiplyAdd( v, v, acc );
}
@@ -89,12 +170,15 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
//-------------------------------------------------------------------------------------
// Copies a rectangle from one image into another
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image& dstImage, DWORD filter, size_t xOffset, size_t yOffset )
{
if ( !srcImage.pixels || !dstImage.pixels )
return E_POINTER;
- if ( IsCompressed( srcImage.format ) || IsCompressed( dstImage.format ) )
+ if ( IsCompressed( srcImage.format ) || IsCompressed( dstImage.format )
+ || IsPlanar( srcImage.format ) || IsPlanar( dstImage.format )
+ || IsPalettized( srcImage.format ) || IsPalettized( dstImage.format ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
// Validate rectangle/offset
@@ -193,7 +277,8 @@ HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image&
//-------------------------------------------------------------------------------------
// Computes the Mean-Squared-Error (MSE) between two images
//-------------------------------------------------------------------------------------
-HRESULT ComputeMSE( const Image& image1, const Image& image2, float& mse, float* mseV )
+_Use_decl_annotations_
+HRESULT ComputeMSE( const Image& image1, const Image& image2, float& mse, float* mseV, DWORD flags )
{
if ( !image1.pixels || !image2.pixels )
return E_POINTER;
@@ -201,6 +286,10 @@ HRESULT ComputeMSE( const Image& image1, const Image& image2, float& mse, float*
if ( image1.width != image2.width || image1.height != image2.height )
return E_INVALIDARG;
+ if ( IsPlanar( image1.format ) || IsPlanar( image2.format )
+ || IsPalettized( image1.format ) || IsPalettized( image2.format ) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
if ( IsCompressed(image1.format) )
{
if ( IsCompressed(image2.format) )
@@ -221,7 +310,7 @@ HRESULT ComputeMSE( const Image& image1, const Image& image2, float& mse, float*
if ( !img1 || !img2 )
return E_POINTER;
- return _ComputeMSE( *img1, *img2, mse, mseV );
+ return _ComputeMSE( *img1, *img2, mse, mseV, flags );
}
else
{
@@ -235,7 +324,7 @@ HRESULT ComputeMSE( const Image& image1, const Image& image2, float& mse, float*
if ( !img )
return E_POINTER;
- return _ComputeMSE( *img, image2, mse, mseV );
+ return _ComputeMSE( *img, image2, mse, mseV, flags );
}
}
else
@@ -252,12 +341,12 @@ HRESULT ComputeMSE( const Image& image1, const Image& image2, float& mse, float*
if ( !img )
return E_POINTER;
- return _ComputeMSE( image1, *img, mse, mseV );
+ return _ComputeMSE( image1, *img, mse, mseV, flags );
}
else
{
// Case 4: neither image is compressed
- return _ComputeMSE( image1, image2, mse, mseV );
+ return _ComputeMSE( image1, image2, mse, mseV, flags );
}
}
}
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexNormalMaps.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexNormalMaps.cpp
index ad594933..3e07c7e0 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexNormalMaps.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexNormalMaps.cpp
@@ -48,7 +48,7 @@ static inline float _EvaluateColor( _In_ FXMVECTOR val, _In_ DWORD flags )
}
}
-static void _EvaluateRow( _In_count_(width) const XMVECTOR* pSource, _Out_cap_(width+2) float* pDest,
+static void _EvaluateRow( _In_reads_(width) const XMVECTOR* pSource, _Out_writes_(width+2) float* pDest,
_In_ size_t width, _In_ DWORD flags )
{
assert( pSource && pDest );
@@ -79,14 +79,12 @@ static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_
if ( !srcImage.pixels || !normalMap.pixels )
return E_INVALIDARG;
- assert( !IsCompressed(format) && !IsTypeless( format ) );
-
const DWORD convFlags = _GetConvertFlags( format );
if ( !convFlags )
return E_FAIL;
if ( !( convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT) ) )
- HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
const size_t width = srcImage.width;
const size_t height = srcImage.height;
@@ -253,10 +251,11 @@ static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_
//-------------------------------------------------------------------------------------
// Generates a normal map from a height-map
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
DXGI_FORMAT format, ScratchImage& normalMap )
{
- if ( !srcImage.pixels || !IsValid(format) || IsCompressed( format ) || IsTypeless( format ) )
+ if ( !srcImage.pixels || !IsValid(format) )
return E_INVALIDARG;
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
@@ -274,7 +273,10 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
return E_INVALIDARG;
}
- if ( IsCompressed( srcImage.format ) || IsTypeless( srcImage.format ) )
+ if ( IsCompressed(format) || IsCompressed(srcImage.format)
+ || IsTypeless(format) || IsTypeless(srcImage.format)
+ || IsPlanar(format) || IsPlanar(srcImage.format)
+ || IsPalettized(format) || IsPalettized(srcImage.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
// Setup target image
@@ -301,14 +303,18 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
return S_OK;
}
+_Use_decl_annotations_
HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DWORD flags, float amplitude, DXGI_FORMAT format, ScratchImage& normalMaps )
{
- if ( !srcImages || !nimages )
+ if ( !srcImages || !nimages || !IsValid(format) )
return E_INVALIDARG;
- if ( !IsValid(format) || IsCompressed(format) || IsTypeless(format) )
- return E_INVALIDARG;
+ if ( IsCompressed(format) || IsCompressed(metadata.format)
+ || IsTypeless(format) || IsTypeless(metadata.format)
+ || IsPlanar(format) || IsPlanar(metadata.format)
+ || IsPalettized(format) || IsPalettized(metadata.format) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
switch( flags & 0xf )
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexP.h b/thirdparty/directxtex/DirectXTex/DirectXTexP.h
index 4659b9bb..d435becf 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexP.h
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexP.h
@@ -13,9 +13,7 @@
// http://go.microsoft.com/fwlink/?LinkId=248926
//-------------------------------------------------------------------------------------
-#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
-#endif
#ifndef NOMINMAX
#define NOMINMAX
@@ -41,20 +39,21 @@
#include <ole2.h>
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
-#include <d2d1.h>
-#endif
+#include "DirectXTex.h"
+#ifndef __MINGW32__
+// VS 2010's stdint.h conflicts with intsafe.h
#pragma warning(push)
#pragma warning(disable : 4005)
#include <wincodec.h>
+#include <intsafe.h>
#pragma warning(pop)
-
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(DXGI_1_2_FORMATS)
-#define DXGI_1_2_FORMATS
+#else
+#include <wincodec.h>
+#include <stdint.h>
#endif
-#include "DirectXTex.h"
+#include <wrl/client.h>
#include "scoped.h"
@@ -66,14 +65,16 @@ namespace DirectX
{
//---------------------------------------------------------------------------------
// WIC helper functions
- DXGI_FORMAT _WICToDXGI( _In_ const GUID& guid );
- bool _DXGIToWIC( _In_ DXGI_FORMAT format, _Out_ GUID& guid );
+ DXGI_FORMAT __cdecl _WICToDXGI( _In_ const GUID& guid );
+ bool __cdecl _DXGIToWIC( _In_ DXGI_FORMAT format, _Out_ GUID& guid, _In_ bool ignoreRGBvsBGR = false );
+
+ DWORD __cdecl _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetGUID );
- IWICImagingFactory* _GetWIC();
+ IWICImagingFactory* __cdecl _GetWIC();
- bool _IsWIC2();
+ bool __cdecl _IsWIC2();
- inline WICBitmapDitherType _GetWICDither( _In_ DWORD flags )
+ inline WICBitmapDitherType __cdecl _GetWICDither( _In_ DWORD flags )
{
static_assert( TEX_FILTER_DITHER == 0x10000, "TEX_FILTER_DITHER* flag values don't match mask" );
@@ -93,7 +94,7 @@ namespace DirectX
}
}
- inline WICBitmapInterpolationMode _GetWICInterp( _In_ DWORD flags )
+ inline WICBitmapInterpolationMode __cdecl _GetWICInterp( _In_ DWORD flags )
{
static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
@@ -121,12 +122,13 @@ namespace DirectX
//---------------------------------------------------------------------------------
// Image helper functions
- void _DetermineImageArray( _In_ const TexMetadata& metadata, _In_ DWORD cpFlags,
- _Out_ size_t& nImages, _Out_ size_t& pixelSize );
+ void __cdecl _DetermineImageArray( _In_ const TexMetadata& metadata, _In_ DWORD cpFlags,
+ _Out_ size_t& nImages, _Out_ size_t& pixelSize );
- bool _SetupImageArray( _In_bytecount_(pixelSize) uint8_t *pMemory, _In_ size_t pixelSize,
- _In_ const TexMetadata& metadata, _In_ DWORD cpFlags,
- _Out_cap_(nImages) Image* images, _In_ size_t nImages );
+ _Success_(return != false)
+ bool __cdecl _SetupImageArray( _In_reads_bytes_(pixelSize) uint8_t *pMemory, _In_ size_t pixelSize,
+ _In_ const TexMetadata& metadata, _In_ DWORD cpFlags,
+ _Out_writes_(nImages) Image* images, _In_ size_t nImages );
//---------------------------------------------------------------------------------
// Conversion helper functions
@@ -149,9 +151,10 @@ namespace DirectX
CONVF_STENCIL = 0x40,
CONVF_SHAREDEXP = 0x80,
CONVF_BGR = 0x100,
- CONVF_X2 = 0x200,
+ CONVF_XR = 0x200,
CONVF_PACKED = 0x400,
CONVF_BC = 0x800,
+ CONVF_YUV = 0x1000,
CONVF_R = 0x10000,
CONVF_G = 0x20000,
CONVF_B = 0x40000,
@@ -160,40 +163,60 @@ namespace DirectX
CONVF_RGBA_MASK = 0xF0000,
};
- DWORD _GetConvertFlags( _In_ DXGI_FORMAT format );
-
- void _CopyScanline( _Out_bytecap_(outSize) LPVOID pDestination, _In_ size_t outSize,
- _In_bytecount_(inSize) LPCVOID pSource, _In_ size_t inSize,
- _In_ DXGI_FORMAT format, _In_ DWORD flags );
-
- void _SwizzleScanline( _Out_bytecap_(outSize) LPVOID pDestination, _In_ size_t outSize,
- _In_bytecount_(inSize) LPCVOID pSource, _In_ size_t inSize,
- _In_ DXGI_FORMAT format, _In_ DWORD flags );
-
- bool _ExpandScanline( _Out_bytecap_(outSize) LPVOID pDestination, _In_ size_t outSize,
- _In_ DXGI_FORMAT outFormat,
- _In_bytecount_(inSize) LPCVOID pSource, _In_ size_t inSize,
- _In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
-
- bool _LoadScanline( _Out_cap_(count) XMVECTOR* pDestination, _In_ size_t count,
- _In_bytecount_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format );
-
- bool _StoreScanline( _Out_bytecap_(size) LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
- _In_count_(count) const XMVECTOR* pSource, _In_ size_t count );
-
- HRESULT _ConvertToR32G32B32A32( _In_ const Image& srcImage, _Inout_ ScratchImage& image );
-
- HRESULT _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ const Image& destImage );
- HRESULT _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _Inout_ ScratchImage& image );
- HRESULT _ConvertFromR32G32B32A32( _In_count_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
- _In_ DXGI_FORMAT format, _Out_ ScratchImage& result );
-
- void _ConvertScanline( _Inout_count_(count) XMVECTOR* pBuffer, _In_ size_t count,
- _In_ DXGI_FORMAT outFormat, _In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
+ DWORD __cdecl _GetConvertFlags( _In_ DXGI_FORMAT format );
+
+ void __cdecl _CopyScanline( _When_(pDestination == pSource, _Inout_updates_bytes_(outSize))
+ _When_(pDestination != pSource, _Out_writes_bytes_(outSize))
+ LPVOID pDestination, _In_ size_t outSize,
+ _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
+ _In_ DXGI_FORMAT format, _In_ DWORD flags );
+
+ void __cdecl _SwizzleScanline( _When_(pDestination == pSource, _In_)
+ _When_(pDestination != pSource, _Out_writes_bytes_(outSize))
+ LPVOID pDestination, _In_ size_t outSize,
+ _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
+ _In_ DXGI_FORMAT format, _In_ DWORD flags );
+
+ _Success_(return != false)
+ bool __cdecl _ExpandScanline( _Out_writes_bytes_(outSize) LPVOID pDestination, _In_ size_t outSize,
+ _In_ DXGI_FORMAT outFormat,
+ _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
+ _In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
+
+ _Success_(return != false)
+ bool __cdecl _LoadScanline( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
+ _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format );
+
+ _Success_(return != false)
+ bool __cdecl _LoadScanlineLinear( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
+ _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags );
+
+ _Success_(return != false)
+ bool __cdecl _StoreScanline( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
+ _In_reads_(count) const XMVECTOR* pSource, _In_ size_t count, _In_ float threshold = 0 );
+
+ _Success_(return != false)
+ bool __cdecl _StoreScanlineLinear( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
+ _Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ DWORD flags, _In_ float threshold = 0 );
+
+ _Success_(return != false)
+ bool __cdecl _StoreScanlineDither( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
+ _Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ float threshold, size_t y, size_t z,
+ _Inout_updates_all_opt_(count+2) XMVECTOR* pDiffusionErrors );
+
+ HRESULT __cdecl _ConvertToR32G32B32A32( _In_ const Image& srcImage, _Inout_ ScratchImage& image );
+
+ HRESULT __cdecl _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ const Image& destImage );
+ HRESULT __cdecl _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ DXGI_FORMAT format, _Inout_ ScratchImage& image );
+ HRESULT __cdecl _ConvertFromR32G32B32A32( _In_reads_(nimages) const Image* srcImages, _In_ size_t nimages, _In_ const TexMetadata& metadata,
+ _In_ DXGI_FORMAT format, _Out_ ScratchImage& result );
+
+ void __cdecl _ConvertScanline( _Inout_updates_all_(count) XMVECTOR* pBuffer, _In_ size_t count,
+ _In_ DXGI_FORMAT outFormat, _In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
//---------------------------------------------------------------------------------
// DDS helper functions
- HRESULT _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
- _Out_opt_cap_x_(maxsize) LPVOID pDestination, _In_ size_t maxsize, _Out_ size_t& required );
+ HRESULT __cdecl _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
+ _Out_writes_bytes_to_opt_(maxsize, required) LPVOID pDestination, _In_ size_t maxsize, _Out_ size_t& required );
}; // namespace
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexPMAlpha.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexPMAlpha.cpp
new file mode 100644
index 00000000..d5da2069
--- /dev/null
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexPMAlpha.cpp
@@ -0,0 +1,229 @@
+//-------------------------------------------------------------------------------------
+// DirectXTexPMAlpha.cpp
+//
+// DirectX Texture Library - Premultiplied alpha operations
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// http://go.microsoft.com/fwlink/?LinkId=248926
+//-------------------------------------------------------------------------------------
+
+#include "directxtexp.h"
+
+namespace DirectX
+{
+
+static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image& destImage )
+{
+ assert( srcImage.width == destImage.width );
+ assert( srcImage.height == destImage.height );
+
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ const uint8_t *pSrc = srcImage.pixels;
+ uint8_t *pDest = destImage.pixels;
+ if ( !pSrc || !pDest )
+ return E_POINTER;
+
+ for( size_t h = 0; h < srcImage.height; ++h )
+ {
+ if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
+ return E_FAIL;
+
+ XMVECTOR* ptr = scanline.get();
+ for( size_t w = 0; w < srcImage.width; ++w )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR alpha = XMVectorSplatW( *ptr );
+ alpha = XMVectorMultiply( v, alpha );
+ *(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
+ }
+
+ if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
+ return E_FAIL;
+
+ pSrc += srcImage.rowPitch;
+ pDest += destImage.rowPitch;
+ }
+
+ return S_OK;
+}
+
+static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
+{
+ assert( srcImage.width == destImage.width );
+ assert( srcImage.height == destImage.height );
+
+ static_assert( TEX_PMALPHA_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
+ static_assert( TEX_PMALPHA_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
+ static_assert( TEX_PMALPHA_SRGB == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
+ flags &= TEX_PMALPHA_SRGB;
+
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ const uint8_t *pSrc = srcImage.pixels;
+ uint8_t *pDest = destImage.pixels;
+ if ( !pSrc || !pDest )
+ return E_POINTER;
+
+ for( size_t h = 0; h < srcImage.height; ++h )
+ {
+ if ( !_LoadScanlineLinear( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags ) )
+ return E_FAIL;
+
+ XMVECTOR* ptr = scanline.get();
+ for( size_t w = 0; w < srcImage.width; ++w )
+ {
+ XMVECTOR v = *ptr;
+ XMVECTOR alpha = XMVectorSplatW( *ptr );
+ alpha = XMVectorMultiply( v, alpha );
+ *(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags ) )
+ return E_FAIL;
+
+ pSrc += srcImage.rowPitch;
+ pDest += destImage.rowPitch;
+ }
+
+ return S_OK;
+}
+
+
+//=====================================================================================
+// Entry-points
+//=====================================================================================
+
+//-------------------------------------------------------------------------------------
+// Converts to a premultiplied alpha version of the texture
+//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
+HRESULT PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& image )
+{
+ if ( !srcImage.pixels )
+ return E_POINTER;
+
+ if ( IsCompressed(srcImage.format)
+ || IsPlanar(srcImage.format)
+ || IsPalettized(srcImage.format)
+ || IsTypeless(srcImage.format)
+ || !HasAlpha(srcImage.format) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
+#ifdef _M_X64
+ if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
+ return E_INVALIDARG;
+#endif
+
+ HRESULT hr = image.Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1 );
+ if ( FAILED(hr) )
+ return hr;
+
+ const Image *rimage = image.GetImage( 0, 0, 0 );
+ if ( !rimage )
+ {
+ image.Release();
+ return E_POINTER;
+ }
+
+ hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( srcImage, *rimage ) : _PremultiplyAlphaLinear( srcImage, flags, *rimage );
+ if ( FAILED(hr) )
+ {
+ image.Release();
+ return hr;
+ }
+
+ return S_OK;
+}
+
+
+//-------------------------------------------------------------------------------------
+// Converts to a premultiplied alpha version of the texture (complex)
+//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
+HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DWORD flags, ScratchImage& result )
+{
+ if ( !srcImages || !nimages )
+ return E_INVALIDARG;
+
+ if ( IsCompressed(metadata.format)
+ || IsPlanar(metadata.format)
+ || IsPalettized(metadata.format)
+ || IsTypeless(metadata.format)
+ || !HasAlpha(metadata.format) )
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+
+#ifdef _M_X64
+ if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) )
+ return E_INVALIDARG;
+#endif
+
+ if ( metadata.IsPMAlpha() )
+ {
+ // Already premultiplied
+ return E_FAIL;
+ }
+
+ TexMetadata mdata2 = metadata;
+ mdata2.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED);
+ HRESULT hr = result.Initialize( mdata2 );
+ if ( FAILED(hr) )
+ return hr;
+
+ if ( nimages != result.GetImageCount() )
+ {
+ result.Release();
+ return E_FAIL;
+ }
+
+ const Image* dest = result.GetImages();
+ if ( !dest )
+ {
+ result.Release();
+ return E_POINTER;
+ }
+
+ for( size_t index=0; index < nimages; ++index )
+ {
+ const Image& src = srcImages[ index ];
+ if ( src.format != metadata.format )
+ {
+ result.Release();
+ return E_FAIL;
+ }
+
+#ifdef _M_X64
+ if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
+ return E_FAIL;
+#endif
+ const Image& dst = dest[ index ];
+ assert( dst.format == metadata.format );
+
+ if ( src.width != dst.width || src.height != dst.height )
+ {
+ result.Release();
+ return E_FAIL;
+ }
+
+ hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( src, dst ) : _PremultiplyAlphaLinear( src, flags, dst );
+ if ( FAILED(hr) )
+ {
+ result.Release();
+ return hr;
+ }
+ }
+
+ return S_OK;
+}
+
+}; // namespace
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexResize.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexResize.cpp
index 9f70c929..81b65beb 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexResize.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexResize.cpp
@@ -15,15 +15,21 @@
#include "DirectXTexP.h"
+#include "filters.h"
+
+using Microsoft::WRL::ComPtr;
+
namespace DirectX
{
+//-------------------------------------------------------------------------------------
+// WIC related helper functions
+//-------------------------------------------------------------------------------------
+
extern HRESULT _ResizeSeparateColorAndAlpha( _In_ IWICImagingFactory* pWIC, _In_ IWICBitmap* original,
_In_ size_t newWidth, _In_ size_t newHeight, _In_ DWORD filter, _Inout_ const Image* img );
-//-------------------------------------------------------------------------------------
-// Do image resize using WIC
-//-------------------------------------------------------------------------------------
+//--- Do image resize using WIC ---
static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD filter,
_In_ const WICPixelFormatGUID& pfGUID, _In_ const Image& destImage )
{
@@ -36,13 +42,13 @@ static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD fi
if ( !pWIC )
return E_NOINTERFACE;
- ScopedObject<IWICComponentInfo> componentInfo;
- HRESULT hr = pWIC->CreateComponentInfo( pfGUID, &componentInfo );
+ ComPtr<IWICComponentInfo> componentInfo;
+ HRESULT hr = pWIC->CreateComponentInfo( pfGUID, componentInfo.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICPixelFormatInfo2> pixelFormatInfo;
- hr = componentInfo->QueryInterface( __uuidof(IWICPixelFormatInfo2), (void**)&pixelFormatInfo );
+ ComPtr<IWICPixelFormatInfo2> pixelFormatInfo;
+ hr = componentInfo.As( &pixelFormatInfo );
if ( FAILED(hr) )
return hr;
@@ -51,10 +57,10 @@ static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD fi
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICBitmap> source;
+ ComPtr<IWICBitmap> source;
hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
- srcImage.pixels, &source );
+ srcImage.pixels, source.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -66,8 +72,8 @@ static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD fi
}
else
{
- ScopedObject<IWICBitmapScaler> scaler;
- hr = pWIC->CreateBitmapScaler( &scaler );
+ ComPtr<IWICBitmapScaler> scaler;
+ hr = pWIC->CreateBitmapScaler( scaler.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -90,11 +96,18 @@ static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD fi
{
// The WIC bitmap scaler is free to return a different pixel format than the source image, so here we
// convert it back
- ScopedObject<IWICFormatConverter> FC;
- hr = pWIC->CreateFormatConverter( &FC );
+ ComPtr<IWICFormatConverter> FC;
+ hr = pWIC->CreateFormatConverter( FC.GetAddressOf() );
if ( FAILED(hr) )
return hr;
+ BOOL canConvert = FALSE;
+ hr = FC->CanConvert( pfScaler, pfGUID, &canConvert );
+ if ( FAILED(hr) || !canConvert )
+ {
+ return E_UNEXPECTED;
+ }
+
hr = FC->Initialize( scaler.Get(), pfGUID, _GetWICDither( filter ), 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
@@ -109,9 +122,7 @@ static HRESULT _PerformResizeUsingWIC( _In_ const Image& srcImage, _In_ DWORD fi
}
-//-------------------------------------------------------------------------------------
-// Do conversion, resize using WIC, conversion cycle
-//-------------------------------------------------------------------------------------
+//--- Do conversion, resize using WIC, conversion cycle ---
static HRESULT _PerformResizeViaF32( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
{
if ( !srcImage.pixels || !destImage.pixels )
@@ -152,6 +163,662 @@ static HRESULT _PerformResizeViaF32( _In_ const Image& srcImage, _In_ DWORD filt
}
+//--- determine when to use WIC vs. non-WIC paths ---
+static bool _UseWICFiltering( _In_ DXGI_FORMAT format, _In_ DWORD filter )
+{
+ if ( filter & TEX_FILTER_FORCE_NON_WIC )
+ {
+ // Explicit flag indicates use of non-WIC code paths
+ return false;
+ }
+
+ if ( filter & TEX_FILTER_FORCE_WIC )
+ {
+ // Explicit flag to use WIC code paths, skips all the case checks below
+ return true;
+ }
+
+ if ( IsSRGB(format) || (filter & TEX_FILTER_SRGB) )
+ {
+ // Use non-WIC code paths for sRGB correct filtering
+ return false;
+ }
+
+#if defined(_XBOX_ONE) && defined(_TITLE)
+ if ( format == DXGI_FORMAT_R16G16B16A16_FLOAT
+ || format == DXGI_FORMAT_R16_FLOAT )
+ {
+ // Use non-WIC code paths as these conversions are not supported by Xbox One XDK
+ return false;
+ }
+#endif
+
+ static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
+
+ switch ( filter & TEX_FILTER_MASK )
+ {
+ case TEX_FILTER_LINEAR:
+ if ( filter & TEX_FILTER_WRAP )
+ {
+ // WIC only supports 'clamp' semantics (MIRROR is equivalent to clamp for linear)
+ return false;
+ }
+
+ if ( BitsPerColor(format) > 8 )
+ {
+ // Avoid the WIC bitmap scaler when doing Linear filtering of XR/HDR formats
+ return false;
+ }
+ break;
+
+ case TEX_FILTER_CUBIC:
+ if ( filter & ( TEX_FILTER_WRAP | TEX_FILTER_MIRROR ) )
+ {
+ // WIC only supports 'clamp' semantics
+ return false;
+ }
+
+ if ( BitsPerColor(format) > 8 )
+ {
+ // Avoid the WIC bitmap scaler when doing Cubic filtering of XR/HDR formats
+ return false;
+ }
+ break;
+
+ case TEX_FILTER_TRIANGLE:
+ // WIC does not implement this filter
+ return false;
+ }
+
+ return true;
+}
+
+
+//-------------------------------------------------------------------------------------
+// Resize custom filters
+//-------------------------------------------------------------------------------------
+
+//--- Point Filter ---
+static HRESULT _ResizePointFilter( _In_ const Image& srcImage, _In_ const Image& destImage )
+{
+ assert( srcImage.pixels && destImage.pixels );
+ assert( srcImage.format == destImage.format );
+
+ // Allocate temporary space (2 scanlines)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc(
+ ( sizeof(XMVECTOR) * (srcImage.width + destImage.width ) ), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* row = target + destImage.width;
+
+#ifdef _DEBUG
+ memset( row, 0xCD, sizeof(XMVECTOR)*srcImage.width );
+#endif
+
+ const uint8_t* pSrc = srcImage.pixels;
+ uint8_t* pDest = destImage.pixels;
+
+ size_t rowPitch = srcImage.rowPitch;
+
+ size_t xinc = ( srcImage.width << 16 ) / destImage.width;
+ size_t yinc = ( srcImage.height << 16 ) / destImage.height;
+
+ size_t lasty = size_t(-1);
+
+ size_t sy = 0;
+ for( size_t y = 0; y < destImage.height; ++y )
+ {
+ if ( (lasty ^ sy) >> 16 )
+ {
+ if ( !_LoadScanline( row, srcImage.width, pSrc + ( rowPitch * (sy >> 16) ), rowPitch, srcImage.format ) )
+ return E_FAIL;
+ lasty = sy;
+ }
+
+ size_t sx = 0;
+ for( size_t x = 0; x < destImage.width; ++x )
+ {
+ target[ x ] = row[ sx >> 16 ];
+ sx += xinc;
+ }
+
+ if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, target, destImage.width ) )
+ return E_FAIL;
+ pDest += destImage.rowPitch;
+
+ sy += yinc;
+ }
+
+ return S_OK;
+}
+
+
+//--- Box Filter ---
+static HRESULT _ResizeBoxFilter( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
+{
+ assert( srcImage.pixels && destImage.pixels );
+ assert( srcImage.format == destImage.format );
+
+ if ( ( (destImage.width << 1) != srcImage.width ) || ( (destImage.height << 1) != srcImage.height ) )
+ return E_FAIL;
+
+ // Allocate temporary space (3 scanlines)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc(
+ ( sizeof(XMVECTOR) * ( srcImage.width*2 + destImage.width ) ), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* urow0 = target + destImage.width;
+ XMVECTOR* urow1 = urow0 + srcImage.width;
+
+#ifdef _DEBUG
+ memset( urow0, 0xCD, sizeof(XMVECTOR)*srcImage.width );
+ memset( urow1, 0xDD, sizeof(XMVECTOR)*srcImage.width );
+#endif
+
+ const XMVECTOR* urow2 = urow0 + 1;
+ const XMVECTOR* urow3 = urow1 + 1;
+
+ const uint8_t* pSrc = srcImage.pixels;
+ uint8_t* pDest = destImage.pixels;
+
+ size_t rowPitch = srcImage.rowPitch;
+
+ for( size_t y = 0; y < destImage.height; ++y )
+ {
+ if ( !_LoadScanlineLinear( urow0, srcImage.width, pSrc, rowPitch, srcImage.format, filter ) )
+ return E_FAIL;
+ pSrc += rowPitch;
+
+ if ( urow0 != urow1 )
+ {
+ if ( !_LoadScanlineLinear( urow1, srcImage.width, pSrc, rowPitch, srcImage.format, filter ) )
+ return E_FAIL;
+ pSrc += rowPitch;
+ }
+
+ for( size_t x = 0; x < destImage.width; ++x )
+ {
+ size_t x2 = x << 1;
+
+ AVERAGE4( target[ x ], urow0[ x2 ], urow1[ x2 ], urow2[ x2 ], urow3[ x2 ] );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, destImage.rowPitch, destImage.format, target, destImage.width, filter ) )
+ return E_FAIL;
+ pDest += destImage.rowPitch;
+ }
+
+ return S_OK;
+}
+
+
+//--- Linear Filter ---
+static HRESULT _ResizeLinearFilter( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
+{
+ assert( srcImage.pixels && destImage.pixels );
+ assert( srcImage.format == destImage.format );
+
+ // Allocate temporary space (3 scanlines, plus X and Y filters)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc(
+ ( sizeof(XMVECTOR) * ( srcImage.width*2 + destImage.width ) ), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ std::unique_ptr<LinearFilter[]> lf( new (std::nothrow) LinearFilter[ destImage.width + destImage.height ] );
+ if ( !lf )
+ return E_OUTOFMEMORY;
+
+ LinearFilter* lfX = lf.get();
+ LinearFilter* lfY = lf.get() + destImage.width;
+
+ _CreateLinearFilter( srcImage.width, destImage.width, (filter & TEX_FILTER_WRAP_U) != 0, lfX );
+ _CreateLinearFilter( srcImage.height, destImage.height, (filter & TEX_FILTER_WRAP_V) != 0, lfY );
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* row0 = target + destImage.width;
+ XMVECTOR* row1 = row0 + srcImage.width;
+
+#ifdef _DEBUG
+ memset( row0, 0xCD, sizeof(XMVECTOR)*srcImage.width );
+ memset( row1, 0xDD, sizeof(XMVECTOR)*srcImage.width );
+#endif
+
+ const uint8_t* pSrc = srcImage.pixels;
+ uint8_t* pDest = destImage.pixels;
+
+ size_t rowPitch = srcImage.rowPitch;
+
+ size_t u0 = size_t(-1);
+ size_t u1 = size_t(-1);
+
+ for( size_t y = 0; y < destImage.height; ++y )
+ {
+ auto& toY = lfY[ y ];
+
+ if ( toY.u0 != u0 )
+ {
+ if ( toY.u0 != u1 )
+ {
+ u0 = toY.u0;
+
+ if ( !_LoadScanlineLinear( row0, srcImage.width, pSrc + (rowPitch * u0), rowPitch, srcImage.format, filter ) )
+ return E_FAIL;
+ }
+ else
+ {
+ u0 = u1;
+ u1 = size_t(-1);
+
+ std::swap( row0, row1 );
+ }
+ }
+
+ if ( toY.u1 != u1 )
+ {
+ u1 = toY.u1;
+
+ if ( !_LoadScanlineLinear( row1, srcImage.width, pSrc + (rowPitch * u1), rowPitch, srcImage.format, filter ) )
+ return E_FAIL;
+ }
+
+ for( size_t x = 0; x < destImage.width; ++x )
+ {
+ auto& toX = lfX[ x ];
+
+ BILINEAR_INTERPOLATE( target[x], toX, toY, row0, row1 );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, destImage.rowPitch, destImage.format, target, destImage.width, filter ) )
+ return E_FAIL;
+ pDest += destImage.rowPitch;
+ }
+
+ return S_OK;
+}
+
+
+//--- Cubic Filter ---
+static HRESULT _ResizeCubicFilter( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
+{
+ assert( srcImage.pixels && destImage.pixels );
+ assert( srcImage.format == destImage.format );
+
+ // Allocate temporary space (5 scanlines, plus X and Y filters)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc(
+ ( sizeof(XMVECTOR) * ( srcImage.width*4 + destImage.width ) ), 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ std::unique_ptr<CubicFilter[]> cf( new (std::nothrow) CubicFilter[ destImage.width + destImage.height ] );
+ if ( !cf )
+ return E_OUTOFMEMORY;
+
+ CubicFilter* cfX = cf.get();
+ CubicFilter* cfY = cf.get() + destImage.width;
+
+ _CreateCubicFilter( srcImage.width, destImage.width, (filter & TEX_FILTER_WRAP_U) != 0, (filter & TEX_FILTER_MIRROR_U) != 0, cfX );
+ _CreateCubicFilter( srcImage.height, destImage.height, (filter & TEX_FILTER_WRAP_V) != 0, (filter & TEX_FILTER_MIRROR_V) != 0, cfY );
+
+ XMVECTOR* target = scanline.get();
+
+ XMVECTOR* row0 = target + destImage.width;
+ XMVECTOR* row1 = row0 + srcImage.width;
+ XMVECTOR* row2 = row0 + srcImage.width*2;
+ XMVECTOR* row3 = row0 + srcImage.width*3;
+
+#ifdef _DEBUG
+ memset( row0, 0xCD, sizeof(XMVECTOR)*srcImage.width );
+ memset( row1, 0xDD, sizeof(XMVECTOR)*srcImage.width );
+ memset( row2, 0xED, sizeof(XMVECTOR)*srcImage.width );
+ memset( row3, 0xFD, sizeof(XMVECTOR)*srcImage.width );
+#endif
+
+ const uint8_t* pSrc = srcImage.pixels;
+ uint8_t* pDest = destImage.pixels;
+
+ size_t rowPitch = srcImage.rowPitch;
+
+ size_t u0 = size_t(-1);
+ size_t u1 = size_t(-1);
+ size_t u2 = size_t(-1);
+ size_t u3 = size_t(-1);
+
+ for( size_t y = 0; y < destImage.height; ++y )
+ {
+ auto& toY = cfY[ y ];
+
+ // Scanline 1
+ if ( toY.u0 != u0 )
+ {
+ if ( toY.u0 != u1 && toY.u0 != u2 && toY.u0 != u3 )
+ {
+ u0 = toY.u0;
+
+ if ( !_LoadScanlineLinear( row0, srcImage.width, pSrc + (rowPitch * u0), rowPitch, srcImage.format, filter ) )
+ return E_FAIL;
+ }
+ else if ( toY.u0 == u1 )
+ {
+ u0 = u1;
+ u1 = size_t(-1);
+
+ std::swap( row0, row1 );
+ }
+ else if ( toY.u0 == u2 )
+ {
+ u0 = u2;
+ u2 = size_t(-1);
+
+ std::swap( row0, row2 );
+ }
+ else if ( toY.u0 == u3 )
+ {
+ u0 = u3;
+ u3 = size_t(-1);
+
+ std::swap( row0, row3 );
+ }
+ }
+
+ // Scanline 2
+ if ( toY.u1 != u1 )
+ {
+ if ( toY.u1 != u2 && toY.u1 != u3 )
+ {
+ u1 = toY.u1;
+
+ if ( !_LoadScanlineLinear( row1, srcImage.width, pSrc + (rowPitch * u1), rowPitch, srcImage.format, filter ) )
+ return E_FAIL;
+ }
+ else if ( toY.u1 == u2 )
+ {
+ u1 = u2;
+ u2 = size_t(-1);
+
+ std::swap( row1, row2 );
+ }
+ else if ( toY.u1 == u3 )
+ {
+ u1 = u3;
+ u3 = size_t(-1);
+
+ std::swap( row1, row3 );
+ }
+ }
+
+ // Scanline 3
+ if ( toY.u2 != u2 )
+ {
+ if ( toY.u2 != u3 )
+ {
+ u2 = toY.u2;
+
+ if ( !_LoadScanlineLinear( row2, srcImage.width, pSrc + (rowPitch * u2), rowPitch, srcImage.format, filter ) )
+ return E_FAIL;
+ }
+ else
+ {
+ u2 = u3;
+ u3 = size_t(-1);
+
+ std::swap( row2, row3 );
+ }
+ }
+
+ // Scanline 4
+ if ( toY.u3 != u3 )
+ {
+ u3 = toY.u3;
+
+ if ( !_LoadScanlineLinear( row3, srcImage.width, pSrc + (rowPitch * u3), rowPitch, srcImage.format, filter ) )
+ return E_FAIL;
+ }
+
+ for( size_t x = 0; x < destImage.width; ++x )
+ {
+ auto& toX = cfX[ x ];
+
+ XMVECTOR C0, C1, C2, C3;
+
+ CUBIC_INTERPOLATE( C0, toX.x, row0[ toX.u0 ], row0[ toX.u1 ], row0[ toX.u2 ], row0[ toX.u3 ] );
+ CUBIC_INTERPOLATE( C1, toX.x, row1[ toX.u0 ], row1[ toX.u1 ], row1[ toX.u2 ], row1[ toX.u3 ] );
+ CUBIC_INTERPOLATE( C2, toX.x, row2[ toX.u0 ], row2[ toX.u1 ], row2[ toX.u2 ], row2[ toX.u3 ] );
+ CUBIC_INTERPOLATE( C3, toX.x, row3[ toX.u0 ], row3[ toX.u1 ], row3[ toX.u2 ], row3[ toX.u3 ] );
+
+ CUBIC_INTERPOLATE( target[x], toY.x, C0, C1, C2, C3 );
+ }
+
+ if ( !_StoreScanlineLinear( pDest, destImage.rowPitch, destImage.format, target, destImage.width, filter ) )
+ return E_FAIL;
+ pDest += destImage.rowPitch;
+ }
+
+ return S_OK;
+}
+
+
+//--- Triangle Filter ---
+static HRESULT _ResizeTriangleFilter( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
+{
+ assert( srcImage.pixels && destImage.pixels );
+ assert( srcImage.format == destImage.format );
+
+ using namespace TriangleFilter;
+
+ // Allocate initial temporary space (1 scanline, accumulation rows, plus X and Y filters)
+ ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( sizeof(XMVECTOR) * srcImage.width, 16 ) ) );
+ if ( !scanline )
+ return E_OUTOFMEMORY;
+
+ std::unique_ptr<TriangleRow[]> rowActive( new (std::nothrow) TriangleRow[ destImage.height ] );
+ if ( !rowActive )
+ return E_OUTOFMEMORY;
+
+ TriangleRow * rowFree = nullptr;
+
+ std::unique_ptr<Filter> tfX;
+ HRESULT hr = _Create( srcImage.width, destImage.width, (filter & TEX_FILTER_WRAP_U) != 0, tfX );
+ if ( FAILED(hr) )
+ return hr;
+
+ std::unique_ptr<Filter> tfY;
+ hr = _Create( srcImage.height, destImage.height, (filter & TEX_FILTER_WRAP_V) != 0, tfY );
+ if ( FAILED(hr) )
+ return hr;
+
+ XMVECTOR* row = scanline.get();
+
+#ifdef _DEBUG
+ memset( row, 0xCD, sizeof(XMVECTOR)*srcImage.width );
+#endif
+
+ auto xFromEnd = reinterpret_cast<const FilterFrom*>( reinterpret_cast<const uint8_t*>( tfX.get() ) + tfX->sizeInBytes );
+ auto yFromEnd = reinterpret_cast<const FilterFrom*>( reinterpret_cast<const uint8_t*>( tfY.get() ) + tfY->sizeInBytes );
+
+ // Count times rows get written
+ for( FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; )
+ {
+ for ( size_t j = 0; j < yFrom->count; ++j )
+ {
+ size_t v = yFrom->to[ j ].u;
+ assert( v < destImage.height );
+ ++rowActive[ v ].remaining;
+ }
+
+ yFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( yFrom ) + yFrom->sizeInBytes );
+ }
+
+ // Filter image
+ const uint8_t* pSrc = srcImage.pixels;
+ size_t rowPitch = srcImage.rowPitch;
+ const uint8_t* pEndSrc = pSrc + rowPitch * srcImage.height;
+
+ uint8_t* pDest = destImage.pixels;
+
+ for( FilterFrom* yFrom = tfY->from; yFrom < yFromEnd; )
+ {
+ // Create accumulation rows as needed
+ for ( size_t j = 0; j < yFrom->count; ++j )
+ {
+ size_t v = yFrom->to[ j ].u;
+ assert( v < destImage.height );
+ TriangleRow* rowAcc = &rowActive[ v ];
+
+ if ( !rowAcc->scanline )
+ {
+ if ( rowFree )
+ {
+ // Steal and reuse scanline from 'free row' list
+ assert( rowFree->scanline != 0 );
+ rowAcc->scanline.reset( rowFree->scanline.release() );
+ rowFree = rowFree->next;
+ }
+ else
+ {
+ rowAcc->scanline.reset( reinterpret_cast<XMVECTOR*>( _aligned_malloc( sizeof(XMVECTOR) * destImage.width, 16 ) ) );
+ if ( !rowAcc->scanline )
+ return E_OUTOFMEMORY;
+ }
+
+ memset( rowAcc->scanline.get(), 0, sizeof(XMVECTOR) * destImage.width );
+ }
+ }
+
+ // Load source scanline
+ if ( (pSrc + rowPitch) > pEndSrc )
+ return E_FAIL;
+
+ if ( !_LoadScanlineLinear( row, srcImage.width, pSrc, rowPitch, srcImage.format, filter ) )
+ return E_FAIL;
+
+ pSrc += rowPitch;
+
+ // Process row
+ size_t x = 0;
+ for( FilterFrom* xFrom = tfX->from; xFrom < xFromEnd; ++x )
+ {
+ for ( size_t j = 0; j < yFrom->count; ++j )
+ {
+ size_t v = yFrom->to[ j ].u;
+ assert( v < destImage.height );
+ float yweight = yFrom->to[ j ].weight;
+
+ XMVECTOR* accPtr = rowActive[ v ].scanline.get();
+ if ( !accPtr )
+ return E_POINTER;
+
+ for ( size_t k = 0; k < xFrom->count; ++k )
+ {
+ size_t u = xFrom->to[ k ].u;
+ assert( u < destImage.width );
+
+ XMVECTOR weight = XMVectorReplicate( yweight * xFrom->to[ k ].weight );
+
+ assert( x < srcImage.width );
+ accPtr[ u ] = XMVectorMultiplyAdd( row[ x ], weight, accPtr[ u ] );
+ }
+ }
+
+ xFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( xFrom ) + xFrom->sizeInBytes );
+ }
+
+ // Write completed accumulation rows
+ for ( size_t j = 0; j < yFrom->count; ++j )
+ {
+ size_t v = yFrom->to[ j ].u;
+ assert( v < destImage.height );
+ TriangleRow* rowAcc = &rowActive[ v ];
+
+ assert( rowAcc->remaining > 0 );
+ --rowAcc->remaining;
+
+ if ( !rowAcc->remaining )
+ {
+ XMVECTOR* pAccSrc = rowAcc->scanline.get();
+ if ( !pAccSrc )
+ return E_POINTER;
+
+ switch( destImage.format )
+ {
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ // Need to slightly bias results for floating-point error accumulation which can
+ // be visible with harshly quantized values
+ static const XMVECTORF32 Bias = { 0.f, 0.f, 0.f, 0.1f };
+
+ XMVECTOR* ptr = pAccSrc;
+ for( size_t i=0; i < destImage.width; ++i, ++ptr )
+ {
+ *ptr = XMVectorAdd( *ptr, Bias );
+ }
+ }
+ break;
+ }
+
+ // This performs any required clamping
+ if ( !_StoreScanlineLinear( pDest + (destImage.rowPitch * v), destImage.rowPitch, destImage.format, pAccSrc, destImage.width, filter ) )
+ return E_FAIL;
+
+ // Put row on freelist to reuse it's allocated scanline
+ rowAcc->next = rowFree;
+ rowFree = rowAcc;
+ }
+ }
+
+ yFrom = reinterpret_cast<FilterFrom*>( reinterpret_cast<uint8_t*>( yFrom ) + yFrom->sizeInBytes );
+ }
+
+ return S_OK;
+}
+
+
+//--- Custom filter resize ---
+static HRESULT _PerformResizeUsingCustomFilters( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
+{
+ if ( !srcImage.pixels || !destImage.pixels )
+ return E_POINTER;
+
+ static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" );
+
+ DWORD filter_select = ( filter & TEX_FILTER_MASK );
+ if ( !filter_select )
+ {
+ // Default filter choice
+ filter_select = ( ( (destImage.width << 1) == srcImage.width ) && ( (destImage.height << 1) == srcImage.height ) )
+ ? TEX_FILTER_BOX : TEX_FILTER_LINEAR;
+ }
+
+ switch( filter_select )
+ {
+ case TEX_FILTER_POINT:
+ return _ResizePointFilter( srcImage, destImage );
+
+ case TEX_FILTER_BOX:
+ return _ResizeBoxFilter( srcImage, filter, destImage );
+
+ case TEX_FILTER_LINEAR:
+ return _ResizeLinearFilter( srcImage, filter, destImage );
+
+ case TEX_FILTER_CUBIC:
+ return _ResizeCubicFilter( srcImage, filter, destImage );
+
+ case TEX_FILTER_TRIANGLE:
+ return _ResizeTriangleFilter( srcImage, filter, destImage );
+
+ default:
+ return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
+ }
+}
+
+
//=====================================================================================
// Entry-points
//=====================================================================================
@@ -159,12 +826,13 @@ static HRESULT _PerformResizeViaF32( _In_ const Image& srcImage, _In_ DWORD filt
//-------------------------------------------------------------------------------------
// Resize image
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT Resize( const Image& srcImage, size_t width, size_t height, DWORD filter, ScratchImage& image )
{
if ( width == 0 || height == 0 )
return E_INVALIDARG;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
return E_INVALIDARG;
@@ -189,18 +857,23 @@ HRESULT Resize( const Image& srcImage, size_t width, size_t height, DWORD filter
if ( !rimage )
return E_POINTER;
- // WIC only supports CLAMP
-
- WICPixelFormatGUID pfGUID;
- if ( _DXGIToWIC( srcImage.format, pfGUID ) )
+ if ( _UseWICFiltering( srcImage.format, filter ) )
{
- // Case 1: Source format is supported by Windows Imaging Component
- hr = _PerformResizeUsingWIC( srcImage, filter, pfGUID, *rimage );
+ WICPixelFormatGUID pfGUID;
+ if ( _DXGIToWIC( srcImage.format, pfGUID, true ) )
+ {
+ // Case 1: Source format is supported by Windows Imaging Component
+ hr = _PerformResizeUsingWIC( srcImage, filter, pfGUID, *rimage );
+ }
+ else
+ {
+ // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back
+ hr = _PerformResizeViaF32( srcImage, filter, *rimage );
+ }
}
else
{
- // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back
- hr = _PerformResizeViaF32( srcImage, filter, *rimage );
+ hr = _PerformResizeUsingCustomFilters( srcImage, filter, *rimage );
}
if ( FAILED(hr) )
@@ -216,13 +889,14 @@ HRESULT Resize( const Image& srcImage, size_t width, size_t height, DWORD filter
//-------------------------------------------------------------------------------------
// Resize image (complex)
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT Resize( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
size_t width, size_t height, DWORD filter, ScratchImage& result )
{
if ( !srcImages || !nimages || width == 0 || height == 0 )
return E_INVALIDARG;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (width > 0xFFFFFFFF) || (height > 0xFFFFFFFF) )
return E_INVALIDARG;
#endif
@@ -235,8 +909,10 @@ HRESULT Resize( const Image* srcImages, size_t nimages, const TexMetadata& metad
if ( FAILED(hr) )
return hr;
- WICPixelFormatGUID pfGUID;
- bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
+ bool usewic = _UseWICFiltering( metadata.format, filter );
+
+ WICPixelFormatGUID pfGUID = {0};
+ bool wicpf = ( usewic ) ? _DXGIToWIC( metadata.format, pfGUID, true ) : false;
switch ( metadata.dimension )
{
@@ -267,7 +943,7 @@ HRESULT Resize( const Image* srcImages, size_t nimages, const TexMetadata& metad
return E_FAIL;
}
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) )
{
result.Release();
@@ -275,15 +951,23 @@ HRESULT Resize( const Image* srcImages, size_t nimages, const TexMetadata& metad
}
#endif
- if ( wicpf )
+ if ( usewic )
{
- // Case 1: Source format is supported by Windows Imaging Component
- hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg );
+ if ( wicpf )
+ {
+ // Case 1: Source format is supported by Windows Imaging Component
+ hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg );
+ }
+ else
+ {
+ // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back
+ hr = _PerformResizeViaF32( *srcimg, filter, *destimg );
+ }
}
else
{
- // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back
- hr = _PerformResizeViaF32( *srcimg, filter, *destimg );
+ // Case 3: not using WIC resizing
+ hr = _PerformResizeUsingCustomFilters( *srcimg, filter, *destimg );
}
if ( FAILED(hr) )
@@ -320,7 +1004,7 @@ HRESULT Resize( const Image* srcImages, size_t nimages, const TexMetadata& metad
return E_FAIL;
}
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (srcimg->width > 0xFFFFFFFF) || (srcimg->height > 0xFFFFFFFF) )
{
result.Release();
@@ -328,15 +1012,23 @@ HRESULT Resize( const Image* srcImages, size_t nimages, const TexMetadata& metad
}
#endif
- if ( wicpf )
+ if ( usewic )
{
- // Case 1: Source format is supported by Windows Imaging Component
- hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg );
+ if ( wicpf )
+ {
+ // Case 1: Source format is supported by Windows Imaging Component
+ hr = _PerformResizeUsingWIC( *srcimg, filter, pfGUID, *destimg );
+ }
+ else
+ {
+ // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back
+ hr = _PerformResizeViaF32( *srcimg, filter, *destimg );
+ }
}
else
{
- // Case 2: Source format is not supported by WIC, so we have to convert, resize, and convert back
- hr = _PerformResizeViaF32( *srcimg, filter, *destimg );
+ // Case 3: not using WIC resizing
+ hr = _PerformResizeUsingCustomFilters( *srcimg, filter, *destimg );
}
if ( FAILED(hr) )
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexTGA.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexTGA.cpp
index e71575a5..3a775bf7 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexTGA.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexTGA.cpp
@@ -19,7 +19,7 @@
// The implementation here has the following limitations:
// * Does not support files that contain color maps (these are rare in practice)
// * Interleaved files are not supported (deprecated aspect of TGA format)
-// * Only supports 8-bit greyscale; 16-, 24-, and 32-bit truecolor images
+// * Only supports 8-bit grayscale; 16-, 24-, and 32-bit truecolor images
// * Always writes uncompressed files (i.e. can read RLE compression, but does not write it)
//
@@ -116,7 +116,7 @@ namespace DirectX
//-------------------------------------------------------------------------------------
// Decodes TGA header
//-------------------------------------------------------------------------------------
-static HRESULT _DecodeTGAHeader( _In_bytecount_(size) LPCVOID pSource, size_t size, _Out_ TexMetadata& metadata, size_t& offset,
+static HRESULT _DecodeTGAHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t size, _Out_ TexMetadata& metadata, size_t& offset,
_Inout_opt_ DWORD* convFlags )
{
if ( !pSource )
@@ -129,8 +129,7 @@ static HRESULT _DecodeTGAHeader( _In_bytecount_(size) LPCVOID pSource, size_t si
return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
}
- const TGA_HEADER* pHeader = reinterpret_cast<const TGA_HEADER*>( pSource );
- assert( pHeader );
+ auto pHeader = reinterpret_cast<const TGA_HEADER*>( pSource );
if ( pHeader->bColorMapType != 0
|| pHeader->wColorMapLength != 0 )
@@ -236,7 +235,7 @@ static HRESULT _SetAlphaChannelToOpaque( _In_ const Image* image )
{
assert( image );
- uint8_t* pPixels = reinterpret_cast<uint8_t*>( image->pixels );
+ auto pPixels = reinterpret_cast<uint8_t*>( image->pixels );
if ( !pPixels )
return E_POINTER;
@@ -253,7 +252,7 @@ static HRESULT _SetAlphaChannelToOpaque( _In_ const Image* image )
//-------------------------------------------------------------------------------------
// Uncompress pixel data from a TGA into the target image
//-------------------------------------------------------------------------------------
-static HRESULT _UncompressPixels( _In_bytecount_(size) LPCVOID pSource, size_t size, _In_ const Image* image, DWORD convFlags )
+static HRESULT _UncompressPixels( _In_reads_bytes_(size) LPCVOID pSource, size_t size, _In_ const Image* image, _In_ DWORD convFlags )
{
assert( pSource && size > 0 );
@@ -272,7 +271,7 @@ static HRESULT _UncompressPixels( _In_bytecount_(size) LPCVOID pSource, size_t s
ComputePitch( image->format, image->width, image->height, rowPitch, slicePitch, CP_FLAGS_NONE );
}
- const uint8_t* sPtr = reinterpret_cast<const uint8_t*>( pSource );
+ auto sPtr = reinterpret_cast<const uint8_t*>( pSource );
const uint8_t* endPtr = sPtr + size;
switch( image->format )
@@ -573,7 +572,7 @@ static HRESULT _UncompressPixels( _In_bytecount_(size) LPCVOID pSource, size_t s
//-------------------------------------------------------------------------------------
// Copies pixel data from a TGA into the target image
//-------------------------------------------------------------------------------------
-static HRESULT _CopyPixels( _In_bytecount_(size) LPCVOID pSource, size_t size, _In_ const Image* image, DWORD convFlags )
+static HRESULT _CopyPixels( _In_reads_bytes_(size) LPCVOID pSource, size_t size, _In_ const Image* image, _In_ DWORD convFlags )
{
assert( pSource && size > 0 );
@@ -737,10 +736,8 @@ static HRESULT _CopyPixels( _In_bytecount_(size) LPCVOID pSource, size_t size, _
//-------------------------------------------------------------------------------------
// Encodes TGA file header
//-------------------------------------------------------------------------------------
-static HRESULT _EncodeTGAHeader( _In_ const Image& image, _Out_ TGA_HEADER& header, DWORD& convFlags )
+static HRESULT _EncodeTGAHeader( _In_ const Image& image, _Out_ TGA_HEADER& header, _Inout_ DWORD& convFlags )
{
- assert( IsValid( image.format ) && !IsVideo( image.format ) );
-
memset( &header, 0, sizeof(TGA_HEADER) );
if ( (image.width > 0xFFFF)
@@ -802,8 +799,8 @@ static HRESULT _EncodeTGAHeader( _In_ const Image& image, _Out_ TGA_HEADER& head
// Copies BGRX data to form BGR 24bpp data
//-------------------------------------------------------------------------------------
#pragma warning(suppress: 6001 6101) // In the case where outSize is insufficient we do not write to pDestination
-static void _Copy24bppScanline( _Out_bytecap_(outSize) LPVOID pDestination, _In_ size_t outSize,
- _In_bytecount_(inSize) LPCVOID pSource, _In_ size_t inSize )
+static void _Copy24bppScanline( _Out_writes_bytes_(outSize) LPVOID pDestination, _In_ size_t outSize,
+ _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize )
{
assert( pDestination && outSize > 0 );
assert( pSource && inSize > 0 );
@@ -813,18 +810,21 @@ static void _Copy24bppScanline( _Out_bytecap_(outSize) LPVOID pDestination, _In_
const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
- const uint8_t* endPtr = dPtr + outSize;
-
- for( size_t count = 0; count < inSize; count += 4 )
+ if ( inSize >= 4 && outSize >= 3 )
{
- uint32_t t = *(sPtr++);
+ const uint8_t* endPtr = dPtr + outSize;
+
+ for( size_t count = 0; count < ( inSize - 3 ); count += 4 )
+ {
+ uint32_t t = *(sPtr++);
- if ( dPtr+2 > endPtr )
- return;
+ if ( dPtr+3 > endPtr )
+ return;
- *(dPtr++) = uint8_t(t & 0xFF); // Blue
- *(dPtr++) = uint8_t((t & 0xFF00) >> 8); // Green
- *(dPtr++) = uint8_t((t & 0xFF0000) >> 16); // Red
+ *(dPtr++) = uint8_t(t & 0xFF); // Blue
+ *(dPtr++) = uint8_t((t & 0xFF00) >> 8); // Green
+ *(dPtr++) = uint8_t((t & 0xFF0000) >> 16); // Red
+ }
}
}
@@ -836,6 +836,7 @@ static void _Copy24bppScanline( _Out_bytecap_(outSize) LPVOID pDestination, _In_
//-------------------------------------------------------------------------------------
// Obtain metadata from TGA file in memory/on disk
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT GetMetadataFromTGAMemory( LPCVOID pSource, size_t size, TexMetadata& metadata )
{
if ( !pSource || size == 0 )
@@ -845,12 +846,13 @@ HRESULT GetMetadataFromTGAMemory( LPCVOID pSource, size_t size, TexMetadata& met
return _DecodeTGAHeader( pSource, size, metadata, offset, 0 );
}
+_Use_decl_annotations_
HRESULT GetMetadataFromTGAFile( LPCWSTR szFile, TexMetadata& metadata )
{
if ( !szFile )
return E_INVALIDARG;
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0 ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( szFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
@@ -906,6 +908,7 @@ HRESULT GetMetadataFromTGAFile( LPCWSTR szFile, TexMetadata& metadata )
//-------------------------------------------------------------------------------------
// Load a TGA file in memory
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT LoadFromTGAMemory( LPCVOID pSource, size_t size, TexMetadata* metadata, ScratchImage& image )
{
if ( !pSource || size == 0 )
@@ -923,8 +926,7 @@ HRESULT LoadFromTGAMemory( LPCVOID pSource, size_t size, TexMetadata* metadata,
if ( offset > size )
return E_FAIL;
- LPCVOID pPixels = reinterpret_cast<LPCVOID>( reinterpret_cast<const uint8_t*>(pSource) + offset );
- assert( pPixels );
+ auto pPixels = reinterpret_cast<LPCVOID>( reinterpret_cast<const uint8_t*>(pSource) + offset );
size_t remaining = size - offset;
if ( remaining == 0 )
@@ -959,6 +961,7 @@ HRESULT LoadFromTGAMemory( LPCVOID pSource, size_t size, TexMetadata* metadata,
//-------------------------------------------------------------------------------------
// Load a TGA file from disk
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT LoadFromTGAFile( LPCWSTR szFile, TexMetadata* metadata, ScratchImage& image )
{
if ( !szFile )
@@ -966,7 +969,7 @@ HRESULT LoadFromTGAFile( LPCWSTR szFile, TexMetadata* metadata, ScratchImage& im
image.Release();
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( szFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0 ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( szFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
@@ -1105,7 +1108,6 @@ HRESULT LoadFromTGAFile( LPCWSTR szFile, TexMetadata* metadata, ScratchImage& im
for( size_t h = 0; h < img->height; ++h )
{
_SwizzleScanline( pPixels, rowPitch, pPixels, rowPitch, mdata.format, tflags );
-
pPixels += rowPitch;
}
}
@@ -1163,7 +1165,7 @@ HRESULT LoadFromTGAFile( LPCWSTR szFile, TexMetadata* metadata, ScratchImage& im
}
else // RLE || EXPAND || INVERTX || !INVERTY
{
- std::unique_ptr<uint8_t[]> temp( new uint8_t[ remaining ] );
+ std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ remaining ] );
if ( !temp )
{
image.Release();
@@ -1208,6 +1210,7 @@ HRESULT LoadFromTGAFile( LPCWSTR szFile, TexMetadata* metadata, ScratchImage& im
//-------------------------------------------------------------------------------------
// Save a TGA file to memory
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT SaveToTGAMemory( const Image& image, Blob& blob )
{
if ( !image.pixels )
@@ -1238,12 +1241,12 @@ HRESULT SaveToTGAMemory( const Image& image, Blob& blob )
return hr;
// Copy header
- uint8_t* dPtr = reinterpret_cast<uint8_t*>( blob.GetBufferPointer() );
+ auto dPtr = reinterpret_cast<uint8_t*>( blob.GetBufferPointer() );
assert( dPtr != 0 );
memcpy_s( dPtr, blob.GetBufferSize(), &tga_header, sizeof(TGA_HEADER) );
dPtr += sizeof(TGA_HEADER);
- const uint8_t* pPixels = reinterpret_cast<const uint8_t*>( image.pixels );
+ auto pPixels = reinterpret_cast<const uint8_t*>( image.pixels );
assert( pPixels );
for( size_t y = 0; y < image.height; ++y )
@@ -1273,6 +1276,7 @@ HRESULT SaveToTGAMemory( const Image& image, Blob& blob )
//-------------------------------------------------------------------------------------
// Save a TGA file to disk
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT SaveToTGAFile( const Image& image, LPCWSTR szFile )
{
if ( !szFile )
@@ -1288,7 +1292,7 @@ HRESULT SaveToTGAFile( const Image& image, LPCWSTR szFile )
return hr;
// Create file and write header
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( szFile, GENERIC_WRITE, 0, CREATE_ALWAYS, 0 ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( szFile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) );
@@ -1336,7 +1340,7 @@ HRESULT SaveToTGAFile( const Image& image, LPCWSTR szFile )
else
{
// Otherwise, write the image one scanline at a time...
- std::unique_ptr<uint8_t[]> temp( new uint8_t[ rowPitch ] );
+ std::unique_ptr<uint8_t[]> temp( new (std::nothrow) uint8_t[ rowPitch ] );
if ( !temp )
return E_OUTOFMEMORY;
@@ -1351,7 +1355,7 @@ HRESULT SaveToTGAFile( const Image& image, LPCWSTR szFile )
return E_FAIL;
// Write pixels
- const uint8_t* pPixels = reinterpret_cast<const uint8_t*>( image.pixels );
+ auto pPixels = reinterpret_cast<const uint8_t*>( image.pixels );
for( size_t y = 0; y < image.height; ++y )
{
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexUtil.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexUtil.cpp
index 9d5e0905..59837f35 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexUtil.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexUtil.cpp
@@ -22,34 +22,34 @@ struct WICTranslate
{
GUID wic;
DXGI_FORMAT format;
+ bool srgb;
};
static WICTranslate g_WICFormats[] =
{
- { GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT },
+ { GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false },
- { GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT },
- { GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM },
+ { GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT, false },
+ { GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM, true },
- { GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM },
- { GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1
- { GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1
+ { GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM, true },
+ { GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM, true }, // DXGI 1.1
+ { GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM, true }, // DXGI 1.1
- { GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1
- { GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM },
- { GUID_WICPixelFormat32bppRGBE, DXGI_FORMAT_R9G9B9E5_SHAREDEXP },
+ { GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, true }, // DXGI 1.1
+ { GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM, true },
- { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
- { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
+ { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM, true },
+ { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM, true },
- { GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT },
- { GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT },
- { GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM },
- { GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM },
+ { GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT, false },
+ { GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT, false },
+ { GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM, true },
+ { GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM, true },
- { GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM },
+ { GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM, false },
- { GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM },
+ { GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM, false },
};
static bool g_WIC2 = false;
@@ -61,6 +61,7 @@ namespace DirectX
// WIC Utilities
//=====================================================================================
+_Use_decl_annotations_
DXGI_FORMAT _WICToDXGI( const GUID& guid )
{
for( size_t i=0; i < _countof(g_WICFormats); ++i )
@@ -69,7 +70,7 @@ DXGI_FORMAT _WICToDXGI( const GUID& guid )
return g_WICFormats[i].format;
}
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
if ( g_WIC2 )
{
if ( memcmp( &GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID) ) == 0 )
@@ -80,12 +81,23 @@ DXGI_FORMAT _WICToDXGI( const GUID& guid )
return DXGI_FORMAT_UNKNOWN;
}
-bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid )
+_Use_decl_annotations_
+bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
{
switch( format )
{
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- memcpy( &guid, &GUID_WICPixelFormat32bppRGBA, sizeof(GUID) );
+ if ( ignoreRGBvsBGR )
+ {
+ // If we are not doing conversion so don't really care about BGR vs RGB color-order,
+ // we can use the canonical WIC 32bppBGRA format which avoids an extra format conversion when using the WIC scaler
+ memcpy( &guid, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID) );
+ }
+ else
+ {
+ memcpy( &guid, &GUID_WICPixelFormat32bppRGBA, sizeof(GUID) );
+ }
return true;
case DXGI_FORMAT_D32_FLOAT:
@@ -104,7 +116,7 @@ bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid )
memcpy( &guid, &GUID_WICPixelFormat32bppBGR, sizeof(GUID) );
return true;
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
case DXGI_FORMAT_R32G32B32_FLOAT:
if ( g_WIC2 )
{
@@ -130,6 +142,33 @@ bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid )
return false;
}
+DWORD _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetGUID )
+{
+ DWORD srgb = 0;
+
+ for( size_t i=0; i < _countof(g_WICFormats); ++i )
+ {
+ if ( memcmp( &g_WICFormats[i].wic, &sourceGUID, sizeof(GUID) ) == 0 )
+ {
+ if ( g_WICFormats[i].srgb )
+ srgb |= TEX_FILTER_SRGB_IN;
+ }
+
+ if ( memcmp( &g_WICFormats[i].wic, &targetGUID, sizeof(GUID) ) == 0 )
+ {
+ if ( g_WICFormats[i].srgb )
+ srgb |= TEX_FILTER_SRGB_OUT;
+ }
+ }
+
+ if ( (srgb & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
+ {
+ srgb &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
+ }
+
+ return srgb;
+}
+
bool _IsWIC2()
{
return g_WIC2;
@@ -142,7 +181,7 @@ IWICImagingFactory* _GetWIC()
if ( s_Factory )
return s_Factory;
-#if(_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
+#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
@@ -195,7 +234,8 @@ IWICImagingFactory* _GetWIC()
//-------------------------------------------------------------------------------------
// Public helper function to get common WIC codec GUIDs
//-------------------------------------------------------------------------------------
-REFGUID GetWICCodec( _In_ WICCodecs codec )
+_Use_decl_annotations_
+REFGUID GetWICCodec( WICCodecs codec )
{
switch( codec )
{
@@ -233,9 +273,10 @@ REFGUID GetWICCodec( _In_ WICCodecs codec )
//-------------------------------------------------------------------------------------
// Returns bits-per-pixel for a given DXGI format, or 0 on failure
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
size_t BitsPerPixel( DXGI_FORMAT fmt )
{
- switch( fmt )
+ switch( static_cast<int>(fmt) )
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
@@ -263,6 +304,9 @@ size_t BitsPerPixel( DXGI_FORMAT fmt )
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ case DXGI_FORMAT_Y416:
+ case DXGI_FORMAT_Y210:
+ case DXGI_FORMAT_Y216:
return 64;
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
@@ -300,8 +344,20 @@ size_t BitsPerPixel( DXGI_FORMAT fmt )
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ case DXGI_FORMAT_AYUV:
+ case DXGI_FORMAT_Y410:
+ case DXGI_FORMAT_YUY2:
+ case 116 /* DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT */:
+ case 117 /* DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT */:
return 32;
+ case DXGI_FORMAT_P010:
+ case DXGI_FORMAT_P016:
+ case 118 /* DXGI_FORMAT_D16_UNORM_S8_UINT */:
+ case 119 /* DXGI_FORMAT_R16_UNORM_X8_TYPELESS */:
+ case 120 /* DXGI_FORMAT_X16_TYPELESS_G8_UINT */:
+ return 24;
+
case DXGI_FORMAT_R8G8_TYPELESS:
case DXGI_FORMAT_R8G8_UNORM:
case DXGI_FORMAT_R8G8_UINT:
@@ -316,14 +372,24 @@ size_t BitsPerPixel( DXGI_FORMAT fmt )
case DXGI_FORMAT_R16_SINT:
case DXGI_FORMAT_B5G6R5_UNORM:
case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_A8P8:
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
return 16;
+ case DXGI_FORMAT_NV12:
+ case DXGI_FORMAT_420_OPAQUE:
+ case DXGI_FORMAT_NV11:
+ return 12;
+
case DXGI_FORMAT_R8_TYPELESS:
case DXGI_FORMAT_R8_UNORM:
case DXGI_FORMAT_R8_UINT:
case DXGI_FORMAT_R8_SNORM:
case DXGI_FORMAT_R8_SINT:
case DXGI_FORMAT_A8_UNORM:
+ case DXGI_FORMAT_AI44:
+ case DXGI_FORMAT_IA44:
+ case DXGI_FORMAT_P8:
return 8;
case DXGI_FORMAT_R1_UNORM:
@@ -354,13 +420,172 @@ size_t BitsPerPixel( DXGI_FORMAT fmt )
case DXGI_FORMAT_BC7_UNORM_SRGB:
return 8;
-#ifdef DXGI_1_2_FORMATS
- case DXGI_FORMAT_B4G4R4A4_UNORM:
+ default:
+ return 0;
+ }
+}
+
+
+//-------------------------------------------------------------------------------------
+// Returns bits-per-color-channel for a given DXGI format, or 0 on failure
+// For mixed formats, it returns the largest color-depth in the format
+//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
+size_t BitsPerColor( DXGI_FORMAT fmt )
+{
+ switch( static_cast<int>(fmt) )
+ {
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R32G32_UINT:
+ case DXGI_FORMAT_R32G32_SINT:
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ case DXGI_FORMAT_R32_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R32_UINT:
+ case DXGI_FORMAT_R32_SINT:
+ return 32;
+
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ return 24;
+
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R16G16_UINT:
+ case DXGI_FORMAT_R16G16_SNORM:
+ case DXGI_FORMAT_R16G16_SINT:
+ case DXGI_FORMAT_R16_TYPELESS:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R16_UINT:
+ case DXGI_FORMAT_R16_SNORM:
+ case DXGI_FORMAT_R16_SINT:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_Y416:
+ case DXGI_FORMAT_P016:
+ case DXGI_FORMAT_Y216:
return 16;
- // We don't support the video formats ( see IsVideo function )
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ return 14;
+
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ return 11;
+
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_Y410:
+ case DXGI_FORMAT_P010:
+ case DXGI_FORMAT_Y210:
+ return 10;
+
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R8G8_UINT:
+ case DXGI_FORMAT_R8G8_SNORM:
+ case DXGI_FORMAT_R8G8_SINT:
+ case DXGI_FORMAT_R8_TYPELESS:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8_UINT:
+ case DXGI_FORMAT_R8_SNORM:
+ case DXGI_FORMAT_R8_SINT:
+ case DXGI_FORMAT_A8_UNORM:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ case DXGI_FORMAT_AYUV:
+ case DXGI_FORMAT_NV12:
+ case DXGI_FORMAT_420_OPAQUE:
+ case DXGI_FORMAT_YUY2:
+ case DXGI_FORMAT_NV11:
+ return 8;
+
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return 7;
+
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ return 6;
+
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return 5;
-#endif // DXGI_1_2_FORMATS
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return 4;
+
+ case DXGI_FORMAT_R1_UNORM:
+ return 1;
+
+ case 116 /* DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT */:
+ case 117 /* DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT */:
+ // These are Xbox One platform specific types
+ return 10;
+
+ case 118 /* DXGI_FORMAT_D16_UNORM_S8_UINT */:
+ case 119 /* DXGI_FORMAT_R16_UNORM_X8_TYPELESS */:
+ case 120 /* DXGI_FORMAT_X16_TYPELESS_G8_UINT */:
+ // These are Xbox One platform specific types
+ return 16;
+
+ case DXGI_FORMAT_AI44:
+ case DXGI_FORMAT_IA44:
+ case DXGI_FORMAT_P8:
+ case DXGI_FORMAT_A8P8:
+ // Palettized formats return 0 for this function
default:
return 0;
@@ -372,10 +597,11 @@ size_t BitsPerPixel( DXGI_FORMAT fmt )
// Computes the image row pitch in bytes, and the slice ptich (size in bytes of the image)
// based on DXGI format, width, and height
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
size_t& rowPitch, size_t& slicePitch, DWORD flags )
{
- assert( IsValid(fmt) && !IsVideo(fmt) );
+ assert( IsValid(fmt) );
if ( IsCompressed(fmt) )
{
@@ -393,10 +619,28 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
}
else if ( IsPacked(fmt) )
{
- rowPitch = ( ( width + 1 ) >> 1) * 4;
+ size_t bpe = ( fmt == DXGI_FORMAT_Y210 || fmt == DXGI_FORMAT_Y216 ) ? 8 : 4;
+ rowPitch = ( ( width + 1 ) >> 1 ) * bpe;
slicePitch = rowPitch * height;
}
+ else if ( fmt == DXGI_FORMAT_NV11 )
+ {
+ rowPitch = ( ( width + 3 ) >> 2 ) * 4;
+
+ // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
+ slicePitch = rowPitch * height * 2;
+ }
+ else if ( IsPlanar(fmt) )
+ {
+ size_t bpe = ( fmt == DXGI_FORMAT_P010 || fmt == DXGI_FORMAT_P016
+ || fmt == DXGI_FORMAT(118 /* DXGI_FORMAT_D16_UNORM_S8_UINT */)
+ || fmt == DXGI_FORMAT(119 /* DXGI_FORMAT_R16_UNORM_X8_TYPELESS */)
+ || fmt == DXGI_FORMAT(120 /* DXGI_FORMAT_X16_TYPELESS_G8_UINT */) ) ? 4 : 2;
+ rowPitch = ( ( width + 1 ) >> 1 ) * bpe;
+
+ slicePitch = rowPitch * ( height + ( ( height + 1 ) >> 1 ) );
+ }
else
{
size_t bpp;
@@ -410,15 +654,39 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
else
bpp = BitsPerPixel( fmt );
- if ( flags & CP_FLAGS_LEGACY_DWORD )
+ if ( flags & ( CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K ) )
{
- // Special computation for some incorrectly created DDS files based on
- // legacy DirectDraw assumptions about pitch alignment
- rowPitch = ( ( width * bpp + 31 ) / 32 ) * sizeof(uint32_t);
- slicePitch = rowPitch * height;
+ if ( flags & CP_FLAGS_PAGE4K )
+ {
+ rowPitch = ( ( width * bpp + 32767 ) / 32768 ) * 4096;
+ slicePitch = rowPitch * height;
+ }
+ else if ( flags & CP_FLAGS_ZMM )
+ {
+ rowPitch = ( ( width * bpp + 511 ) / 512 ) * 64;
+ slicePitch = rowPitch * height;
+ }
+ else if ( flags & CP_FLAGS_YMM )
+ {
+ rowPitch = ( ( width * bpp + 255 ) / 256) * 32;
+ slicePitch = rowPitch * height;
+ }
+ else if ( flags & CP_FLAGS_PARAGRAPH )
+ {
+ rowPitch = ( ( width * bpp + 127 ) / 128 ) * 16;
+ slicePitch = rowPitch * height;
+ }
+ else // DWORD alignment
+ {
+ // Special computation for some incorrectly created DDS files based on
+ // legacy DirectDraw assumptions about pitch alignment
+ rowPitch = ( ( width * bpp + 31 ) / 32 ) * sizeof(uint32_t);
+ slicePitch = rowPitch * height;
+ }
}
else
{
+ // Default byte alignment
rowPitch = ( width * bpp + 7 ) / 8;
slicePitch = rowPitch * height;
}
@@ -429,7 +697,8 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
//-------------------------------------------------------------------------------------
// Converts to an SRGB equivalent type if available
//-------------------------------------------------------------------------------------
-DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT fmt )
+_Use_decl_annotations_
+DXGI_FORMAT MakeSRGB( DXGI_FORMAT fmt )
{
switch( fmt )
{
@@ -463,7 +732,8 @@ DXGI_FORMAT MakeSRGB( _In_ DXGI_FORMAT fmt )
//-------------------------------------------------------------------------------------
// Converts to a format to an equivalent TYPELESS format if available
//-------------------------------------------------------------------------------------
-DXGI_FORMAT MakeTypeless( _In_ DXGI_FORMAT fmt )
+_Use_decl_annotations_
+DXGI_FORMAT MakeTypeless( DXGI_FORMAT fmt )
{
switch( fmt )
{
@@ -531,7 +801,6 @@ DXGI_FORMAT MakeTypeless( _In_ DXGI_FORMAT fmt )
case DXGI_FORMAT_R8_UINT:
case DXGI_FORMAT_R8_SNORM:
case DXGI_FORMAT_R8_SINT:
- case DXGI_FORMAT_A8_UNORM:
return DXGI_FORMAT_R8_TYPELESS;
case DXGI_FORMAT_BC1_UNORM:
@@ -579,7 +848,8 @@ DXGI_FORMAT MakeTypeless( _In_ DXGI_FORMAT fmt )
//-------------------------------------------------------------------------------------
// Converts to a TYPELESS format to an equivalent UNORM format if available
//-------------------------------------------------------------------------------------
-DXGI_FORMAT MakeTypelessUNORM( _In_ DXGI_FORMAT fmt )
+_Use_decl_annotations_
+DXGI_FORMAT MakeTypelessUNORM( DXGI_FORMAT fmt )
{
switch( fmt )
{
@@ -637,7 +907,8 @@ DXGI_FORMAT MakeTypelessUNORM( _In_ DXGI_FORMAT fmt )
//-------------------------------------------------------------------------------------
// Converts to a TYPELESS format to an equivalent FLOAT format if available
//-------------------------------------------------------------------------------------
-DXGI_FORMAT MakeTypelessFLOAT( _In_ DXGI_FORMAT fmt )
+_Use_decl_annotations_
+DXGI_FORMAT MakeTypelessFLOAT( DXGI_FORMAT fmt )
{
switch( fmt )
{
@@ -672,7 +943,8 @@ DXGI_FORMAT MakeTypelessFLOAT( _In_ DXGI_FORMAT fmt )
// TexMetadata
//=====================================================================================
-size_t TexMetadata::ComputeIndex( _In_ size_t mip, _In_ size_t item, _In_ size_t slice ) const
+_Use_decl_annotations_
+size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
{
if ( mip >= mipLevels )
return size_t(-1);
@@ -726,6 +998,21 @@ size_t TexMetadata::ComputeIndex( _In_ size_t mip, _In_ size_t item, _In_ size_t
// Blob - Bitmap image container
//=====================================================================================
+Blob& Blob::operator= (Blob&& moveFrom)
+{
+ if ( this != &moveFrom )
+ {
+ Release();
+
+ _buffer = moveFrom._buffer;
+ _size = moveFrom._size;
+
+ moveFrom._buffer = nullptr;
+ moveFrom._size = 0;
+ }
+ return *this;
+}
+
void Blob::Release()
{
if ( _buffer )
@@ -737,6 +1024,7 @@ void Blob::Release()
_size = 0;
}
+_Use_decl_annotations_
HRESULT Blob::Initialize( size_t size )
{
if ( !size )
diff --git a/thirdparty/directxtex/DirectXTex/DirectXTexWIC.cpp b/thirdparty/directxtex/DirectXTex/DirectXTexWIC.cpp
index 05cb76a3..0bebfafb 100644
--- a/thirdparty/directxtex/DirectXTex/DirectXTexWIC.cpp
+++ b/thirdparty/directxtex/DirectXTex/DirectXTexWIC.cpp
@@ -15,6 +15,58 @@
#include "DirectXTexP.h"
+using Microsoft::WRL::ComPtr;
+
+//-------------------------------------------------------------------------------------
+// IStream support for WIC Memory routines
+//-------------------------------------------------------------------------------------
+
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
+
+ #include <shcore.h>
+ #pragma comment(lib,"shcore.lib")
+
+#ifdef __cplusplus_winrt
+
+ static inline HRESULT CreateMemoryStream( _Outptr_ IStream** stream )
+ {
+ auto randomAccessStream = ref new ::Windows::Storage::Streams::InMemoryRandomAccessStream();
+ return CreateStreamOverRandomAccessStream( randomAccessStream, IID_PPV_ARGS( stream ) );
+ }
+
+#else
+
+ #include <wrl/client.h>
+ #include <wrl/wrappers/corewrappers.h>
+ #include <windows.storage.streams.h>
+
+ static inline HRESULT CreateMemoryStream( _Outptr_ IStream** stream )
+ {
+ Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> abiStream;
+ HRESULT hr = Windows::Foundation::ActivateInstance(
+ Microsoft::WRL::Wrappers::HStringReference( RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream ).Get(),
+ abiStream.GetAddressOf() );
+
+ if (SUCCEEDED(hr))
+ {
+ hr = CreateStreamOverRandomAccessStream( abiStream.Get(), IID_PPV_ARGS( stream ) );
+ }
+ return hr;
+ }
+
+#endif // __cplusplus_winrt
+
+#else
+
+ #pragma prefast(suppress:28196, "a simple wrapper around an existing annotated function" );
+ static inline HRESULT CreateMemoryStream( _Outptr_ IStream** stream )
+ {
+ return CreateStreamOnHGlobal( 0, TRUE, stream );
+ }
+
+#endif
+
+
//-------------------------------------------------------------------------------------
// WIC Pixel Format nearest conversion table
//-------------------------------------------------------------------------------------
@@ -67,13 +119,14 @@ static WICConvert g_WICConvert[] =
{ GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
{ GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
{ GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
+ { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
{ GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
{ GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
@@ -100,7 +153,7 @@ static DXGI_FORMAT _DetermineFormat( _In_ const WICPixelFormatGUID& pixelFormat,
{
if ( memcmp( &GUID_WICPixelFormat96bppRGBFixedPoint, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 )
{
-#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) || defined(_WIN7_PLATFORM_UPDATE)
+#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
if ( _IsWIC2() )
{
if ( pConvert )
@@ -222,7 +275,66 @@ static HRESULT _DecodeMetadata( _In_ DWORD flags,
if ( metadata.format == DXGI_FORMAT_UNKNOWN )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
- return S_OK;
+ if ( !( flags & WIC_FLAGS_IGNORE_SRGB ) )
+ {
+ GUID containerFormat;
+ hr = decoder->GetContainerFormat( &containerFormat );
+ if ( FAILED(hr) )
+ return hr;
+
+ ComPtr<IWICMetadataQueryReader> metareader;
+ hr = frame->GetMetadataQueryReader( metareader.GetAddressOf() );
+ if ( SUCCEEDED(hr) )
+ {
+ // Check for sRGB colorspace metadata
+ bool sRGB = false;
+
+ PROPVARIANT value;
+ PropVariantInit( &value );
+
+ if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 )
+ {
+ // Check for sRGB chunk
+ if ( SUCCEEDED( metareader->GetMetadataByName( L"/sRGB/RenderingIntent", &value ) ) && value.vt == VT_UI1 )
+ {
+ sRGB = true;
+ }
+ }
+#if defined(_XBOX_ONE) && defined(_TITLE)
+ else if ( memcmp( &containerFormat, &GUID_ContainerFormatJpeg, sizeof(GUID) ) == 0 )
+ {
+ if ( SUCCEEDED( metareader->GetMetadataByName( L"/app1/ifd/exif/{ushort=40961}", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 )
+ {
+ sRGB = true;
+ }
+ }
+ else if ( memcmp( &containerFormat, &GUID_ContainerFormatTiff, sizeof(GUID) ) == 0 )
+ {
+ if ( SUCCEEDED( metareader->GetMetadataByName( L"/ifd/exif/{ushort=40961}", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 )
+ {
+ sRGB = true;
+ }
+ }
+#else
+ else if ( SUCCEEDED( metareader->GetMetadataByName( L"System.Image.ColorSpace", &value ) ) && value.vt == VT_UI2 && value.uiVal == 1 )
+ {
+ sRGB = true;
+ }
+#endif
+
+ PropVariantClear( &value );
+
+ if ( sRGB )
+ metadata.format = MakeSRGB( metadata.format );
+ }
+ else if ( hr == WINCODEC_ERR_UNSUPPORTEDOPERATION )
+ {
+ // Some formats just don't support metadata (BMP, ICO, etc.), so ignore this failure
+ hr = S_OK;
+ }
+ }
+
+ return hr;
}
@@ -255,11 +367,23 @@ static HRESULT _DecodeSingleFrame( _In_ DWORD flags, _In_ const TexMetadata& met
}
else
{
- ScopedObject<IWICFormatConverter> FC;
- hr = pWIC->CreateFormatConverter( &FC );
+ ComPtr<IWICFormatConverter> FC;
+ hr = pWIC->CreateFormatConverter( FC.GetAddressOf() );
if ( FAILED(hr) )
return hr;
+ WICPixelFormatGUID pixelFormat;
+ hr = frame->GetPixelFormat( &pixelFormat );
+ if ( FAILED(hr) )
+ return hr;
+
+ BOOL canConvert = FALSE;
+ hr = FC->CanConvert( pixelFormat, convertGUID, &canConvert );
+ if ( FAILED(hr) || !canConvert )
+ {
+ return E_UNEXPECTED;
+ }
+
hr = FC->Initialize( frame, convertGUID, _GetWICDither( flags ), 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
@@ -300,8 +424,8 @@ static HRESULT _DecodeMultiframe( _In_ DWORD flags, _In_ const TexMetadata& meta
if ( !img )
return E_POINTER;
- ScopedObject<IWICBitmapFrameDecode> frame;
- hr = decoder->GetFrame( static_cast<UINT>( index ), &frame );
+ ComPtr<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame( static_cast<UINT>( index ), frame.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -315,64 +439,82 @@ static HRESULT _DecodeMultiframe( _In_ DWORD flags, _In_ const TexMetadata& meta
if ( FAILED(hr) )
return hr;
- if ( memcmp( &pfGuid, &sourceGUID, sizeof(WICPixelFormatGUID) ) == 0 )
+ if ( w == metadata.width && h == metadata.height )
{
- if ( w == metadata.width && h == metadata.height )
+ // This frame does not need resized
+ if ( memcmp( &pfGuid, &sourceGUID, sizeof(WICPixelFormatGUID) ) == 0 )
{
- // This frame does not need resized or format converted, just copy...
hr = frame->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
if ( FAILED(hr) )
return hr;
}
else
{
- // This frame needs resizing, but not format converted
- ScopedObject<IWICBitmapScaler> scaler;
- hr = pWIC->CreateBitmapScaler( &scaler );
+ ComPtr<IWICFormatConverter> FC;
+ hr = pWIC->CreateFormatConverter( FC.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- hr = scaler->Initialize( frame.Get(), static_cast<UINT>( metadata.width ), static_cast<UINT>( metadata.height ), _GetWICInterp( flags ) );
+ BOOL canConvert = FALSE;
+ hr = FC->CanConvert( pfGuid, sourceGUID, &canConvert );
+ if ( FAILED(hr) || !canConvert )
+ {
+ return E_UNEXPECTED;
+ }
+
+ hr = FC->Initialize( frame.Get(), sourceGUID, _GetWICDither( flags ), 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
-
- hr = scaler->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
+
+ hr = FC->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
if ( FAILED(hr) )
return hr;
}
}
else
{
- // This frame required format conversion
- ScopedObject<IWICFormatConverter> FC;
- hr = pWIC->CreateFormatConverter( &FC );
+ // This frame needs resizing
+ ComPtr<IWICBitmapScaler> scaler;
+ hr = pWIC->CreateBitmapScaler( scaler.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- hr = FC->Initialize( frame.Get(), pfGuid, _GetWICDither( flags ), 0, 0, WICBitmapPaletteTypeCustom );
+ hr = scaler->Initialize( frame.Get(), static_cast<UINT>( metadata.width ), static_cast<UINT>( metadata.height ), _GetWICInterp( flags ) );
if ( FAILED(hr) )
return hr;
-
- if ( w == metadata.width && h == metadata.height )
+
+ WICPixelFormatGUID pfScaler;
+ hr = scaler->GetPixelFormat( &pfScaler );
+ if ( FAILED(hr) )
+ return hr;
+
+ if ( memcmp( &pfScaler, &sourceGUID, sizeof(WICPixelFormatGUID) ) == 0 )
{
- // This frame is the same size, no need to scale
- hr = FC->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
+ hr = scaler->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
if ( FAILED(hr) )
return hr;
}
else
{
- // This frame needs resizing and format converted
- ScopedObject<IWICBitmapScaler> scaler;
- hr = pWIC->CreateBitmapScaler( &scaler );
+ // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we
+ // convert it to our desired format
+ ComPtr<IWICFormatConverter> FC;
+ hr = pWIC->CreateFormatConverter( FC.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- hr = scaler->Initialize( FC.Get(), static_cast<UINT>( metadata.width ), static_cast<UINT>( metadata.height ), _GetWICInterp( flags ) );
+ BOOL canConvert = FALSE;
+ hr = FC->CanConvert( pfScaler, sourceGUID, &canConvert );
+ if ( FAILED(hr) || !canConvert )
+ {
+ return E_UNEXPECTED;
+ }
+
+ hr = FC->Initialize( scaler.Get(), sourceGUID, _GetWICDither( flags ), 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
- hr = scaler->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
+ hr = FC->CopyPixels( 0, static_cast<UINT>( img->rowPitch ), static_cast<UINT>( img->slicePitch ), img->pixels );
if ( FAILED(hr) )
return hr;
}
@@ -384,9 +526,96 @@ static HRESULT _DecodeMultiframe( _In_ DWORD flags, _In_ const TexMetadata& meta
//-------------------------------------------------------------------------------------
+// Encodes image metadata
+//-------------------------------------------------------------------------------------
+static HRESULT _EncodeMetadata( _In_ IWICBitmapFrameEncode* frame, _In_ const GUID& containerFormat, _In_ DXGI_FORMAT format )
+{
+ if ( !frame )
+ return E_POINTER;
+
+ ComPtr<IWICMetadataQueryWriter> metawriter;
+ HRESULT hr = frame->GetMetadataQueryWriter( metawriter.GetAddressOf() );
+ if ( SUCCEEDED( hr ) )
+ {
+ PROPVARIANT value;
+ PropVariantInit( &value );
+
+ bool sRGB = IsSRGB( format );
+
+ value.vt = VT_LPSTR;
+ value.pszVal = "DirectXTex";
+
+ if ( memcmp( &containerFormat, &GUID_ContainerFormatPng, sizeof(GUID) ) == 0 )
+ {
+ // Set Software name
+ (void)metawriter->SetMetadataByName( L"/tEXt/{str=Software}", &value );
+
+ // Set sRGB chunk
+ if ( sRGB )
+ {
+ value.vt = VT_UI1;
+ value.bVal = 0;
+ (void)metawriter->SetMetadataByName( L"/sRGB/RenderingIntent", &value );
+ }
+ }
+#if defined(_XBOX_ONE) && defined(_TITLE)
+ else if ( memcmp( &containerFormat, &GUID_ContainerFormatJpeg, sizeof(GUID) ) == 0 )
+ {
+ // Set Software name
+ (void)metawriter->SetMetadataByName( L"/app1/ifd/{ushort=305}", &value );
+
+ if ( sRGB )
+ {
+ // Set EXIF Colorspace of sRGB
+ value.vt = VT_UI2;
+ value.uiVal = 1;
+ (void)metawriter->SetMetadataByName( L"/app1/ifd/exif/{ushort=40961}", &value );
+ }
+ }
+ else if ( memcmp( &containerFormat, &GUID_ContainerFormatTiff, sizeof(GUID) ) == 0 )
+ {
+ // Set Software name
+ (void)metawriter->SetMetadataByName( L"/ifd/{ushort=305}", &value );
+
+ if ( sRGB )
+ {
+ // Set EXIF Colorspace of sRGB
+ value.vt = VT_UI2;
+ value.uiVal = 1;
+ (void)metawriter->SetMetadataByName( L"/ifd/exif/{ushort=40961}", &value );
+ }
+ }
+#else
+ else
+ {
+ // Set Software name
+ (void)metawriter->SetMetadataByName( L"System.ApplicationName", &value );
+
+ if ( sRGB )
+ {
+ // Set EXIF Colorspace of sRGB
+ value.vt = VT_UI2;
+ value.uiVal = 1;
+ (void)metawriter->SetMetadataByName( L"System.Image.ColorSpace", &value );
+ }
+ }
+#endif
+ }
+ else if ( hr == WINCODEC_ERR_UNSUPPORTEDOPERATION )
+ {
+ // Some formats just don't support metadata (BMP, ICO, etc.), so ignore this failure
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+
+//-------------------------------------------------------------------------------------
// Encodes a single frame
//-------------------------------------------------------------------------------------
-static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ IWICBitmapFrameEncode* frame, _In_opt_ IPropertyBag2* props, _In_opt_ const GUID* targetFormat )
+static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID containerFormat,
+ _In_ IWICBitmapFrameEncode* frame, _In_opt_ IPropertyBag2* props, _In_opt_ const GUID* targetFormat )
{
if ( !frame )
return E_INVALIDARG;
@@ -402,7 +631,7 @@ static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ IWI
if ( FAILED(hr) )
return hr;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( (image.width > 0xFFFFFFFF) || (image.height > 0xFFFFFFFF) )
return E_INVALIDARG;
#endif
@@ -420,6 +649,16 @@ static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ IWI
if ( FAILED(hr) )
return hr;
+ if ( targetFormat && memcmp( targetFormat, &targetGuid, sizeof(WICPixelFormatGUID) ) != 0 )
+ {
+ // Requested output pixel format is not supported by the WIC codec
+ return E_FAIL;
+ }
+
+ hr = _EncodeMetadata( frame, containerFormat, image.format );
+ if ( FAILED(hr) )
+ return hr;
+
if ( memcmp( &targetGuid, &pfGuid, sizeof(WICPixelFormatGUID) ) != 0 )
{
// Conversion required to write
@@ -427,23 +666,30 @@ static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ IWI
if ( !pWIC )
return E_NOINTERFACE;
- ScopedObject<IWICBitmap> source;
+ ComPtr<IWICBitmap> source;
hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( image.width ), static_cast<UINT>( image.height ), pfGuid,
static_cast<UINT>( image.rowPitch ), static_cast<UINT>( image.slicePitch ),
- image.pixels, &source );
+ image.pixels, source.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICFormatConverter> FC;
- hr = pWIC->CreateFormatConverter( &FC );
+ ComPtr<IWICFormatConverter> FC;
+ hr = pWIC->CreateFormatConverter( FC.GetAddressOf() );
if ( FAILED(hr) )
return hr;
+ BOOL canConvert = FALSE;
+ hr = FC->CanConvert( pfGuid, targetGuid, &canConvert );
+ if ( FAILED(hr) || !canConvert )
+ {
+ return E_UNEXPECTED;
+ }
+
hr = FC->Initialize( source.Get(), targetGuid, _GetWICDither( flags ), 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
- WICRect rect = { 0, 0, static_cast<UINT>( image.width ), static_cast<UINT>( image.height ) };
+ WICRect rect = { 0, 0, static_cast<INT>( image.width ), static_cast<INT>( image.height ) };
hr = frame->WriteSource( FC.Get(), &rect );
if ( FAILED(hr) )
return hr;
@@ -465,7 +711,8 @@ static HRESULT _EncodeImage( _In_ const Image& image, _In_ DWORD flags, _In_ IWI
}
static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
- _In_ REFGUID guidContainerFormat, _Inout_ IStream* stream, _In_opt_ const GUID* targetFormat )
+ _In_ REFGUID containerFormat, _Inout_ IStream* stream,
+ _In_opt_ const GUID* targetFormat, _In_opt_ std::function<void(IPropertyBag2*)> setCustomProps )
{
if ( !stream )
return E_INVALIDARG;
@@ -475,8 +722,8 @@ static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
if ( !pWIC )
return E_NOINTERFACE;
- ScopedObject<IWICBitmapEncoder> encoder;
- HRESULT hr = pWIC->CreateEncoder( guidContainerFormat, 0, &encoder );
+ ComPtr<IWICBitmapEncoder> encoder;
+ HRESULT hr = pWIC->CreateEncoder( containerFormat, 0, encoder.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -484,30 +731,30 @@ static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICBitmapFrameEncode> frame;
- ScopedObject<IPropertyBag2> props;
- hr = encoder->CreateNewFrame( &frame, &props );
+ ComPtr<IWICBitmapFrameEncode> frame;
+ ComPtr<IPropertyBag2> props;
+ hr = encoder->CreateNewFrame( frame.GetAddressOf(), props.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- if ( memcmp( &guidContainerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID) ) == 0 )
+ if ( memcmp( &containerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID) ) == 0 && _IsWIC2() )
{
- // Opt-in to the Windows 8 support for writing 32-bit Windows BMP files with an alpha channel if supported
+ // Opt-in to the WIC2 support for writing 32-bit Windows BMP files with an alpha channel
PROPBAG2 option = { 0 };
option.pstrName = L"EnableV5Header32bppBGRA";
VARIANT varValue;
varValue.vt = VT_BOOL;
varValue.boolVal = VARIANT_TRUE;
- hr = props->Write( 1, &option, &varValue );
- if ( FAILED(hr) )
- {
- // Fails on older versions of WIC, so we default to the null property bag
- props.Reset();
- }
+ (void)props->Write( 1, &option, &varValue );
+ }
+
+ if ( setCustomProps )
+ {
+ setCustomProps( props.Get() );
}
- hr = _EncodeImage( image, flags, frame.Get(), props.Get(), targetFormat );
+ hr = _EncodeImage( image, flags, containerFormat, frame.Get(), props.Get(), targetFormat );
if ( FAILED(hr) )
return hr;
@@ -522,8 +769,9 @@ static HRESULT _EncodeSingleFrame( _In_ const Image& image, _In_ DWORD flags,
//-------------------------------------------------------------------------------------
// Encodes an image array
//-------------------------------------------------------------------------------------
-static HRESULT _EncodeMultiframe( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags,
- _In_ REFGUID guidContainerFormat, _Inout_ IStream* stream, _In_opt_ const GUID* targetFormat )
+static HRESULT _EncodeMultiframe( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags,
+ _In_ REFGUID containerFormat, _Inout_ IStream* stream,
+ _In_opt_ const GUID* targetFormat, _In_opt_ std::function<void(IPropertyBag2*)> setCustomProps )
{
if ( !stream || nimages < 2 )
return E_INVALIDARG;
@@ -536,13 +784,13 @@ static HRESULT _EncodeMultiframe( _In_count_(nimages) const Image* images, _In_
if ( !pWIC )
return E_NOINTERFACE;
- ScopedObject<IWICBitmapEncoder> encoder;
- HRESULT hr = pWIC->CreateEncoder( guidContainerFormat, 0, &encoder );
+ ComPtr<IWICBitmapEncoder> encoder;
+ HRESULT hr = pWIC->CreateEncoder( containerFormat, 0, encoder.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICBitmapEncoderInfo> einfo;
- hr = encoder->GetEncoderInfo( &einfo );
+ ComPtr<IWICBitmapEncoderInfo> einfo;
+ hr = encoder->GetEncoderInfo( einfo.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -560,12 +808,18 @@ static HRESULT _EncodeMultiframe( _In_count_(nimages) const Image* images, _In_
for( size_t index=0; index < nimages; ++index )
{
- ScopedObject<IWICBitmapFrameEncode> frame;
- hr = encoder->CreateNewFrame( &frame, nullptr );
+ ComPtr<IWICBitmapFrameEncode> frame;
+ ComPtr<IPropertyBag2> props;
+ hr = encoder->CreateNewFrame( frame.GetAddressOf(), props.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- hr = _EncodeImage( images[index], flags, frame.Get(), nullptr, targetFormat );
+ if ( setCustomProps )
+ {
+ setCustomProps( props.Get() );
+ }
+
+ hr = _EncodeImage( images[index], flags, containerFormat, frame.Get(), props.Get(), targetFormat );
if ( FAILED(hr) )
return hr;
}
@@ -585,12 +839,13 @@ static HRESULT _EncodeMultiframe( _In_count_(nimages) const Image* images, _In_
//-------------------------------------------------------------------------------------
// Obtain metadata from WIC-supported file in memory
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT GetMetadataFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadata& metadata )
{
if ( !pSource || size == 0 )
return E_INVALIDARG;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( size > 0xFFFFFFFF )
return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
#endif
@@ -600,8 +855,8 @@ HRESULT GetMetadataFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, Tex
return E_NOINTERFACE;
// Create input stream for memory
- ScopedObject<IWICStream> stream;
- HRESULT hr = pWIC->CreateStream( &stream );
+ ComPtr<IWICStream> stream;
+ HRESULT hr = pWIC->CreateStream( stream.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -611,13 +866,13 @@ HRESULT GetMetadataFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, Tex
return hr;
// Initialize WIC
- ScopedObject<IWICBitmapDecoder> decoder;
- hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder );
+ ComPtr<IWICBitmapDecoder> decoder;
+ hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICBitmapFrameDecode> frame;
- hr = decoder->GetFrame( 0, &frame );
+ ComPtr<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame( 0, frame.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -633,6 +888,7 @@ HRESULT GetMetadataFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, Tex
//-------------------------------------------------------------------------------------
// Obtain metadata from WIC-supported file on disk
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT GetMetadataFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata& metadata )
{
if ( !szFile )
@@ -643,13 +899,13 @@ HRESULT GetMetadataFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata& metada
return E_NOINTERFACE;
// Initialize WIC
- ScopedObject<IWICBitmapDecoder> decoder;
- HRESULT hr = pWIC->CreateDecoderFromFilename( szFile, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder );
+ ComPtr<IWICBitmapDecoder> decoder;
+ HRESULT hr = pWIC->CreateDecoderFromFilename( szFile, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICBitmapFrameDecode> frame;
- hr = decoder->GetFrame( 0, &frame );
+ ComPtr<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame( 0, frame.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -665,12 +921,13 @@ HRESULT GetMetadataFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata& metada
//-------------------------------------------------------------------------------------
// Load a WIC-supported file in memory
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT LoadFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadata* metadata, ScratchImage& image )
{
if ( !pSource || size == 0 )
return E_INVALIDARG;
-#ifdef _AMD64_
+#ifdef _M_X64
if ( size > 0xFFFFFFFF )
return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
#endif
@@ -682,8 +939,8 @@ HRESULT LoadFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadat
image.Release();
// Create input stream for memory
- ScopedObject<IWICStream> stream;
- HRESULT hr = pWIC->CreateStream( &stream );
+ ComPtr<IWICStream> stream;
+ HRESULT hr = pWIC->CreateStream( stream.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -692,13 +949,13 @@ HRESULT LoadFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadat
return hr;
// Initialize WIC
- ScopedObject<IWICBitmapDecoder> decoder;
- hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder );
+ ComPtr<IWICBitmapDecoder> decoder;
+ hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICBitmapFrameDecode> frame;
- hr = decoder->GetFrame( 0, &frame );
+ ComPtr<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame( 0, frame.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -734,6 +991,7 @@ HRESULT LoadFromWICMemory( LPCVOID pSource, size_t size, DWORD flags, TexMetadat
//-------------------------------------------------------------------------------------
// Load a WIC-supported file from disk
//-------------------------------------------------------------------------------------
+_Use_decl_annotations_
HRESULT LoadFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, ScratchImage& image )
{
if ( !szFile )
@@ -746,13 +1004,13 @@ HRESULT LoadFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
image.Release();
// Initialize WIC
- ScopedObject<IWICBitmapDecoder> decoder;
- HRESULT hr = pWIC->CreateDecoderFromFilename( szFile, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder );
+ ComPtr<IWICBitmapDecoder> decoder;
+ HRESULT hr = pWIC->CreateDecoderFromFilename( szFile, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- ScopedObject<IWICBitmapFrameDecode> frame;
- hr = decoder->GetFrame( 0, &frame );
+ ComPtr<IWICBitmapFrameDecode> frame;
+ hr = decoder->GetFrame( 0, frame.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -788,19 +1046,21 @@ HRESULT LoadFromWICFile( LPCWSTR szFile, DWORD flags, TexMetadata* metadata, Scr
//-------------------------------------------------------------------------------------
// Save a WIC-supported file to memory
//-------------------------------------------------------------------------------------
-HRESULT SaveToWICMemory( const Image& image, DWORD flags, REFGUID guidContainerFormat, Blob& blob, const GUID* targetFormat )
+_Use_decl_annotations_
+HRESULT SaveToWICMemory( const Image& image, DWORD flags, REFGUID containerFormat, Blob& blob,
+ const GUID* targetFormat, std::function<void(IPropertyBag2*)> setCustomProps )
{
if ( !image.pixels )
return E_POINTER;
blob.Release();
- ScopedObject<IStream> stream;
- HRESULT hr = CreateStreamOnHGlobal( 0, TRUE, &stream );
+ ComPtr<IStream> stream;
+ HRESULT hr = CreateMemoryStream( stream.GetAddressOf() );
if ( FAILED(hr) )
return hr;
- hr = _EncodeSingleFrame( image, flags, guidContainerFormat, stream.Get(), targetFormat );
+ hr = _EncodeSingleFrame( image, flags, containerFormat, stream.Get(), targetFormat, setCustomProps );
if ( FAILED(hr) )
return hr;
@@ -833,22 +1093,24 @@ HRESULT SaveToWICMemory( const Image& image, DWORD flags, REFGUID guidContainerF
return S_OK;
}
-HRESULT SaveToWICMemory( const Image* images, size_t nimages, DWORD flags, REFGUID guidContainerFormat, Blob& blob, const GUID* targetFormat )
+_Use_decl_annotations_
+HRESULT SaveToWICMemory( const Image* images, size_t nimages, DWORD flags, REFGUID containerFormat, Blob& blob,
+ const GUID* targetFormat, std::function<void(IPropertyBag2*)> setCustomProps )
{
if ( !images || nimages == 0 )
return E_INVALIDARG;
blob.Release();
- ScopedObject<IStream> stream;
- HRESULT hr = CreateStreamOnHGlobal( 0, TRUE, &stream );
+ ComPtr<IStream> stream;
+ HRESULT hr = CreateMemoryStream( stream.GetAddressOf() );
if ( FAILED(hr) )
return hr;
if ( nimages > 1 )
- hr = _EncodeMultiframe( images, nimages, flags, guidContainerFormat, stream.Get(), targetFormat );
+ hr = _EncodeMultiframe( images, nimages, flags, containerFormat, stream.Get(), targetFormat, setCustomProps );
else
- hr = _EncodeSingleFrame( images[0], flags, guidContainerFormat, stream.Get(), targetFormat );
+ hr = _EncodeSingleFrame( images[0], flags, containerFormat, stream.Get(), targetFormat, setCustomProps );
if ( FAILED(hr) )
return hr;
@@ -886,7 +1148,9 @@ HRESULT SaveToWICMemory( const Image* images, size_t nimages, DWORD flags, REFGU
//-------------------------------------------------------------------------------------
// Save a WIC-supported file to disk
//-------------------------------------------------------------------------------------
-HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID guidContainerFormat, LPCWSTR szFile, const GUID* targetFormat )
+_Use_decl_annotations_
+HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID containerFormat, LPCWSTR szFile,
+ const GUID* targetFormat, std::function<void(IPropertyBag2*)> setCustomProps )
{
if ( !szFile )
return E_INVALIDARG;
@@ -898,8 +1162,8 @@ HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID guidContainerFor
if ( !pWIC )
return E_NOINTERFACE;
- ScopedObject<IWICStream> stream;
- HRESULT hr = pWIC->CreateStream( &stream );
+ ComPtr<IWICStream> stream;
+ HRESULT hr = pWIC->CreateStream( stream.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -907,14 +1171,16 @@ HRESULT SaveToWICFile( const Image& image, DWORD flags, REFGUID guidContainerFor
if ( FAILED(hr) )
return hr;
- hr = _EncodeSingleFrame( image, flags, guidContainerFormat, stream.Get(), targetFormat );
+ hr = _EncodeSingleFrame( image, flags, containerFormat, stream.Get(), targetFormat, setCustomProps );
if ( FAILED(hr) )
return hr;
return S_OK;
}
-HRESULT SaveToWICFile( const Image* images, size_t nimages, DWORD flags, REFGUID guidContainerFormat, LPCWSTR szFile, const GUID* targetFormat )
+_Use_decl_annotations_
+HRESULT SaveToWICFile( const Image* images, size_t nimages, DWORD flags, REFGUID containerFormat, LPCWSTR szFile, const GUID* targetFormat,
+ std::function<void(IPropertyBag2*)> setCustomProps )
{
if ( !szFile || !images || nimages == 0 )
return E_INVALIDARG;
@@ -923,8 +1189,8 @@ HRESULT SaveToWICFile( const Image* images, size_t nimages, DWORD flags, REFGUID
if ( !pWIC )
return E_NOINTERFACE;
- ScopedObject<IWICStream> stream;
- HRESULT hr = pWIC->CreateStream( &stream );
+ ComPtr<IWICStream> stream;
+ HRESULT hr = pWIC->CreateStream( stream.GetAddressOf() );
if ( FAILED(hr) )
return hr;
@@ -933,9 +1199,9 @@ HRESULT SaveToWICFile( const Image* images, size_t nimages, DWORD flags, REFGUID
return hr;
if ( nimages > 1 )
- hr = _EncodeMultiframe( images, nimages, flags, guidContainerFormat, stream.Get(), targetFormat );
+ hr = _EncodeMultiframe( images, nimages, flags, containerFormat, stream.Get(), targetFormat, setCustomProps );
else
- hr = _EncodeSingleFrame( images[0], flags, guidContainerFormat, stream.Get(), targetFormat );
+ hr = _EncodeSingleFrame( images[0], flags, containerFormat, stream.Get(), targetFormat, setCustomProps );
if ( FAILED(hr) )
return hr;
diff --git a/thirdparty/directxtex/DirectXTex/filters.h b/thirdparty/directxtex/DirectXTex/filters.h
new file mode 100644
index 00000000..9579fa4e
--- /dev/null
+++ b/thirdparty/directxtex/DirectXTex/filters.h
@@ -0,0 +1,426 @@
+//-------------------------------------------------------------------------------------
+// filters.h
+//
+// Utility header with helpers for implementing image filters
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//-------------------------------------------------------------------------------------
+
+#pragma once
+
+#ifdef USE_XNAMATH
+#include <xnamath.h>
+#else
+#include <directxmath.h>
+#include <directxpackedvector.h>
+#endif
+
+#include <memory>
+
+#include "scoped.h"
+
+namespace DirectX
+{
+
+//-------------------------------------------------------------------------------------
+// Box filtering helpers
+//-------------------------------------------------------------------------------------
+
+XMGLOBALCONST XMVECTORF32 g_boxScale = { 0.25f, 0.25f, 0.25f, 0.25f };
+XMGLOBALCONST XMVECTORF32 g_boxScale3D = { 0.125f, 0.125f, 0.125f, 0.125f };
+
+#define AVERAGE4( res, p0, p1, p2, p3 ) \
+{ \
+ XMVECTOR v = XMVectorAdd( (p0), (p1) ); \
+ v = XMVectorAdd( v, (p2) ); \
+ v = XMVectorAdd( v, (p3) ); \
+ res = XMVectorMultiply( v, g_boxScale ); \
+}
+
+#define AVERAGE8( res, p0, p1, p2, p3, p4, p5, p6, p7) \
+{ \
+ XMVECTOR v = XMVectorAdd( (p0), (p1) ); \
+ v = XMVectorAdd( v, (p2) ); \
+ v = XMVectorAdd( v, (p3) ); \
+ v = XMVectorAdd( v, (p4) ); \
+ v = XMVectorAdd( v, (p5) ); \
+ v = XMVectorAdd( v, (p6) ); \
+ v = XMVectorAdd( v, (p7) ); \
+ res = XMVectorMultiply( v, g_boxScale3D ); \
+}
+
+
+//-------------------------------------------------------------------------------------
+// Linear filtering helpers
+//-------------------------------------------------------------------------------------
+
+struct LinearFilter
+{
+ size_t u0;
+ float weight0;
+ size_t u1;
+ float weight1;
+};
+
+inline void _CreateLinearFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Out_writes_(dest) LinearFilter* lf )
+{
+ assert( source > 0 );
+ assert( dest > 0 );
+ assert( lf != 0 );
+
+ float scale = float(source) / float(dest);
+
+ // Mirror is the same case as clamp for linear
+
+ for( size_t u = 0; u < dest; ++u )
+ {
+ float srcB = ( float(u) + 0.5f ) * scale + 0.5f;
+
+ ptrdiff_t isrcB = ptrdiff_t(srcB);
+ ptrdiff_t isrcA = isrcB - 1;
+
+ if ( isrcA < 0 )
+ {
+ isrcA = ( wrap ) ? ( source - 1) : 0;
+ }
+
+ if ( size_t(isrcB) >= source )
+ {
+ isrcB = ( wrap ) ? 0 : ( source - 1);
+ }
+
+ float weight = 1.0f + float(isrcB) - srcB;
+
+ auto& entry = lf[ u ];
+ entry.u0 = size_t(isrcA);
+ entry.weight0 = weight;
+
+ entry.u1 = size_t(isrcB);
+ entry.weight1 = 1.0f - weight;
+ }
+}
+
+#define BILINEAR_INTERPOLATE( res, x, y, r0, r1 ) \
+ res = ( y.weight0 * ( (r0)[ x.u0 ] * x.weight0 + (r0)[ x.u1 ] * x.weight1 ) ) \
+ + ( y.weight1 * ( (r1)[ x.u0 ] * x.weight0 + (r1)[ x.u1 ] * x.weight1 ) )
+
+#define TRILINEAR_INTERPOLATE( res, x, y, z, r0, r1, r2, r3 ) \
+ res = ( z.weight0 * ( ( y.weight0 * ( (r0)[ x.u0 ] * x.weight0 + (r0)[ x.u1 ] * x.weight1 ) ) \
+ + ( y.weight1 * ( (r1)[ x.u0 ] * x.weight0 + (r1)[ x.u1 ] * x.weight1 ) ) ) ) \
+ + ( z.weight1 * ( ( y.weight0 * ( (r2)[ x.u0 ] * x.weight0 + (r2)[ x.u1 ] * x.weight1 ) ) \
+ + ( y.weight1 * ( (r3)[ x.u0 ] * x.weight0 + (r3)[ x.u1 ] * x.weight1 ) ) ) )
+
+
+//-------------------------------------------------------------------------------------
+// Cubic filtering helpers
+//-------------------------------------------------------------------------------------
+
+XMGLOBALCONST XMVECTORF32 g_cubicThird = { 1.f/3.f, 1.f/3.f, 1.f/3.f, 1.f/3.f };
+XMGLOBALCONST XMVECTORF32 g_cubicSixth = { 1.f/6.f, 1.f/6.f, 1.f/6.f, 1.f/6.f };
+XMGLOBALCONST XMVECTORF32 g_cubicHalf = { 1.f/2.f, 1.f/2.f, 1.f/2.f, 1.f/2.f };
+
+inline ptrdiff_t bounduvw( ptrdiff_t u, ptrdiff_t maxu, bool wrap, bool mirror )
+{
+ if ( wrap )
+ {
+ if ( u < 0 )
+ {
+ u = maxu + u + 1;
+ }
+ else if ( u > maxu )
+ {
+ u = u - maxu - 1;
+ }
+ }
+ else if ( mirror )
+ {
+ if ( u < 0 )
+ {
+ u = ( -u ) - 1;
+ }
+ else if ( u > maxu )
+ {
+ u = maxu - (u - maxu - 1);
+ }
+ }
+
+ // Handles clamp, but also a safety factor for degenerate images for wrap/mirror
+ u = std::min<ptrdiff_t>( u, maxu );
+ u = std::max<ptrdiff_t>( u, 0 );
+
+ return u;
+}
+
+struct CubicFilter
+{
+ size_t u0;
+ size_t u1;
+ size_t u2;
+ size_t u3;
+ float x;
+};
+
+inline void _CreateCubicFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _In_ bool mirror, _Out_writes_(dest) CubicFilter* cf )
+{
+ assert( source > 0 );
+ assert( dest > 0 );
+ assert( cf != 0 );
+
+ float scale = float(source) / float(dest);
+
+ for( size_t u = 0; u < dest; ++u )
+ {
+ float srcB = ( float(u) + 0.5f ) * scale - 0.5f;
+
+ ptrdiff_t isrcB = bounduvw( ptrdiff_t(srcB), source - 1, wrap, mirror );
+ ptrdiff_t isrcA = bounduvw( isrcB - 1, source - 1, wrap, mirror );
+ ptrdiff_t isrcC = bounduvw( isrcB + 1, source - 1, wrap, mirror );
+ ptrdiff_t isrcD = bounduvw( isrcB + 2, source - 1, wrap, mirror );
+
+ auto& entry = cf[ u ];
+ entry.u0 = size_t(isrcA);
+ entry.u1 = size_t(isrcB);
+ entry.u2 = size_t(isrcC);
+ entry.u3 = size_t(isrcD);
+
+ float x = srcB - float(isrcB);
+ entry.x = x;
+ }
+}
+
+#define CUBIC_INTERPOLATE( res, dx, p0, p1, p2, p3 ) \
+{ \
+ XMVECTOR a0 = (p1); \
+ XMVECTOR d0 = (p0) - a0; \
+ XMVECTOR d2 = (p2) - a0; \
+ XMVECTOR d3 = (p3) - a0; \
+ XMVECTOR a1 = d2 - g_cubicThird*d0 - g_cubicSixth*d3; \
+ XMVECTOR a2 = g_cubicHalf*d0 + g_cubicHalf*d2; \
+ XMVECTOR a3 = g_cubicSixth*d3 - g_cubicSixth*d0 - g_cubicHalf*d2; \
+ XMVECTOR vdx = XMVectorReplicate( dx ); \
+ XMVECTOR vdx2 = vdx * vdx; \
+ XMVECTOR vdx3 = vdx2 * vdx; \
+ res = a0 + a1*vdx + a2*vdx2 + a3*vdx3; \
+}
+
+
+//-------------------------------------------------------------------------------------
+// Triangle filtering helpers
+//-------------------------------------------------------------------------------------
+
+namespace TriangleFilter
+{
+ struct FilterTo
+ {
+ size_t u;
+ float weight;
+ };
+
+ struct FilterFrom
+ {
+ size_t count;
+ size_t sizeInBytes;
+ FilterTo to[1]; // variable-sized array
+ };
+
+ struct Filter
+ {
+ size_t sizeInBytes;
+ size_t totalSize;
+ FilterFrom from[1]; // variable-sized array
+ };
+
+ struct TriangleRow
+ {
+ size_t remaining;
+ TriangleRow* next;
+ ScopedAlignedArrayXMVECTOR scanline;
+
+ TriangleRow() : remaining(0), next(nullptr) {}
+ };
+
+ static const size_t TF_FILTER_SIZE = sizeof(Filter) - sizeof(FilterFrom);
+ static const size_t TF_FROM_SIZE = sizeof(FilterFrom) - sizeof(FilterTo);
+ static const size_t TF_TO_SIZE = sizeof(FilterTo);
+
+ static const float TF_EPSILON = 0.00001f;
+
+ inline HRESULT _Create( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Inout_ std::unique_ptr<Filter>& tf )
+ {
+ assert( source > 0 );
+ assert( dest > 0 );
+
+ float scale = float(dest) / float(source);
+ float scaleInv = 0.5f / scale;
+
+ // Determine storage required for filter and allocate memory if needed
+ size_t totalSize = TF_FILTER_SIZE + TF_FROM_SIZE + TF_TO_SIZE;
+ float repeat = (wrap) ? 1.f : 0.f;
+
+ for( size_t u = 0; u < source; ++u )
+ {
+ float src = float(u) - 0.5f;
+ float destMin = src * scale;
+ float destMax = destMin + scale;
+
+ totalSize += TF_FROM_SIZE + TF_TO_SIZE + size_t( destMax - destMin + repeat + 1.f ) * TF_TO_SIZE * 2;
+ }
+
+ uint8_t* pFilter = nullptr;
+
+ if ( tf )
+ {
+ // See if existing filter memory block is large enough to reuse
+ if ( tf->totalSize >= totalSize )
+ {
+ pFilter = reinterpret_cast<uint8_t*>( tf.get() );
+ }
+ else
+ {
+ // Need to reallocate filter memory block
+ tf.reset( nullptr );
+ }
+ }
+
+ if ( !tf )
+ {
+ // Allocate filter memory block
+ pFilter = new (std::nothrow) uint8_t[ totalSize ];
+ if ( !pFilter )
+ return E_OUTOFMEMORY;
+
+ tf.reset( reinterpret_cast<Filter*>( pFilter ) );
+ tf->totalSize = totalSize;
+ }
+
+ assert( pFilter != 0 );
+
+ // Filter setup
+ size_t sizeInBytes = TF_FILTER_SIZE;
+ size_t accumU = 0;
+ float accumWeight = 0.f;
+
+ for( size_t u = 0; u < source; ++u )
+ {
+ // Setup from entry
+ size_t sizeFrom = sizeInBytes;
+ auto pFrom = reinterpret_cast<FilterFrom*>( pFilter + sizeInBytes );
+ sizeInBytes += TF_FROM_SIZE;
+
+ if ( sizeInBytes > totalSize )
+ return E_FAIL;
+
+ size_t toCount = 0;
+
+ // Perform two passes to capture the influences from both sides
+ for( size_t j = 0; j < 2; ++j )
+ {
+ float src = float( u + j ) - 0.5f;
+
+ float destMin = src * scale;
+ float destMax = destMin + scale;
+
+ if ( !wrap )
+ {
+ // Clamp
+ if ( destMin < 0.f )
+ destMin = 0.f;
+ if ( destMax > float(dest) )
+ destMax = float(dest);
+ }
+
+ for( auto k = static_cast<ptrdiff_t>( floorf( destMin ) ); float(k) < destMax; ++k )
+ {
+ float d0 = float(k);
+ float d1 = d0 + 1.f;
+
+ size_t u0;
+ if ( k < 0 )
+ {
+ // Handle wrap
+ u0 = size_t( k + ptrdiff_t(dest) );
+ }
+ else if ( k >= ptrdiff_t(dest) )
+ {
+ // Handle wrap
+ u0 = size_t( k - ptrdiff_t(dest) );
+ }
+ else
+ {
+ u0 = size_t( k );
+ }
+
+ // Save previous accumulated weight (if any)
+ if ( u0 != accumU )
+ {
+ if ( accumWeight > TF_EPSILON )
+ {
+ auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
+ sizeInBytes += TF_TO_SIZE;
+ ++toCount;
+
+ if ( sizeInBytes > totalSize )
+ return E_FAIL;
+
+ pTo->u = accumU;
+ pTo->weight = accumWeight;
+ }
+
+ accumWeight = 0.f;
+ accumU = u0;
+ }
+
+ // Clip destination
+ if ( d0 < destMin )
+ d0 = destMin;
+ if ( d1 > destMax )
+ d1 = destMax;
+
+ // Calculate average weight over destination pixel
+
+ float weight;
+ if ( !wrap && src < 0.f )
+ weight = 1.f;
+ else if ( !wrap && ( ( src + 1.f ) >= float(source) ) )
+ weight = 0.f;
+ else
+ weight = (d0 + d1) * scaleInv - src;
+
+ accumWeight += (d1 - d0) * ( j ? (1.f - weight) : weight );
+ }
+ }
+
+ // Store accumulated weight
+ if ( accumWeight > TF_EPSILON )
+ {
+ auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
+ sizeInBytes += TF_TO_SIZE;
+ ++toCount;
+
+ if ( sizeInBytes > totalSize )
+ return E_FAIL;
+
+ pTo->u = accumU;
+ pTo->weight = accumWeight;
+ }
+
+ accumWeight = 0.f;
+
+ // Finalize from entry
+ pFrom->count = toCount;
+ pFrom->sizeInBytes = sizeInBytes - sizeFrom;
+ }
+
+ tf->sizeInBytes = sizeInBytes;
+
+ return S_OK;
+ }
+
+}; // namespace
+
+}; // namespace
diff --git a/thirdparty/directxtex/DirectXTex/scoped.h b/thirdparty/directxtex/DirectXTex/scoped.h
index 81816069..a02ae69a 100644
--- a/thirdparty/directxtex/DirectXTex/scoped.h
+++ b/thirdparty/directxtex/DirectXTex/scoped.h
@@ -11,9 +11,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
//-------------------------------------------------------------------------------------
-#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
-#endif
#include <assert.h>
#include <memory>
@@ -22,12 +20,12 @@
//---------------------------------------------------------------------------------
struct aligned_deleter { void operator()(void* p) { _aligned_free(p); } };
-typedef std::unique_ptr<float, aligned_deleter> ScopedAlignedArrayFloat;
+typedef std::unique_ptr<float[], aligned_deleter> ScopedAlignedArrayFloat;
#ifdef USE_XNAMATH
-typedef std::unique_ptr<XMVECTOR, aligned_deleter> ScopedAlignedArrayXMVECTOR;
+typedef std::unique_ptr<XMVECTOR[], aligned_deleter> ScopedAlignedArrayXMVECTOR;
#else
-typedef std::unique_ptr<DirectX::XMVECTOR, aligned_deleter> ScopedAlignedArrayXMVECTOR;
+typedef std::unique_ptr<DirectX::XMVECTOR[], aligned_deleter> ScopedAlignedArrayXMVECTOR;
#endif
//---------------------------------------------------------------------------------
@@ -36,35 +34,3 @@ struct handle_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VA
typedef std::unique_ptr<void, handle_closer> ScopedHandle;
inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }
-
-
-//---------------------------------------------------------------------------------
-template<class T> class ScopedObject
-{
-public:
- explicit ScopedObject( T *p = 0 ) : _pointer(p) {}
- ~ScopedObject()
- {
- if ( _pointer )
- {
- _pointer->Release();
- _pointer = nullptr;
- }
- }
-
- bool IsNull() const { return (!_pointer); }
-
- T& operator*() { return *_pointer; }
- T* operator->() { return _pointer; }
- T** operator&() { return &_pointer; }
-
- void Reset(T *p = 0) { if ( _pointer ) { _pointer->Release(); } _pointer = p; }
-
- T* Get() const { return _pointer; }
-
-private:
- ScopedObject(const ScopedObject&);
- ScopedObject& operator=(const ScopedObject&);
-
- T* _pointer;
-};
diff --git a/thirdparty/directxtex/MIT.txt b/thirdparty/directxtex/MIT.txt
new file mode 100644
index 00000000..a2336dbc
--- /dev/null
+++ b/thirdparty/directxtex/MIT.txt
@@ -0,0 +1,21 @@
+ The MIT License (MIT)
+
+Copyright (c) 2015 Microsoft Corp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all copies
+or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/thirdparty/directxtex/Microsoft Public License.rtf b/thirdparty/directxtex/Microsoft Public License.rtf
deleted file mode 100644
index 390c7adb..00000000
--- a/thirdparty/directxtex/Microsoft Public License.rtf
+++ /dev/null
@@ -1,234 +0,0 @@
-{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}
-{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f36\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\f38\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}
-{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}Verdana;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}
-{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
-{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
-{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f40\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f41\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
-{\f43\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f44\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f45\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f46\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\f47\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f48\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f50\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f51\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;}
-{\f53\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f54\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f55\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f56\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);}
-{\f57\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f58\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f380\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f381\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}
-{\f383\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f384\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f387\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f388\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}
-{\f400\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f401\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f403\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f404\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
-{\f407\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f408\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f420\fbidi \fswiss\fcharset238\fprq2 Tahoma CE;}{\f421\fbidi \fswiss\fcharset204\fprq2 Tahoma Cyr;}
-{\f423\fbidi \fswiss\fcharset161\fprq2 Tahoma Greek;}{\f424\fbidi \fswiss\fcharset162\fprq2 Tahoma Tur;}{\f425\fbidi \fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f426\fbidi \fswiss\fcharset178\fprq2 Tahoma (Arabic);}
-{\f427\fbidi \fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f428\fbidi \fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f429\fbidi \fswiss\fcharset222\fprq2 Tahoma (Thai);}{\f430\fbidi \fswiss\fcharset238\fprq2 Verdana CE;}
-{\f431\fbidi \fswiss\fcharset204\fprq2 Verdana Cyr;}{\f433\fbidi \fswiss\fcharset161\fprq2 Verdana Greek;}{\f434\fbidi \fswiss\fcharset162\fprq2 Verdana Tur;}{\f437\fbidi \fswiss\fcharset186\fprq2 Verdana Baltic;}
-{\f438\fbidi \fswiss\fcharset163\fprq2 Verdana (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
-{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
-{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
-{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}
-{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
-{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
-{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
-{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
-{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
-{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
-{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
-{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
-{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
-{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
-{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
-{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
-{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
-{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
-{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
-\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp }{\*\defpap
-\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0
-\f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\s1\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0
-\f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink15 \sqformat \spriority9 heading 1;}{\s2\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0
-\f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink16 \sqformat \spriority9 heading 2;}{\*\cs10 \additive \ssemihidden Default Paragraph Font;}{\*
-\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
-\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20\alang1025 \ltrch\fcs0 \fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive
-\rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0 \b\f36\fs32\kerning32 \sbasedon10 \slink1 \slocked \spriority9 Heading 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \ab\ai\af0\afs28 \ltrch\fcs0 \b\i\f36\fs28 \sbasedon10 \slink2 \slocked \spriority9 Heading 2 Char;}{
-\s17\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af38\afs16\alang1025 \ltrch\fcs0 \f38\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext17 \slink18 \ssemihidden \sunhideused \styrsid7424395 Balloon Text;}
-{\*\cs18 \additive \rtlch\fcs1 \af38\afs16 \ltrch\fcs0 \f38\fs16 \sbasedon10 \slink17 \slocked \ssemihidden \styrsid7424395 Balloon Text Char;}{\*\cs19 \additive \rtlch\fcs1 \af0\afs16 \ltrch\fcs0 \fs16
-\sbasedon10 \ssemihidden \sunhideused \styrsid4538388 annotation reference;}{\s20\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs20\alang1025 \ltrch\fcs0 \f1\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033
-\sbasedon0 \snext20 \slink21 \ssemihidden \sunhideused \styrsid4538388 annotation text;}{\*\cs21 \additive \rtlch\fcs1 \af1 \ltrch\fcs0 \f1 \sbasedon10 \slink20 \slocked \ssemihidden \styrsid4538388 Comment Text Char;}{
-\s22\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \ab\af1\afs20\alang1025 \ltrch\fcs0 \b\f1\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon20 \snext20 \slink23 \ssemihidden \sunhideused \styrsid4538388
-annotation subject;}{\*\cs23 \additive \rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f1 \sbasedon21 \slink22 \slocked \ssemihidden \styrsid4538388 Comment Subject Char;}}{\*\rsidtbl \rsid213160\rsid284417\rsid417145\rsid481196\rsid551334\rsid723397\rsid786968
-\rsid1382437\rsid1390003\rsid1521043\rsid1530955\rsid1708989\rsid1783212\rsid1903779\rsid2431884\rsid3165084\rsid3416120\rsid3419781\rsid3754103\rsid3768194\rsid3831520\rsid4538130\rsid4538388\rsid4552277\rsid4680449\rsid4729674\rsid4865270\rsid4987534
-\rsid5128131\rsid5186068\rsid5601121\rsid5864350\rsid6186044\rsid6311778\rsid6384507\rsid6434687\rsid6561471\rsid6910344\rsid6947552\rsid7033180\rsid7424395\rsid7682010\rsid7690850\rsid7744081\rsid8151618\rsid8196281\rsid8198206\rsid8342723\rsid8350925
-\rsid8722561\rsid8852349\rsid8934457\rsid8944153\rsid9573035\rsid9635349\rsid9638545\rsid9724918\rsid10044820\rsid10095979\rsid10228618\rsid10449644\rsid10494075\rsid11166278\rsid11166751\rsid11285353\rsid11366513\rsid11494815\rsid11932529\rsid12061202
-\rsid12533699\rsid12536400\rsid12916885\rsid13264736\rsid13322831\rsid13440556\rsid13455614\rsid13597357\rsid13768671\rsid14097590\rsid14157399\rsid14229900\rsid14305025\rsid14314735\rsid14436896\rsid14565916\rsid14572556\rsid14688892\rsid14752433
-\rsid14904394\rsid15086147\rsid15749945\rsid15814398\rsid15927751\rsid16071312\rsid16126175\rsid16279402\rsid16391569\rsid16404661\rsid16452939\rsid16537688\rsid16606866\rsid16674896}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1
-\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\title Microsoft Permissive License (Ms-PL)}{\author Jonr}{\operator Chuck Walbourn}{\creatim\yr2007\mo2\dy23\hr15\min10}{\revtim\yr2011\mo8\dy15\hr15\min2}
-{\printim\yr2006\mo9\dy28\hr8\min46}{\version3}{\edmins1}{\nofpages1}{\nofwords391}{\nofchars2230}{\*\company Microsoft}{\nofcharsws2616}{\vern49273}}{\*\userprops {\propname _NewReviewCycle}\proptype30{\staticval }}{\*\xmlnstbl {\xmlns1 http://schemas.mi
-crosoft.com/office/word/2003/wordml}{\xmlns2 urn:schemas-microsoft-com:office:smarttags}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect
-\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\hyphcaps0\horzdoc\dghspace120\dgvspace120
-\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\splytwnine\ftnlytwnine\htmautsp\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot10494075
-\newtblstyruls\nogrowautofit\utinl \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}
-{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}
-{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar
-\s1\ql \li0\ri0\sb180\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs31 \ltrch\fcs0
-\fs31\cf1\kerning36\insrsid10494075\charrsid14688892 Microsoft}{\rtlch\fcs1 \af1\afs31 \ltrch\fcs0 \fs31\cf1\kerning36\insrsid10494075 }{\rtlch\fcs1 \af1\afs31 \ltrch\fcs0 \fs31\cf1\kerning36\insrsid5601121 Public}{\rtlch\fcs1 \af1\afs31 \ltrch\fcs0
-\fs31\cf1\kerning36\insrsid14688892 }{\rtlch\fcs1 \af1\afs31 \ltrch\fcs0 \fs31\cf1\kerning36\insrsid10494075 License (Ms-PL}{\rtlch\fcs1 \af1\afs31 \ltrch\fcs0 \fs31\cf1\kerning36\insrsid4552277 )}{\rtlch\fcs1 \af1\afs31 \ltrch\fcs0
-\fs31\cf1\kerning36\insrsid10494075
-\par }\pard\plain \ltrpar\ql \li0\ri0\sl336\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af39\afs17 \ltrch\fcs0
-\b\f39\fs17\insrsid10494075
-\par This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
-\par }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid6910344
-\par }\pard\plain \ltrpar\s2\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af39\afs23 \ltrch\fcs0
-\b\f39\fs23\insrsid10494075 1. Definitions
-\par }\pard\plain \ltrpar\ql \li0\ri0\sl336\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid10494075 The terms \'93reproduce,\'94 \'93reproduction}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid7744081 ,}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 \'94 }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid551334 \'93derivative works,\'94}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid7744081\charrsid7744081 }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 and \'93distribution\'94 have the same meaning here as under
-{\*\xmlopen\xmlns2{\factoidname place}}{\*\xmlopen\xmlns2{\factoidname country-region}}U.S.{\*\xmlclose}{\*\xmlclose} copyright law.
-\par }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid12536400 A \'93contribution\'94 is the original software}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid4865270 ,}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid12536400 }{\rtlch\fcs1
-\af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid11932529 or}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid12536400 any additions or changes to the software.
-\par }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid551334 A \'93c}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid551334\charrsid551334 ontributor\'94 }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid12536400 is}{\rtlch\fcs1 \af39\afs17
-\ltrch\fcs0 \f39\fs17\insrsid12536400\charrsid551334 }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid551334\charrsid551334 any person that }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid12536400
-distributes its contribution under this license.}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075
-\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14229900 {\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid4729674\delrsid4729674 }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 \'93Licensed patents
-\'94 }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid12536400 are }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid3831520 a contributor\rquote s }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 patent claims }{\rtlch\fcs1
-\af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid3831520 that }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 read directly on }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid3831520 its contribution.}{\rtlch\fcs1 \af1 \ltrch\fcs0
-\insrsid14229900\charrsid14229900
-\par }\pard\plain \ltrpar\s2\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af39\afs23 \ltrch\fcs0
-\b\f39\fs23\insrsid5186068
-\par }{\rtlch\fcs1 \ab\af39\afs23 \ltrch\fcs0 \b\f39\fs23\insrsid10494075 2. Grant of Rights
-\par }\pard\plain \ltrpar\ql \li0\ri0\sl336\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid10494075 (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid3754103 each contributor }{\rtlch\fcs1 \af39\afs17
-\ltrch\fcs0 \f39\fs17\insrsid10494075 grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid3754103 its contribution}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid10494075 , prepare derivative works of }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid3754103 its contribution}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid12536400 ,}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid10494075 and distribute }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid3754103 its contribution}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 or any derivative works that you create.
-\par (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid9724918 each contributor }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid10494075 grants you a non-exclusive, worldwide, royalty-free license under }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid15814398 its }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075
-licensed patents to make, have made, use, sell, offer for sale, }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid1390003 import, }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 and/or otherwise dispose of }{\rtlch\fcs1 \af39\afs17
-\ltrch\fcs0 \f39\fs17\insrsid8944153 its contribution in }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 the software or derivative works of }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid8944153 the contribution in }{\rtlch\fcs1
-\af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 the software.
-\par }\pard\plain \ltrpar\s2\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af39\afs23 \ltrch\fcs0
-\b\f39\fs23\insrsid5186068
-\par }{\rtlch\fcs1 \ab\af39\afs23 \ltrch\fcs0 \b\f39\fs23\insrsid10494075 3. Conditions and Limitations
-\par }\pard\plain \ltrpar\ql \li0\ri0\sl336\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid1530955 }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 (A) No Trademark License- This license does not grant you rights to use }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid1708989 any contributors\rquote }{
-\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 name, logo, or trademarks.
-\par (B) If you }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid8934457 bring a patent claim against }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10095979 any contributor}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075
- over patents that you }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid6947552 claim }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid7682010 are }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid6947552 infringe}{\rtlch\fcs1
-\af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid7682010 d by}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 the software, your }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid7682010 patent }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid10494075 license}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid7682010 from such contributor}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 to the software ends automatically.
-\par (C) If you distribute }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid3165084 any portion of }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075
-the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
-\par (D) If you distribute }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid15749945 any portion of the }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 software in source code form}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid14904394 ,}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 you may do so only under this license}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid6384507 }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid14904394 by including }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 a complete copy of this license with your distribution}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid6384507 .}{\rtlch\fcs1 \af39\afs17
-\ltrch\fcs0 \f39\fs17\insrsid10494075 }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid6384507 I}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 f you distribute }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid15749945
-any portion of }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 the software in compiled or object code form}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid16452939 ,}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075
- you may only do so under a license that complies with this license.
-\par }\pard \ltrpar\ql \li0\ri0\sl336\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14572556 {\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 (E) The software is licensed \'93as-is.\'94 You bear the risk of using it. }{
-\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid284417 The contributors }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075
-give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid1783212 the contributors }{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0 \f39\fs17\insrsid10494075 exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.}{\rtlch\fcs1 \af39\afs17 \ltrch\fcs0
-\f39\fs17\insrsid10494075\charrsid14572556
-\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
-9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
-5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
-b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
-0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
-a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
-c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
-0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
-a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
-6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
-4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
-4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f
-7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87
-615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad
-79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b
-5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab
-999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9
-699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586
-8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6
-0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f
-9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be
-15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979
-3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d
-32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a
-f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86
-e877f0034e16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb
-44f95d843b5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a
-6409fb44d08741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c
-3d9058edf2c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db0256
-5e85f3b9660d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276
-b9f7dec44b7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8
-c33585b5fb9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e
-51440ca2e0088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95
-b21be5ceaf8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff
-6dce591a26ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec6
-9ffb9e65d028d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239
-b75a5bb1e6345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a449
-59d366ad93b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e8
-2db8df9f30254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468
-656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4
-350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d2624
-52282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe5141
-73d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c020000130000000000000000
-0000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000
-000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c0000000000000000000000000019
-0200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b00001600000000
-000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027
-00000000000000000000000000a00900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d0100009b0a00000000}
-{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
-617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
-6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
-656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
-{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;
-\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;
-\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdqformat1 \lsdpriority39 \lsdlocked0 toc 1;\lsdqformat1 \lsdpriority39 \lsdlocked0 toc 2;\lsdqformat1 \lsdpriority39 \lsdlocked0 toc 3;\lsdqformat1 \lsdpriority39 \lsdlocked0 toc 4;
-\lsdqformat1 \lsdpriority39 \lsdlocked0 toc 5;\lsdqformat1 \lsdpriority39 \lsdlocked0 toc 6;\lsdqformat1 \lsdpriority39 \lsdlocked0 toc 7;\lsdqformat1 \lsdpriority39 \lsdlocked0 toc 8;\lsdqformat1 \lsdpriority39 \lsdlocked0 toc 9;
-\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;
-\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;
-\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;
-\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;
-\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 0105000002000000180000004d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000
-d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
-ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000808a
-33fc965bcc01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
-000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
-0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file
diff --git a/thirdparty/directxtex/ReadMe.txt b/thirdparty/directxtex/ReadMe.txt
index 0423b920..41649e87 100644
--- a/thirdparty/directxtex/ReadMe.txt
+++ b/thirdparty/directxtex/ReadMe.txt
@@ -3,7 +3,7 @@ DIRECTX TEXTURE LIBRARY (DirectXTex)
Copyright (c) Microsoft Corporation. All rights reserved.
-November 15, 2012
+July 29, 2015
This package contains DirectXTex, a shared source library for reading and writing DDS
files, and performing various texture content processing operations including
@@ -13,12 +13,11 @@ use of the Windows Image Component (WIC) APIs. It also includes a simple .TGA re
writer since this image file format is commonly used for texture content processing pipelines,
but is not currently supported by a built-in WIC codec.
-The source is written for Visual C++ 2010 using the Direct3D headers from either
-a current DirectX SDK or Windows SDK. It can also be compiled using Visual Studio 2012 and the
-Windows SDK 8.0 headers.
+The source is written for Visual Studio 2012, 2013, or 2015. It is recommended that
+you make use of the Windows 8.1 SDK and Windows 7 Service Pack 1 or later.
-It is recommended that you make use of Visual C++ 2010 Service Pack 1 or VS 2012, and
-Windows 7 Service Pack 1 or Windows 8.
+NOTE: DirectXTex is not supported on Windows phone 8.0 because WIC is not available on
+that platform. It is available on Windows phone starting in version 8.1.
DDSTextureLoader\
This contains a streamlined version of the DirectX SDK sample DDSWithoutD3DX11 texture
@@ -59,25 +58,25 @@ Texconv\
It supports the same arguments as the Texture Conversion Tool Extended (texconvex.exe) DirectX
SDK utility. See <http://msdn.microsoft.com/en-us/library/ee422506.aspx>. The primary differences
are the -10 and -11 arguments are not applicable; the filter names (POINT, LINEAR, CUBIC,
- FANT, POINT_DITHER, LINEAR_DITHER, CUBIC_DITHER, FANT_DITHER); and support for the .TGA file format.
+ FANT or BOX, TRIANGLE, *_DITHER, *_DITHER_DIFFUSION); and support for the .TGA file format.
This also includes support for JPEG XR/HD Photo bitmap formats (see
<http://blogs.msdn.com/b/chuckw/archive/2011/01/19/known-issue-texconvex.aspx>)
+
+Texassemble\
+ This DirectXTex sample is a command-line utility for creating cubemaps, volume maps, or
+ texture arrays from a set of individual input image files.
DDSView\
This DirectXTex sample is a simple Direct3D 11-based viewer for DDS files. For array textures
or volume maps, the "<" and ">" keyboard keys will show different images contained in the DDS.
The "1" through "0" keys can also be used to jump to a specific image index.
-XNAMath\
- This contains a copy of XNA Math version 2.05, which is an updated version of the library. This is
- required if building content with USE_XNAMATH (the default for the VS 2010 projects). The VS 2012
- projects use DirectXMath in the Windows SDK 8.0 instead.
- For details see
- <http://blogs.msdn.com/b/chuckw/archive/2012/06/22/xna-math-version-2-05-smoothing-the-transition-to-directxmath.aspx>
+All content and source code for this package are subject to the terms of the MIT License.
+<http://opensource.org/licenses/MIT>.
-All content and source code for this package except XNA Math are bound to the Microsoft Public License (Ms-PL)
-<http://www.microsoft.com/en-us/openness/licenses.aspx#MPL>. The XNA Math library is subject
-to the DirectX SDK (June 2010) End-User License Agreement.
+Documentation is available at <https://github.com/Microsoft/DirectXTex/wiki>.
+
+For the latest version of DirectXTex, bug reports, etc. please visit the project site.
http://go.microsoft.com/fwlink/?LinkId=248926
@@ -85,29 +84,17 @@ http://go.microsoft.com/fwlink/?LinkId=248926
------------------------------------
RELEASE NOTES
-* The DirectXTex library does not support block compression or decompression of mipmapped non-power-of-2 textures,
- although DDSTextureLoader will load these files correctly if the underlying device supports it.
-
-* The DirectXTex library only supports CLAMP filtering, and does not yet support MIRROR or WRAP filtering
- (WIC operations only support CLAMP filtering).
+* The alpha mode specification for DDS files was updated between the March 2013 and April 2013 releases. Any
+ DDS files created using the DDS_FLAGS_FORCE_DX10_EXT_MISC2 flag or the texconv -dx10 switch using the
+ March 2013 release should be refreshed.
-* The DirectXTex library only supports box and POINT filtering, and does not support LINEAR or CUBIC filtering,
- for 3D volume mipmap-generation.
-
-* Due to the underlying Windows BMP WIC codec, alpha channels are not supported for 16bpp or 32bpp BMP pixel format files. The Windows 8
+* Due to the underlying Windows BMP WIC codec, alpha channels are not supported for 16bpp or 32bpp BMP pixel format files. The Windows 8.x
version of the Windows BMP WIC codec does support 32bpp pixel formats with alpha when using the BITMAPV5HEADER file header. Note the updated
WIC is available on Windows 7 SP1 with KB 2670838 installed.
-* The WIC conversion cases currently ignore TEX_FILTER_SRGB_IN and TEX_FILTER_SRGB_OUT out.
-
-* For the DXGI 1.1 version of DirectXTex, 4:4:4:4 pixel format DDS files are always expanded to 8:8:8:8 upon load since DXGI 1.0
- and DXGI 1.1 versions of Direct3D do not support these resource formats. The DXGI 1.2 versions of DirectXTex and DDSTextureLoader
- make use of the DXGI_FORMAT_B4G4R4A4_UNORM format instead.
-
* While DXGI 1.0 and DXGI 1.1 include 5:6:5 (DXGI_FORMAT_B5G6R5_UNORM) and 5:5:5:1 (DXGI_FORMAT_B5G5R5A1_UNORM)
pixel format enumerations, the DirectX 10.x and 11.0 Runtimes do not support these formats for use with Direct3D. The DirectX 11.1 runtime,
- DXGI 1.2, and the WDDM 1.2 driver model fully support 16bpp formats (5:6:5, 5:5:5:1, and 4:4:4:4). The DXGI 1.2 version of WICTextureLoader
- will load 16bpp pixel images as 5:6:5 or 5:5:5:1 rather than expand them to 32bpp RGBA.
+ DXGI 1.2, and the WDDM 1.2 driver model fully support 16bpp formats (5:6:5, 5:5:5:1, and 4:4:4:4).
* WICTextureLoader cannot load .TGA files unless the system has a 3rd party WIC codec installed. You must use the DirectXTex
library for TGA file format support without relying on an add-on WIC codec.
@@ -119,6 +106,129 @@ RELEASE NOTES
------------------------------------
RELEASE HISTORY
+July 29, 2015
+ Fixed rounding problem with 32-bit RGBA/BGRA format conversions
+ texconv: use CPU parallel compression for BC1-BC5 (-singleproc disables)
+ Updated for VS 2015 and Windows 10 SDK RTM
+ Retired VS 2010 and Windows 8.0 Store projects
+
+June 18, 2015
+ New BC_FLAGS_USE_3SUBSETS option for BC7 compressors; now defaults to skipping 3 subset blocks
+ Fixed bug with MakeTypeless and A8_UNORM
+ Fixed file length validation problem in LoadDDSFromFile
+
+March 27, 2015
+ Added projects for Windows apps Technical Preview
+ Fixed bug with WIC-based mipmap generation for non-WIC supported formats
+ Fixed bug with WIC multiframe loader when resizing required
+ texconv: Added -nmap/-nmapamp for generating normal maps from height maps
+ texconv/texassemble: Updated to load multiframe WIC files (tiff, gif)
+ Minor code cleanup
+
+November 24, 2014
+ Updates for Visual Studio 2015 Technical Preview
+ Minor code cleanup
+
+September 22, 2014
+ Format conversion improvements and bug fixes (depth/stencil, alpha-only, float16, RGB -> 1 channel)
+ Fixed issue when BC decompressing non-standard compressed rowPitch images
+ Explicit calling-convention annotation for all 'public' functions
+ Code cleanup
+ Xbox One platform updates
+
+July 15, 2014
+ texconv command-line tool fixes
+ Fixed problem with 'wide' images with CPU Compress
+ Updates to Xbox One platform support
+
+April 3, 2014
+ Windows phone 8.1 platform support
+
+February 24, 2014
+ Direct3D 11 video and Xbox One extended format support
+ New APIs: IsPlanar, IsPalettized, IsDepthStencil, ConvertToSinglePlane
+ Added 'alphaWeight' parameter to GPU Compress [breaking change]
+ texconv '-aw' switch to control the alpha weighting for the BC7 GPU compressor
+ Fixed bug with ordered dithering in non-WIC conversion codepaths
+ Fixed SaveToDDS* functions when using arbitrary row pitch values
+
+January 24, 2014
+ Added sRGB flags for Compress (TEX_COMPRESS_SRGB*)
+ Added 'compress' flag parameter to GPU versions of Compress [breaking change]
+ Minor fix for potential rounding problem in GPU Compress
+ Code cleanup (removed DXGI_1_2_FORMATS control define; ScopedObject typedef removed)
+ Dropped VS 2010 support without the Windows 8.1 SDK (removed USE_XNAMATH control define)
+
+December 24, 2013
+ texconv updated with -fl and -pow2 command-line switches
+ Fixed bug in Resize when doing custom filtering which occurred when exactly doubling the image size
+ Added move operators to ScratchImage and Blob classes
+ Xbox One platform support
+
+October 21, 2013
+ Updated for Visual Studio 2013 and Windows 8.1 SDK RTM
+ PremultiplyAlpha updated with new 'flags' parameter and to use sRGB correct blending
+ Fixed colorspace conversion issue with DirectCompute compressor when compressing for BC7 SRGB
+
+August 13, 2013
+ DirectCompute 4.0 BC6H/BC7 compressor integration
+ texconv utility uses DirectCompute compression by default for BC6H/BC7, -nogpu disables use of DirectCompute
+
+August 1, 2013
+ Support for BC compression/decompression of non-power-of-2 mipmapped textures
+ Fixes for BC6H / BC7 codecs to better match published standard
+ Fix for BC4 / BC5 codecs when compressing RGB images
+ Minor fix for the BC1-3 codec
+ New optional flags for ComputeMSE to compare UNORM vs. SNORM images
+ New WIC loading flag added to control use of WIC metadata to return sRGB vs. non-sRGB formats
+ Code cleanup and /analyze fixes
+ Project file cleanup
+ Texconv utility uses parallel BC compression by default for BC6H/BC7, -singleproc disables multithreaded behavior
+
+July 1, 2013
+ VS 2013 Preview projects added
+ SaveToWIC functions updated with new optional setCustomProps parameter
+
+June 15, 2013
+ Custom filtering implementation for Resize & GenerateMipMaps(3D) - Point, Box, Linear, Cubic, and Triangle
+ TEX_FILTER_TRIANGLE finite low-pass triangle filter
+ TEX_FILTER_WRAP, TEX_FILTER_MIRROR texture semantics for custom filtering
+ TEX_FILTER_BOX alias for TEX_FILTER_FANT WIC
+ Ordered and error diffusion dithering for non-WIC conversion
+ sRGB gamma correct custom filtering and conversion
+ DDS_FLAGS_EXPAND_LUMINANCE - Reader conversion option for L8, L16, and A8L8 legacy DDS files
+ Added use of WIC metadata for sRGB pixel formats
+ Added BitsPerColor utility function
+ Fixed Convert threshold parameter usage
+ Non-power-of-2 volume map support, fixed bug with non-square volume maps
+ Texconv utility update with -xlum, -wrap, and -mirror options; reworked -if options for improved dithering
+ Texassemble utility for creating cubemaps, volume maps, and texture arrays
+ DDSTextureLoader and WICTextureLoader sync'd with DirectXTK versions
+
+April 16, 2013
+ Updated alpha-mode metadata details in .DDS files
+ Added new control flags for Convert
+ Added new optional flags for ComputeMSE
+ Fixed conversion handling for sRGB formats
+ Fixed internal routines for handling R10G10B10_XR_BIAS_A2_UNORM, R9G9B9E5_SHAREDEXP, and FORMAT_R1_UNORM
+ Fixed WIC I/O for GUID_WICPixelFormat32bppRGBE pixel format files (HD Photo)
+ Fixed non-square image handling in GenerateMipMaps3D
+ Fixed some error handling in the DDS load code
+
+March 22, 2013
+ Supports reading and writing alpha-mode (straight, premultiplied, etc.) metadata in .DDS files
+ Added build option to use WICCreateImagingFactory_Proxy instead of CoCreateInstance to obtain WIC factory
+
+January 29, 2013
+ Added PremultiplyAlpha to DirectXTex; -pmalpha switch for texconv command-line tool
+ Fixed problem with forceSRGB implementation for Ex versions of CreateTexture, CreateShaderResourceView, DDSTextureLoader and WICTextureLoader
+
+December 11, 2012
+ Ex versions of CreateTexture, CreateShaderResourceView, DDSTextureLoader and WICTextureLoader
+ Fixed BC2 and BC3 decompression issue for unusual color encoding case
+ Converted annotation to SAL2 for improved VS 2012 /analyze experience
+ Updated DirectXTex, DDSView, and Texconv with VS 2010 + Windows 8.0 SDK project using official 'property sheets'
+
November 15, 2012
Added support for WIC2 when available on Windows 8 and Windows 7 with KB 2670838
Added optional targetGUID parameter to SaveWIC* APIs to influence final container pixel format choice
diff --git a/thirdparty/directxtex/mingw/tweaks.h b/thirdparty/directxtex/mingw/tweaks.h
index 8dac7c52..a8d0d536 100644
--- a/thirdparty/directxtex/mingw/tweaks.h
+++ b/thirdparty/directxtex/mingw/tweaks.h
@@ -37,16 +37,6 @@
#include <malloc.h>
-/*
- * Several of the defines in compat.h clash with libstdc++ internal variables,
- * so include the headers now, before they are re-defined.
- */
-#include <algorithm>
-#include <iostream>
-#include <memory>
-#include <vector>
-
-
#include <string.h>
#define memcpy_s(dest, numberOfElements, src, count) memcpy(dest, src, count)
diff --git a/thirdparty/dxerr/CMakeLists.txt b/thirdparty/dxerr/CMakeLists.txt
new file mode 100644
index 00000000..5f7c05db
--- /dev/null
+++ b/thirdparty/dxerr/CMakeLists.txt
@@ -0,0 +1,29 @@
+if (MINGW)
+ include_directories (BEFORE
+ ${CMAKE_SOURCE_DIR}/dispatch # for compat.h
+ )
+endif ()
+
+macro (HaveDirectXInclude NAME)
+ if (DirectX_${NAME}_INCLUDE_FOUND)
+ include_directories (BEFORE SYSTEM
+ ${DirectX_${NAME}_INCLUDE_DIR}
+ )
+ add_definitions (-DHAVE_${NAME})
+ endif ()
+endmacro ()
+
+havedirectxinclude (DDRAW)
+havedirectxinclude (D3D9)
+havedirectxinclude (D3D10_1)
+havedirectxinclude (D3D11_1)
+
+add_library (dxerr STATIC
+ dxerr.cpp
+)
+
+install (
+ FILES license.txt
+ DESTINATION ${DOC_INSTALL_DIR}
+ RENAME LICENSE-dxerr.txt
+)
diff --git a/thirdparty/dxerr/dxerr.cpp b/thirdparty/dxerr/dxerr.cpp
new file mode 100644
index 00000000..0be20337
--- /dev/null
+++ b/thirdparty/dxerr/dxerr.cpp
@@ -0,0 +1,3984 @@
+//--------------------------------------------------------------------------------------
+// File: DXErr.cpp
+//
+// DirectX Error Library
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+
+// This version only supports ASCII.
+
+#include "dxerr.h"
+
+#include <stdio.h>
+#include <algorithm>
+
+#ifdef __MINGW32__
+#include "compat.h"
+#endif
+
+#ifdef HAVE_DDRAW
+#include <ddraw.h>
+#endif
+
+#ifdef HAVE_D3D9
+#include <d3d9.h>
+#endif
+
+#ifdef HAVE_DSOUND
+#include <dsound.h>
+#endif
+
+#ifdef HAVE_DINPUT
+#include <dinput.h>
+#include <dinputd.h>
+#endif
+
+#ifdef HAVE_D3D10_1
+#include <d3d10_1.h>
+#endif
+
+#ifdef HAVE_D3D11_1
+#include <d3d11_1.h>
+#endif
+
+#ifdef HAVE_D2D
+#include <wincodec.h>
+#include <d2derr.h>
+#include <dwrite.h>
+#endif
+
+#ifdef __MINGW32__
+#include "d3derr.hpp"
+#endif
+
+#define XAUDIO2_E_INVALID_CALL 0x88960001
+#define XAUDIO2_E_XMA_DECODER_ERROR 0x88960002
+#define XAUDIO2_E_XAPO_CREATION_FAILED 0x88960003
+#define XAUDIO2_E_DEVICE_INVALIDATED 0x88960004
+
+#define XAPO_E_FORMAT_UNSUPPORTED MAKE_HRESULT(SEVERITY_ERROR, 0x897, 0x01)
+
+#define DXUTERR_NODIRECT3D MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0901)
+#define DXUTERR_NOCOMPATIBLEDEVICES MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0902)
+#define DXUTERR_MEDIANOTFOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0903)
+#define DXUTERR_NONZEROREFCOUNT MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0904)
+#define DXUTERR_CREATINGDEVICE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0905)
+#define DXUTERR_RESETTINGDEVICE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0906)
+#define DXUTERR_CREATINGDEVICEOBJECTS MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0907)
+#define DXUTERR_RESETTINGDEVICEOBJECTS MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0908)
+#define DXUTERR_INCORRECTVERSION MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0909)
+#define DXUTERR_DEVICEREMOVED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x090A)
+
+//-----------------------------------------------------------------------------
+#define BUFFER_SIZE 3000
+
+#ifdef _MSC_VER
+#pragma warning( disable : 6001 6221 )
+#endif
+
+#if defined(__MINGW32__) && !defined(MINGW_HAS_SECURE_API)
+
+static inline errno_t
+strcpy_s(char *strDestination, size_t numberOfElements, const char *strSource)
+{
+ strncpy(strDestination, strSource, numberOfElements - 1);
+ if (numberOfElements > 0) {
+ strDestination[numberOfElements - 1] = '\0';
+ }
+ return 0;
+}
+
+#endif
+
+//--------------------------------------------------------------------------------------
+#define CHK_ERR(hrchk, strOut) \
+ case hrchk: \
+ return strOut;
+
+#define CHK_ERRA(hrchk) \
+ case hrchk: \
+ return #hrchk;
+
+#define HRESULT_FROM_WIN32b(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)))
+
+#define CHK_ERR_WIN32A(hrchk) \
+ case HRESULT_FROM_WIN32b(hrchk): \
+ case hrchk: \
+ return #hrchk;
+
+#define CHK_ERR_WIN32_ONLY(hrchk, strOut) \
+ case HRESULT_FROM_WIN32b(hrchk): \
+ return strOut;
+
+//-----------------------------------------------------
+const char* WINAPI DXGetErrorStringA( HRESULT hr )
+{
+ switch(hr)
+ {
+// Commmented out codes are actually alises for other codes
+
+// -------------------------------------------------------------
+// Common Win32 error codes
+// -------------------------------------------------------------
+ CHK_ERRA(S_OK)
+ CHK_ERRA(S_FALSE)
+
+ CHK_ERRA(E_UNEXPECTED)
+ CHK_ERRA(E_NOTIMPL)
+ CHK_ERRA(E_OUTOFMEMORY)
+ CHK_ERRA(E_INVALIDARG)
+ CHK_ERRA(E_NOINTERFACE)
+ CHK_ERRA(E_POINTER)
+ CHK_ERRA(E_HANDLE)
+ CHK_ERRA(E_ABORT)
+ CHK_ERRA(E_FAIL)
+ CHK_ERRA(E_ACCESSDENIED)
+ CHK_ERRA(E_PENDING)
+ CHK_ERRA(CO_E_INIT_TLS)
+ CHK_ERRA(CO_E_INIT_SHARED_ALLOCATOR)
+ CHK_ERRA(CO_E_INIT_MEMORY_ALLOCATOR)
+ CHK_ERRA(CO_E_INIT_CLASS_CACHE)
+ CHK_ERRA(CO_E_INIT_RPC_CHANNEL)
+ CHK_ERRA(CO_E_INIT_TLS_SET_CHANNEL_CONTROL)
+ CHK_ERRA(CO_E_INIT_TLS_CHANNEL_CONTROL)
+ CHK_ERRA(CO_E_INIT_UNACCEPTED_USER_ALLOCATOR)
+ CHK_ERRA(CO_E_INIT_SCM_MUTEX_EXISTS)
+ CHK_ERRA(CO_E_INIT_SCM_FILE_MAPPING_EXISTS)
+ CHK_ERRA(CO_E_INIT_SCM_MAP_VIEW_OF_FILE)
+ CHK_ERRA(CO_E_INIT_SCM_EXEC_FAILURE)
+ CHK_ERRA(CO_E_INIT_ONLY_SINGLE_THREADED)
+ CHK_ERRA(CO_E_CANT_REMOTE)
+ CHK_ERRA(CO_E_BAD_SERVER_NAME)
+ CHK_ERRA(CO_E_WRONG_SERVER_IDENTITY)
+ CHK_ERRA(CO_E_OLE1DDE_DISABLED)
+ CHK_ERRA(CO_E_RUNAS_SYNTAX)
+ CHK_ERRA(CO_E_CREATEPROCESS_FAILURE)
+ CHK_ERRA(CO_E_RUNAS_CREATEPROCESS_FAILURE)
+ CHK_ERRA(CO_E_RUNAS_LOGON_FAILURE)
+ CHK_ERRA(CO_E_LAUNCH_PERMSSION_DENIED)
+ CHK_ERRA(CO_E_START_SERVICE_FAILURE)
+ CHK_ERRA(CO_E_REMOTE_COMMUNICATION_FAILURE)
+ CHK_ERRA(CO_E_SERVER_START_TIMEOUT)
+ CHK_ERRA(CO_E_CLSREG_INCONSISTENT)
+ CHK_ERRA(CO_E_IIDREG_INCONSISTENT)
+ CHK_ERRA(CO_E_NOT_SUPPORTED)
+ CHK_ERRA(CO_E_RELOAD_DLL)
+ CHK_ERRA(CO_E_MSI_ERROR)
+ CHK_ERRA(OLE_E_FIRST)
+ CHK_ERRA(OLE_E_LAST)
+ CHK_ERRA(OLE_S_FIRST)
+ CHK_ERRA(OLE_S_LAST)
+// CHK_ERRA(OLE_E_OLEVERB)
+ CHK_ERRA(OLE_E_ADVF)
+ CHK_ERRA(OLE_E_ENUM_NOMORE)
+ CHK_ERRA(OLE_E_ADVISENOTSUPPORTED)
+ CHK_ERRA(OLE_E_NOCONNECTION)
+ CHK_ERRA(OLE_E_NOTRUNNING)
+ CHK_ERRA(OLE_E_NOCACHE)
+ CHK_ERRA(OLE_E_BLANK)
+ CHK_ERRA(OLE_E_CLASSDIFF)
+ CHK_ERRA(OLE_E_CANT_GETMONIKER)
+ CHK_ERRA(OLE_E_CANT_BINDTOSOURCE)
+ CHK_ERRA(OLE_E_STATIC)
+ CHK_ERRA(OLE_E_PROMPTSAVECANCELLED)
+ CHK_ERRA(OLE_E_INVALIDRECT)
+ CHK_ERRA(OLE_E_WRONGCOMPOBJ)
+ CHK_ERRA(OLE_E_INVALIDHWND)
+ CHK_ERRA(OLE_E_NOT_INPLACEACTIVE)
+ CHK_ERRA(OLE_E_CANTCONVERT)
+ CHK_ERRA(OLE_E_NOSTORAGE)
+ CHK_ERRA(DV_E_FORMATETC)
+ CHK_ERRA(DV_E_DVTARGETDEVICE)
+ CHK_ERRA(DV_E_STGMEDIUM)
+ CHK_ERRA(DV_E_STATDATA)
+ CHK_ERRA(DV_E_LINDEX)
+ CHK_ERRA(DV_E_TYMED)
+ CHK_ERRA(DV_E_CLIPFORMAT)
+ CHK_ERRA(DV_E_DVASPECT)
+ CHK_ERRA(DV_E_DVTARGETDEVICE_SIZE)
+ CHK_ERRA(DV_E_NOIVIEWOBJECT)
+ CHK_ERRA(DRAGDROP_E_FIRST)
+ CHK_ERRA(DRAGDROP_E_LAST)
+ CHK_ERRA(DRAGDROP_S_FIRST)
+ CHK_ERRA(DRAGDROP_S_LAST)
+// CHK_ERRA(DRAGDROP_E_NOTREGISTERED)
+ CHK_ERRA(DRAGDROP_E_ALREADYREGISTERED)
+ CHK_ERRA(DRAGDROP_E_INVALIDHWND)
+ CHK_ERRA(CLASSFACTORY_E_FIRST)
+ CHK_ERRA(CLASSFACTORY_E_LAST)
+ CHK_ERRA(CLASSFACTORY_S_FIRST)
+ CHK_ERRA(CLASSFACTORY_S_LAST)
+// CHK_ERRA(CLASS_E_NOAGGREGATION)
+ CHK_ERRA(CLASS_E_CLASSNOTAVAILABLE)
+ CHK_ERRA(CLASS_E_NOTLICENSED)
+ CHK_ERRA(MARSHAL_E_FIRST)
+ CHK_ERRA(MARSHAL_E_LAST)
+ CHK_ERRA(MARSHAL_S_FIRST)
+ CHK_ERRA(MARSHAL_S_LAST)
+ CHK_ERRA(DATA_E_FIRST)
+ CHK_ERRA(DATA_E_LAST)
+ CHK_ERRA(DATA_S_FIRST)
+ CHK_ERRA(DATA_S_LAST)
+ CHK_ERRA(VIEW_E_FIRST)
+ CHK_ERRA(VIEW_E_LAST)
+ CHK_ERRA(VIEW_S_FIRST)
+ CHK_ERRA(VIEW_S_LAST)
+// CHK_ERRA(VIEW_E_DRAW)
+ CHK_ERRA(REGDB_E_FIRST)
+ CHK_ERRA(REGDB_E_LAST)
+ CHK_ERRA(REGDB_S_FIRST)
+ CHK_ERRA(REGDB_S_LAST)
+// CHK_ERRA(REGDB_E_READREGDB)
+ CHK_ERRA(REGDB_E_WRITEREGDB)
+ CHK_ERRA(REGDB_E_KEYMISSING)
+ CHK_ERRA(REGDB_E_INVALIDVALUE)
+ CHK_ERRA(REGDB_E_CLASSNOTREG)
+ CHK_ERRA(REGDB_E_IIDNOTREG)
+ CHK_ERRA(CAT_E_FIRST)
+ CHK_ERRA(CAT_E_LAST)
+// CHK_ERRA(CAT_E_CATIDNOEXIST)
+// CHK_ERRA(CAT_E_NODESCRIPTION)
+ CHK_ERRA(CS_E_FIRST)
+ CHK_ERRA(CS_E_LAST)
+// CHK_ERRA(CS_E_PACKAGE_NOTFOUND)
+ CHK_ERRA(CS_E_NOT_DELETABLE)
+ CHK_ERRA(CS_E_CLASS_NOTFOUND)
+ CHK_ERRA(CS_E_INVALID_VERSION)
+ CHK_ERRA(CS_E_NO_CLASSSTORE)
+ CHK_ERRA(CS_E_OBJECT_NOTFOUND)
+ CHK_ERRA(CS_E_OBJECT_ALREADY_EXISTS)
+ CHK_ERRA(CS_E_INVALID_PATH)
+ CHK_ERRA(CS_E_NETWORK_ERROR)
+ CHK_ERRA(CS_E_ADMIN_LIMIT_EXCEEDED)
+ CHK_ERRA(CS_E_SCHEMA_MISMATCH)
+// CHK_ERRA(CS_E_INTERNAL_ERROR)
+ CHK_ERRA(CACHE_E_FIRST)
+ CHK_ERRA(CACHE_E_LAST)
+ CHK_ERRA(CACHE_S_FIRST)
+ CHK_ERRA(CACHE_S_LAST)
+// CHK_ERRA(CACHE_E_NOCACHE_UPDATED)
+ CHK_ERRA(OLEOBJ_E_FIRST)
+ CHK_ERRA(OLEOBJ_E_LAST)
+ CHK_ERRA(OLEOBJ_S_FIRST)
+ CHK_ERRA(OLEOBJ_S_LAST)
+// CHK_ERRA(OLEOBJ_E_NOVERBS)
+ CHK_ERRA(OLEOBJ_E_INVALIDVERB)
+ CHK_ERRA(CLIENTSITE_E_FIRST)
+ CHK_ERRA(CLIENTSITE_E_LAST)
+ CHK_ERRA(CLIENTSITE_S_FIRST)
+ CHK_ERRA(CLIENTSITE_S_LAST)
+ CHK_ERRA(INPLACE_E_NOTUNDOABLE)
+ CHK_ERRA(INPLACE_E_NOTOOLSPACE)
+// CHK_ERRA(INPLACE_E_FIRST)
+ CHK_ERRA(INPLACE_E_LAST)
+ CHK_ERRA(INPLACE_S_FIRST)
+ CHK_ERRA(INPLACE_S_LAST)
+ CHK_ERRA(ENUM_E_FIRST)
+ CHK_ERRA(ENUM_E_LAST)
+ CHK_ERRA(ENUM_S_FIRST)
+ CHK_ERRA(ENUM_S_LAST)
+ CHK_ERRA(CONVERT10_E_FIRST)
+ CHK_ERRA(CONVERT10_E_LAST)
+ CHK_ERRA(CONVERT10_S_FIRST)
+ CHK_ERRA(CONVERT10_S_LAST)
+// CHK_ERRA(CONVERT10_E_OLESTREAM_GET)
+ CHK_ERRA(CONVERT10_E_OLESTREAM_PUT)
+ CHK_ERRA(CONVERT10_E_OLESTREAM_FMT)
+ CHK_ERRA(CONVERT10_E_OLESTREAM_BITMAP_TO_DIB)
+ CHK_ERRA(CONVERT10_E_STG_FMT)
+ CHK_ERRA(CONVERT10_E_STG_NO_STD_STREAM)
+ CHK_ERRA(CONVERT10_E_STG_DIB_TO_BITMAP)
+ CHK_ERRA(CLIPBRD_E_FIRST)
+ CHK_ERRA(CLIPBRD_E_LAST)
+ CHK_ERRA(CLIPBRD_S_FIRST)
+ CHK_ERRA(CLIPBRD_S_LAST)
+// CHK_ERRA(CLIPBRD_E_CANT_OPEN)
+ CHK_ERRA(CLIPBRD_E_CANT_EMPTY)
+ CHK_ERRA(CLIPBRD_E_CANT_SET)
+ CHK_ERRA(CLIPBRD_E_BAD_DATA)
+ CHK_ERRA(CLIPBRD_E_CANT_CLOSE)
+ CHK_ERRA(MK_E_FIRST)
+ CHK_ERRA(MK_E_LAST)
+ CHK_ERRA(MK_S_FIRST)
+ CHK_ERRA(MK_S_LAST)
+// CHK_ERRA(MK_E_CONNECTMANUALLY)
+ CHK_ERRA(MK_E_EXCEEDEDDEADLINE)
+ CHK_ERRA(MK_E_NEEDGENERIC)
+ CHK_ERRA(MK_E_UNAVAILABLE)
+ CHK_ERRA(MK_E_SYNTAX)
+ CHK_ERRA(MK_E_NOOBJECT)
+ CHK_ERRA(MK_E_INVALIDEXTENSION)
+ CHK_ERRA(MK_E_INTERMEDIATEINTERFACENOTSUPPORTED)
+ CHK_ERRA(MK_E_NOTBINDABLE)
+ CHK_ERRA(MK_E_NOTBOUND)
+ CHK_ERRA(MK_E_CANTOPENFILE)
+ CHK_ERRA(MK_E_MUSTBOTHERUSER)
+ CHK_ERRA(MK_E_NOINVERSE)
+ CHK_ERRA(MK_E_NOSTORAGE)
+ CHK_ERRA(MK_E_NOPREFIX)
+// CHK_ERRA(MK_E_ENUMERATION_FAILED)
+ CHK_ERRA(CO_E_NOTINITIALIZED)
+ CHK_ERRA(CO_E_ALREADYINITIALIZED)
+ CHK_ERRA(CO_E_CANTDETERMINECLASS)
+ CHK_ERRA(CO_E_CLASSSTRING)
+ CHK_ERRA(CO_E_IIDSTRING)
+ CHK_ERRA(CO_E_APPNOTFOUND)
+ CHK_ERRA(CO_E_APPSINGLEUSE)
+ CHK_ERRA(CO_E_ERRORINAPP)
+ CHK_ERRA(CO_E_DLLNOTFOUND)
+ CHK_ERRA(CO_E_ERRORINDLL)
+ CHK_ERRA(CO_E_WRONGOSFORAPP)
+ CHK_ERRA(CO_E_OBJNOTREG)
+ CHK_ERRA(CO_E_OBJISREG)
+ CHK_ERRA(CO_E_OBJNOTCONNECTED)
+ CHK_ERRA(CO_E_APPDIDNTREG)
+ CHK_ERRA(CO_E_RELEASED)
+// CHK_ERRA(OLE_S_USEREG)
+ CHK_ERRA(OLE_S_STATIC)
+ CHK_ERRA(OLE_S_MAC_CLIPFORMAT)
+// CHK_ERRA(DRAGDROP_S_DROP)
+ CHK_ERRA(DRAGDROP_S_CANCEL)
+ CHK_ERRA(DRAGDROP_S_USEDEFAULTCURSORS)
+// CHK_ERRA(DATA_S_SAMEFORMATETC)
+// CHK_ERRA(VIEW_S_ALREADY_FROZEN)
+// CHK_ERRA(CACHE_S_FORMATETC_NOTSUPPORTED)
+ CHK_ERRA(CACHE_S_SAMECACHE)
+ CHK_ERRA(CACHE_S_SOMECACHES_NOTUPDATED)
+// CHK_ERRA(OLEOBJ_S_INVALIDVERB)
+ CHK_ERRA(OLEOBJ_S_CANNOT_DOVERB_NOW)
+ CHK_ERRA(OLEOBJ_S_INVALIDHWND)
+// CHK_ERRA(INPLACE_S_TRUNCATED)
+// CHK_ERRA(CONVERT10_S_NO_PRESENTATION)
+ CHK_ERRA(MK_S_REDUCED_TO_SELF)
+ CHK_ERRA(MK_S_ME)
+ CHK_ERRA(MK_S_HIM)
+ CHK_ERRA(MK_S_US)
+ CHK_ERRA(MK_S_MONIKERALREADYREGISTERED)
+ CHK_ERRA(CO_E_CLASS_CREATE_FAILED)
+ CHK_ERRA(CO_E_SCM_ERROR)
+ CHK_ERRA(CO_E_SCM_RPC_FAILURE)
+ CHK_ERRA(CO_E_BAD_PATH)
+ CHK_ERRA(CO_E_SERVER_EXEC_FAILURE)
+ CHK_ERRA(CO_E_OBJSRV_RPC_FAILURE)
+ CHK_ERRA(MK_E_NO_NORMALIZED)
+ CHK_ERRA(CO_E_SERVER_STOPPING)
+ CHK_ERRA(MEM_E_INVALID_ROOT)
+ CHK_ERRA(MEM_E_INVALID_LINK)
+ CHK_ERRA(MEM_E_INVALID_SIZE)
+ CHK_ERRA(CO_S_NOTALLINTERFACES)
+ CHK_ERRA(DISP_E_UNKNOWNINTERFACE)
+ CHK_ERRA(DISP_E_MEMBERNOTFOUND)
+ CHK_ERRA(DISP_E_PARAMNOTFOUND)
+ CHK_ERRA(DISP_E_TYPEMISMATCH)
+ CHK_ERRA(DISP_E_UNKNOWNNAME)
+ CHK_ERRA(DISP_E_NONAMEDARGS)
+ CHK_ERRA(DISP_E_BADVARTYPE)
+ CHK_ERRA(DISP_E_EXCEPTION)
+ CHK_ERRA(DISP_E_OVERFLOW)
+ CHK_ERRA(DISP_E_BADINDEX)
+ CHK_ERRA(DISP_E_UNKNOWNLCID)
+ CHK_ERRA(DISP_E_ARRAYISLOCKED)
+ CHK_ERRA(DISP_E_BADPARAMCOUNT)
+ CHK_ERRA(DISP_E_PARAMNOTOPTIONAL)
+ CHK_ERRA(DISP_E_BADCALLEE)
+ CHK_ERRA(DISP_E_NOTACOLLECTION)
+ CHK_ERRA(DISP_E_DIVBYZERO)
+ CHK_ERRA(DISP_E_BUFFERTOOSMALL)
+ CHK_ERRA(TYPE_E_BUFFERTOOSMALL)
+ CHK_ERRA(TYPE_E_FIELDNOTFOUND)
+ CHK_ERRA(TYPE_E_INVDATAREAD)
+ CHK_ERRA(TYPE_E_UNSUPFORMAT)
+ CHK_ERRA(TYPE_E_REGISTRYACCESS)
+ CHK_ERRA(TYPE_E_LIBNOTREGISTERED)
+ CHK_ERRA(TYPE_E_UNDEFINEDTYPE)
+ CHK_ERRA(TYPE_E_QUALIFIEDNAMEDISALLOWED)
+ CHK_ERRA(TYPE_E_INVALIDSTATE)
+ CHK_ERRA(TYPE_E_WRONGTYPEKIND)
+ CHK_ERRA(TYPE_E_ELEMENTNOTFOUND)
+ CHK_ERRA(TYPE_E_AMBIGUOUSNAME)
+ CHK_ERRA(TYPE_E_NAMECONFLICT)
+ CHK_ERRA(TYPE_E_UNKNOWNLCID)
+ CHK_ERRA(TYPE_E_DLLFUNCTIONNOTFOUND)
+ CHK_ERRA(TYPE_E_BADMODULEKIND)
+ CHK_ERRA(TYPE_E_SIZETOOBIG)
+ CHK_ERRA(TYPE_E_DUPLICATEID)
+ CHK_ERRA(TYPE_E_INVALIDID)
+ CHK_ERRA(TYPE_E_TYPEMISMATCH)
+ CHK_ERRA(TYPE_E_OUTOFBOUNDS)
+ CHK_ERRA(TYPE_E_IOERROR)
+ CHK_ERRA(TYPE_E_CANTCREATETMPFILE)
+ CHK_ERRA(TYPE_E_CANTLOADLIBRARY)
+ CHK_ERRA(TYPE_E_INCONSISTENTPROPFUNCS)
+ CHK_ERRA(TYPE_E_CIRCULARTYPE)
+ CHK_ERRA(STG_E_INVALIDFUNCTION)
+ CHK_ERRA(STG_E_FILENOTFOUND)
+ CHK_ERRA(STG_E_PATHNOTFOUND)
+ CHK_ERRA(STG_E_TOOMANYOPENFILES)
+ CHK_ERRA(STG_E_ACCESSDENIED)
+ CHK_ERRA(STG_E_INVALIDHANDLE)
+ CHK_ERRA(STG_E_INSUFFICIENTMEMORY)
+ CHK_ERRA(STG_E_INVALIDPOINTER)
+ CHK_ERRA(STG_E_NOMOREFILES)
+ CHK_ERRA(STG_E_DISKISWRITEPROTECTED)
+ CHK_ERRA(STG_E_SEEKERROR)
+ CHK_ERRA(STG_E_WRITEFAULT)
+ CHK_ERRA(STG_E_READFAULT)
+ CHK_ERRA(STG_E_SHAREVIOLATION)
+ CHK_ERRA(STG_E_LOCKVIOLATION)
+ CHK_ERRA(STG_E_FILEALREADYEXISTS)
+ CHK_ERRA(STG_E_INVALIDPARAMETER)
+ CHK_ERRA(STG_E_MEDIUMFULL)
+ CHK_ERRA(STG_E_PROPSETMISMATCHED)
+ CHK_ERRA(STG_E_ABNORMALAPIEXIT)
+ CHK_ERRA(STG_E_INVALIDHEADER)
+ CHK_ERRA(STG_E_INVALIDNAME)
+ CHK_ERRA(STG_E_UNKNOWN)
+ CHK_ERRA(STG_E_UNIMPLEMENTEDFUNCTION)
+ CHK_ERRA(STG_E_INVALIDFLAG)
+ CHK_ERRA(STG_E_INUSE)
+ CHK_ERRA(STG_E_NOTCURRENT)
+ CHK_ERRA(STG_E_REVERTED)
+ CHK_ERRA(STG_E_CANTSAVE)
+ CHK_ERRA(STG_E_OLDFORMAT)
+ CHK_ERRA(STG_E_OLDDLL)
+ CHK_ERRA(STG_E_SHAREREQUIRED)
+ CHK_ERRA(STG_E_NOTFILEBASEDSTORAGE)
+ CHK_ERRA(STG_E_EXTANTMARSHALLINGS)
+ CHK_ERRA(STG_E_DOCFILECORRUPT)
+ CHK_ERRA(STG_E_BADBASEADDRESS)
+ CHK_ERRA(STG_E_DOCFILETOOLARGE)
+ CHK_ERRA(STG_E_NOTSIMPLEFORMAT)
+ CHK_ERRA(STG_E_INCOMPLETE)
+ CHK_ERRA(STG_E_TERMINATED)
+ CHK_ERRA(STG_S_CONVERTED)
+ CHK_ERRA(STG_S_BLOCK)
+ CHK_ERRA(STG_S_RETRYNOW)
+ CHK_ERRA(STG_S_MONITORING)
+ CHK_ERRA(STG_S_MULTIPLEOPENS)
+ CHK_ERRA(STG_S_CONSOLIDATIONFAILED)
+ CHK_ERRA(STG_S_CANNOTCONSOLIDATE)
+ CHK_ERRA(RPC_E_CALL_REJECTED)
+ CHK_ERRA(RPC_E_CALL_CANCELED)
+ CHK_ERRA(RPC_E_CANTPOST_INSENDCALL)
+ CHK_ERRA(RPC_E_CANTCALLOUT_INASYNCCALL)
+ CHK_ERRA(RPC_E_CANTCALLOUT_INEXTERNALCALL)
+ CHK_ERRA(RPC_E_CONNECTION_TERMINATED)
+ CHK_ERRA(RPC_E_SERVER_DIED)
+ CHK_ERRA(RPC_E_CLIENT_DIED)
+ CHK_ERRA(RPC_E_INVALID_DATAPACKET)
+ CHK_ERRA(RPC_E_CANTTRANSMIT_CALL)
+ CHK_ERRA(RPC_E_CLIENT_CANTMARSHAL_DATA)
+ CHK_ERRA(RPC_E_CLIENT_CANTUNMARSHAL_DATA)
+ CHK_ERRA(RPC_E_SERVER_CANTMARSHAL_DATA)
+ CHK_ERRA(RPC_E_SERVER_CANTUNMARSHAL_DATA)
+ CHK_ERRA(RPC_E_INVALID_DATA)
+ CHK_ERRA(RPC_E_INVALID_PARAMETER)
+ CHK_ERRA(RPC_E_CANTCALLOUT_AGAIN)
+ CHK_ERRA(RPC_E_SERVER_DIED_DNE)
+ CHK_ERRA(RPC_E_SYS_CALL_FAILED)
+ CHK_ERRA(RPC_E_OUT_OF_RESOURCES)
+ CHK_ERRA(RPC_E_ATTEMPTED_MULTITHREAD)
+ CHK_ERRA(RPC_E_NOT_REGISTERED)
+ CHK_ERRA(RPC_E_FAULT)
+ CHK_ERRA(RPC_E_SERVERFAULT)
+ CHK_ERRA(RPC_E_CHANGED_MODE)
+ CHK_ERRA(RPC_E_INVALIDMETHOD)
+ CHK_ERRA(RPC_E_DISCONNECTED)
+ CHK_ERRA(RPC_E_RETRY)
+ CHK_ERRA(RPC_E_SERVERCALL_RETRYLATER)
+ CHK_ERRA(RPC_E_SERVERCALL_REJECTED)
+ CHK_ERRA(RPC_E_INVALID_CALLDATA)
+ CHK_ERRA(RPC_E_CANTCALLOUT_ININPUTSYNCCALL)
+ CHK_ERRA(RPC_E_WRONG_THREAD)
+ CHK_ERRA(RPC_E_THREAD_NOT_INIT)
+ CHK_ERRA(RPC_E_VERSION_MISMATCH)
+ CHK_ERRA(RPC_E_INVALID_HEADER)
+ CHK_ERRA(RPC_E_INVALID_EXTENSION)
+ CHK_ERRA(RPC_E_INVALID_IPID)
+ CHK_ERRA(RPC_E_INVALID_OBJECT)
+ CHK_ERRA(RPC_S_CALLPENDING)
+ CHK_ERRA(RPC_S_WAITONTIMER)
+ CHK_ERRA(RPC_E_CALL_COMPLETE)
+ CHK_ERRA(RPC_E_UNSECURE_CALL)
+ CHK_ERRA(RPC_E_TOO_LATE)
+ CHK_ERRA(RPC_E_NO_GOOD_SECURITY_PACKAGES)
+ CHK_ERRA(RPC_E_ACCESS_DENIED)
+ CHK_ERRA(RPC_E_REMOTE_DISABLED)
+ CHK_ERRA(RPC_E_INVALID_OBJREF)
+ CHK_ERRA(RPC_E_NO_CONTEXT)
+ CHK_ERRA(RPC_E_TIMEOUT)
+ CHK_ERRA(RPC_E_NO_SYNC)
+ CHK_ERRA(RPC_E_FULLSIC_REQUIRED)
+ CHK_ERRA(RPC_E_INVALID_STD_NAME)
+ CHK_ERRA(CO_E_FAILEDTOIMPERSONATE)
+ CHK_ERRA(CO_E_FAILEDTOGETSECCTX)
+ CHK_ERRA(CO_E_FAILEDTOOPENTHREADTOKEN)
+ CHK_ERRA(CO_E_FAILEDTOGETTOKENINFO)
+ CHK_ERRA(CO_E_TRUSTEEDOESNTMATCHCLIENT)
+ CHK_ERRA(CO_E_FAILEDTOQUERYCLIENTBLANKET)
+ CHK_ERRA(CO_E_FAILEDTOSETDACL)
+ CHK_ERRA(CO_E_ACCESSCHECKFAILED)
+ CHK_ERRA(CO_E_NETACCESSAPIFAILED)
+ CHK_ERRA(CO_E_WRONGTRUSTEENAMESYNTAX)
+ CHK_ERRA(CO_E_INVALIDSID)
+ CHK_ERRA(CO_E_CONVERSIONFAILED)
+ CHK_ERRA(CO_E_NOMATCHINGSIDFOUND)
+ CHK_ERRA(CO_E_LOOKUPACCSIDFAILED)
+ CHK_ERRA(CO_E_NOMATCHINGNAMEFOUND)
+ CHK_ERRA(CO_E_LOOKUPACCNAMEFAILED)
+ CHK_ERRA(CO_E_SETSERLHNDLFAILED)
+ CHK_ERRA(CO_E_FAILEDTOGETWINDIR)
+ CHK_ERRA(CO_E_PATHTOOLONG)
+ CHK_ERRA(CO_E_FAILEDTOGENUUID)
+ CHK_ERRA(CO_E_FAILEDTOCREATEFILE)
+ CHK_ERRA(CO_E_FAILEDTOCLOSEHANDLE)
+ CHK_ERRA(CO_E_EXCEEDSYSACLLIMIT)
+ CHK_ERRA(CO_E_ACESINWRONGORDER)
+ CHK_ERRA(CO_E_INCOMPATIBLESTREAMVERSION)
+ CHK_ERRA(CO_E_FAILEDTOOPENPROCESSTOKEN)
+ CHK_ERRA(CO_E_DECODEFAILED)
+ CHK_ERRA(CO_E_ACNOTINITIALIZED)
+ CHK_ERRA(RPC_E_UNEXPECTED)
+ CHK_ERRA(NTE_BAD_UID)
+ CHK_ERRA(NTE_BAD_HASH)
+ CHK_ERRA(NTE_BAD_KEY)
+ CHK_ERRA(NTE_BAD_LEN)
+ CHK_ERRA(NTE_BAD_DATA)
+ CHK_ERRA(NTE_BAD_SIGNATURE)
+ CHK_ERRA(NTE_BAD_VER)
+ CHK_ERRA(NTE_BAD_ALGID)
+ CHK_ERRA(NTE_BAD_FLAGS)
+ CHK_ERRA(NTE_BAD_TYPE)
+ CHK_ERRA(NTE_BAD_KEY_STATE)
+ CHK_ERRA(NTE_BAD_HASH_STATE)
+ CHK_ERRA(NTE_NO_KEY)
+ CHK_ERRA(NTE_NO_MEMORY)
+ CHK_ERRA(NTE_EXISTS)
+ CHK_ERRA(NTE_PERM)
+ CHK_ERRA(NTE_NOT_FOUND)
+ CHK_ERRA(NTE_DOUBLE_ENCRYPT)
+ CHK_ERRA(NTE_BAD_PROVIDER)
+ CHK_ERRA(NTE_BAD_PROV_TYPE)
+ CHK_ERRA(NTE_BAD_PUBLIC_KEY)
+ CHK_ERRA(NTE_BAD_KEYSET)
+ CHK_ERRA(NTE_PROV_TYPE_NOT_DEF)
+ CHK_ERRA(NTE_PROV_TYPE_ENTRY_BAD)
+ CHK_ERRA(NTE_KEYSET_NOT_DEF)
+ CHK_ERRA(NTE_KEYSET_ENTRY_BAD)
+ CHK_ERRA(NTE_PROV_TYPE_NO_MATCH)
+ CHK_ERRA(NTE_SIGNATURE_FILE_BAD)
+ CHK_ERRA(NTE_PROVIDER_DLL_FAIL)
+ CHK_ERRA(NTE_PROV_DLL_NOT_FOUND)
+ CHK_ERRA(NTE_BAD_KEYSET_PARAM)
+ CHK_ERRA(NTE_FAIL)
+ CHK_ERRA(NTE_SYS_ERR)
+ CHK_ERRA(NTE_SILENT_CONTEXT)
+ CHK_ERRA(NTE_TOKEN_KEYSET_STORAGE_FULL)
+ CHK_ERRA(CRYPT_E_MSG_ERROR)
+ CHK_ERRA(CRYPT_E_UNKNOWN_ALGO)
+ CHK_ERRA(CRYPT_E_OID_FORMAT)
+ CHK_ERRA(CRYPT_E_INVALID_MSG_TYPE)
+ CHK_ERRA(CRYPT_E_UNEXPECTED_ENCODING)
+ CHK_ERRA(CRYPT_E_AUTH_ATTR_MISSING)
+ CHK_ERRA(CRYPT_E_HASH_VALUE)
+ CHK_ERRA(CRYPT_E_INVALID_INDEX)
+ CHK_ERRA(CRYPT_E_ALREADY_DECRYPTED)
+ CHK_ERRA(CRYPT_E_NOT_DECRYPTED)
+ CHK_ERRA(CRYPT_E_RECIPIENT_NOT_FOUND)
+ CHK_ERRA(CRYPT_E_CONTROL_TYPE)
+ CHK_ERRA(CRYPT_E_ISSUER_SERIALNUMBER)
+ CHK_ERRA(CRYPT_E_SIGNER_NOT_FOUND)
+ CHK_ERRA(CRYPT_E_ATTRIBUTES_MISSING)
+ CHK_ERRA(CRYPT_E_STREAM_MSG_NOT_READY)
+ CHK_ERRA(CRYPT_E_STREAM_INSUFFICIENT_DATA)
+ CHK_ERRA(CRYPT_E_BAD_LEN)
+ CHK_ERRA(CRYPT_E_BAD_ENCODE)
+ CHK_ERRA(CRYPT_E_FILE_ERROR)
+ CHK_ERRA(CRYPT_E_NOT_FOUND)
+ CHK_ERRA(CRYPT_E_EXISTS)
+ CHK_ERRA(CRYPT_E_NO_PROVIDER)
+ CHK_ERRA(CRYPT_E_SELF_SIGNED)
+ CHK_ERRA(CRYPT_E_DELETED_PREV)
+ CHK_ERRA(CRYPT_E_NO_MATCH)
+ CHK_ERRA(CRYPT_E_UNEXPECTED_MSG_TYPE)
+ CHK_ERRA(CRYPT_E_NO_KEY_PROPERTY)
+ CHK_ERRA(CRYPT_E_NO_DECRYPT_CERT)
+ CHK_ERRA(CRYPT_E_BAD_MSG)
+ CHK_ERRA(CRYPT_E_NO_SIGNER)
+ CHK_ERRA(CRYPT_E_PENDING_CLOSE)
+ CHK_ERRA(CRYPT_E_REVOKED)
+ CHK_ERRA(CRYPT_E_NO_REVOCATION_DLL)
+ CHK_ERRA(CRYPT_E_NO_REVOCATION_CHECK)
+ CHK_ERRA(CRYPT_E_REVOCATION_OFFLINE)
+ CHK_ERRA(CRYPT_E_NOT_IN_REVOCATION_DATABASE)
+ CHK_ERRA(CRYPT_E_INVALID_NUMERIC_STRING)
+ CHK_ERRA(CRYPT_E_INVALID_PRINTABLE_STRING)
+ CHK_ERRA(CRYPT_E_INVALID_IA5_STRING)
+ CHK_ERRA(CRYPT_E_INVALID_X500_STRING)
+ CHK_ERRA(CRYPT_E_NOT_CHAR_STRING)
+ CHK_ERRA(CRYPT_E_FILERESIZED)
+ CHK_ERRA(CRYPT_E_SECURITY_SETTINGS)
+ CHK_ERRA(CRYPT_E_NO_VERIFY_USAGE_DLL)
+ CHK_ERRA(CRYPT_E_NO_VERIFY_USAGE_CHECK)
+ CHK_ERRA(CRYPT_E_VERIFY_USAGE_OFFLINE)
+ CHK_ERRA(CRYPT_E_NOT_IN_CTL)
+ CHK_ERRA(CRYPT_E_NO_TRUSTED_SIGNER)
+ CHK_ERRA(CRYPT_E_OSS_ERROR)
+ CHK_ERRA(OSS_MORE_BUF)
+ CHK_ERRA(OSS_NEGATIVE_UINTEGER)
+ CHK_ERRA(OSS_PDU_RANGE)
+ CHK_ERRA(OSS_MORE_INPUT)
+ CHK_ERRA(OSS_DATA_ERROR)
+ CHK_ERRA(OSS_BAD_ARG)
+ CHK_ERRA(OSS_BAD_VERSION)
+ CHK_ERRA(OSS_OUT_MEMORY)
+ CHK_ERRA(OSS_PDU_MISMATCH)
+ CHK_ERRA(OSS_LIMITED)
+ CHK_ERRA(OSS_BAD_PTR)
+ CHK_ERRA(OSS_BAD_TIME)
+ CHK_ERRA(OSS_INDEFINITE_NOT_SUPPORTED)
+ CHK_ERRA(OSS_MEM_ERROR)
+ CHK_ERRA(OSS_BAD_TABLE)
+ CHK_ERRA(OSS_TOO_LONG)
+ CHK_ERRA(OSS_CONSTRAINT_VIOLATED)
+ CHK_ERRA(OSS_FATAL_ERROR)
+ CHK_ERRA(OSS_ACCESS_SERIALIZATION_ERROR)
+ CHK_ERRA(OSS_NULL_TBL)
+ CHK_ERRA(OSS_NULL_FCN)
+ CHK_ERRA(OSS_BAD_ENCRULES)
+ CHK_ERRA(OSS_UNAVAIL_ENCRULES)
+ CHK_ERRA(OSS_CANT_OPEN_TRACE_WINDOW)
+ CHK_ERRA(OSS_UNIMPLEMENTED)
+ CHK_ERRA(OSS_OID_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_CANT_OPEN_TRACE_FILE)
+ CHK_ERRA(OSS_TRACE_FILE_ALREADY_OPEN)
+ CHK_ERRA(OSS_TABLE_MISMATCH)
+ CHK_ERRA(OSS_TYPE_NOT_SUPPORTED)
+ CHK_ERRA(OSS_REAL_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_REAL_CODE_NOT_LINKED)
+ CHK_ERRA(OSS_OUT_OF_RANGE)
+ CHK_ERRA(OSS_COPIER_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_CONSTRAINT_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_COMPARATOR_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_COMPARATOR_CODE_NOT_LINKED)
+ CHK_ERRA(OSS_MEM_MGR_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_PDV_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_PDV_CODE_NOT_LINKED)
+ CHK_ERRA(OSS_API_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_BERDER_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_PER_DLL_NOT_LINKED)
+ CHK_ERRA(OSS_OPEN_TYPE_ERROR)
+ CHK_ERRA(OSS_MUTEX_NOT_CREATED)
+ CHK_ERRA(OSS_CANT_CLOSE_TRACE_FILE)
+ CHK_ERRA(CERTSRV_E_BAD_REQUESTSUBJECT)
+ CHK_ERRA(CERTSRV_E_NO_REQUEST)
+ CHK_ERRA(CERTSRV_E_BAD_REQUESTSTATUS)
+ CHK_ERRA(CERTSRV_E_PROPERTY_EMPTY)
+ CHK_ERRA(CERTSRV_E_INVALID_CA_CERTIFICATE)
+ CHK_ERRA(CERTSRV_E_UNSUPPORTED_CERT_TYPE)
+ CHK_ERRA(CERTSRV_E_NO_CERT_TYPE)
+ CHK_ERRA(TRUST_E_SYSTEM_ERROR)
+ CHK_ERRA(TRUST_E_NO_SIGNER_CERT)
+ CHK_ERRA(TRUST_E_COUNTER_SIGNER)
+ CHK_ERRA(TRUST_E_CERT_SIGNATURE)
+ CHK_ERRA(TRUST_E_TIME_STAMP)
+ CHK_ERRA(TRUST_E_BAD_DIGEST)
+ CHK_ERRA(TRUST_E_BASIC_CONSTRAINTS)
+ CHK_ERRA(TRUST_E_FINANCIAL_CRITERIA)
+// CHK_ERRA(NTE_OP_OK)
+ CHK_ERRA(TRUST_E_PROVIDER_UNKNOWN)
+ CHK_ERRA(TRUST_E_ACTION_UNKNOWN)
+ CHK_ERRA(TRUST_E_SUBJECT_FORM_UNKNOWN)
+ CHK_ERRA(TRUST_E_SUBJECT_NOT_TRUSTED)
+ CHK_ERRA(DIGSIG_E_ENCODE)
+ CHK_ERRA(DIGSIG_E_DECODE)
+ CHK_ERRA(DIGSIG_E_EXTENSIBILITY)
+ CHK_ERRA(DIGSIG_E_CRYPTO)
+ CHK_ERRA(PERSIST_E_SIZEDEFINITE)
+ CHK_ERRA(PERSIST_E_SIZEINDEFINITE)
+ CHK_ERRA(PERSIST_E_NOTSELFSIZING)
+ CHK_ERRA(TRUST_E_NOSIGNATURE)
+ CHK_ERRA(CERT_E_EXPIRED)
+ CHK_ERRA(CERT_E_VALIDITYPERIODNESTING)
+ CHK_ERRA(CERT_E_ROLE)
+ CHK_ERRA(CERT_E_PATHLENCONST)
+ CHK_ERRA(CERT_E_CRITICAL)
+ CHK_ERRA(CERT_E_PURPOSE)
+ CHK_ERRA(CERT_E_ISSUERCHAINING)
+ CHK_ERRA(CERT_E_MALFORMED)
+ CHK_ERRA(CERT_E_UNTRUSTEDROOT)
+ CHK_ERRA(CERT_E_CHAINING)
+ CHK_ERRA(TRUST_E_FAIL)
+ CHK_ERRA(CERT_E_REVOKED)
+ CHK_ERRA(CERT_E_UNTRUSTEDTESTROOT)
+ CHK_ERRA(CERT_E_REVOCATION_FAILURE)
+ CHK_ERRA(CERT_E_CN_NO_MATCH)
+ CHK_ERRA(CERT_E_WRONG_USAGE)
+ CHK_ERRA(SPAPI_E_EXPECTED_SECTION_NAME)
+ CHK_ERRA(SPAPI_E_BAD_SECTION_NAME_LINE)
+ CHK_ERRA(SPAPI_E_SECTION_NAME_TOO_LONG)
+ CHK_ERRA(SPAPI_E_GENERAL_SYNTAX)
+ CHK_ERRA(SPAPI_E_WRONG_INF_STYLE)
+ CHK_ERRA(SPAPI_E_SECTION_NOT_FOUND)
+ CHK_ERRA(SPAPI_E_LINE_NOT_FOUND)
+ CHK_ERRA(SPAPI_E_NO_BACKUP)
+ CHK_ERRA(SPAPI_E_NO_ASSOCIATED_CLASS)
+ CHK_ERRA(SPAPI_E_CLASS_MISMATCH)
+ CHK_ERRA(SPAPI_E_DUPLICATE_FOUND)
+ CHK_ERRA(SPAPI_E_NO_DRIVER_SELECTED)
+ CHK_ERRA(SPAPI_E_KEY_DOES_NOT_EXIST)
+ CHK_ERRA(SPAPI_E_INVALID_DEVINST_NAME)
+ CHK_ERRA(SPAPI_E_INVALID_CLASS)
+ CHK_ERRA(SPAPI_E_DEVINST_ALREADY_EXISTS)
+ CHK_ERRA(SPAPI_E_DEVINFO_NOT_REGISTERED)
+ CHK_ERRA(SPAPI_E_INVALID_REG_PROPERTY)
+ CHK_ERRA(SPAPI_E_NO_INF)
+ CHK_ERRA(SPAPI_E_NO_SUCH_DEVINST)
+ CHK_ERRA(SPAPI_E_CANT_LOAD_CLASS_ICON)
+ CHK_ERRA(SPAPI_E_INVALID_CLASS_INSTALLER)
+ CHK_ERRA(SPAPI_E_DI_DO_DEFAULT)
+ CHK_ERRA(SPAPI_E_DI_NOFILECOPY)
+ CHK_ERRA(SPAPI_E_INVALID_HWPROFILE)
+ CHK_ERRA(SPAPI_E_NO_DEVICE_SELECTED)
+ CHK_ERRA(SPAPI_E_DEVINFO_LIST_LOCKED)
+ CHK_ERRA(SPAPI_E_DEVINFO_DATA_LOCKED)
+ CHK_ERRA(SPAPI_E_DI_BAD_PATH)
+ CHK_ERRA(SPAPI_E_NO_CLASSINSTALL_PARAMS)
+ CHK_ERRA(SPAPI_E_FILEQUEUE_LOCKED)
+ CHK_ERRA(SPAPI_E_BAD_SERVICE_INSTALLSECT)
+ CHK_ERRA(SPAPI_E_NO_CLASS_DRIVER_LIST)
+ CHK_ERRA(SPAPI_E_NO_ASSOCIATED_SERVICE)
+ CHK_ERRA(SPAPI_E_NO_DEFAULT_DEVICE_INTERFACE)
+ CHK_ERRA(SPAPI_E_DEVICE_INTERFACE_ACTIVE)
+ CHK_ERRA(SPAPI_E_DEVICE_INTERFACE_REMOVED)
+ CHK_ERRA(SPAPI_E_BAD_INTERFACE_INSTALLSECT)
+ CHK_ERRA(SPAPI_E_NO_SUCH_INTERFACE_CLASS)
+ CHK_ERRA(SPAPI_E_INVALID_REFERENCE_STRING)
+ CHK_ERRA(SPAPI_E_INVALID_MACHINENAME)
+ CHK_ERRA(SPAPI_E_REMOTE_COMM_FAILURE)
+ CHK_ERRA(SPAPI_E_MACHINE_UNAVAILABLE)
+ CHK_ERRA(SPAPI_E_NO_CONFIGMGR_SERVICES)
+ CHK_ERRA(SPAPI_E_INVALID_PROPPAGE_PROVIDER)
+ CHK_ERRA(SPAPI_E_NO_SUCH_DEVICE_INTERFACE)
+ CHK_ERRA(SPAPI_E_DI_POSTPROCESSING_REQUIRED)
+ CHK_ERRA(SPAPI_E_INVALID_COINSTALLER)
+ CHK_ERRA(SPAPI_E_NO_COMPAT_DRIVERS)
+ CHK_ERRA(SPAPI_E_NO_DEVICE_ICON)
+ CHK_ERRA(SPAPI_E_INVALID_INF_LOGCONFIG)
+ CHK_ERRA(SPAPI_E_DI_DONT_INSTALL)
+ CHK_ERRA(SPAPI_E_INVALID_FILTER_DRIVER)
+ CHK_ERRA(SPAPI_E_NON_WINDOWS_NT_DRIVER)
+ CHK_ERRA(SPAPI_E_NON_WINDOWS_DRIVER)
+ CHK_ERRA(SPAPI_E_NO_CATALOG_FOR_OEM_INF)
+ CHK_ERRA(SPAPI_E_DEVINSTALL_QUEUE_NONNATIVE)
+ CHK_ERRA(SPAPI_E_ERROR_NOT_INSTALLED)
+// CHK_ERRA(SCARD_S_SUCCESS)
+ CHK_ERRA(SCARD_F_INTERNAL_ERROR)
+ CHK_ERRA(SCARD_E_CANCELLED)
+ CHK_ERRA(SCARD_E_INVALID_HANDLE)
+ CHK_ERRA(SCARD_E_INVALID_PARAMETER)
+ CHK_ERRA(SCARD_E_INVALID_TARGET)
+ CHK_ERRA(SCARD_E_NO_MEMORY)
+ CHK_ERRA(SCARD_F_WAITED_TOO_LONG)
+ CHK_ERRA(SCARD_E_INSUFFICIENT_BUFFER)
+ CHK_ERRA(SCARD_E_UNKNOWN_READER)
+ CHK_ERRA(SCARD_E_TIMEOUT)
+ CHK_ERRA(SCARD_E_SHARING_VIOLATION)
+ CHK_ERRA(SCARD_E_NO_SMARTCARD)
+ CHK_ERRA(SCARD_E_UNKNOWN_CARD)
+ CHK_ERRA(SCARD_E_CANT_DISPOSE)
+ CHK_ERRA(SCARD_E_PROTO_MISMATCH)
+ CHK_ERRA(SCARD_E_NOT_READY)
+ CHK_ERRA(SCARD_E_INVALID_VALUE)
+ CHK_ERRA(SCARD_E_SYSTEM_CANCELLED)
+ CHK_ERRA(SCARD_F_COMM_ERROR)
+ CHK_ERRA(SCARD_F_UNKNOWN_ERROR)
+ CHK_ERRA(SCARD_E_INVALID_ATR)
+ CHK_ERRA(SCARD_E_NOT_TRANSACTED)
+ CHK_ERRA(SCARD_E_READER_UNAVAILABLE)
+ CHK_ERRA(SCARD_P_SHUTDOWN)
+ CHK_ERRA(SCARD_E_PCI_TOO_SMALL)
+ CHK_ERRA(SCARD_E_READER_UNSUPPORTED)
+ CHK_ERRA(SCARD_E_DUPLICATE_READER)
+ CHK_ERRA(SCARD_E_CARD_UNSUPPORTED)
+ CHK_ERRA(SCARD_E_NO_SERVICE)
+ CHK_ERRA(SCARD_E_SERVICE_STOPPED)
+ CHK_ERRA(SCARD_E_UNEXPECTED)
+ CHK_ERRA(SCARD_E_ICC_INSTALLATION)
+ CHK_ERRA(SCARD_E_ICC_CREATEORDER)
+ CHK_ERRA(SCARD_E_UNSUPPORTED_FEATURE)
+ CHK_ERRA(SCARD_E_DIR_NOT_FOUND)
+ CHK_ERRA(SCARD_E_FILE_NOT_FOUND)
+ CHK_ERRA(SCARD_E_NO_DIR)
+ CHK_ERRA(SCARD_E_NO_FILE)
+ CHK_ERRA(SCARD_E_NO_ACCESS)
+ CHK_ERRA(SCARD_E_WRITE_TOO_MANY)
+ CHK_ERRA(SCARD_E_BAD_SEEK)
+ CHK_ERRA(SCARD_E_INVALID_CHV)
+ CHK_ERRA(SCARD_E_UNKNOWN_RES_MNG)
+ CHK_ERRA(SCARD_E_NO_SUCH_CERTIFICATE)
+ CHK_ERRA(SCARD_E_CERTIFICATE_UNAVAILABLE)
+ CHK_ERRA(SCARD_E_NO_READERS_AVAILABLE)
+ CHK_ERRA(SCARD_E_COMM_DATA_LOST)
+ CHK_ERRA(SCARD_W_UNSUPPORTED_CARD)
+ CHK_ERRA(SCARD_W_UNRESPONSIVE_CARD)
+ CHK_ERRA(SCARD_W_UNPOWERED_CARD)
+ CHK_ERRA(SCARD_W_RESET_CARD)
+ CHK_ERRA(SCARD_W_REMOVED_CARD)
+ CHK_ERRA(SCARD_W_SECURITY_VIOLATION)
+ CHK_ERRA(SCARD_W_WRONG_CHV)
+ CHK_ERRA(SCARD_W_CHV_BLOCKED)
+ CHK_ERRA(SCARD_W_EOF)
+ CHK_ERRA(SCARD_W_CANCELLED_BY_USER)
+ CHK_ERR_WIN32_ONLY(ERROR_INVALID_FUNCTION, "ERROR_INVALID_FUNCTION")
+ CHK_ERR_WIN32A(ERROR_FILE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_PATH_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_OPEN_FILES)
+ CHK_ERRA(ERROR_ACCESS_DENIED)
+ CHK_ERRA(ERROR_INVALID_HANDLE)
+ CHK_ERR_WIN32A(ERROR_ARENA_TRASHED)
+ CHK_ERR_WIN32A(ERROR_NOT_ENOUGH_MEMORY)
+ CHK_ERR_WIN32A(ERROR_INVALID_BLOCK)
+ CHK_ERR_WIN32A(ERROR_BAD_ENVIRONMENT)
+ CHK_ERR_WIN32A(ERROR_BAD_FORMAT)
+ CHK_ERR_WIN32A(ERROR_INVALID_ACCESS)
+ CHK_ERR_WIN32A(ERROR_INVALID_DATA)
+ CHK_ERRA(ERROR_OUTOFMEMORY)
+ CHK_ERR_WIN32A(ERROR_INVALID_DRIVE)
+ CHK_ERR_WIN32A(ERROR_CURRENT_DIRECTORY)
+ CHK_ERR_WIN32A(ERROR_NOT_SAME_DEVICE)
+ CHK_ERR_WIN32A(ERROR_NO_MORE_FILES)
+ CHK_ERR_WIN32A(ERROR_WRITE_PROTECT)
+ CHK_ERR_WIN32A(ERROR_BAD_UNIT)
+ CHK_ERR_WIN32A(ERROR_NOT_READY)
+ CHK_ERR_WIN32A(ERROR_BAD_COMMAND)
+ CHK_ERR_WIN32A(ERROR_CRC)
+ CHK_ERR_WIN32A(ERROR_BAD_LENGTH)
+ CHK_ERR_WIN32A(ERROR_SEEK)
+ CHK_ERR_WIN32A(ERROR_NOT_DOS_DISK)
+ CHK_ERR_WIN32A(ERROR_SECTOR_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_OUT_OF_PAPER)
+ CHK_ERR_WIN32A(ERROR_WRITE_FAULT)
+ CHK_ERR_WIN32A(ERROR_READ_FAULT)
+ CHK_ERR_WIN32A(ERROR_GEN_FAILURE)
+ CHK_ERR_WIN32A(ERROR_SHARING_VIOLATION)
+ CHK_ERR_WIN32A(ERROR_LOCK_VIOLATION)
+ CHK_ERR_WIN32A(ERROR_WRONG_DISK)
+ CHK_ERR_WIN32A(ERROR_SHARING_BUFFER_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_HANDLE_EOF)
+ CHK_ERR_WIN32A(ERROR_HANDLE_DISK_FULL)
+ CHK_ERR_WIN32A(ERROR_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_REM_NOT_LIST)
+ CHK_ERR_WIN32A(ERROR_DUP_NAME)
+ CHK_ERR_WIN32A(ERROR_BAD_NETPATH)
+ CHK_ERR_WIN32A(ERROR_NETWORK_BUSY)
+ CHK_ERR_WIN32A(ERROR_DEV_NOT_EXIST)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_CMDS)
+ CHK_ERR_WIN32A(ERROR_ADAP_HDW_ERR)
+ CHK_ERR_WIN32A(ERROR_BAD_NET_RESP)
+ CHK_ERR_WIN32A(ERROR_UNEXP_NET_ERR)
+ CHK_ERR_WIN32A(ERROR_BAD_REM_ADAP)
+ CHK_ERR_WIN32A(ERROR_PRINTQ_FULL)
+ CHK_ERR_WIN32A(ERROR_NO_SPOOL_SPACE)
+ CHK_ERR_WIN32A(ERROR_PRINT_CANCELLED)
+ CHK_ERR_WIN32A(ERROR_NETNAME_DELETED)
+ CHK_ERR_WIN32A(ERROR_NETWORK_ACCESS_DENIED)
+ CHK_ERR_WIN32A(ERROR_BAD_DEV_TYPE)
+ CHK_ERR_WIN32A(ERROR_BAD_NET_NAME)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_NAMES)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_SESS)
+ CHK_ERR_WIN32A(ERROR_SHARING_PAUSED)
+ CHK_ERR_WIN32A(ERROR_REQ_NOT_ACCEP)
+ CHK_ERR_WIN32A(ERROR_REDIR_PAUSED)
+ CHK_ERR_WIN32A(ERROR_FILE_EXISTS)
+ CHK_ERR_WIN32A(ERROR_CANNOT_MAKE)
+ CHK_ERR_WIN32A(ERROR_FAIL_I24)
+ CHK_ERR_WIN32A(ERROR_OUT_OF_STRUCTURES)
+ CHK_ERR_WIN32A(ERROR_ALREADY_ASSIGNED)
+ CHK_ERR_WIN32A(ERROR_INVALID_PASSWORD)
+ CHK_ERRA(ERROR_INVALID_PARAMETER)
+ CHK_ERR_WIN32A(ERROR_NET_WRITE_FAULT)
+ CHK_ERR_WIN32A(ERROR_NO_PROC_SLOTS)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_SEMAPHORES)
+ CHK_ERR_WIN32A(ERROR_EXCL_SEM_ALREADY_OWNED)
+ CHK_ERR_WIN32A(ERROR_SEM_IS_SET)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_SEM_REQUESTS)
+ CHK_ERR_WIN32A(ERROR_INVALID_AT_INTERRUPT_TIME)
+ CHK_ERR_WIN32A(ERROR_SEM_OWNER_DIED)
+ CHK_ERR_WIN32A(ERROR_SEM_USER_LIMIT)
+ CHK_ERR_WIN32A(ERROR_DISK_CHANGE)
+ CHK_ERR_WIN32A(ERROR_DRIVE_LOCKED)
+ CHK_ERR_WIN32A(ERROR_BROKEN_PIPE)
+ CHK_ERR_WIN32A(ERROR_OPEN_FAILED)
+ CHK_ERR_WIN32A(ERROR_BUFFER_OVERFLOW)
+ CHK_ERR_WIN32A(ERROR_DISK_FULL)
+ CHK_ERR_WIN32A(ERROR_NO_MORE_SEARCH_HANDLES)
+ CHK_ERR_WIN32A(ERROR_INVALID_TARGET_HANDLE)
+ CHK_ERR_WIN32A(ERROR_INVALID_CATEGORY)
+ CHK_ERR_WIN32A(ERROR_INVALID_VERIFY_SWITCH)
+ CHK_ERR_WIN32A(ERROR_BAD_DRIVER_LEVEL)
+ CHK_ERR_WIN32A(ERROR_CALL_NOT_IMPLEMENTED)
+ CHK_ERR_WIN32A(ERROR_SEM_TIMEOUT)
+ CHK_ERR_WIN32A(ERROR_INSUFFICIENT_BUFFER)
+ CHK_ERR_WIN32A(ERROR_INVALID_NAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_LEVEL)
+ CHK_ERR_WIN32A(ERROR_NO_VOLUME_LABEL)
+ CHK_ERR_WIN32A(ERROR_MOD_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_PROC_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_WAIT_NO_CHILDREN)
+ CHK_ERR_WIN32A(ERROR_CHILD_NOT_COMPLETE)
+ CHK_ERR_WIN32A(ERROR_DIRECT_ACCESS_HANDLE)
+ CHK_ERR_WIN32A(ERROR_NEGATIVE_SEEK)
+ CHK_ERR_WIN32A(ERROR_SEEK_ON_DEVICE)
+ CHK_ERR_WIN32A(ERROR_IS_JOIN_TARGET)
+ CHK_ERR_WIN32A(ERROR_IS_JOINED)
+ CHK_ERR_WIN32A(ERROR_IS_SUBSTED)
+ CHK_ERR_WIN32A(ERROR_NOT_JOINED)
+ CHK_ERR_WIN32A(ERROR_NOT_SUBSTED)
+ CHK_ERR_WIN32A(ERROR_JOIN_TO_JOIN)
+ CHK_ERR_WIN32A(ERROR_SUBST_TO_SUBST)
+ CHK_ERR_WIN32A(ERROR_JOIN_TO_SUBST)
+ CHK_ERR_WIN32A(ERROR_SUBST_TO_JOIN)
+ CHK_ERR_WIN32A(ERROR_BUSY_DRIVE)
+ CHK_ERR_WIN32A(ERROR_SAME_DRIVE)
+ CHK_ERR_WIN32A(ERROR_DIR_NOT_ROOT)
+ CHK_ERR_WIN32A(ERROR_DIR_NOT_EMPTY)
+ CHK_ERR_WIN32A(ERROR_IS_SUBST_PATH)
+ CHK_ERR_WIN32A(ERROR_IS_JOIN_PATH)
+ CHK_ERR_WIN32A(ERROR_PATH_BUSY)
+ CHK_ERR_WIN32A(ERROR_IS_SUBST_TARGET)
+ CHK_ERR_WIN32A(ERROR_SYSTEM_TRACE)
+ CHK_ERR_WIN32A(ERROR_INVALID_EVENT_COUNT)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_MUXWAITERS)
+ CHK_ERR_WIN32A(ERROR_INVALID_LIST_FORMAT)
+ CHK_ERR_WIN32A(ERROR_LABEL_TOO_LONG)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_TCBS)
+ CHK_ERR_WIN32A(ERROR_SIGNAL_REFUSED)
+ CHK_ERR_WIN32A(ERROR_DISCARDED)
+ CHK_ERR_WIN32A(ERROR_NOT_LOCKED)
+ CHK_ERR_WIN32A(ERROR_BAD_THREADID_ADDR)
+ CHK_ERR_WIN32A(ERROR_BAD_ARGUMENTS)
+ CHK_ERR_WIN32A(ERROR_BAD_PATHNAME)
+ CHK_ERR_WIN32A(ERROR_SIGNAL_PENDING)
+ CHK_ERR_WIN32A(ERROR_MAX_THRDS_REACHED)
+ CHK_ERR_WIN32A(ERROR_LOCK_FAILED)
+ CHK_ERR_WIN32A(ERROR_BUSY)
+ CHK_ERR_WIN32A(ERROR_CANCEL_VIOLATION)
+ CHK_ERR_WIN32A(ERROR_ATOMIC_LOCKS_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_INVALID_SEGMENT_NUMBER)
+ CHK_ERR_WIN32A(ERROR_INVALID_ORDINAL)
+ CHK_ERR_WIN32A(ERROR_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_INVALID_FLAG_NUMBER)
+ CHK_ERR_WIN32A(ERROR_SEM_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_INVALID_STARTING_CODESEG)
+ CHK_ERR_WIN32A(ERROR_INVALID_STACKSEG)
+ CHK_ERR_WIN32A(ERROR_INVALID_MODULETYPE)
+ CHK_ERR_WIN32A(ERROR_INVALID_EXE_SIGNATURE)
+ CHK_ERR_WIN32A(ERROR_EXE_MARKED_INVALID)
+ CHK_ERR_WIN32A(ERROR_BAD_EXE_FORMAT)
+ CHK_ERR_WIN32A(ERROR_ITERATED_DATA_EXCEEDS_64k)
+ CHK_ERR_WIN32A(ERROR_INVALID_MINALLOCSIZE)
+ CHK_ERR_WIN32A(ERROR_DYNLINK_FROM_INVALID_RING)
+ CHK_ERR_WIN32A(ERROR_IOPL_NOT_ENABLED)
+ CHK_ERR_WIN32A(ERROR_INVALID_SEGDPL)
+ CHK_ERR_WIN32A(ERROR_AUTODATASEG_EXCEEDS_64k)
+ CHK_ERRA(ERROR_RING2SEG_MUST_BE_MOVABLE)
+ CHK_ERRA(ERROR_RELOC_CHAIN_XEEDS_SEGLIM)
+ CHK_ERR_WIN32A(ERROR_INFLOOP_IN_RELOC_CHAIN)
+ CHK_ERR_WIN32A(ERROR_ENVVAR_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_NO_SIGNAL_SENT)
+ CHK_ERR_WIN32A(ERROR_FILENAME_EXCED_RANGE)
+ CHK_ERR_WIN32A(ERROR_RING2_STACK_IN_USE)
+ CHK_ERR_WIN32A(ERROR_META_EXPANSION_TOO_LONG)
+ CHK_ERR_WIN32A(ERROR_INVALID_SIGNAL_NUMBER)
+ CHK_ERR_WIN32A(ERROR_THREAD_1_INACTIVE)
+ CHK_ERR_WIN32A(ERROR_LOCKED)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_MODULES)
+ CHK_ERR_WIN32A(ERROR_NESTING_NOT_ALLOWED)
+ CHK_ERR_WIN32A(ERROR_EXE_MACHINE_TYPE_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_BAD_PIPE)
+ CHK_ERR_WIN32A(ERROR_PIPE_BUSY)
+ CHK_ERR_WIN32A(ERROR_NO_DATA)
+ CHK_ERR_WIN32A(ERROR_PIPE_NOT_CONNECTED)
+ CHK_ERR_WIN32A(ERROR_MORE_DATA)
+ CHK_ERR_WIN32A(ERROR_VC_DISCONNECTED)
+ CHK_ERR_WIN32A(ERROR_INVALID_EA_NAME)
+ CHK_ERR_WIN32A(ERROR_EA_LIST_INCONSISTENT)
+ CHK_ERR_WIN32A(WAIT_TIMEOUT)
+ CHK_ERR_WIN32A(ERROR_NO_MORE_ITEMS)
+ CHK_ERR_WIN32A(ERROR_CANNOT_COPY)
+ CHK_ERR_WIN32A(ERROR_DIRECTORY)
+ CHK_ERR_WIN32A(ERROR_EAS_DIDNT_FIT)
+ CHK_ERR_WIN32A(ERROR_EA_FILE_CORRUPT)
+ CHK_ERR_WIN32A(ERROR_EA_TABLE_FULL)
+ CHK_ERR_WIN32A(ERROR_INVALID_EA_HANDLE)
+ CHK_ERR_WIN32A(ERROR_EAS_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_NOT_OWNER)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_POSTS)
+ CHK_ERR_WIN32A(ERROR_PARTIAL_COPY)
+ CHK_ERR_WIN32A(ERROR_OPLOCK_NOT_GRANTED)
+ CHK_ERR_WIN32A(ERROR_INVALID_OPLOCK_PROTOCOL)
+ CHK_ERR_WIN32A(ERROR_MR_MID_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_INVALID_ADDRESS)
+ CHK_ERR_WIN32A(ERROR_ARITHMETIC_OVERFLOW)
+ CHK_ERR_WIN32A(ERROR_PIPE_CONNECTED)
+ CHK_ERR_WIN32A(ERROR_PIPE_LISTENING)
+ CHK_ERR_WIN32A(ERROR_EA_ACCESS_DENIED)
+ CHK_ERR_WIN32A(ERROR_OPERATION_ABORTED)
+ CHK_ERR_WIN32A(ERROR_IO_INCOMPLETE)
+ CHK_ERR_WIN32A(ERROR_IO_PENDING)
+ CHK_ERR_WIN32A(ERROR_NOACCESS)
+ CHK_ERR_WIN32A(ERROR_SWAPERROR)
+ CHK_ERR_WIN32A(ERROR_STACK_OVERFLOW)
+ CHK_ERR_WIN32A(ERROR_INVALID_MESSAGE)
+ CHK_ERR_WIN32A(ERROR_CAN_NOT_COMPLETE)
+ CHK_ERR_WIN32A(ERROR_INVALID_FLAGS)
+ CHK_ERR_WIN32A(ERROR_UNRECOGNIZED_VOLUME)
+ CHK_ERR_WIN32A(ERROR_FILE_INVALID)
+ CHK_ERR_WIN32A(ERROR_FULLSCREEN_MODE)
+ CHK_ERR_WIN32A(ERROR_NO_TOKEN)
+ CHK_ERR_WIN32A(ERROR_BADDB)
+ CHK_ERR_WIN32A(ERROR_BADKEY)
+ CHK_ERR_WIN32A(ERROR_CANTOPEN)
+ CHK_ERR_WIN32A(ERROR_CANTREAD)
+ CHK_ERR_WIN32A(ERROR_CANTWRITE)
+ CHK_ERR_WIN32A(ERROR_REGISTRY_RECOVERED)
+ CHK_ERR_WIN32A(ERROR_REGISTRY_CORRUPT)
+ CHK_ERR_WIN32A(ERROR_REGISTRY_IO_FAILED)
+ CHK_ERR_WIN32A(ERROR_NOT_REGISTRY_FILE)
+ CHK_ERR_WIN32A(ERROR_KEY_DELETED)
+ CHK_ERR_WIN32A(ERROR_NO_LOG_SPACE)
+ CHK_ERR_WIN32A(ERROR_KEY_HAS_CHILDREN)
+ CHK_ERR_WIN32A(ERROR_CHILD_MUST_BE_VOLATILE)
+ CHK_ERR_WIN32A(ERROR_NOTIFY_ENUM_DIR)
+ CHK_ERR_WIN32A(ERROR_DEPENDENT_SERVICES_RUNNING)
+ CHK_ERR_WIN32A(ERROR_INVALID_SERVICE_CONTROL)
+ CHK_ERR_WIN32A(ERROR_SERVICE_REQUEST_TIMEOUT)
+ CHK_ERR_WIN32A(ERROR_SERVICE_NO_THREAD)
+ CHK_ERR_WIN32A(ERROR_SERVICE_DATABASE_LOCKED)
+ CHK_ERR_WIN32A(ERROR_SERVICE_ALREADY_RUNNING)
+ CHK_ERR_WIN32A(ERROR_INVALID_SERVICE_ACCOUNT)
+ CHK_ERR_WIN32A(ERROR_SERVICE_DISABLED)
+ CHK_ERR_WIN32A(ERROR_CIRCULAR_DEPENDENCY)
+ CHK_ERR_WIN32A(ERROR_SERVICE_DOES_NOT_EXIST)
+ CHK_ERR_WIN32A(ERROR_SERVICE_CANNOT_ACCEPT_CTRL)
+ CHK_ERR_WIN32A(ERROR_SERVICE_NOT_ACTIVE)
+ CHK_ERR_WIN32A(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
+ CHK_ERR_WIN32A(ERROR_EXCEPTION_IN_SERVICE)
+ CHK_ERR_WIN32A(ERROR_DATABASE_DOES_NOT_EXIST)
+ CHK_ERR_WIN32A(ERROR_SERVICE_SPECIFIC_ERROR)
+ CHK_ERR_WIN32A(ERROR_PROCESS_ABORTED)
+ CHK_ERR_WIN32A(ERROR_SERVICE_DEPENDENCY_FAIL)
+ CHK_ERR_WIN32A(ERROR_SERVICE_LOGON_FAILED)
+ CHK_ERR_WIN32A(ERROR_SERVICE_START_HANG)
+ CHK_ERR_WIN32A(ERROR_INVALID_SERVICE_LOCK)
+ CHK_ERR_WIN32A(ERROR_SERVICE_MARKED_FOR_DELETE)
+ CHK_ERR_WIN32A(ERROR_SERVICE_EXISTS)
+ CHK_ERR_WIN32A(ERROR_ALREADY_RUNNING_LKG)
+ CHK_ERR_WIN32A(ERROR_SERVICE_DEPENDENCY_DELETED)
+ CHK_ERR_WIN32A(ERROR_BOOT_ALREADY_ACCEPTED)
+ CHK_ERR_WIN32A(ERROR_SERVICE_NEVER_STARTED)
+ CHK_ERR_WIN32A(ERROR_DUPLICATE_SERVICE_NAME)
+ CHK_ERR_WIN32A(ERROR_DIFFERENT_SERVICE_ACCOUNT)
+ CHK_ERR_WIN32A(ERROR_CANNOT_DETECT_DRIVER_FAILURE)
+ CHK_ERR_WIN32A(ERROR_CANNOT_DETECT_PROCESS_ABORT)
+ CHK_ERR_WIN32A(ERROR_NO_RECOVERY_PROGRAM)
+ CHK_ERR_WIN32A(ERROR_SERVICE_NOT_IN_EXE)
+ CHK_ERR_WIN32A(ERROR_END_OF_MEDIA)
+ CHK_ERR_WIN32A(ERROR_FILEMARK_DETECTED)
+ CHK_ERR_WIN32A(ERROR_BEGINNING_OF_MEDIA)
+ CHK_ERR_WIN32A(ERROR_SETMARK_DETECTED)
+ CHK_ERR_WIN32A(ERROR_NO_DATA_DETECTED)
+ CHK_ERR_WIN32A(ERROR_PARTITION_FAILURE)
+ CHK_ERR_WIN32A(ERROR_INVALID_BLOCK_LENGTH)
+ CHK_ERR_WIN32A(ERROR_DEVICE_NOT_PARTITIONED)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_LOCK_MEDIA)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_UNLOAD_MEDIA)
+ CHK_ERR_WIN32A(ERROR_MEDIA_CHANGED)
+ CHK_ERR_WIN32A(ERROR_BUS_RESET)
+ CHK_ERR_WIN32A(ERROR_NO_MEDIA_IN_DRIVE)
+ CHK_ERR_WIN32A(ERROR_NO_UNICODE_TRANSLATION)
+ CHK_ERR_WIN32A(ERROR_DLL_INIT_FAILED)
+ CHK_ERR_WIN32A(ERROR_SHUTDOWN_IN_PROGRESS)
+ CHK_ERR_WIN32A(ERROR_NO_SHUTDOWN_IN_PROGRESS)
+ CHK_ERR_WIN32A(ERROR_IO_DEVICE)
+ CHK_ERR_WIN32A(ERROR_SERIAL_NO_DEVICE)
+ CHK_ERR_WIN32A(ERROR_IRQ_BUSY)
+ CHK_ERR_WIN32A(ERROR_MORE_WRITES)
+ CHK_ERR_WIN32A(ERROR_COUNTER_TIMEOUT)
+ CHK_ERR_WIN32A(ERROR_FLOPPY_ID_MARK_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_FLOPPY_WRONG_CYLINDER)
+ CHK_ERR_WIN32A(ERROR_FLOPPY_UNKNOWN_ERROR)
+ CHK_ERR_WIN32A(ERROR_FLOPPY_BAD_REGISTERS)
+ CHK_ERR_WIN32A(ERROR_DISK_RECALIBRATE_FAILED)
+ CHK_ERR_WIN32A(ERROR_DISK_OPERATION_FAILED)
+ CHK_ERR_WIN32A(ERROR_DISK_RESET_FAILED)
+ CHK_ERR_WIN32A(ERROR_EOM_OVERFLOW)
+ CHK_ERR_WIN32A(ERROR_NOT_ENOUGH_SERVER_MEMORY)
+ CHK_ERR_WIN32A(ERROR_POSSIBLE_DEADLOCK)
+ CHK_ERR_WIN32A(ERROR_MAPPED_ALIGNMENT)
+ CHK_ERR_WIN32A(ERROR_SET_POWER_STATE_VETOED)
+ CHK_ERR_WIN32A(ERROR_SET_POWER_STATE_FAILED)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_LINKS)
+ CHK_ERR_WIN32A(ERROR_OLD_WIN_VERSION)
+ CHK_ERR_WIN32A(ERROR_APP_WRONG_OS)
+ CHK_ERR_WIN32A(ERROR_SINGLE_INSTANCE_APP)
+ CHK_ERR_WIN32A(ERROR_RMODE_APP)
+ CHK_ERR_WIN32A(ERROR_INVALID_DLL)
+ CHK_ERR_WIN32A(ERROR_NO_ASSOCIATION)
+ CHK_ERR_WIN32A(ERROR_DDE_FAIL)
+ CHK_ERR_WIN32A(ERROR_DLL_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_NO_MORE_USER_HANDLES)
+ CHK_ERR_WIN32A(ERROR_MESSAGE_SYNC_ONLY)
+ CHK_ERR_WIN32A(ERROR_SOURCE_ELEMENT_EMPTY)
+ CHK_ERR_WIN32A(ERROR_DESTINATION_ELEMENT_FULL)
+ CHK_ERR_WIN32A(ERROR_ILLEGAL_ELEMENT_ADDRESS)
+ CHK_ERR_WIN32A(ERROR_MAGAZINE_NOT_PRESENT)
+ CHK_ERR_WIN32A(ERROR_DEVICE_REINITIALIZATION_NEEDED)
+ CHK_ERR_WIN32A(ERROR_DEVICE_REQUIRES_CLEANING)
+ CHK_ERR_WIN32A(ERROR_DEVICE_DOOR_OPEN)
+ CHK_ERR_WIN32A(ERROR_DEVICE_NOT_CONNECTED)
+ CHK_ERR_WIN32A(ERROR_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_NO_MATCH)
+ CHK_ERR_WIN32A(ERROR_SET_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_POINT_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_NO_TRACKING_SERVICE)
+ CHK_ERR_WIN32A(ERROR_NO_VOLUME_ID)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_REMOVE_REPLACED)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_MOVE_REPLACEMENT)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_MOVE_REPLACEMENT_2)
+ CHK_ERR_WIN32A(ERROR_JOURNAL_DELETE_IN_PROGRESS)
+ CHK_ERR_WIN32A(ERROR_JOURNAL_NOT_ACTIVE)
+ CHK_ERR_WIN32A(ERROR_POTENTIAL_FILE_FOUND)
+ CHK_ERR_WIN32A(ERROR_BAD_DEVICE)
+ CHK_ERR_WIN32A(ERROR_CONNECTION_UNAVAIL)
+ CHK_ERR_WIN32A(ERROR_DEVICE_ALREADY_REMEMBERED)
+ CHK_ERR_WIN32A(ERROR_NO_NET_OR_BAD_PATH)
+ CHK_ERR_WIN32A(ERROR_BAD_PROVIDER)
+ CHK_ERR_WIN32A(ERROR_CANNOT_OPEN_PROFILE)
+ CHK_ERR_WIN32A(ERROR_BAD_PROFILE)
+ CHK_ERR_WIN32A(ERROR_NOT_CONTAINER)
+ CHK_ERR_WIN32A(ERROR_EXTENDED_ERROR)
+ CHK_ERR_WIN32A(ERROR_INVALID_GROUPNAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_COMPUTERNAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_EVENTNAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_DOMAINNAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_SERVICENAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_NETNAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_SHARENAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_PASSWORDNAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_MESSAGENAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_MESSAGEDEST)
+ CHK_ERR_WIN32A(ERROR_SESSION_CREDENTIAL_CONFLICT)
+ CHK_ERR_WIN32A(ERROR_REMOTE_SESSION_LIMIT_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_DUP_DOMAINNAME)
+ CHK_ERR_WIN32A(ERROR_NO_NETWORK)
+ CHK_ERR_WIN32A(ERROR_CANCELLED)
+ CHK_ERR_WIN32A(ERROR_USER_MAPPED_FILE)
+ CHK_ERR_WIN32A(ERROR_CONNECTION_REFUSED)
+ CHK_ERR_WIN32A(ERROR_GRACEFUL_DISCONNECT)
+ CHK_ERR_WIN32A(ERROR_ADDRESS_ALREADY_ASSOCIATED)
+ CHK_ERR_WIN32A(ERROR_ADDRESS_NOT_ASSOCIATED)
+ CHK_ERR_WIN32A(ERROR_CONNECTION_INVALID)
+ CHK_ERR_WIN32A(ERROR_CONNECTION_ACTIVE)
+ CHK_ERR_WIN32A(ERROR_NETWORK_UNREACHABLE)
+ CHK_ERR_WIN32A(ERROR_HOST_UNREACHABLE)
+ CHK_ERR_WIN32A(ERROR_PROTOCOL_UNREACHABLE)
+ CHK_ERR_WIN32A(ERROR_PORT_UNREACHABLE)
+ CHK_ERR_WIN32A(ERROR_REQUEST_ABORTED)
+ CHK_ERR_WIN32A(ERROR_CONNECTION_ABORTED)
+ CHK_ERR_WIN32A(ERROR_RETRY)
+ CHK_ERR_WIN32A(ERROR_CONNECTION_COUNT_LIMIT)
+ CHK_ERR_WIN32A(ERROR_LOGIN_TIME_RESTRICTION)
+ CHK_ERR_WIN32A(ERROR_LOGIN_WKSTA_RESTRICTION)
+ CHK_ERR_WIN32A(ERROR_INCORRECT_ADDRESS)
+ CHK_ERR_WIN32A(ERROR_ALREADY_REGISTERED)
+ CHK_ERR_WIN32A(ERROR_SERVICE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_NOT_AUTHENTICATED)
+ CHK_ERR_WIN32A(ERROR_NOT_LOGGED_ON)
+ CHK_ERR_WIN32A(ERROR_CONTINUE)
+ CHK_ERR_WIN32A(ERROR_ALREADY_INITIALIZED)
+ CHK_ERR_WIN32A(ERROR_NO_MORE_DEVICES)
+ CHK_ERR_WIN32A(ERROR_NO_SUCH_SITE)
+ CHK_ERR_WIN32A(ERROR_DOMAIN_CONTROLLER_EXISTS)
+ CHK_ERR_WIN32A(ERROR_NOT_ALL_ASSIGNED)
+ CHK_ERR_WIN32A(ERROR_SOME_NOT_MAPPED)
+ CHK_ERR_WIN32A(ERROR_NO_QUOTAS_FOR_ACCOUNT)
+ CHK_ERR_WIN32A(ERROR_LOCAL_USER_SESSION_KEY)
+ CHK_ERR_WIN32A(ERROR_NULL_LM_PASSWORD)
+ CHK_ERR_WIN32A(ERROR_UNKNOWN_REVISION)
+ CHK_ERR_WIN32A(ERROR_REVISION_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_INVALID_OWNER)
+ CHK_ERR_WIN32A(ERROR_INVALID_PRIMARY_GROUP)
+ CHK_ERR_WIN32A(ERROR_NO_IMPERSONATION_TOKEN)
+ CHK_ERR_WIN32A(ERROR_CANT_DISABLE_MANDATORY)
+ CHK_ERR_WIN32A(ERROR_NO_LOGON_SERVERS)
+ CHK_ERR_WIN32A(ERROR_NO_SUCH_LOGON_SESSION)
+ CHK_ERR_WIN32A(ERROR_NO_SUCH_PRIVILEGE)
+ CHK_ERR_WIN32A(ERROR_PRIVILEGE_NOT_HELD)
+ CHK_ERR_WIN32A(ERROR_INVALID_ACCOUNT_NAME)
+ CHK_ERR_WIN32A(ERROR_USER_EXISTS)
+ CHK_ERR_WIN32A(ERROR_NO_SUCH_USER)
+ CHK_ERR_WIN32A(ERROR_GROUP_EXISTS)
+ CHK_ERR_WIN32A(ERROR_NO_SUCH_GROUP)
+ CHK_ERR_WIN32A(ERROR_MEMBER_IN_GROUP)
+ CHK_ERR_WIN32A(ERROR_MEMBER_NOT_IN_GROUP)
+ CHK_ERR_WIN32A(ERROR_LAST_ADMIN)
+ CHK_ERR_WIN32A(ERROR_WRONG_PASSWORD)
+ CHK_ERR_WIN32A(ERROR_ILL_FORMED_PASSWORD)
+ CHK_ERR_WIN32A(ERROR_PASSWORD_RESTRICTION)
+ CHK_ERR_WIN32A(ERROR_LOGON_FAILURE)
+ CHK_ERR_WIN32A(ERROR_ACCOUNT_RESTRICTION)
+ CHK_ERR_WIN32A(ERROR_INVALID_LOGON_HOURS)
+ CHK_ERR_WIN32A(ERROR_INVALID_WORKSTATION)
+ CHK_ERR_WIN32A(ERROR_PASSWORD_EXPIRED)
+ CHK_ERR_WIN32A(ERROR_ACCOUNT_DISABLED)
+ CHK_ERR_WIN32A(ERROR_NONE_MAPPED)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_LUIDS_REQUESTED)
+ CHK_ERR_WIN32A(ERROR_LUIDS_EXHAUSTED)
+ CHK_ERR_WIN32A(ERROR_INVALID_SUB_AUTHORITY)
+ CHK_ERR_WIN32A(ERROR_INVALID_ACL)
+ CHK_ERR_WIN32A(ERROR_INVALID_SID)
+ CHK_ERR_WIN32A(ERROR_INVALID_SECURITY_DESCR)
+ CHK_ERR_WIN32A(ERROR_BAD_INHERITANCE_ACL)
+ CHK_ERR_WIN32A(ERROR_SERVER_DISABLED)
+ CHK_ERR_WIN32A(ERROR_SERVER_NOT_DISABLED)
+ CHK_ERR_WIN32A(ERROR_INVALID_ID_AUTHORITY)
+ CHK_ERR_WIN32A(ERROR_ALLOTTED_SPACE_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_INVALID_GROUP_ATTRIBUTES)
+ CHK_ERR_WIN32A(ERROR_BAD_IMPERSONATION_LEVEL)
+ CHK_ERR_WIN32A(ERROR_CANT_OPEN_ANONYMOUS)
+ CHK_ERR_WIN32A(ERROR_BAD_VALIDATION_CLASS)
+ CHK_ERR_WIN32A(ERROR_BAD_TOKEN_TYPE)
+ CHK_ERR_WIN32A(ERROR_NO_SECURITY_ON_OBJECT)
+ CHK_ERR_WIN32A(ERROR_CANT_ACCESS_DOMAIN_INFO)
+ CHK_ERR_WIN32A(ERROR_INVALID_SERVER_STATE)
+ CHK_ERR_WIN32A(ERROR_INVALID_DOMAIN_STATE)
+ CHK_ERR_WIN32A(ERROR_INVALID_DOMAIN_ROLE)
+ CHK_ERR_WIN32A(ERROR_NO_SUCH_DOMAIN)
+ CHK_ERR_WIN32A(ERROR_DOMAIN_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DOMAIN_LIMIT_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_INTERNAL_DB_CORRUPTION)
+ CHK_ERR_WIN32A(ERROR_INTERNAL_ERROR)
+ CHK_ERR_WIN32A(ERROR_GENERIC_NOT_MAPPED)
+ CHK_ERR_WIN32A(ERROR_BAD_DESCRIPTOR_FORMAT)
+ CHK_ERR_WIN32A(ERROR_NOT_LOGON_PROCESS)
+ CHK_ERR_WIN32A(ERROR_LOGON_SESSION_EXISTS)
+ CHK_ERR_WIN32A(ERROR_NO_SUCH_PACKAGE)
+ CHK_ERR_WIN32A(ERROR_BAD_LOGON_SESSION_STATE)
+ CHK_ERR_WIN32A(ERROR_LOGON_SESSION_COLLISION)
+ CHK_ERR_WIN32A(ERROR_INVALID_LOGON_TYPE)
+ CHK_ERR_WIN32A(ERROR_CANNOT_IMPERSONATE)
+ CHK_ERR_WIN32A(ERROR_RXACT_INVALID_STATE)
+ CHK_ERR_WIN32A(ERROR_RXACT_COMMIT_FAILURE)
+ CHK_ERR_WIN32A(ERROR_SPECIAL_ACCOUNT)
+ CHK_ERR_WIN32A(ERROR_SPECIAL_GROUP)
+ CHK_ERR_WIN32A(ERROR_SPECIAL_USER)
+ CHK_ERR_WIN32A(ERROR_MEMBERS_PRIMARY_GROUP)
+ CHK_ERR_WIN32A(ERROR_TOKEN_ALREADY_IN_USE)
+ CHK_ERR_WIN32A(ERROR_NO_SUCH_ALIAS)
+ CHK_ERR_WIN32A(ERROR_MEMBER_NOT_IN_ALIAS)
+ CHK_ERR_WIN32A(ERROR_MEMBER_IN_ALIAS)
+ CHK_ERR_WIN32A(ERROR_ALIAS_EXISTS)
+ CHK_ERR_WIN32A(ERROR_LOGON_NOT_GRANTED)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_SECRETS)
+ CHK_ERR_WIN32A(ERROR_SECRET_TOO_LONG)
+ CHK_ERR_WIN32A(ERROR_INTERNAL_DB_ERROR)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_CONTEXT_IDS)
+ CHK_ERR_WIN32A(ERROR_LOGON_TYPE_NOT_GRANTED)
+ CHK_ERR_WIN32A(ERROR_NT_CROSS_ENCRYPTION_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_NO_SUCH_MEMBER)
+ CHK_ERR_WIN32A(ERROR_INVALID_MEMBER)
+ CHK_ERR_WIN32A(ERROR_TOO_MANY_SIDS)
+ CHK_ERR_WIN32A(ERROR_LM_CROSS_ENCRYPTION_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_NO_INHERITANCE)
+ CHK_ERR_WIN32A(ERROR_FILE_CORRUPT)
+ CHK_ERR_WIN32A(ERROR_DISK_CORRUPT)
+ CHK_ERR_WIN32A(ERROR_NO_USER_SESSION_KEY)
+ CHK_ERR_WIN32A(ERROR_LICENSE_QUOTA_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_WRONG_TARGET_NAME)
+ CHK_ERR_WIN32A(ERROR_MUTUAL_AUTH_FAILED)
+ CHK_ERR_WIN32A(ERROR_TIME_SKEW)
+ CHK_ERR_WIN32A(ERROR_INVALID_WINDOW_HANDLE)
+ CHK_ERR_WIN32A(ERROR_INVALID_MENU_HANDLE)
+ CHK_ERR_WIN32A(ERROR_INVALID_CURSOR_HANDLE)
+ CHK_ERR_WIN32A(ERROR_INVALID_ACCEL_HANDLE)
+ CHK_ERR_WIN32A(ERROR_INVALID_HOOK_HANDLE)
+ CHK_ERR_WIN32A(ERROR_INVALID_DWP_HANDLE)
+ CHK_ERR_WIN32A(ERROR_TLW_WITH_WSCHILD)
+ CHK_ERR_WIN32A(ERROR_CANNOT_FIND_WND_CLASS)
+ CHK_ERR_WIN32A(ERROR_WINDOW_OF_OTHER_THREAD)
+ CHK_ERR_WIN32A(ERROR_HOTKEY_ALREADY_REGISTERED)
+ CHK_ERR_WIN32A(ERROR_CLASS_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_CLASS_DOES_NOT_EXIST)
+ CHK_ERR_WIN32A(ERROR_CLASS_HAS_WINDOWS)
+ CHK_ERR_WIN32A(ERROR_INVALID_INDEX)
+ CHK_ERR_WIN32A(ERROR_INVALID_ICON_HANDLE)
+ CHK_ERR_WIN32A(ERROR_PRIVATE_DIALOG_INDEX)
+ CHK_ERR_WIN32A(ERROR_LISTBOX_ID_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_NO_WILDCARD_CHARACTERS)
+ CHK_ERR_WIN32A(ERROR_CLIPBOARD_NOT_OPEN)
+ CHK_ERR_WIN32A(ERROR_HOTKEY_NOT_REGISTERED)
+ CHK_ERR_WIN32A(ERROR_WINDOW_NOT_DIALOG)
+ CHK_ERR_WIN32A(ERROR_CONTROL_ID_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_INVALID_COMBOBOX_MESSAGE)
+ CHK_ERR_WIN32A(ERROR_WINDOW_NOT_COMBOBOX)
+ CHK_ERR_WIN32A(ERROR_INVALID_EDIT_HEIGHT)
+ CHK_ERR_WIN32A(ERROR_DC_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_INVALID_HOOK_FILTER)
+ CHK_ERR_WIN32A(ERROR_INVALID_FILTER_PROC)
+ CHK_ERR_WIN32A(ERROR_HOOK_NEEDS_HMOD)
+ CHK_ERR_WIN32A(ERROR_GLOBAL_ONLY_HOOK)
+ CHK_ERR_WIN32A(ERROR_JOURNAL_HOOK_SET)
+ CHK_ERR_WIN32A(ERROR_HOOK_NOT_INSTALLED)
+ CHK_ERR_WIN32A(ERROR_INVALID_LB_MESSAGE)
+ CHK_ERR_WIN32A(ERROR_SETCOUNT_ON_BAD_LB)
+ CHK_ERR_WIN32A(ERROR_LB_WITHOUT_TABSTOPS)
+ CHK_ERR_WIN32A(ERROR_DESTROY_OBJECT_OF_OTHER_THREAD)
+ CHK_ERR_WIN32A(ERROR_CHILD_WINDOW_MENU)
+ CHK_ERR_WIN32A(ERROR_NO_SYSTEM_MENU)
+ CHK_ERR_WIN32A(ERROR_INVALID_MSGBOX_STYLE)
+ CHK_ERR_WIN32A(ERROR_INVALID_SPI_VALUE)
+ CHK_ERR_WIN32A(ERROR_SCREEN_ALREADY_LOCKED)
+ CHK_ERR_WIN32A(ERROR_HWNDS_HAVE_DIFF_PARENT)
+ CHK_ERR_WIN32A(ERROR_NOT_CHILD_WINDOW)
+ CHK_ERR_WIN32A(ERROR_INVALID_GW_COMMAND)
+ CHK_ERR_WIN32A(ERROR_INVALID_THREAD_ID)
+ CHK_ERR_WIN32A(ERROR_NON_MDICHILD_WINDOW)
+ CHK_ERR_WIN32A(ERROR_POPUP_ALREADY_ACTIVE)
+ CHK_ERR_WIN32A(ERROR_NO_SCROLLBARS)
+ CHK_ERR_WIN32A(ERROR_INVALID_SCROLLBAR_RANGE)
+ CHK_ERR_WIN32A(ERROR_INVALID_SHOWWIN_COMMAND)
+ CHK_ERR_WIN32A(ERROR_NO_SYSTEM_RESOURCES)
+ CHK_ERR_WIN32A(ERROR_NONPAGED_SYSTEM_RESOURCES)
+ CHK_ERR_WIN32A(ERROR_PAGED_SYSTEM_RESOURCES)
+ CHK_ERR_WIN32A(ERROR_WORKING_SET_QUOTA)
+ CHK_ERR_WIN32A(ERROR_PAGEFILE_QUOTA)
+ CHK_ERR_WIN32A(ERROR_COMMITMENT_LIMIT)
+ CHK_ERR_WIN32A(ERROR_MENU_ITEM_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_INVALID_KEYBOARD_HANDLE)
+ CHK_ERR_WIN32A(ERROR_HOOK_TYPE_NOT_ALLOWED)
+ CHK_ERR_WIN32A(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION)
+ CHK_ERR_WIN32A(ERROR_TIMEOUT)
+ CHK_ERR_WIN32A(ERROR_INVALID_MONITOR_HANDLE)
+ CHK_ERR_WIN32A(ERROR_EVENTLOG_FILE_CORRUPT)
+ CHK_ERR_WIN32A(ERROR_EVENTLOG_CANT_START)
+ CHK_ERR_WIN32A(ERROR_LOG_FILE_FULL)
+ CHK_ERR_WIN32A(ERROR_EVENTLOG_FILE_CHANGED)
+ CHK_ERR_WIN32A(ERROR_INSTALL_USEREXIT)
+ CHK_ERR_WIN32A(ERROR_INSTALL_FAILURE)
+ CHK_ERR_WIN32A(ERROR_INSTALL_SUSPEND)
+ CHK_ERR_WIN32A(ERROR_UNKNOWN_PRODUCT)
+ CHK_ERR_WIN32A(ERROR_UNKNOWN_FEATURE)
+ CHK_ERR_WIN32A(ERROR_UNKNOWN_COMPONENT)
+ CHK_ERR_WIN32A(ERROR_UNKNOWN_PROPERTY)
+ CHK_ERR_WIN32A(ERROR_INVALID_HANDLE_STATE)
+ CHK_ERR_WIN32A(ERROR_BAD_CONFIGURATION)
+ CHK_ERR_WIN32A(ERROR_INDEX_ABSENT)
+ CHK_ERR_WIN32A(ERROR_INSTALL_SOURCE_ABSENT)
+ CHK_ERR_WIN32A(ERROR_PRODUCT_UNINSTALLED)
+ CHK_ERR_WIN32A(ERROR_BAD_QUERY_SYNTAX)
+ CHK_ERR_WIN32A(ERROR_INVALID_FIELD)
+ CHK_ERR_WIN32A(ERROR_DEVICE_REMOVED)
+ CHK_ERR_WIN32A(RPC_S_INVALID_STRING_BINDING)
+ CHK_ERR_WIN32A(RPC_S_WRONG_KIND_OF_BINDING)
+ CHK_ERR_WIN32A(RPC_S_INVALID_BINDING)
+ CHK_ERR_WIN32A(RPC_S_PROTSEQ_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(RPC_S_INVALID_RPC_PROTSEQ)
+ CHK_ERR_WIN32A(RPC_S_INVALID_STRING_UUID)
+ CHK_ERR_WIN32A(RPC_S_INVALID_ENDPOINT_FORMAT)
+ CHK_ERR_WIN32A(RPC_S_INVALID_NET_ADDR)
+ CHK_ERR_WIN32A(RPC_S_NO_ENDPOINT_FOUND)
+ CHK_ERR_WIN32A(RPC_S_INVALID_TIMEOUT)
+ CHK_ERR_WIN32A(RPC_S_OBJECT_NOT_FOUND)
+ CHK_ERR_WIN32A(RPC_S_ALREADY_REGISTERED)
+ CHK_ERR_WIN32A(RPC_S_TYPE_ALREADY_REGISTERED)
+ CHK_ERR_WIN32A(RPC_S_ALREADY_LISTENING)
+ CHK_ERR_WIN32A(RPC_S_NO_PROTSEQS_REGISTERED)
+ CHK_ERR_WIN32A(RPC_S_NOT_LISTENING)
+ CHK_ERR_WIN32A(RPC_S_UNKNOWN_MGR_TYPE)
+ CHK_ERR_WIN32A(RPC_S_UNKNOWN_IF)
+ CHK_ERR_WIN32A(RPC_S_NO_BINDINGS)
+ CHK_ERR_WIN32A(RPC_S_NO_PROTSEQS)
+ CHK_ERR_WIN32A(RPC_S_CANT_CREATE_ENDPOINT)
+ CHK_ERR_WIN32A(RPC_S_OUT_OF_RESOURCES)
+ CHK_ERR_WIN32A(RPC_S_SERVER_UNAVAILABLE)
+ CHK_ERR_WIN32A(RPC_S_SERVER_TOO_BUSY)
+ CHK_ERR_WIN32A(RPC_S_INVALID_NETWORK_OPTIONS)
+ CHK_ERR_WIN32A(RPC_S_NO_CALL_ACTIVE)
+ CHK_ERR_WIN32A(RPC_S_CALL_FAILED)
+ CHK_ERR_WIN32A(RPC_S_CALL_FAILED_DNE)
+ CHK_ERR_WIN32A(RPC_S_PROTOCOL_ERROR)
+ CHK_ERR_WIN32A(RPC_S_UNSUPPORTED_TRANS_SYN)
+ CHK_ERR_WIN32A(RPC_S_UNSUPPORTED_TYPE)
+ CHK_ERR_WIN32A(RPC_S_INVALID_TAG)
+ CHK_ERR_WIN32A(RPC_S_INVALID_BOUND)
+ CHK_ERR_WIN32A(RPC_S_NO_ENTRY_NAME)
+ CHK_ERR_WIN32A(RPC_S_INVALID_NAME_SYNTAX)
+ CHK_ERR_WIN32A(RPC_S_UNSUPPORTED_NAME_SYNTAX)
+ CHK_ERR_WIN32A(RPC_S_UUID_NO_ADDRESS)
+ CHK_ERR_WIN32A(RPC_S_DUPLICATE_ENDPOINT)
+ CHK_ERR_WIN32A(RPC_S_UNKNOWN_AUTHN_TYPE)
+ CHK_ERR_WIN32A(RPC_S_MAX_CALLS_TOO_SMALL)
+ CHK_ERR_WIN32A(RPC_S_STRING_TOO_LONG)
+ CHK_ERR_WIN32A(RPC_S_PROTSEQ_NOT_FOUND)
+ CHK_ERR_WIN32A(RPC_S_PROCNUM_OUT_OF_RANGE)
+ CHK_ERR_WIN32A(RPC_S_BINDING_HAS_NO_AUTH)
+ CHK_ERR_WIN32A(RPC_S_UNKNOWN_AUTHN_SERVICE)
+ CHK_ERR_WIN32A(RPC_S_UNKNOWN_AUTHN_LEVEL)
+ CHK_ERR_WIN32A(RPC_S_INVALID_AUTH_IDENTITY)
+ CHK_ERR_WIN32A(RPC_S_UNKNOWN_AUTHZ_SERVICE)
+ CHK_ERR_WIN32A(EPT_S_INVALID_ENTRY)
+ CHK_ERR_WIN32A(EPT_S_CANT_PERFORM_OP)
+ CHK_ERR_WIN32A(EPT_S_NOT_REGISTERED)
+ CHK_ERR_WIN32A(RPC_S_NOTHING_TO_EXPORT)
+ CHK_ERR_WIN32A(RPC_S_INCOMPLETE_NAME)
+ CHK_ERR_WIN32A(RPC_S_INVALID_VERS_OPTION)
+ CHK_ERR_WIN32A(RPC_S_NO_MORE_MEMBERS)
+ CHK_ERR_WIN32A(RPC_S_NOT_ALL_OBJS_UNEXPORTED)
+ CHK_ERR_WIN32A(RPC_S_INTERFACE_NOT_FOUND)
+ CHK_ERR_WIN32A(RPC_S_ENTRY_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(RPC_S_ENTRY_NOT_FOUND)
+ CHK_ERR_WIN32A(RPC_S_NAME_SERVICE_UNAVAILABLE)
+ CHK_ERR_WIN32A(RPC_S_INVALID_NAF_ID)
+ CHK_ERR_WIN32A(RPC_S_CANNOT_SUPPORT)
+ CHK_ERR_WIN32A(RPC_S_NO_CONTEXT_AVAILABLE)
+ CHK_ERR_WIN32A(RPC_S_INTERNAL_ERROR)
+ CHK_ERR_WIN32A(RPC_S_ZERO_DIVIDE)
+ CHK_ERR_WIN32A(RPC_S_ADDRESS_ERROR)
+ CHK_ERR_WIN32A(RPC_S_FP_DIV_ZERO)
+ CHK_ERR_WIN32A(RPC_S_FP_UNDERFLOW)
+ CHK_ERR_WIN32A(RPC_S_FP_OVERFLOW)
+ CHK_ERR_WIN32A(RPC_X_NO_MORE_ENTRIES)
+ CHK_ERR_WIN32A(RPC_X_SS_CHAR_TRANS_OPEN_FAIL)
+ CHK_ERR_WIN32A(RPC_X_SS_CHAR_TRANS_SHORT_FILE)
+ CHK_ERR_WIN32A(RPC_X_SS_IN_NULL_CONTEXT)
+ CHK_ERR_WIN32A(RPC_X_SS_CONTEXT_DAMAGED)
+ CHK_ERR_WIN32A(RPC_X_SS_HANDLES_MISMATCH)
+ CHK_ERR_WIN32A(RPC_X_SS_CANNOT_GET_CALL_HANDLE)
+ CHK_ERR_WIN32A(RPC_X_NULL_REF_POINTER)
+ CHK_ERR_WIN32A(RPC_X_ENUM_VALUE_OUT_OF_RANGE)
+ CHK_ERR_WIN32A(RPC_X_BYTE_COUNT_TOO_SMALL)
+ CHK_ERR_WIN32A(RPC_X_BAD_STUB_DATA)
+ CHK_ERR_WIN32A(ERROR_INVALID_USER_BUFFER)
+ CHK_ERR_WIN32A(ERROR_UNRECOGNIZED_MEDIA)
+ CHK_ERR_WIN32A(ERROR_NO_TRUST_LSA_SECRET)
+ CHK_ERR_WIN32A(ERROR_NO_TRUST_SAM_ACCOUNT)
+ CHK_ERR_WIN32A(ERROR_TRUSTED_DOMAIN_FAILURE)
+ CHK_ERR_WIN32A(ERROR_TRUSTED_RELATIONSHIP_FAILURE)
+ CHK_ERR_WIN32A(ERROR_TRUST_FAILURE)
+ CHK_ERR_WIN32A(RPC_S_CALL_IN_PROGRESS)
+ CHK_ERR_WIN32A(ERROR_NETLOGON_NOT_STARTED)
+ CHK_ERR_WIN32A(ERROR_ACCOUNT_EXPIRED)
+ CHK_ERR_WIN32A(ERROR_REDIRECTOR_HAS_OPEN_HANDLES)
+ CHK_ERR_WIN32A(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED)
+ CHK_ERR_WIN32A(ERROR_UNKNOWN_PORT)
+ CHK_ERR_WIN32A(ERROR_UNKNOWN_PRINTER_DRIVER)
+ CHK_ERR_WIN32A(ERROR_UNKNOWN_PRINTPROCESSOR)
+ CHK_ERR_WIN32A(ERROR_INVALID_SEPARATOR_FILE)
+ CHK_ERR_WIN32A(ERROR_INVALID_PRIORITY)
+ CHK_ERR_WIN32A(ERROR_INVALID_PRINTER_NAME)
+ CHK_ERR_WIN32A(ERROR_PRINTER_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_INVALID_PRINTER_COMMAND)
+ CHK_ERR_WIN32A(ERROR_INVALID_DATATYPE)
+ CHK_ERR_WIN32A(ERROR_INVALID_ENVIRONMENT)
+ CHK_ERR_WIN32A(RPC_S_NO_MORE_BINDINGS)
+ CHK_ERR_WIN32A(ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)
+ CHK_ERR_WIN32A(ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
+ CHK_ERR_WIN32A(ERROR_NOLOGON_SERVER_TRUST_ACCOUNT)
+ CHK_ERR_WIN32A(ERROR_DOMAIN_TRUST_INCONSISTENT)
+ CHK_ERR_WIN32A(ERROR_SERVER_HAS_OPEN_HANDLES)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_DATA_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_TYPE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_NAME_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_LANG_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_NOT_ENOUGH_QUOTA)
+ CHK_ERR_WIN32A(RPC_S_NO_INTERFACES)
+ CHK_ERR_WIN32A(RPC_S_CALL_CANCELLED)
+ CHK_ERR_WIN32A(RPC_S_BINDING_INCOMPLETE)
+ CHK_ERR_WIN32A(RPC_S_COMM_FAILURE)
+ CHK_ERR_WIN32A(RPC_S_UNSUPPORTED_AUTHN_LEVEL)
+ CHK_ERR_WIN32A(RPC_S_NO_PRINC_NAME)
+ CHK_ERR_WIN32A(RPC_S_NOT_RPC_ERROR)
+ CHK_ERR_WIN32A(RPC_S_UUID_LOCAL_ONLY)
+ CHK_ERR_WIN32A(RPC_S_SEC_PKG_ERROR)
+ CHK_ERR_WIN32A(RPC_S_NOT_CANCELLED)
+ CHK_ERR_WIN32A(RPC_X_INVALID_ES_ACTION)
+ CHK_ERR_WIN32A(RPC_X_WRONG_ES_VERSION)
+ CHK_ERR_WIN32A(RPC_X_WRONG_STUB_VERSION)
+ CHK_ERR_WIN32A(RPC_X_INVALID_PIPE_OBJECT)
+ CHK_ERR_WIN32A(RPC_X_WRONG_PIPE_ORDER)
+ CHK_ERR_WIN32A(RPC_X_WRONG_PIPE_VERSION)
+ CHK_ERR_WIN32A(RPC_S_GROUP_MEMBER_NOT_FOUND)
+ CHK_ERR_WIN32A(EPT_S_CANT_CREATE)
+ CHK_ERR_WIN32A(RPC_S_INVALID_OBJECT)
+ CHK_ERR_WIN32A(ERROR_INVALID_TIME)
+ CHK_ERR_WIN32A(ERROR_INVALID_FORM_NAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_FORM_SIZE)
+ CHK_ERR_WIN32A(ERROR_ALREADY_WAITING)
+ CHK_ERR_WIN32A(ERROR_PRINTER_DELETED)
+ CHK_ERR_WIN32A(ERROR_INVALID_PRINTER_STATE)
+ CHK_ERR_WIN32A(ERROR_PASSWORD_MUST_CHANGE)
+ CHK_ERR_WIN32A(ERROR_DOMAIN_CONTROLLER_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_ACCOUNT_LOCKED_OUT)
+ CHK_ERR_WIN32A(OR_INVALID_OXID)
+ CHK_ERR_WIN32A(OR_INVALID_OID)
+ CHK_ERR_WIN32A(OR_INVALID_SET)
+ CHK_ERR_WIN32A(RPC_S_SEND_INCOMPLETE)
+ CHK_ERR_WIN32A(RPC_S_INVALID_ASYNC_HANDLE)
+ CHK_ERR_WIN32A(RPC_S_INVALID_ASYNC_CALL)
+ CHK_ERR_WIN32A(RPC_X_PIPE_CLOSED)
+ CHK_ERR_WIN32A(RPC_X_PIPE_DISCIPLINE_ERROR)
+ CHK_ERR_WIN32A(RPC_X_PIPE_EMPTY)
+ CHK_ERR_WIN32A(ERROR_NO_SITENAME)
+ CHK_ERR_WIN32A(ERROR_CANT_ACCESS_FILE)
+ CHK_ERR_WIN32A(ERROR_CANT_RESOLVE_FILENAME)
+ CHK_ERR_WIN32A(ERROR_INVALID_PIXEL_FORMAT)
+ CHK_ERR_WIN32A(ERROR_BAD_DRIVER)
+ CHK_ERR_WIN32A(ERROR_INVALID_WINDOW_STYLE)
+ CHK_ERR_WIN32A(ERROR_METAFILE_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_TRANSFORM_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_CLIPPING_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_INVALID_CMM)
+ CHK_ERR_WIN32A(ERROR_INVALID_PROFILE)
+ CHK_ERR_WIN32A(ERROR_TAG_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_TAG_NOT_PRESENT)
+ CHK_ERR_WIN32A(ERROR_DUPLICATE_TAG)
+ CHK_ERR_WIN32A(ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE)
+ CHK_ERR_WIN32A(ERROR_PROFILE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_INVALID_COLORSPACE)
+ CHK_ERR_WIN32A(ERROR_ICM_NOT_ENABLED)
+ CHK_ERR_WIN32A(ERROR_DELETING_ICM_XFORM)
+ CHK_ERR_WIN32A(ERROR_INVALID_TRANSFORM)
+ CHK_ERR_WIN32A(ERROR_COLORSPACE_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_INVALID_COLORINDEX)
+ CHK_ERR_WIN32A(ERROR_CONNECTED_OTHER_PASSWORD)
+ CHK_ERR_WIN32A(ERROR_BAD_USERNAME)
+ CHK_ERR_WIN32A(ERROR_NOT_CONNECTED)
+ CHK_ERR_WIN32A(ERROR_OPEN_FILES)
+ CHK_ERR_WIN32A(ERROR_ACTIVE_CONNECTIONS)
+ CHK_ERR_WIN32A(ERROR_DEVICE_IN_USE)
+ CHK_ERR_WIN32A(ERROR_UNKNOWN_PRINT_MONITOR)
+ CHK_ERR_WIN32A(ERROR_PRINTER_DRIVER_IN_USE)
+ CHK_ERR_WIN32A(ERROR_SPOOL_FILE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_SPL_NO_STARTDOC)
+ CHK_ERR_WIN32A(ERROR_SPL_NO_ADDJOB)
+ CHK_ERR_WIN32A(ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED)
+ CHK_ERR_WIN32A(ERROR_PRINT_MONITOR_ALREADY_INSTALLED)
+ CHK_ERR_WIN32A(ERROR_INVALID_PRINT_MONITOR)
+ CHK_ERR_WIN32A(ERROR_PRINT_MONITOR_IN_USE)
+ CHK_ERR_WIN32A(ERROR_PRINTER_HAS_JOBS_QUEUED)
+ CHK_ERR_WIN32A(ERROR_SUCCESS_REBOOT_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_SUCCESS_RESTART_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_PRINTER_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_WINS_INTERNAL)
+ CHK_ERR_WIN32A(ERROR_CAN_NOT_DEL_LOCAL_WINS)
+ CHK_ERR_WIN32A(ERROR_STATIC_INIT)
+ CHK_ERR_WIN32A(ERROR_INC_BACKUP)
+ CHK_ERR_WIN32A(ERROR_FULL_BACKUP)
+ CHK_ERR_WIN32A(ERROR_REC_NON_EXISTENT)
+ CHK_ERR_WIN32A(ERROR_RPL_NOT_ALLOWED)
+ CHK_ERR_WIN32A(ERROR_DHCP_ADDRESS_CONFLICT)
+ CHK_ERR_WIN32A(ERROR_WMI_GUID_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_WMI_INSTANCE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_WMI_ITEMID_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_WMI_TRY_AGAIN)
+ CHK_ERR_WIN32A(ERROR_WMI_DP_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_WMI_UNRESOLVED_INSTANCE_REF)
+ CHK_ERR_WIN32A(ERROR_WMI_ALREADY_ENABLED)
+ CHK_ERR_WIN32A(ERROR_WMI_GUID_DISCONNECTED)
+ CHK_ERR_WIN32A(ERROR_WMI_SERVER_UNAVAILABLE)
+ CHK_ERR_WIN32A(ERROR_WMI_DP_FAILED)
+ CHK_ERR_WIN32A(ERROR_WMI_INVALID_MOF)
+ CHK_ERR_WIN32A(ERROR_WMI_INVALID_REGINFO)
+ CHK_ERR_WIN32A(ERROR_WMI_ALREADY_DISABLED)
+ CHK_ERR_WIN32A(ERROR_WMI_READ_ONLY)
+ CHK_ERR_WIN32A(ERROR_WMI_SET_FAILURE)
+ CHK_ERR_WIN32A(ERROR_INVALID_MEDIA)
+ CHK_ERR_WIN32A(ERROR_INVALID_LIBRARY)
+ CHK_ERR_WIN32A(ERROR_INVALID_MEDIA_POOL)
+ CHK_ERR_WIN32A(ERROR_DRIVE_MEDIA_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_MEDIA_OFFLINE)
+ CHK_ERR_WIN32A(ERROR_LIBRARY_OFFLINE)
+ CHK_ERR_WIN32A(ERROR_EMPTY)
+ CHK_ERR_WIN32A(ERROR_NOT_EMPTY)
+ CHK_ERR_WIN32A(ERROR_MEDIA_UNAVAILABLE)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_DISABLED)
+ CHK_ERR_WIN32A(ERROR_INVALID_CLEANER)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_CLEAN)
+ CHK_ERR_WIN32A(ERROR_OBJECT_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_DATABASE_FAILURE)
+ CHK_ERR_WIN32A(ERROR_DATABASE_FULL)
+ CHK_ERR_WIN32A(ERROR_MEDIA_INCOMPATIBLE)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_NOT_PRESENT)
+ CHK_ERR_WIN32A(ERROR_INVALID_OPERATION)
+ CHK_ERR_WIN32A(ERROR_MEDIA_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_DEVICE_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_REQUEST_REFUSED)
+ CHK_ERR_WIN32A(ERROR_INVALID_DRIVE_OBJECT)
+ CHK_ERR_WIN32A(ERROR_LIBRARY_FULL)
+ CHK_ERR_WIN32A(ERROR_MEDIUM_NOT_ACCESSIBLE)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_LOAD_MEDIUM)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_INVENTORY_DRIVE)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_INVENTORY_SLOT)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_INVENTORY_TRANSPORT)
+ CHK_ERR_WIN32A(ERROR_TRANSPORT_FULL)
+ CHK_ERR_WIN32A(ERROR_CONTROLLING_IEPORT)
+ CHK_ERR_WIN32A(ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA)
+ CHK_ERR_WIN32A(ERROR_CLEANER_SLOT_SET)
+ CHK_ERR_WIN32A(ERROR_CLEANER_SLOT_NOT_SET)
+ CHK_ERR_WIN32A(ERROR_CLEANER_CARTRIDGE_SPENT)
+ CHK_ERR_WIN32A(ERROR_UNEXPECTED_OMID)
+ CHK_ERR_WIN32A(ERROR_CANT_DELETE_LAST_ITEM)
+ CHK_ERR_WIN32A(ERROR_MESSAGE_EXCEEDS_MAX_SIZE)
+ CHK_ERR_WIN32A(ERROR_FILE_OFFLINE)
+ CHK_ERR_WIN32A(ERROR_REMOTE_STORAGE_NOT_ACTIVE)
+ CHK_ERR_WIN32A(ERROR_REMOTE_STORAGE_MEDIA_ERROR)
+ CHK_ERR_WIN32A(ERROR_NOT_A_REPARSE_POINT)
+ CHK_ERR_WIN32A(ERROR_REPARSE_ATTRIBUTE_CONFLICT)
+ CHK_ERR_WIN32A(ERROR_INVALID_REPARSE_DATA)
+ CHK_ERR_WIN32A(ERROR_DEPENDENT_RESOURCE_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DEPENDENCY_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_DEPENDENCY_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_NOT_ONLINE)
+ CHK_ERR_WIN32A(ERROR_HOST_NODE_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_SHUTDOWN_CLUSTER)
+ CHK_ERR_WIN32A(ERROR_CANT_EVICT_ACTIVE_NODE)
+ CHK_ERR_WIN32A(ERROR_OBJECT_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_OBJECT_IN_LIST)
+ CHK_ERR_WIN32A(ERROR_GROUP_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_GROUP_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_GROUP_NOT_ONLINE)
+ CHK_ERR_WIN32A(ERROR_HOST_NODE_NOT_RESOURCE_OWNER)
+ CHK_ERR_WIN32A(ERROR_HOST_NODE_NOT_GROUP_OWNER)
+ CHK_ERR_WIN32A(ERROR_RESMON_CREATE_FAILED)
+ CHK_ERR_WIN32A(ERROR_RESMON_ONLINE_FAILED)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_ONLINE)
+ CHK_ERR_WIN32A(ERROR_QUORUM_RESOURCE)
+ CHK_ERR_WIN32A(ERROR_NOT_QUORUM_CAPABLE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_SHUTTING_DOWN)
+ CHK_ERR_WIN32A(ERROR_INVALID_STATE)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_PROPERTIES_STORED)
+ CHK_ERR_WIN32A(ERROR_NOT_QUORUM_CLASS)
+ CHK_ERR_WIN32A(ERROR_CORE_RESOURCE)
+ CHK_ERR_WIN32A(ERROR_QUORUM_RESOURCE_ONLINE_FAILED)
+ CHK_ERR_WIN32A(ERROR_QUORUMLOG_OPEN_FAILED)
+ CHK_ERR_WIN32A(ERROR_CLUSTERLOG_CORRUPT)
+ CHK_ERR_WIN32A(ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE)
+ CHK_ERR_WIN32A(ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE)
+ CHK_ERR_WIN32A(ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE)
+ CHK_ERR_WIN32A(ERROR_ENCRYPTION_FAILED)
+ CHK_ERR_WIN32A(ERROR_DECRYPTION_FAILED)
+ CHK_ERR_WIN32A(ERROR_FILE_ENCRYPTED)
+ CHK_ERR_WIN32A(ERROR_NO_RECOVERY_POLICY)
+ CHK_ERR_WIN32A(ERROR_NO_EFS)
+ CHK_ERR_WIN32A(ERROR_WRONG_EFS)
+ CHK_ERR_WIN32A(ERROR_NO_USER_KEYS)
+ CHK_ERR_WIN32A(ERROR_FILE_NOT_ENCRYPTED)
+ CHK_ERR_WIN32A(ERROR_NOT_EXPORT_FORMAT)
+ CHK_ERR_WIN32A(ERROR_NO_BROWSER_SERVERS_FOUND)
+ CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_NAME_INVALID)
+ CHK_ERR_WIN32A(ERROR_CTX_INVALID_PD)
+ CHK_ERR_WIN32A(ERROR_CTX_PD_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CTX_WD_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY)
+ CHK_ERR_WIN32A(ERROR_CTX_SERVICE_NAME_COLLISION)
+ CHK_ERR_WIN32A(ERROR_CTX_CLOSE_PENDING)
+ CHK_ERR_WIN32A(ERROR_CTX_NO_OUTBUF)
+ CHK_ERR_WIN32A(ERROR_CTX_MODEM_INF_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CTX_INVALID_MODEMNAME)
+ CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_ERROR)
+ CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_TIMEOUT)
+ CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_NO_CARRIER)
+ CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE)
+ CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_BUSY)
+ CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_VOICE)
+ CHK_ERR_WIN32A(ERROR_CTX_TD_ERROR)
+ CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_BUSY)
+ CHK_ERR_WIN32A(ERROR_CTX_BAD_VIDEO_MODE)
+ CHK_ERR_WIN32A(ERROR_CTX_GRAPHICS_INVALID)
+ CHK_ERR_WIN32A(ERROR_CTX_LOGON_DISABLED)
+ CHK_ERR_WIN32A(ERROR_CTX_NOT_CONSOLE)
+ CHK_ERR_WIN32A(ERROR_CTX_CLIENT_QUERY_TIMEOUT)
+ CHK_ERR_WIN32A(ERROR_CTX_CONSOLE_DISCONNECT)
+ CHK_ERR_WIN32A(ERROR_CTX_CONSOLE_CONNECT)
+ CHK_ERR_WIN32A(ERROR_CTX_SHADOW_DENIED)
+ CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_ACCESS_DENIED)
+ CHK_ERR_WIN32A(ERROR_CTX_INVALID_WD)
+ CHK_ERR_WIN32A(ERROR_CTX_SHADOW_INVALID)
+ CHK_ERR_WIN32A(ERROR_CTX_SHADOW_DISABLED)
+ CHK_ERR_WIN32A(FRS_ERR_INVALID_API_SEQUENCE)
+ CHK_ERR_WIN32A(FRS_ERR_STARTING_SERVICE)
+ CHK_ERR_WIN32A(FRS_ERR_STOPPING_SERVICE)
+ CHK_ERR_WIN32A(FRS_ERR_INTERNAL_API)
+ CHK_ERR_WIN32A(FRS_ERR_INTERNAL)
+ CHK_ERR_WIN32A(FRS_ERR_SERVICE_COMM)
+ CHK_ERR_WIN32A(FRS_ERR_INSUFFICIENT_PRIV)
+ CHK_ERR_WIN32A(FRS_ERR_AUTHENTICATION)
+ CHK_ERR_WIN32A(FRS_ERR_PARENT_INSUFFICIENT_PRIV)
+ CHK_ERR_WIN32A(FRS_ERR_PARENT_AUTHENTICATION)
+ CHK_ERR_WIN32A(FRS_ERR_CHILD_TO_PARENT_COMM)
+ CHK_ERR_WIN32A(FRS_ERR_PARENT_TO_CHILD_COMM)
+ CHK_ERR_WIN32A(FRS_ERR_SYSVOL_POPULATE)
+ CHK_ERR_WIN32A(FRS_ERR_SYSVOL_POPULATE_TIMEOUT)
+ CHK_ERR_WIN32A(FRS_ERR_SYSVOL_IS_BUSY)
+ CHK_ERR_WIN32A(FRS_ERR_SYSVOL_DEMOTE)
+ CHK_ERR_WIN32A(FRS_ERR_INVALID_SERVICE_PARAMETER)
+// CHK_ERR_WIN32A(DS_S_SUCCESS)
+ CHK_ERR_WIN32A(ERROR_DS_NOT_INSTALLED)
+ CHK_ERR_WIN32A(ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY)
+ CHK_ERR_WIN32A(ERROR_DS_NO_ATTRIBUTE_OR_VALUE)
+ CHK_ERR_WIN32A(ERROR_DS_INVALID_ATTRIBUTE_SYNTAX)
+ CHK_ERR_WIN32A(ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED)
+ CHK_ERR_WIN32A(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DS_BUSY)
+ CHK_ERR_WIN32A(ERROR_DS_UNAVAILABLE)
+ CHK_ERR_WIN32A(ERROR_DS_NO_RIDS_ALLOCATED)
+ CHK_ERR_WIN32A(ERROR_DS_NO_MORE_RIDS)
+ CHK_ERR_WIN32A(ERROR_DS_INCORRECT_ROLE_OWNER)
+ CHK_ERR_WIN32A(ERROR_DS_RIDMGR_INIT_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_OBJ_CLASS_VIOLATION)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_ON_NON_LEAF)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_ON_RDN)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_MOD_OBJ_CLASS)
+ CHK_ERR_WIN32A(ERROR_DS_CROSS_DOM_MOVE_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_GC_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_SHARED_POLICY)
+ CHK_ERR_WIN32A(ERROR_POLICY_OBJECT_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_POLICY_ONLY_IN_DS)
+ CHK_ERR_WIN32A(ERROR_PROMOTION_ACTIVE)
+ CHK_ERR_WIN32A(ERROR_NO_PROMOTION_ACTIVE)
+ CHK_ERR_WIN32A(ERROR_DS_OPERATIONS_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_PROTOCOL_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_TIMELIMIT_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_DS_SIZELIMIT_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_DS_ADMIN_LIMIT_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_DS_COMPARE_FALSE)
+ CHK_ERR_WIN32A(ERROR_DS_COMPARE_TRUE)
+ CHK_ERR_WIN32A(ERROR_DS_AUTH_METHOD_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_DS_STRONG_AUTH_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_DS_INAPPROPRIATE_AUTH)
+ CHK_ERR_WIN32A(ERROR_DS_AUTH_UNKNOWN)
+ CHK_ERR_WIN32A(ERROR_DS_REFERRAL)
+ CHK_ERR_WIN32A(ERROR_DS_UNAVAILABLE_CRIT_EXTENSION)
+ CHK_ERR_WIN32A(ERROR_DS_CONFIDENTIALITY_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_DS_INAPPROPRIATE_MATCHING)
+ CHK_ERR_WIN32A(ERROR_DS_CONSTRAINT_VIOLATION)
+ CHK_ERR_WIN32A(ERROR_DS_NO_SUCH_OBJECT)
+ CHK_ERR_WIN32A(ERROR_DS_ALIAS_PROBLEM)
+ CHK_ERR_WIN32A(ERROR_DS_INVALID_DN_SYNTAX)
+ CHK_ERR_WIN32A(ERROR_DS_IS_LEAF)
+ CHK_ERR_WIN32A(ERROR_DS_ALIAS_DEREF_PROBLEM)
+ CHK_ERR_WIN32A(ERROR_DS_UNWILLING_TO_PERFORM)
+ CHK_ERR_WIN32A(ERROR_DS_LOOP_DETECT)
+ CHK_ERR_WIN32A(ERROR_DS_NAMING_VIOLATION)
+ CHK_ERR_WIN32A(ERROR_DS_OBJECT_RESULTS_TOO_LARGE)
+ CHK_ERR_WIN32A(ERROR_DS_AFFECTS_MULTIPLE_DSAS)
+ CHK_ERR_WIN32A(ERROR_DS_SERVER_DOWN)
+ CHK_ERR_WIN32A(ERROR_DS_LOCAL_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_ENCODING_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_DECODING_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_FILTER_UNKNOWN)
+ CHK_ERR_WIN32A(ERROR_DS_PARAM_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_DS_NO_RESULTS_RETURNED)
+ CHK_ERR_WIN32A(ERROR_DS_CONTROL_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_DS_CLIENT_LOOP)
+ CHK_ERR_WIN32A(ERROR_DS_REFERRAL_LIMIT_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_DS_ROOT_MUST_BE_NC)
+ CHK_ERR_WIN32A(ERROR_DS_ADD_REPLICA_INHIBITED)
+ CHK_ERR_WIN32A(ERROR_DS_ATT_NOT_DEF_IN_SCHEMA)
+ CHK_ERR_WIN32A(ERROR_DS_MAX_OBJ_SIZE_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_DS_OBJ_STRING_NAME_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA)
+ CHK_ERR_WIN32A(ERROR_DS_RDN_DOESNT_MATCH_SCHEMA)
+ CHK_ERR_WIN32A(ERROR_DS_NO_REQUESTED_ATTS_FOUND)
+ CHK_ERR_WIN32A(ERROR_DS_USER_BUFFER_TO_SMALL)
+ CHK_ERR_WIN32A(ERROR_DS_ATT_IS_NOT_ON_OBJ)
+ CHK_ERR_WIN32A(ERROR_DS_ILLEGAL_MOD_OPERATION)
+ CHK_ERR_WIN32A(ERROR_DS_OBJ_TOO_LARGE)
+ CHK_ERR_WIN32A(ERROR_DS_BAD_INSTANCE_TYPE)
+ CHK_ERR_WIN32A(ERROR_DS_MASTERDSA_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_DS_OBJECT_CLASS_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_DS_MISSING_REQUIRED_ATT)
+ CHK_ERR_WIN32A(ERROR_DS_ATT_NOT_DEF_FOR_CLASS)
+ CHK_ERR_WIN32A(ERROR_DS_ATT_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_ADD_ATT_VALUES)
+ CHK_ERR_WIN32A(ERROR_DS_SINGLE_VALUE_CONSTRAINT)
+ CHK_ERR_WIN32A(ERROR_DS_RANGE_CONSTRAINT)
+ CHK_ERR_WIN32A(ERROR_DS_ATT_VAL_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_REM_MISSING_ATT)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_REM_MISSING_ATT_VAL)
+ CHK_ERR_WIN32A(ERROR_DS_ROOT_CANT_BE_SUBREF)
+ CHK_ERR_WIN32A(ERROR_DS_NO_CHAINING)
+ CHK_ERR_WIN32A(ERROR_DS_NO_CHAINED_EVAL)
+ CHK_ERR_WIN32A(ERROR_DS_NO_PARENT_OBJECT)
+ CHK_ERR_WIN32A(ERROR_DS_PARENT_IS_AN_ALIAS)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_MIX_MASTER_AND_REPS)
+ CHK_ERR_WIN32A(ERROR_DS_CHILDREN_EXIST)
+ CHK_ERR_WIN32A(ERROR_DS_OBJ_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_DS_ALIASED_OBJ_MISSING)
+ CHK_ERR_WIN32A(ERROR_DS_BAD_NAME_SYNTAX)
+ CHK_ERR_WIN32A(ERROR_DS_ALIAS_POINTS_TO_ALIAS)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_DEREF_ALIAS)
+ CHK_ERR_WIN32A(ERROR_DS_OUT_OF_SCOPE)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_DELETE_DSA_OBJ)
+ CHK_ERR_WIN32A(ERROR_DS_GENERIC_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_DSA_MUST_BE_INT_MASTER)
+ CHK_ERR_WIN32A(ERROR_DS_CLASS_NOT_DSA)
+ CHK_ERR_WIN32A(ERROR_DS_INSUFF_ACCESS_RIGHTS)
+ CHK_ERR_WIN32A(ERROR_DS_ILLEGAL_SUPERIOR)
+ CHK_ERR_WIN32A(ERROR_DS_ATTRIBUTE_OWNED_BY_SAM)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_TOO_MANY_PARTS)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_TOO_LONG)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_VALUE_TOO_LONG)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_UNPARSEABLE)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_TYPE_UNKNOWN)
+ CHK_ERR_WIN32A(ERROR_DS_NOT_AN_OBJECT)
+ CHK_ERR_WIN32A(ERROR_DS_SEC_DESC_TOO_SHORT)
+ CHK_ERR_WIN32A(ERROR_DS_SEC_DESC_INVALID)
+ CHK_ERR_WIN32A(ERROR_DS_NO_DELETED_NAME)
+ CHK_ERR_WIN32A(ERROR_DS_SUBREF_MUST_HAVE_PARENT)
+ CHK_ERR_WIN32A(ERROR_DS_NCNAME_MUST_BE_NC)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_ADD_SYSTEM_ONLY)
+ CHK_ERR_WIN32A(ERROR_DS_CLASS_MUST_BE_CONCRETE)
+ CHK_ERR_WIN32A(ERROR_DS_INVALID_DMD)
+ CHK_ERR_WIN32A(ERROR_DS_OBJ_GUID_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DS_NOT_ON_BACKLINK)
+ CHK_ERR_WIN32A(ERROR_DS_NO_CROSSREF_FOR_NC)
+ CHK_ERR_WIN32A(ERROR_DS_SHUTTING_DOWN)
+ CHK_ERR_WIN32A(ERROR_DS_UNKNOWN_OPERATION)
+ CHK_ERR_WIN32A(ERROR_DS_INVALID_ROLE_OWNER)
+ CHK_ERR_WIN32A(ERROR_DS_COULDNT_CONTACT_FSMO)
+ CHK_ERR_WIN32A(ERROR_DS_CROSS_NC_DN_RENAME)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_MOD_SYSTEM_ONLY)
+ CHK_ERR_WIN32A(ERROR_DS_REPLICATOR_ONLY)
+ CHK_ERR_WIN32A(ERROR_DS_OBJ_CLASS_NOT_DEFINED)
+ CHK_ERR_WIN32A(ERROR_DS_OBJ_CLASS_NOT_SUBCLASS)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_REFERENCE_INVALID)
+ CHK_ERR_WIN32A(ERROR_DS_CROSS_REF_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_DEL_MASTER_CROSSREF)
+ CHK_ERR_WIN32A(ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD)
+ CHK_ERR_WIN32A(ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX)
+ CHK_ERR_WIN32A(ERROR_DS_DUP_RDN)
+ CHK_ERR_WIN32A(ERROR_DS_DUP_OID)
+ CHK_ERR_WIN32A(ERROR_DS_DUP_MAPI_ID)
+ CHK_ERR_WIN32A(ERROR_DS_DUP_SCHEMA_ID_GUID)
+ CHK_ERR_WIN32A(ERROR_DS_DUP_LDAP_DISPLAY_NAME)
+ CHK_ERR_WIN32A(ERROR_DS_SEMANTIC_ATT_TEST)
+ CHK_ERR_WIN32A(ERROR_DS_SYNTAX_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_MUST_HAVE)
+ CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_MAY_HAVE)
+ CHK_ERR_WIN32A(ERROR_DS_NONEXISTENT_MAY_HAVE)
+ CHK_ERR_WIN32A(ERROR_DS_NONEXISTENT_MUST_HAVE)
+ CHK_ERR_WIN32A(ERROR_DS_AUX_CLS_TEST_FAIL)
+ CHK_ERR_WIN32A(ERROR_DS_NONEXISTENT_POSS_SUP)
+ CHK_ERR_WIN32A(ERROR_DS_SUB_CLS_TEST_FAIL)
+ CHK_ERR_WIN32A(ERROR_DS_BAD_RDN_ATT_ID_SYNTAX)
+ CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_AUX_CLS)
+ CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_SUB_CLS)
+ CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_POSS_SUP)
+ CHK_ERR_WIN32A(ERROR_DS_RECALCSCHEMA_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_TREE_DELETE_NOT_FINISHED)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_DELETE)
+ CHK_ERR_WIN32A(ERROR_DS_ATT_SCHEMA_REQ_ID)
+ CHK_ERR_WIN32A(ERROR_DS_BAD_ATT_SCHEMA_SYNTAX)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_CACHE_ATT)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_CACHE_CLASS)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_REMOVE_ATT_CACHE)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_REMOVE_CLASS_CACHE)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_DN)
+ CHK_ERR_WIN32A(ERROR_DS_MISSING_SUPREF)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_INSTANCE)
+ CHK_ERR_WIN32A(ERROR_DS_CODE_INCONSISTENCY)
+ CHK_ERR_WIN32A(ERROR_DS_DATABASE_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_GOVERNSID_MISSING)
+ CHK_ERR_WIN32A(ERROR_DS_MISSING_EXPECTED_ATT)
+ CHK_ERR_WIN32A(ERROR_DS_NCNAME_MISSING_CR_REF)
+ CHK_ERR_WIN32A(ERROR_DS_SECURITY_CHECKING_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_SCHEMA_NOT_LOADED)
+ CHK_ERR_WIN32A(ERROR_DS_SCHEMA_ALLOC_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_ATT_SCHEMA_REQ_SYNTAX)
+ CHK_ERR_WIN32A(ERROR_DS_GCVERIFY_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_SCHEMA_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_FIND_DSA_OBJ)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_FIND_EXPECTED_NC)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_FIND_NC_IN_CACHE)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_CHILD)
+ CHK_ERR_WIN32A(ERROR_DS_SECURITY_ILLEGAL_MODIFY)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_REPLACE_HIDDEN_REC)
+ CHK_ERR_WIN32A(ERROR_DS_BAD_HIERARCHY_FILE)
+ CHK_ERR_WIN32A(ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_CONFIG_PARAM_MISSING)
+ CHK_ERR_WIN32A(ERROR_DS_COUNTING_AB_INDICES_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_INTERNAL_FAILURE)
+ CHK_ERR_WIN32A(ERROR_DS_UNKNOWN_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_ROOT_REQUIRES_CLASS_TOP)
+ CHK_ERR_WIN32A(ERROR_DS_REFUSING_FSMO_ROLES)
+ CHK_ERR_WIN32A(ERROR_DS_MISSING_FSMO_SETTINGS)
+ CHK_ERR_WIN32A(ERROR_DS_UNABLE_TO_SURRENDER_ROLES)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_GENERIC)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_INVALID_PARAMETER)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_BUSY)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_BAD_DN)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_BAD_NC)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_DN_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_INTERNAL_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_INCONSISTENT_DIT)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_CONNECTION_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_BAD_INSTANCE_TYPE)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_OUT_OF_MEM)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_MAIL_PROBLEM)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_REF_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_REF_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_OBJ_IS_REP_SOURCE)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_DB_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_NO_REPLICA)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_ACCESS_DENIED)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_RPC_CANCELLED)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_SOURCE_DISABLED)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_SINK_DISABLED)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_NAME_COLLISION)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_SOURCE_REINSTALLED)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_MISSING_PARENT)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_PREEMPTED)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_ABANDON_SYNC)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_SHUTDOWN)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_EXTN_CONNECTION_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_INSTALL_SCHEMA_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_DS_DUP_LINK_ID)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_RESOLVING)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_NOT_UNIQUE)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_NO_MAPPING)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_DOMAIN_ONLY)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING)
+ CHK_ERR_WIN32A(ERROR_DS_CONSTRUCTED_ATT_MOD)
+ CHK_ERR_WIN32A(ERROR_DS_WRONG_OM_OBJ_CLASS)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_REPL_PENDING)
+ CHK_ERR_WIN32A(DNS_ERROR_RESPONSE_CODES_BASE)
+// CHK_ERR_WIN32A(DNS_ERROR_MASK)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_FORMAT_ERROR)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_SERVER_FAILURE)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_NAME_ERROR)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_NOT_IMPLEMENTED)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_REFUSED)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_YXDOMAIN)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_YXRRSET)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_NXRRSET)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_NOTAUTH)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_NOTZONE)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_BADSIG)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_BADKEY)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE_BADTIME)
+ CHK_ERR_WIN32A(DNS_ERROR_PACKET_FMT_BASE)
+ CHK_ERR_WIN32A(DNS_INFO_NO_RECORDS)
+ CHK_ERR_WIN32A(DNS_ERROR_BAD_PACKET)
+ CHK_ERR_WIN32A(DNS_ERROR_NO_PACKET)
+ CHK_ERR_WIN32A(DNS_ERROR_RCODE)
+ CHK_ERR_WIN32A(DNS_ERROR_UNSECURE_PACKET)
+ CHK_ERR_WIN32A(DNS_ERROR_GENERAL_API_BASE)
+ CHK_ERR_WIN32A(DNS_ERROR_INVALID_TYPE)
+ CHK_ERR_WIN32A(DNS_ERROR_INVALID_IP_ADDRESS)
+ CHK_ERR_WIN32A(DNS_ERROR_INVALID_PROPERTY)
+ CHK_ERR_WIN32A(DNS_ERROR_TRY_AGAIN_LATER)
+ CHK_ERR_WIN32A(DNS_ERROR_NOT_UNIQUE)
+ CHK_ERR_WIN32A(DNS_ERROR_NON_RFC_NAME)
+ CHK_ERR_WIN32A(DNS_STATUS_FQDN)
+ CHK_ERR_WIN32A(DNS_STATUS_DOTTED_NAME)
+ CHK_ERR_WIN32A(DNS_STATUS_SINGLE_PART_NAME)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_BASE)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_DOES_NOT_EXIST)
+ CHK_ERR_WIN32A(DNS_ERROR_NO_ZONE_INFO)
+ CHK_ERR_WIN32A(DNS_ERROR_INVALID_ZONE_OPERATION)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_CONFIGURATION_ERROR)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_HAS_NO_SOA_RECORD)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_HAS_NO_NS_RECORDS)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_LOCKED)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_CREATION_FAILED)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(DNS_ERROR_AUTOZONE_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(DNS_ERROR_INVALID_ZONE_TYPE)
+ CHK_ERR_WIN32A(DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_NOT_SECONDARY)
+ CHK_ERR_WIN32A(DNS_ERROR_NEED_SECONDARY_ADDRESSES)
+ CHK_ERR_WIN32A(DNS_ERROR_WINS_INIT_FAILED)
+ CHK_ERR_WIN32A(DNS_ERROR_NEED_WINS_SERVERS)
+ CHK_ERR_WIN32A(DNS_ERROR_NBSTAT_INIT_FAILED)
+ CHK_ERR_WIN32A(DNS_ERROR_SOA_DELETE_INVALID)
+ CHK_ERR_WIN32A(DNS_ERROR_DATAFILE_BASE)
+ CHK_ERR_WIN32A(DNS_ERROR_PRIMARY_REQUIRES_DATAFILE)
+ CHK_ERR_WIN32A(DNS_ERROR_INVALID_DATAFILE_NAME)
+ CHK_ERR_WIN32A(DNS_ERROR_DATAFILE_OPEN_FAILURE)
+ CHK_ERR_WIN32A(DNS_ERROR_FILE_WRITEBACK_FAILED)
+ CHK_ERR_WIN32A(DNS_ERROR_DATAFILE_PARSING)
+ CHK_ERR_WIN32A(DNS_ERROR_DATABASE_BASE)
+ CHK_ERR_WIN32A(DNS_ERROR_RECORD_DOES_NOT_EXIST)
+ CHK_ERR_WIN32A(DNS_ERROR_RECORD_FORMAT)
+ CHK_ERR_WIN32A(DNS_ERROR_NODE_CREATION_FAILED)
+ CHK_ERR_WIN32A(DNS_ERROR_UNKNOWN_RECORD_TYPE)
+ CHK_ERR_WIN32A(DNS_ERROR_RECORD_TIMED_OUT)
+ CHK_ERR_WIN32A(DNS_ERROR_NAME_NOT_IN_ZONE)
+ CHK_ERR_WIN32A(DNS_ERROR_CNAME_LOOP)
+ CHK_ERR_WIN32A(DNS_ERROR_NODE_IS_CNAME)
+ CHK_ERR_WIN32A(DNS_ERROR_CNAME_COLLISION)
+ CHK_ERR_WIN32A(DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT)
+ CHK_ERR_WIN32A(DNS_ERROR_RECORD_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(DNS_ERROR_SECONDARY_DATA)
+ CHK_ERR_WIN32A(DNS_ERROR_NO_CREATE_CACHE_DATA)
+ CHK_ERR_WIN32A(DNS_ERROR_NAME_DOES_NOT_EXIST)
+ CHK_ERR_WIN32A(DNS_WARNING_PTR_CREATE_FAILED)
+ CHK_ERR_WIN32A(DNS_WARNING_DOMAIN_UNDELETED)
+ CHK_ERR_WIN32A(DNS_ERROR_DS_UNAVAILABLE)
+ CHK_ERR_WIN32A(DNS_ERROR_DS_ZONE_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE)
+ CHK_ERR_WIN32A(DNS_ERROR_OPERATION_BASE)
+ CHK_ERR_WIN32A(DNS_INFO_AXFR_COMPLETE)
+ CHK_ERR_WIN32A(DNS_ERROR_AXFR)
+ CHK_ERR_WIN32A(DNS_INFO_ADDED_LOCAL_WINS)
+ CHK_ERR_WIN32A(DNS_ERROR_SECURE_BASE)
+ CHK_ERR_WIN32A(DNS_STATUS_CONTINUE_NEEDED)
+ CHK_ERR_WIN32A(DNS_ERROR_SETUP_BASE)
+ CHK_ERR_WIN32A(DNS_ERROR_NO_TCPIP)
+ CHK_ERR_WIN32A(DNS_ERROR_NO_DNS_SERVERS)
+ CHK_ERR_WIN32A(WSABASEERR)
+ CHK_ERR_WIN32A(WSAEINTR)
+ CHK_ERR_WIN32A(WSAEBADF)
+ CHK_ERR_WIN32A(WSAEACCES)
+ CHK_ERR_WIN32A(WSAEFAULT)
+ CHK_ERR_WIN32A(WSAEINVAL)
+ CHK_ERR_WIN32A(WSAEMFILE)
+ CHK_ERR_WIN32A(WSAEWOULDBLOCK)
+ CHK_ERR_WIN32A(WSAEINPROGRESS)
+ CHK_ERR_WIN32A(WSAEALREADY)
+ CHK_ERR_WIN32A(WSAENOTSOCK)
+ CHK_ERR_WIN32A(WSAEDESTADDRREQ)
+ CHK_ERR_WIN32A(WSAEMSGSIZE)
+ CHK_ERR_WIN32A(WSAEPROTOTYPE)
+ CHK_ERR_WIN32A(WSAENOPROTOOPT)
+ CHK_ERR_WIN32A(WSAEPROTONOSUPPORT)
+ CHK_ERR_WIN32A(WSAESOCKTNOSUPPORT)
+ CHK_ERR_WIN32A(WSAEOPNOTSUPP)
+ CHK_ERR_WIN32A(WSAEPFNOSUPPORT)
+ CHK_ERR_WIN32A(WSAEAFNOSUPPORT)
+ CHK_ERR_WIN32A(WSAEADDRINUSE)
+ CHK_ERR_WIN32A(WSAEADDRNOTAVAIL)
+ CHK_ERR_WIN32A(WSAENETDOWN)
+ CHK_ERR_WIN32A(WSAENETUNREACH)
+ CHK_ERR_WIN32A(WSAENETRESET)
+ CHK_ERR_WIN32A(WSAECONNABORTED)
+ CHK_ERR_WIN32A(WSAECONNRESET)
+ CHK_ERR_WIN32A(WSAENOBUFS)
+ CHK_ERR_WIN32A(WSAEISCONN)
+ CHK_ERR_WIN32A(WSAENOTCONN)
+ CHK_ERR_WIN32A(WSAESHUTDOWN)
+ CHK_ERR_WIN32A(WSAETOOMANYREFS)
+ CHK_ERR_WIN32A(WSAETIMEDOUT)
+ CHK_ERR_WIN32A(WSAECONNREFUSED)
+ CHK_ERR_WIN32A(WSAELOOP)
+ CHK_ERR_WIN32A(WSAENAMETOOLONG)
+ CHK_ERR_WIN32A(WSAEHOSTDOWN)
+ CHK_ERR_WIN32A(WSAEHOSTUNREACH)
+ CHK_ERR_WIN32A(WSAENOTEMPTY)
+ CHK_ERR_WIN32A(WSAEPROCLIM)
+ CHK_ERR_WIN32A(WSAEUSERS)
+ CHK_ERR_WIN32A(WSAEDQUOT)
+ CHK_ERR_WIN32A(WSAESTALE)
+ CHK_ERR_WIN32A(WSAEREMOTE)
+ CHK_ERR_WIN32A(WSASYSNOTREADY)
+ CHK_ERR_WIN32A(WSAVERNOTSUPPORTED)
+ CHK_ERR_WIN32A(WSANOTINITIALISED)
+ CHK_ERR_WIN32A(WSAEDISCON)
+ CHK_ERR_WIN32A(WSAENOMORE)
+ CHK_ERR_WIN32A(WSAECANCELLED)
+ CHK_ERR_WIN32A(WSAEINVALIDPROCTABLE)
+ CHK_ERR_WIN32A(WSAEINVALIDPROVIDER)
+ CHK_ERR_WIN32A(WSAEPROVIDERFAILEDINIT)
+ CHK_ERR_WIN32A(WSASYSCALLFAILURE)
+ CHK_ERR_WIN32A(WSASERVICE_NOT_FOUND)
+ CHK_ERR_WIN32A(WSATYPE_NOT_FOUND)
+ CHK_ERR_WIN32A(WSA_E_NO_MORE)
+ CHK_ERR_WIN32A(WSA_E_CANCELLED)
+ CHK_ERR_WIN32A(WSAEREFUSED)
+ CHK_ERR_WIN32A(WSAHOST_NOT_FOUND)
+ CHK_ERR_WIN32A(WSATRY_AGAIN)
+ CHK_ERR_WIN32A(WSANO_RECOVERY)
+ CHK_ERR_WIN32A(WSANO_DATA)
+ CHK_ERR_WIN32A(WSA_QOS_RECEIVERS)
+ CHK_ERR_WIN32A(WSA_QOS_SENDERS)
+ CHK_ERR_WIN32A(WSA_QOS_NO_SENDERS)
+ CHK_ERR_WIN32A(WSA_QOS_NO_RECEIVERS)
+ CHK_ERR_WIN32A(WSA_QOS_REQUEST_CONFIRMED)
+ CHK_ERR_WIN32A(WSA_QOS_ADMISSION_FAILURE)
+ CHK_ERR_WIN32A(WSA_QOS_POLICY_FAILURE)
+ CHK_ERR_WIN32A(WSA_QOS_BAD_STYLE)
+ CHK_ERR_WIN32A(WSA_QOS_BAD_OBJECT)
+ CHK_ERR_WIN32A(WSA_QOS_TRAFFIC_CTRL_ERROR)
+ CHK_ERR_WIN32A(WSA_QOS_GENERIC_ERROR)
+
+ CHK_ERRA(CO_E_ATTEMPT_TO_CREATE_OUTSIDE_CLIENT_CONTEXT)
+ CHK_ERRA(CO_E_SERVER_PAUSED)
+ CHK_ERRA(CO_E_SERVER_NOT_PAUSED)
+ CHK_ERRA(CO_E_CLASS_DISABLED)
+ CHK_ERRA(CO_E_CLRNOTAVAILABLE)
+ CHK_ERRA(CO_E_ASYNC_WORK_REJECTED)
+ CHK_ERRA(CO_E_SERVER_INIT_TIMEOUT)
+ CHK_ERRA(CO_E_NO_SECCTX_IN_ACTIVATE)
+ CHK_ERRA(CO_E_TRACKER_CONFIG)
+ CHK_ERRA(CO_E_THREADPOOL_CONFIG)
+ CHK_ERRA(CO_E_SXS_CONFIG)
+ CHK_ERRA(CO_E_MALFORMED_SPN)
+ CHK_ERRA(REGDB_E_BADTHREADINGMODEL)
+// CHK_ERRA(EVENT_E_FIRST)
+// CHK_ERRA(EVENT_E_LAST)
+// CHK_ERRA(EVENT_S_FIRST)
+// CHK_ERRA(EVENT_S_LAST)
+// CHK_ERRA(EVENT_S_SOME_SUBSCRIBERS_FAILED)
+// CHK_ERRA(EVENT_E_ALL_SUBSCRIBERS_FAILED)
+ CHK_ERRA(EVENT_S_NOSUBSCRIBERS)
+// CHK_ERRA(EVENT_E_QUERYSYNTAX)
+// CHK_ERRA(EVENT_E_QUERYFIELD)
+// CHK_ERRA(EVENT_E_INTERNALEXCEPTION)
+// CHK_ERRA(EVENT_E_INTERNALERROR)
+// CHK_ERRA(EVENT_E_INVALID_PER_USER_SID)
+// CHK_ERRA(EVENT_E_USER_EXCEPTION)
+// CHK_ERRA(EVENT_E_TOO_MANY_METHODS)
+// CHK_ERRA(EVENT_E_MISSING_EVENTCLASS)
+// CHK_ERRA(EVENT_E_NOT_ALL_REMOVED)
+// CHK_ERRA(EVENT_E_COMPLUS_NOT_INSTALLED)
+// CHK_ERRA(EVENT_E_CANT_MODIFY_OR_DELETE_UNCONFIGURED_OBJECT)
+// CHK_ERRA(EVENT_E_CANT_MODIFY_OR_DELETE_CONFIGURED_OBJECT)
+// CHK_ERRA(EVENT_E_INVALID_EVENT_CLASS_PARTITION)
+// CHK_ERRA(EVENT_E_PER_USER_SID_NOT_LOGGED_ON)
+ CHK_ERRA(CONTEXT_E_FIRST)
+ CHK_ERRA(CONTEXT_E_LAST)
+ CHK_ERRA(CONTEXT_S_FIRST)
+ CHK_ERRA(CONTEXT_S_LAST)
+ CHK_ERRA(CONTEXT_E_ABORTED)
+ CHK_ERRA(CONTEXT_E_ABORTING)
+ CHK_ERRA(CONTEXT_E_NOCONTEXT)
+// CHK_ERRA(CONTEXT_E_WOULD_DEADLOCK)
+ CHK_ERRA(CONTEXT_E_SYNCH_TIMEOUT)
+ CHK_ERRA(CONTEXT_E_OLDREF)
+ CHK_ERRA(CONTEXT_E_ROLENOTFOUND)
+ CHK_ERRA(CONTEXT_E_TMNOTAVAILABLE)
+ CHK_ERRA(CO_E_ACTIVATIONFAILED)
+ CHK_ERRA(CO_E_ACTIVATIONFAILED_EVENTLOGGED)
+ CHK_ERRA(CO_E_ACTIVATIONFAILED_CATALOGERROR)
+ CHK_ERRA(CO_E_ACTIVATIONFAILED_TIMEOUT)
+ CHK_ERRA(CO_E_INITIALIZATIONFAILED)
+ CHK_ERRA(CONTEXT_E_NOJIT)
+ CHK_ERRA(CONTEXT_E_NOTRANSACTION)
+ CHK_ERRA(CO_E_THREADINGMODEL_CHANGED)
+ CHK_ERRA(CO_E_NOIISINTRINSICS)
+ CHK_ERRA(CO_E_NOCOOKIES)
+ CHK_ERRA(CO_E_DBERROR)
+ CHK_ERRA(CO_E_NOTPOOLED)
+ CHK_ERRA(CO_E_NOTCONSTRUCTED)
+ CHK_ERRA(CO_E_NOSYNCHRONIZATION)
+// CHK_ERRA(CO_E_ISOLEVELMISMATCH)
+ CHK_ERRA(SCHED_S_TASK_READY)
+ CHK_ERRA(SCHED_S_TASK_RUNNING)
+ CHK_ERRA(SCHED_S_TASK_DISABLED)
+ CHK_ERRA(SCHED_S_TASK_HAS_NOT_RUN)
+ CHK_ERRA(SCHED_S_TASK_NO_MORE_RUNS)
+ CHK_ERRA(SCHED_S_TASK_NOT_SCHEDULED)
+ CHK_ERRA(SCHED_S_TASK_TERMINATED)
+ CHK_ERRA(SCHED_S_TASK_NO_VALID_TRIGGERS)
+ CHK_ERRA(SCHED_S_EVENT_TRIGGER)
+ CHK_ERRA(SCHED_E_TRIGGER_NOT_FOUND)
+ CHK_ERRA(SCHED_E_TASK_NOT_READY)
+ CHK_ERRA(SCHED_E_TASK_NOT_RUNNING)
+ CHK_ERRA(SCHED_E_SERVICE_NOT_INSTALLED)
+ CHK_ERRA(SCHED_E_CANNOT_OPEN_TASK)
+ CHK_ERRA(SCHED_E_INVALID_TASK)
+ CHK_ERRA(SCHED_E_ACCOUNT_INFORMATION_NOT_SET)
+ CHK_ERRA(SCHED_E_ACCOUNT_NAME_NOT_FOUND)
+ CHK_ERRA(SCHED_E_ACCOUNT_DBASE_CORRUPT)
+ CHK_ERRA(SCHED_E_NO_SECURITY_SERVICES)
+ CHK_ERRA(SCHED_E_UNKNOWN_OBJECT_VERSION)
+ CHK_ERRA(SCHED_E_UNSUPPORTED_ACCOUNT_OPTION)
+ CHK_ERRA(SCHED_E_SERVICE_NOT_RUNNING)
+ CHK_ERRA(CO_S_MACHINENAMENOTFOUND)
+ CHK_ERRA(STG_E_STATUS_COPY_PROTECTION_FAILURE)
+ CHK_ERRA(STG_E_CSS_AUTHENTICATION_FAILURE)
+ CHK_ERRA(STG_E_CSS_KEY_NOT_PRESENT)
+ CHK_ERRA(STG_E_CSS_KEY_NOT_ESTABLISHED)
+ CHK_ERRA(STG_E_CSS_SCRAMBLED_SECTOR)
+ CHK_ERRA(STG_E_CSS_REGION_MISMATCH)
+ CHK_ERRA(STG_E_RESETS_EXHAUSTED)
+ CHK_ERRA(CO_E_CANCEL_DISABLED)
+ CHK_ERRA(ERROR_AUDITING_DISABLED)
+ CHK_ERRA(ERROR_ALL_SIDS_FILTERED)
+ CHK_ERRA(NTE_TEMPORARY_PROFILE)
+ CHK_ERRA(NTE_FIXEDPARAMETER)
+ CHK_ERRA(SEC_E_INSUFFICIENT_MEMORY)
+ CHK_ERRA(SEC_E_INVALID_HANDLE)
+ CHK_ERRA(SEC_E_UNSUPPORTED_FUNCTION)
+ CHK_ERRA(SEC_E_TARGET_UNKNOWN)
+ CHK_ERRA(SEC_E_INTERNAL_ERROR)
+ CHK_ERRA(SEC_E_SECPKG_NOT_FOUND)
+ CHK_ERRA(SEC_E_NOT_OWNER)
+ CHK_ERRA(SEC_E_CANNOT_INSTALL)
+ CHK_ERRA(SEC_E_INVALID_TOKEN)
+ CHK_ERRA(SEC_E_CANNOT_PACK)
+ CHK_ERRA(SEC_E_QOP_NOT_SUPPORTED)
+ CHK_ERRA(SEC_E_NO_IMPERSONATION)
+ CHK_ERRA(SEC_E_LOGON_DENIED)
+ CHK_ERRA(SEC_E_UNKNOWN_CREDENTIALS)
+ CHK_ERRA(SEC_E_NO_CREDENTIALS)
+ CHK_ERRA(SEC_E_MESSAGE_ALTERED)
+ CHK_ERRA(SEC_E_OUT_OF_SEQUENCE)
+ CHK_ERRA(SEC_E_NO_AUTHENTICATING_AUTHORITY)
+ CHK_ERRA(SEC_I_CONTINUE_NEEDED)
+ CHK_ERRA(SEC_I_COMPLETE_NEEDED)
+ CHK_ERRA(SEC_I_COMPLETE_AND_CONTINUE)
+ CHK_ERRA(SEC_I_LOCAL_LOGON)
+ CHK_ERRA(SEC_E_BAD_PKGID)
+ CHK_ERRA(SEC_E_CONTEXT_EXPIRED)
+ CHK_ERRA(SEC_I_CONTEXT_EXPIRED)
+ CHK_ERRA(SEC_E_INCOMPLETE_MESSAGE)
+ CHK_ERRA(SEC_E_INCOMPLETE_CREDENTIALS)
+ CHK_ERRA(SEC_E_BUFFER_TOO_SMALL)
+ CHK_ERRA(SEC_I_INCOMPLETE_CREDENTIALS)
+ CHK_ERRA(SEC_I_RENEGOTIATE)
+ CHK_ERRA(SEC_E_WRONG_PRINCIPAL)
+ CHK_ERRA(SEC_I_NO_LSA_CONTEXT)
+ CHK_ERRA(SEC_E_TIME_SKEW)
+ CHK_ERRA(SEC_E_UNTRUSTED_ROOT)
+ CHK_ERRA(SEC_E_ILLEGAL_MESSAGE)
+ CHK_ERRA(SEC_E_CERT_UNKNOWN)
+ CHK_ERRA(SEC_E_CERT_EXPIRED)
+ CHK_ERRA(SEC_E_ENCRYPT_FAILURE)
+ CHK_ERRA(SEC_E_DECRYPT_FAILURE)
+ CHK_ERRA(SEC_E_ALGORITHM_MISMATCH)
+ CHK_ERRA(SEC_E_SECURITY_QOS_FAILED)
+ CHK_ERRA(SEC_E_UNFINISHED_CONTEXT_DELETED)
+ CHK_ERRA(SEC_E_NO_TGT_REPLY)
+ CHK_ERRA(SEC_E_NO_IP_ADDRESSES)
+ CHK_ERRA(SEC_E_WRONG_CREDENTIAL_HANDLE)
+ CHK_ERRA(SEC_E_CRYPTO_SYSTEM_INVALID)
+ CHK_ERRA(SEC_E_MAX_REFERRALS_EXCEEDED)
+ CHK_ERRA(SEC_E_MUST_BE_KDC)
+ CHK_ERRA(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED)
+ CHK_ERRA(SEC_E_TOO_MANY_PRINCIPALS)
+ CHK_ERRA(SEC_E_NO_PA_DATA)
+ CHK_ERRA(SEC_E_PKINIT_NAME_MISMATCH)
+ CHK_ERRA(SEC_E_SMARTCARD_LOGON_REQUIRED)
+ CHK_ERRA(SEC_E_SHUTDOWN_IN_PROGRESS)
+ CHK_ERRA(SEC_E_KDC_INVALID_REQUEST)
+ CHK_ERRA(SEC_E_KDC_UNABLE_TO_REFER)
+ CHK_ERRA(SEC_E_KDC_UNKNOWN_ETYPE)
+ CHK_ERRA(SEC_E_UNSUPPORTED_PREAUTH)
+ CHK_ERRA(SEC_E_DELEGATION_REQUIRED)
+ CHK_ERRA(SEC_E_BAD_BINDINGS)
+ CHK_ERRA(SEC_E_MULTIPLE_ACCOUNTS)
+ CHK_ERRA(SEC_E_NO_KERB_KEY)
+// CHK_ERRA(SEC_E_CERT_WRONG_USAGE)
+// CHK_ERRA(SEC_E_DOWNGRADE_DETECTED)
+ CHK_ERRA(SEC_E_SMARTCARD_CERT_REVOKED)
+ CHK_ERRA(SEC_E_ISSUING_CA_UNTRUSTED)
+ CHK_ERRA(SEC_E_REVOCATION_OFFLINE_C)
+ CHK_ERRA(SEC_E_PKINIT_CLIENT_FAILURE)
+ CHK_ERRA(SEC_E_SMARTCARD_CERT_EXPIRED)
+// CHK_ERRA(SEC_E_NO_SPM)
+// CHK_ERRA(SEC_E_NOT_SUPPORTED)
+ CHK_ERRA(CRYPT_I_NEW_PROTECTION_REQUIRED)
+ CHK_ERRA(CRYPT_E_MISSING_PUBKEY_PARA)
+ CHK_ERRA(CRYPT_E_ASN1_ERROR)
+ CHK_ERRA(CRYPT_E_ASN1_INTERNAL)
+ CHK_ERRA(CRYPT_E_ASN1_EOD)
+ CHK_ERRA(CRYPT_E_ASN1_CORRUPT)
+ CHK_ERRA(CRYPT_E_ASN1_LARGE)
+ CHK_ERRA(CRYPT_E_ASN1_CONSTRAINT)
+ CHK_ERRA(CRYPT_E_ASN1_MEMORY)
+ CHK_ERRA(CRYPT_E_ASN1_OVERFLOW)
+ CHK_ERRA(CRYPT_E_ASN1_BADPDU)
+ CHK_ERRA(CRYPT_E_ASN1_BADARGS)
+ CHK_ERRA(CRYPT_E_ASN1_BADREAL)
+ CHK_ERRA(CRYPT_E_ASN1_BADTAG)
+ CHK_ERRA(CRYPT_E_ASN1_CHOICE)
+ CHK_ERRA(CRYPT_E_ASN1_RULE)
+ CHK_ERRA(CRYPT_E_ASN1_UTF8)
+ CHK_ERRA(CRYPT_E_ASN1_PDU_TYPE)
+ CHK_ERRA(CRYPT_E_ASN1_NYI)
+ CHK_ERRA(CRYPT_E_ASN1_EXTENDED)
+ CHK_ERRA(CRYPT_E_ASN1_NOEOD)
+ CHK_ERRA(CERTSRV_E_SERVER_SUSPENDED)
+ CHK_ERRA(CERTSRV_E_ENCODING_LENGTH)
+ CHK_ERRA(CERTSRV_E_ROLECONFLICT)
+ CHK_ERRA(CERTSRV_E_RESTRICTEDOFFICER)
+ CHK_ERRA(CERTSRV_E_KEY_ARCHIVAL_NOT_CONFIGURED)
+ CHK_ERRA(CERTSRV_E_NO_VALID_KRA)
+ CHK_ERRA(CERTSRV_E_BAD_REQUEST_KEY_ARCHIVAL)
+ CHK_ERRA(CERTSRV_E_NO_CAADMIN_DEFINED)
+ CHK_ERRA(CERTSRV_E_BAD_RENEWAL_CERT_ATTRIBUTE)
+ CHK_ERRA(CERTSRV_E_NO_DB_SESSIONS)
+ CHK_ERRA(CERTSRV_E_ALIGNMENT_FAULT)
+ CHK_ERRA(CERTSRV_E_ENROLL_DENIED)
+ CHK_ERRA(CERTSRV_E_TEMPLATE_DENIED)
+// CHK_ERRA(CERTSRV_E_DOWNLEVEL_DC_SSL_OR_UPGRADE)
+ CHK_ERRA(CERTSRV_E_TEMPLATE_CONFLICT)
+ CHK_ERRA(CERTSRV_E_SUBJECT_ALT_NAME_REQUIRED)
+ CHK_ERRA(CERTSRV_E_ARCHIVED_KEY_REQUIRED)
+ CHK_ERRA(CERTSRV_E_SMIME_REQUIRED)
+ CHK_ERRA(CERTSRV_E_BAD_RENEWAL_SUBJECT)
+ CHK_ERRA(CERTSRV_E_BAD_TEMPLATE_VERSION)
+ CHK_ERRA(CERTSRV_E_TEMPLATE_POLICY_REQUIRED)
+ CHK_ERRA(CERTSRV_E_SIGNATURE_POLICY_REQUIRED)
+ CHK_ERRA(CERTSRV_E_SIGNATURE_COUNT)
+ CHK_ERRA(CERTSRV_E_SIGNATURE_REJECTED)
+ CHK_ERRA(CERTSRV_E_ISSUANCE_POLICY_REQUIRED)
+ CHK_ERRA(CERTSRV_E_SUBJECT_UPN_REQUIRED)
+ CHK_ERRA(CERTSRV_E_SUBJECT_DIRECTORY_GUID_REQUIRED)
+ CHK_ERRA(CERTSRV_E_SUBJECT_DNS_REQUIRED)
+ CHK_ERRA(CERTSRV_E_ARCHIVED_KEY_UNEXPECTED)
+ CHK_ERRA(CERTSRV_E_KEY_LENGTH)
+// CHK_ERRA(CERTSRV_E_SUBJECT_EMAIL_REQUIRED)
+// CHK_ERRA(CERTSRV_E_UNKNOWN_CERT_TYPE)
+// CHK_ERRA(CERTSRV_E_CERT_TYPE_OVERLAP)
+ CHK_ERRA(XENROLL_E_KEY_NOT_EXPORTABLE)
+ CHK_ERRA(XENROLL_E_CANNOT_ADD_ROOT_CERT)
+ CHK_ERRA(XENROLL_E_RESPONSE_KA_HASH_NOT_FOUND)
+ CHK_ERRA(XENROLL_E_RESPONSE_UNEXPECTED_KA_HASH)
+ CHK_ERRA(XENROLL_E_RESPONSE_KA_HASH_MISMATCH)
+ CHK_ERRA(XENROLL_E_KEYSPEC_SMIME_MISMATCH)
+ CHK_ERRA(MSSIPOTF_E_OUTOFMEMRANGE)
+ CHK_ERRA(MSSIPOTF_E_CANTGETOBJECT)
+ CHK_ERRA(MSSIPOTF_E_NOHEADTABLE)
+ CHK_ERRA(MSSIPOTF_E_BAD_MAGICNUMBER)
+ CHK_ERRA(MSSIPOTF_E_BAD_OFFSET_TABLE)
+ CHK_ERRA(MSSIPOTF_E_TABLE_TAGORDER)
+ CHK_ERRA(MSSIPOTF_E_TABLE_LONGWORD)
+ CHK_ERRA(MSSIPOTF_E_BAD_FIRST_TABLE_PLACEMENT)
+ CHK_ERRA(MSSIPOTF_E_TABLES_OVERLAP)
+ CHK_ERRA(MSSIPOTF_E_TABLE_PADBYTES)
+ CHK_ERRA(MSSIPOTF_E_FILETOOSMALL)
+ CHK_ERRA(MSSIPOTF_E_TABLE_CHECKSUM)
+ CHK_ERRA(MSSIPOTF_E_FILE_CHECKSUM)
+ CHK_ERRA(MSSIPOTF_E_FAILED_POLICY)
+ CHK_ERRA(MSSIPOTF_E_FAILED_HINTS_CHECK)
+ CHK_ERRA(MSSIPOTF_E_NOT_OPENTYPE)
+ CHK_ERRA(MSSIPOTF_E_FILE)
+ CHK_ERRA(MSSIPOTF_E_CRYPT)
+ CHK_ERRA(MSSIPOTF_E_BADVERSION)
+ CHK_ERRA(MSSIPOTF_E_DSIG_STRUCTURE)
+ CHK_ERRA(MSSIPOTF_E_PCONST_CHECK)
+ CHK_ERRA(MSSIPOTF_E_STRUCTURE)
+ CHK_ERRA(TRUST_E_EXPLICIT_DISTRUST)
+ CHK_ERRA(CERT_E_UNTRUSTEDCA)
+ CHK_ERRA(CERT_E_INVALID_POLICY)
+ CHK_ERRA(CERT_E_INVALID_NAME)
+ CHK_ERRA(SPAPI_E_NOT_DISABLEABLE)
+ CHK_ERRA(SPAPI_E_CANT_REMOVE_DEVINST)
+ CHK_ERRA(SPAPI_E_INVALID_TARGET)
+ CHK_ERRA(SPAPI_E_DRIVER_NONNATIVE)
+ CHK_ERRA(SPAPI_E_IN_WOW64)
+ CHK_ERRA(SPAPI_E_SET_SYSTEM_RESTORE_POINT)
+ CHK_ERRA(SPAPI_E_INCORRECTLY_COPIED_INF)
+ CHK_ERRA(SPAPI_E_SCE_DISABLED)
+ CHK_ERRA(SCARD_E_NO_KEY_CONTAINER)
+ CHK_ERRA(SCARD_W_CARD_NOT_AUTHENTICATED)
+ CHK_ERRA(COMADMIN_E_OBJECTERRORS)
+ CHK_ERRA(COMADMIN_E_OBJECTINVALID)
+ CHK_ERRA(COMADMIN_E_KEYMISSING)
+ CHK_ERRA(COMADMIN_E_ALREADYINSTALLED)
+ CHK_ERRA(COMADMIN_E_APP_FILE_WRITEFAIL)
+ CHK_ERRA(COMADMIN_E_APP_FILE_READFAIL)
+ CHK_ERRA(COMADMIN_E_APP_FILE_VERSION)
+ CHK_ERRA(COMADMIN_E_BADPATH)
+ CHK_ERRA(COMADMIN_E_APPLICATIONEXISTS)
+ CHK_ERRA(COMADMIN_E_ROLEEXISTS)
+ CHK_ERRA(COMADMIN_E_CANTCOPYFILE)
+ CHK_ERRA(COMADMIN_E_NOUSER)
+ CHK_ERRA(COMADMIN_E_INVALIDUSERIDS)
+ CHK_ERRA(COMADMIN_E_NOREGISTRYCLSID)
+ CHK_ERRA(COMADMIN_E_BADREGISTRYPROGID)
+ CHK_ERRA(COMADMIN_E_AUTHENTICATIONLEVEL)
+ CHK_ERRA(COMADMIN_E_USERPASSWDNOTVALID)
+ CHK_ERRA(COMADMIN_E_CLSIDORIIDMISMATCH)
+ CHK_ERRA(COMADMIN_E_REMOTEINTERFACE)
+ CHK_ERRA(COMADMIN_E_DLLREGISTERSERVER)
+ CHK_ERRA(COMADMIN_E_NOSERVERSHARE)
+ CHK_ERRA(COMADMIN_E_DLLLOADFAILED)
+ CHK_ERRA(COMADMIN_E_BADREGISTRYLIBID)
+ CHK_ERRA(COMADMIN_E_APPDIRNOTFOUND)
+ CHK_ERRA(COMADMIN_E_REGISTRARFAILED)
+ CHK_ERRA(COMADMIN_E_COMPFILE_DOESNOTEXIST)
+ CHK_ERRA(COMADMIN_E_COMPFILE_LOADDLLFAIL)
+ CHK_ERRA(COMADMIN_E_COMPFILE_GETCLASSOBJ)
+ CHK_ERRA(COMADMIN_E_COMPFILE_CLASSNOTAVAIL)
+ CHK_ERRA(COMADMIN_E_COMPFILE_BADTLB)
+ CHK_ERRA(COMADMIN_E_COMPFILE_NOTINSTALLABLE)
+ CHK_ERRA(COMADMIN_E_NOTCHANGEABLE)
+ CHK_ERRA(COMADMIN_E_NOTDELETEABLE)
+ CHK_ERRA(COMADMIN_E_SESSION)
+ CHK_ERRA(COMADMIN_E_COMP_MOVE_LOCKED)
+ CHK_ERRA(COMADMIN_E_COMP_MOVE_BAD_DEST)
+ CHK_ERRA(COMADMIN_E_REGISTERTLB)
+ CHK_ERRA(COMADMIN_E_SYSTEMAPP)
+ CHK_ERRA(COMADMIN_E_COMPFILE_NOREGISTRAR)
+ CHK_ERRA(COMADMIN_E_COREQCOMPINSTALLED)
+ CHK_ERRA(COMADMIN_E_SERVICENOTINSTALLED)
+ CHK_ERRA(COMADMIN_E_PROPERTYSAVEFAILED)
+ CHK_ERRA(COMADMIN_E_OBJECTEXISTS)
+ CHK_ERRA(COMADMIN_E_COMPONENTEXISTS)
+ CHK_ERRA(COMADMIN_E_REGFILE_CORRUPT)
+ CHK_ERRA(COMADMIN_E_PROPERTY_OVERFLOW)
+ CHK_ERRA(COMADMIN_E_NOTINREGISTRY)
+ CHK_ERRA(COMADMIN_E_OBJECTNOTPOOLABLE)
+ CHK_ERRA(COMADMIN_E_APPLID_MATCHES_CLSID)
+ CHK_ERRA(COMADMIN_E_ROLE_DOES_NOT_EXIST)
+ CHK_ERRA(COMADMIN_E_START_APP_NEEDS_COMPONENTS)
+ CHK_ERRA(COMADMIN_E_REQUIRES_DIFFERENT_PLATFORM)
+ CHK_ERRA(COMADMIN_E_CAN_NOT_EXPORT_APP_PROXY)
+ CHK_ERRA(COMADMIN_E_CAN_NOT_START_APP)
+ CHK_ERRA(COMADMIN_E_CAN_NOT_EXPORT_SYS_APP)
+ CHK_ERRA(COMADMIN_E_CANT_SUBSCRIBE_TO_COMPONENT)
+ CHK_ERRA(COMADMIN_E_EVENTCLASS_CANT_BE_SUBSCRIBER)
+ CHK_ERRA(COMADMIN_E_LIB_APP_PROXY_INCOMPATIBLE)
+ CHK_ERRA(COMADMIN_E_BASE_PARTITION_ONLY)
+ CHK_ERRA(COMADMIN_E_START_APP_DISABLED)
+ CHK_ERRA(COMADMIN_E_CAT_DUPLICATE_PARTITION_NAME)
+ CHK_ERRA(COMADMIN_E_CAT_INVALID_PARTITION_NAME)
+ CHK_ERRA(COMADMIN_E_CAT_PARTITION_IN_USE)
+ CHK_ERRA(COMADMIN_E_FILE_PARTITION_DUPLICATE_FILES)
+ CHK_ERRA(COMADMIN_E_CAT_IMPORTED_COMPONENTS_NOT_ALLOWED)
+ CHK_ERRA(COMADMIN_E_AMBIGUOUS_APPLICATION_NAME)
+ CHK_ERRA(COMADMIN_E_AMBIGUOUS_PARTITION_NAME)
+ CHK_ERRA(COMADMIN_E_REGDB_NOTINITIALIZED)
+ CHK_ERRA(COMADMIN_E_REGDB_NOTOPEN)
+ CHK_ERRA(COMADMIN_E_REGDB_SYSTEMERR)
+ CHK_ERRA(COMADMIN_E_REGDB_ALREADYRUNNING)
+ CHK_ERRA(COMADMIN_E_MIG_VERSIONNOTSUPPORTED)
+ CHK_ERRA(COMADMIN_E_MIG_SCHEMANOTFOUND)
+ CHK_ERRA(COMADMIN_E_CAT_BITNESSMISMATCH)
+ CHK_ERRA(COMADMIN_E_CAT_UNACCEPTABLEBITNESS)
+ CHK_ERRA(COMADMIN_E_CAT_WRONGAPPBITNESS)
+ CHK_ERRA(COMADMIN_E_CAT_PAUSE_RESUME_NOT_SUPPORTED)
+ CHK_ERRA(COMADMIN_E_CAT_SERVERFAULT)
+ CHK_ERRA(COMQC_E_APPLICATION_NOT_QUEUED)
+ CHK_ERRA(COMQC_E_NO_QUEUEABLE_INTERFACES)
+ CHK_ERRA(COMQC_E_QUEUING_SERVICE_NOT_AVAILABLE)
+ CHK_ERRA(COMQC_E_NO_IPERSISTSTREAM)
+ CHK_ERRA(COMQC_E_BAD_MESSAGE)
+ CHK_ERRA(COMQC_E_UNAUTHENTICATED)
+ CHK_ERRA(COMQC_E_UNTRUSTED_ENQUEUER)
+ CHK_ERRA(MSDTC_E_DUPLICATE_RESOURCE)
+ CHK_ERRA(COMADMIN_E_OBJECT_PARENT_MISSING)
+ CHK_ERRA(COMADMIN_E_OBJECT_DOES_NOT_EXIST)
+ CHK_ERRA(COMADMIN_E_APP_NOT_RUNNING)
+ CHK_ERRA(COMADMIN_E_INVALID_PARTITION)
+ CHK_ERRA(COMADMIN_E_SVCAPP_NOT_POOLABLE_OR_RECYCLABLE)
+ CHK_ERRA(COMADMIN_E_USER_IN_SET)
+ CHK_ERRA(COMADMIN_E_CANTRECYCLELIBRARYAPPS)
+ CHK_ERRA(COMADMIN_E_CANTRECYCLESERVICEAPPS)
+ CHK_ERRA(COMADMIN_E_PROCESSALREADYRECYCLED)
+ CHK_ERRA(COMADMIN_E_PAUSEDPROCESSMAYNOTBERECYCLED)
+ CHK_ERRA(COMADMIN_E_CANTMAKEINPROCSERVICE)
+ CHK_ERRA(COMADMIN_E_PROGIDINUSEBYCLSID)
+ CHK_ERRA(COMADMIN_E_DEFAULT_PARTITION_NOT_IN_SET)
+ CHK_ERRA(COMADMIN_E_RECYCLEDPROCESSMAYNOTBEPAUSED)
+ CHK_ERRA(COMADMIN_E_PARTITION_ACCESSDENIED)
+ CHK_ERRA(COMADMIN_E_PARTITION_MSI_ONLY)
+ CHK_ERRA(COMADMIN_E_LEGACYCOMPS_NOT_ALLOWED_IN_1_0_FORMAT)
+ CHK_ERRA(COMADMIN_E_LEGACYCOMPS_NOT_ALLOWED_IN_NONBASE_PARTITIONS)
+ CHK_ERRA(COMADMIN_E_COMP_MOVE_SOURCE)
+ CHK_ERRA(COMADMIN_E_COMP_MOVE_DEST)
+ CHK_ERRA(COMADMIN_E_COMP_MOVE_PRIVATE)
+ CHK_ERRA(COMADMIN_E_BASEPARTITION_REQUIRED_IN_SET)
+ CHK_ERRA(COMADMIN_E_CANNOT_ALIAS_EVENTCLASS)
+ CHK_ERRA(COMADMIN_E_PRIVATE_ACCESSDENIED)
+ CHK_ERRA(COMADMIN_E_SAFERINVALID)
+ CHK_ERRA(COMADMIN_E_REGISTRY_ACCESSDENIED)
+// CHK_ERRA(COMADMIN_E_PARTITIONS_DISABLED)
+// CHK_ERR_WIN32A(ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY)
+// CHK_ERR_WIN32A(ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY)
+ CHK_ERR_WIN32A(ERROR_DISK_TOO_FRAGMENTED)
+ CHK_ERR_WIN32A(ERROR_DELETE_PENDING)
+// CHK_ERR_WIN32A(ERROR_SCOPE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_NOT_SAFEBOOT_SERVICE)
+ CHK_ERR_WIN32A(ERROR_JOURNAL_ENTRY_DELETED)
+ CHK_ERR_WIN32A(ERROR_ONLY_IF_CONNECTED)
+ CHK_ERR_WIN32A(ERROR_OVERRIDE_NOCHANGES)
+ CHK_ERR_WIN32A(ERROR_BAD_USER_PROFILE)
+ CHK_ERR_WIN32A(ERROR_NOT_SUPPORTED_ON_SBS)
+ CHK_ERR_WIN32A(ERROR_SERVER_SHUTDOWN_IN_PROGRESS)
+ CHK_ERR_WIN32A(ERROR_HOST_DOWN)
+ CHK_ERR_WIN32A(ERROR_NON_ACCOUNT_SID)
+ CHK_ERR_WIN32A(ERROR_NON_DOMAIN_SID)
+ CHK_ERR_WIN32A(ERROR_APPHELP_BLOCK)
+ CHK_ERR_WIN32A(ERROR_ACCESS_DISABLED_BY_POLICY)
+ CHK_ERR_WIN32A(ERROR_REG_NAT_CONSUMPTION)
+ CHK_ERR_WIN32A(ERROR_CSCSHARE_OFFLINE)
+ CHK_ERR_WIN32A(ERROR_PKINIT_FAILURE)
+ CHK_ERR_WIN32A(ERROR_SMARTCARD_SUBSYSTEM_FAILURE)
+ CHK_ERR_WIN32A(ERROR_DOWNGRADE_DETECTED)
+ CHK_ERR_WIN32A(ERROR_MACHINE_LOCKED)
+ CHK_ERR_WIN32A(ERROR_CALLBACK_SUPPLIED_INVALID_DATA)
+ CHK_ERR_WIN32A(ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_DRIVER_BLOCKED)
+ CHK_ERR_WIN32A(ERROR_INVALID_IMPORT_OF_NON_DLL)
+// CHK_ERR_WIN32A(ERROR_ACCESS_DISABLED_WEBBLADE)
+// CHK_ERR_WIN32A(ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER)
+// CHK_ERR_WIN32A(ERROR_RECOVERY_FAILURE)
+// CHK_ERR_WIN32A(ERROR_ALREADY_FIBER)
+// CHK_ERR_WIN32A(ERROR_ALREADY_THREAD)
+// CHK_ERR_WIN32A(ERROR_STACK_BUFFER_OVERRUN)
+// CHK_ERR_WIN32A(ERROR_PARAMETER_QUOTA_EXCEEDED)
+// CHK_ERR_WIN32A(ERROR_DEBUGGER_INACTIVE)
+// CHK_ERR_WIN32A(ERROR_DELAY_LOAD_FAILED)
+ CHK_ERR_WIN32A(ERROR_CURRENT_DOMAIN_NOT_ALLOWED)
+ CHK_ERR_WIN32A(ERROR_INSTALL_SERVICE_FAILURE)
+ CHK_ERR_WIN32A(ERROR_INSTALL_PACKAGE_VERSION)
+ CHK_ERR_WIN32A(ERROR_INSTALL_ALREADY_RUNNING)
+ CHK_ERR_WIN32A(ERROR_INSTALL_PACKAGE_OPEN_FAILED)
+ CHK_ERR_WIN32A(ERROR_INSTALL_PACKAGE_INVALID)
+ CHK_ERR_WIN32A(ERROR_INSTALL_UI_FAILURE)
+ CHK_ERR_WIN32A(ERROR_INSTALL_LOG_FAILURE)
+ CHK_ERR_WIN32A(ERROR_INSTALL_LANGUAGE_UNSUPPORTED)
+ CHK_ERR_WIN32A(ERROR_INSTALL_TRANSFORM_FAILURE)
+ CHK_ERR_WIN32A(ERROR_INSTALL_PACKAGE_REJECTED)
+ CHK_ERR_WIN32A(ERROR_FUNCTION_NOT_CALLED)
+ CHK_ERR_WIN32A(ERROR_FUNCTION_FAILED)
+ CHK_ERR_WIN32A(ERROR_INVALID_TABLE)
+ CHK_ERR_WIN32A(ERROR_DATATYPE_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_UNSUPPORTED_TYPE)
+ CHK_ERR_WIN32A(ERROR_CREATE_FAILED)
+ CHK_ERR_WIN32A(ERROR_INSTALL_TEMP_UNWRITABLE)
+ CHK_ERR_WIN32A(ERROR_INSTALL_PLATFORM_UNSUPPORTED)
+ CHK_ERR_WIN32A(ERROR_INSTALL_NOTUSED)
+ CHK_ERR_WIN32A(ERROR_PATCH_PACKAGE_OPEN_FAILED)
+ CHK_ERR_WIN32A(ERROR_PATCH_PACKAGE_INVALID)
+ CHK_ERR_WIN32A(ERROR_PATCH_PACKAGE_UNSUPPORTED)
+ CHK_ERR_WIN32A(ERROR_PRODUCT_VERSION)
+ CHK_ERR_WIN32A(ERROR_INVALID_COMMAND_LINE)
+ CHK_ERR_WIN32A(ERROR_INSTALL_REMOTE_DISALLOWED)
+ CHK_ERR_WIN32A(ERROR_SUCCESS_REBOOT_INITIATED)
+ CHK_ERR_WIN32A(ERROR_PATCH_TARGET_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_PATCH_PACKAGE_REJECTED)
+ CHK_ERR_WIN32A(ERROR_INSTALL_TRANSFORM_REJECTED)
+// CHK_ERR_WIN32A(ERROR_INSTALL_REMOTE_PROHIBITED)
+ CHK_ERR_WIN32A(RPC_S_ENTRY_TYPE_MISMATCH)
+ CHK_ERR_WIN32A(RPC_S_NOT_ALL_OBJS_EXPORTED)
+ CHK_ERR_WIN32A(RPC_S_INTERFACE_NOT_EXPORTED)
+ CHK_ERR_WIN32A(RPC_S_PROFILE_NOT_ADDED)
+ CHK_ERR_WIN32A(RPC_S_PRF_ELT_NOT_ADDED)
+ CHK_ERR_WIN32A(RPC_S_PRF_ELT_NOT_REMOVED)
+ CHK_ERR_WIN32A(RPC_S_GRP_ELT_NOT_ADDED)
+ CHK_ERR_WIN32A(RPC_S_GRP_ELT_NOT_REMOVED)
+ CHK_ERR_WIN32A(ERROR_KM_DRIVER_BLOCKED)
+ CHK_ERR_WIN32A(ERROR_CONTEXT_EXPIRED)
+// CHK_ERR_WIN32A(ERROR_PER_USER_TRUST_QUOTA_EXCEEDED)
+// CHK_ERR_WIN32A(ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED)
+// CHK_ERR_WIN32A(ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT)
+ CHK_ERR_WIN32A(ERROR_PRINTER_DRIVER_WARNED)
+ CHK_ERR_WIN32A(ERROR_PRINTER_DRIVER_BLOCKED)
+ CHK_ERR_WIN32A(ERROR_VOLUME_CONTAINS_SYS_FILES)
+ CHK_ERR_WIN32A(ERROR_INDIGENOUS_TYPE)
+ CHK_ERR_WIN32A(ERROR_NO_SUPPORTING_DRIVES)
+ CHK_ERR_WIN32A(ERROR_CLEANER_CARTRIDGE_INSTALLED)
+ CHK_ERR_WIN32A(ERROR_REPARSE_TAG_INVALID)
+ CHK_ERR_WIN32A(ERROR_REPARSE_TAG_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_VOLUME_NOT_SIS_ENABLED)
+ CHK_ERR_WIN32A(ERROR_QUORUM_OWNER_ALIVE)
+ CHK_ERR_WIN32A(ERROR_NETWORK_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_NODE_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_ALL_NODES_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_FAILED)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_INVALID_NODE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_EXISTS)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_JOIN_IN_PROGRESS)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_EXISTS)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NETINTERFACE_EXISTS)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NETINTERFACE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_INVALID_REQUEST)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_INVALID_NETWORK_PROVIDER)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_DOWN)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_UNREACHABLE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_NOT_MEMBER)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_INVALID_NETWORK)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_UP)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_IPADDR_IN_USE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_NOT_PAUSED)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NO_SECURITY_CONTEXT)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_NOT_INTERNAL)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_ALREADY_UP)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_ALREADY_DOWN)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_ALREADY_ONLINE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_ALREADY_MEMBER)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_LAST_INTERNAL_NETWORK)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS)
+ CHK_ERR_WIN32A(ERROR_INVALID_OPERATION_ON_QUORUM)
+ CHK_ERR_WIN32A(ERROR_DEPENDENCY_NOT_ALLOWED)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_PAUSED)
+ CHK_ERR_WIN32A(ERROR_NODE_CANT_HOST_RESOURCE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_NOT_READY)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_SHUTTING_DOWN)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_JOIN_ABORTED)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_INCOMPATIBLE_VERSIONS)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_RESNAME_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_DATABASE_SEQMISMATCH)
+ CHK_ERR_WIN32A(ERROR_RESMON_INVALID_STATE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_GUM_NOT_LOCKER)
+ CHK_ERR_WIN32A(ERROR_QUORUM_DISK_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_DATABASE_BACKUP_CORRUPT)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT)
+ CHK_ERR_WIN32A(ERROR_RESOURCE_PROPERTY_UNCHANGEABLE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_QUORUMLOG_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_MEMBERSHIP_HALT)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_INSTANCE_ID_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_PARAMETER_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_NODE_CANNOT_BE_CLUSTERED)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_WRONG_OS_VERSION)
+ CHK_ERR_WIN32A(ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME)
+// CHK_ERR_WIN32A(ERROR_CLUSCFG_ALREADY_COMMITTED)
+// CHK_ERR_WIN32A(ERROR_CLUSCFG_ROLLBACK_FAILED)
+// CHK_ERR_WIN32A(ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT)
+// CHK_ERR_WIN32A(ERROR_CLUSTER_OLD_VERSION)
+// CHK_ERR_WIN32A(ERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME)
+ CHK_ERR_WIN32A(ERROR_FILE_READ_ONLY)
+ CHK_ERR_WIN32A(ERROR_DIR_EFS_DISALLOWED)
+ CHK_ERR_WIN32A(ERROR_EFS_SERVER_NOT_TRUSTED)
+ CHK_ERR_WIN32A(ERROR_BAD_RECOVERY_POLICY)
+ CHK_ERR_WIN32A(ERROR_EFS_ALG_BLOB_TOO_BIG)
+ CHK_ERR_WIN32A(ERROR_VOLUME_NOT_SUPPORT_EFS)
+ CHK_ERR_WIN32A(ERROR_EFS_DISABLED)
+ CHK_ERR_WIN32A(ERROR_EFS_VERSION_NOT_SUPPORT)
+ CHK_ERR_WIN32A(SCHED_E_SERVICE_NOT_LOCALSYSTEM)
+ CHK_ERR_WIN32A(ERROR_CTX_CLIENT_LICENSE_IN_USE)
+ CHK_ERR_WIN32A(ERROR_CTX_CLIENT_LICENSE_NOT_SET)
+ CHK_ERR_WIN32A(ERROR_CTX_LICENSE_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_CTX_LICENSE_CLIENT_INVALID)
+ CHK_ERR_WIN32A(ERROR_CTX_LICENSE_EXPIRED)
+ CHK_ERR_WIN32A(ERROR_CTX_SHADOW_NOT_RUNNING)
+ CHK_ERR_WIN32A(ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE)
+// CHK_ERR_WIN32A(ERROR_ACTIVATION_COUNT_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_DS_SORT_CONTROL_MISSING)
+ CHK_ERR_WIN32A(ERROR_DS_OFFSET_RANGE_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_OBJECT_BEING_REMOVED)
+ CHK_ERR_WIN32A(ERROR_DS_DS_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_DS_INVALID_LDAP_DISPLAY_NAME)
+ CHK_ERR_WIN32A(ERROR_DS_NON_BASE_SEARCH)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_ATTS)
+ CHK_ERR_WIN32A(ERROR_DS_BACKLINK_WITHOUT_LINK)
+ CHK_ERR_WIN32A(ERROR_DS_EPOCH_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_DS_SRC_NAME_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_DS_SRC_AND_DST_NC_IDENTICAL)
+ CHK_ERR_WIN32A(ERROR_DS_DST_NC_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC)
+ CHK_ERR_WIN32A(ERROR_DS_SRC_GUID_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_DELETED_OBJECT)
+ CHK_ERR_WIN32A(ERROR_DS_PDC_OPERATION_IN_PROGRESS)
+ CHK_ERR_WIN32A(ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD)
+ CHK_ERR_WIN32A(ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS)
+ CHK_ERR_WIN32A(ERROR_DS_NC_MUST_HAVE_NC_PARENT)
+ CHK_ERR_WIN32A(ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE)
+ CHK_ERR_WIN32A(ERROR_DS_DST_DOMAIN_NOT_NATIVE)
+ CHK_ERR_WIN32A(ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_ACCOUNT_GROUP)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_RESOURCE_GROUP)
+ CHK_ERR_WIN32A(ERROR_DS_INVALID_SEARCH_FLAG)
+ CHK_ERR_WIN32A(ERROR_DS_NO_TREE_DELETE_ABOVE_NC)
+ CHK_ERR_WIN32A(ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE)
+ CHK_ERR_WIN32A(ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE)
+ CHK_ERR_WIN32A(ERROR_DS_SAM_INIT_FAILURE)
+ CHK_ERR_WIN32A(ERROR_DS_SENSITIVE_GROUP_VIOLATION)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_MOD_PRIMARYGROUPID)
+ CHK_ERR_WIN32A(ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD)
+ CHK_ERR_WIN32A(ERROR_DS_NONSAFE_SCHEMA_CHANGE)
+ CHK_ERR_WIN32A(ERROR_DS_SCHEMA_UPDATE_DISALLOWED)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_CREATE_UNDER_SCHEMA)
+ CHK_ERR_WIN32A(ERROR_DS_INSTALL_NO_SRC_SCH_VERSION)
+ CHK_ERR_WIN32A(ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE)
+ CHK_ERR_WIN32A(ERROR_DS_INVALID_GROUP_TYPE)
+ CHK_ERR_WIN32A(ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN)
+ CHK_ERR_WIN32A(ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN)
+ CHK_ERR_WIN32A(ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER)
+ CHK_ERR_WIN32A(ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER)
+ CHK_ERR_WIN32A(ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER)
+ CHK_ERR_WIN32A(ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER)
+ CHK_ERR_WIN32A(ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER)
+ CHK_ERR_WIN32A(ERROR_DS_HAVE_PRIMARY_MEMBERS)
+ CHK_ERR_WIN32A(ERROR_DS_STRING_SD_CONVERSION_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_NAMING_MASTER_GC)
+ CHK_ERR_WIN32A(ERROR_DS_DNS_LOOKUP_FAILURE)
+ CHK_ERR_WIN32A(ERROR_DS_COULDNT_UPDATE_SPNS)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_SD)
+ CHK_ERR_WIN32A(ERROR_DS_KEY_NOT_UNIQUE)
+ CHK_ERR_WIN32A(ERROR_DS_WRONG_LINKED_ATT_SYNTAX)
+ CHK_ERR_WIN32A(ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD)
+ CHK_ERR_WIN32A(ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_START)
+ CHK_ERR_WIN32A(ERROR_DS_INIT_FAILURE)
+ CHK_ERR_WIN32A(ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION)
+ CHK_ERR_WIN32A(ERROR_DS_SOURCE_DOMAIN_IN_FOREST)
+ CHK_ERR_WIN32A(ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST)
+ CHK_ERR_WIN32A(ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN)
+ CHK_ERR_WIN32A(ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER)
+ CHK_ERR_WIN32A(ERROR_DS_SRC_SID_EXISTS_IN_FOREST)
+ CHK_ERR_WIN32A(ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_SAM_INIT_FAILURE)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_SCHEMA_INFO_SHIP)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_SCHEMA_CONFLICT)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT)
+ CHK_ERR_WIN32A(ERROR_DS_DRA_OBJ_NC_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_DS_NC_STILL_HAS_DSAS)
+ CHK_ERR_WIN32A(ERROR_DS_GC_REQUIRED)
+ CHK_ERR_WIN32A(ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY)
+ CHK_ERR_WIN32A(ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_ADD_TO_GC)
+ CHK_ERR_WIN32A(ERROR_DS_NO_CHECKPOINT_WITH_PDC)
+ CHK_ERR_WIN32A(ERROR_DS_SOURCE_AUDITING_NOT_ENABLED)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC)
+ CHK_ERR_WIN32A(ERROR_DS_INVALID_NAME_FOR_SPN)
+ CHK_ERR_WIN32A(ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS)
+ CHK_ERR_WIN32A(ERROR_DS_UNICODEPWD_NOT_IN_QUOTES)
+ CHK_ERR_WIN32A(ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_DS_MUST_BE_RUN_ON_DST_DC)
+ CHK_ERR_WIN32A(ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ)
+ CHK_ERR_WIN32A(ERROR_DS_INIT_FAILURE_CONSOLE)
+ CHK_ERR_WIN32A(ERROR_DS_SAM_INIT_FAILURE_CONSOLE)
+ CHK_ERR_WIN32A(ERROR_DS_FOREST_VERSION_TOO_HIGH)
+ CHK_ERR_WIN32A(ERROR_DS_DOMAIN_VERSION_TOO_HIGH)
+ CHK_ERR_WIN32A(ERROR_DS_FOREST_VERSION_TOO_LOW)
+ CHK_ERR_WIN32A(ERROR_DS_DOMAIN_VERSION_TOO_LOW)
+ CHK_ERR_WIN32A(ERROR_DS_INCOMPATIBLE_VERSION)
+ CHK_ERR_WIN32A(ERROR_DS_LOW_DSA_VERSION)
+ CHK_ERR_WIN32A(ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN)
+ CHK_ERR_WIN32A(ERROR_DS_NOT_SUPPORTED_SORT_ORDER)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_NOT_UNIQUE)
+ CHK_ERR_WIN32A(ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)
+ CHK_ERR_WIN32A(ERROR_DS_OUT_OF_VERSION_STORE)
+ CHK_ERR_WIN32A(ERROR_DS_INCOMPATIBLE_CONTROLS_USED)
+ CHK_ERR_WIN32A(ERROR_DS_NO_REF_DOMAIN)
+ CHK_ERR_WIN32A(ERROR_DS_RESERVED_LINK_ID)
+ CHK_ERR_WIN32A(ERROR_DS_LINK_ID_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER)
+ CHK_ERR_WIN32A(ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE)
+ CHK_ERR_WIN32A(ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC)
+ CHK_ERR_WIN32A(ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG)
+ CHK_ERR_WIN32A(ERROR_DS_MODIFYDN_WRONG_GRANDPARENT)
+ CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_TRUST_REFERRAL)
+ CHK_ERR_WIN32A(ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD)
+ CHK_ERR_WIN32A(ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2)
+ CHK_ERR_WIN32A(ERROR_DS_THREAD_LIMIT_EXCEEDED)
+ CHK_ERR_WIN32A(ERROR_DS_NOT_CLOSEST)
+ CHK_ERR_WIN32A(ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF)
+ CHK_ERR_WIN32A(ERROR_DS_SINGLE_USER_MODE_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_NTDSCRIPT_SYNTAX_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_NTDSCRIPT_PROCESS_ERROR)
+ CHK_ERR_WIN32A(ERROR_DS_DIFFERENT_REPL_EPOCHS)
+ CHK_ERR_WIN32A(ERROR_DS_DRS_EXTENSIONS_CHANGED)
+ CHK_ERR_WIN32A(ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR)
+ CHK_ERR_WIN32A(ERROR_DS_NO_MSDS_INTID)
+ CHK_ERR_WIN32A(ERROR_DS_DUP_MSDS_INTID)
+ CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_RDNATTID)
+ CHK_ERR_WIN32A(ERROR_DS_AUTHORIZATION_FAILED)
+ CHK_ERR_WIN32A(ERROR_DS_INVALID_SCRIPT)
+ CHK_ERR_WIN32A(ERROR_DS_REMOTE_CROSSREF_OP_FAILED)
+// CHK_ERR_WIN32A(ERROR_DS_CROSS_REF_BUSY)
+// CHK_ERR_WIN32A(ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN)
+// CHK_ERR_WIN32A(ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC)
+// CHK_ERR_WIN32A(ERROR_DS_DUPLICATE_ID_FOUND)
+// CHK_ERR_WIN32A(ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT)
+// CHK_ERR_WIN32A(ERROR_DS_GROUP_CONVERSION_ERROR)
+// CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_APP_BASIC_GROUP)
+// CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_APP_QUERY_GROUP)
+// CHK_ERR_WIN32A(ERROR_DS_ROLE_NOT_VERIFIED)
+// CHK_ERR_WIN32A(ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL)
+// CHK_ERR_WIN32A(ERROR_DS_DOMAIN_RENAME_IN_PROGRESS)
+// CHK_ERR_WIN32A(ERROR_DS_EXISTING_AD_CHILD_NC)
+// CHK_ERR_WIN32A(DNS_ERROR_INVALID_NAME_CHAR)
+// CHK_ERR_WIN32A(DNS_ERROR_NUMERIC_NAME)
+// CHK_ERR_WIN32A(DNS_ERROR_NOT_ALLOWED_ON_ROOT_SERVER)
+// CHK_ERR_WIN32A(DNS_ERROR_NOT_ALLOWED_UNDER_DELEGATION)
+// CHK_ERR_WIN32A(DNS_ERROR_CANNOT_FIND_ROOT_HINTS)
+// CHK_ERR_WIN32A(DNS_ERROR_INCONSISTENT_ROOT_HINTS)
+ CHK_ERR_WIN32A(DNS_ERROR_FORWARDER_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_REQUIRES_MASTER_IP)
+ CHK_ERR_WIN32A(DNS_ERROR_ZONE_IS_SHUTDOWN)
+ CHK_ERR_WIN32A(DNS_ERROR_DP_BASE)
+ CHK_ERR_WIN32A(DNS_ERROR_DP_DOES_NOT_EXIST)
+ CHK_ERR_WIN32A(DNS_ERROR_DP_ALREADY_EXISTS)
+ CHK_ERR_WIN32A(DNS_ERROR_DP_NOT_ENLISTED)
+ CHK_ERR_WIN32A(DNS_ERROR_DP_ALREADY_ENLISTED)
+// CHK_ERR_WIN32A(DNS_ERROR_DP_NOT_AVAILABLE)
+ CHK_ERR_WIN32A(WSA_QOS_ESERVICETYPE)
+ CHK_ERR_WIN32A(WSA_QOS_EFLOWSPEC)
+ CHK_ERR_WIN32A(WSA_QOS_EPROVSPECBUF)
+ CHK_ERR_WIN32A(WSA_QOS_EFILTERSTYLE)
+ CHK_ERR_WIN32A(WSA_QOS_EFILTERTYPE)
+ CHK_ERR_WIN32A(WSA_QOS_EFILTERCOUNT)
+ CHK_ERR_WIN32A(WSA_QOS_EOBJLENGTH)
+ CHK_ERR_WIN32A(WSA_QOS_EFLOWCOUNT)
+ CHK_ERR_WIN32A(WSA_QOS_EUNKOWNPSOBJ)
+ CHK_ERR_WIN32A(WSA_QOS_EPOLICYOBJ)
+ CHK_ERR_WIN32A(WSA_QOS_EFLOWDESC)
+ CHK_ERR_WIN32A(WSA_QOS_EPSFLOWSPEC)
+ CHK_ERR_WIN32A(WSA_QOS_EPSFILTERSPEC)
+ CHK_ERR_WIN32A(WSA_QOS_ESDMODEOBJ)
+ CHK_ERR_WIN32A(WSA_QOS_ESHAPERATEOBJ)
+ CHK_ERR_WIN32A(WSA_QOS_RESERVED_PETYPE)
+ CHK_ERR_WIN32A(ERROR_SXS_SECTION_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_SXS_CANT_GEN_ACTCTX)
+ CHK_ERR_WIN32A(ERROR_SXS_INVALID_ACTCTXDATA_FORMAT)
+ CHK_ERR_WIN32A(ERROR_SXS_ASSEMBLY_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_SXS_MANIFEST_FORMAT_ERROR)
+ CHK_ERR_WIN32A(ERROR_SXS_MANIFEST_PARSE_ERROR)
+ CHK_ERR_WIN32A(ERROR_SXS_ACTIVATION_CONTEXT_DISABLED)
+ CHK_ERR_WIN32A(ERROR_SXS_KEY_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_SXS_VERSION_CONFLICT)
+ CHK_ERR_WIN32A(ERROR_SXS_WRONG_SECTION_TYPE)
+ CHK_ERR_WIN32A(ERROR_SXS_THREAD_QUERIES_DISABLED)
+ CHK_ERR_WIN32A(ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET)
+ CHK_ERR_WIN32A(ERROR_SXS_UNKNOWN_ENCODING_GROUP)
+ CHK_ERR_WIN32A(ERROR_SXS_UNKNOWN_ENCODING)
+ CHK_ERR_WIN32A(ERROR_SXS_INVALID_XML_NAMESPACE_URI)
+ CHK_ERR_WIN32A(ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED)
+ CHK_ERR_WIN32A(ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED)
+ CHK_ERR_WIN32A(ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE)
+ CHK_ERR_WIN32A(ERROR_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE)
+ CHK_ERR_WIN32A(ERROR_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE)
+ CHK_ERR_WIN32A(ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT)
+ CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_DLL_NAME)
+ CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME)
+ CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_CLSID)
+ CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_IID)
+ CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_TLBID)
+ CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_PROGID)
+ CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_ASSEMBLY_NAME)
+ CHK_ERR_WIN32A(ERROR_SXS_FILE_HASH_MISMATCH)
+ CHK_ERR_WIN32A(ERROR_SXS_POLICY_PARSE_ERROR)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGQUOTE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_COMMENTSYNTAX)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADSTARTNAMECHAR)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADNAMECHAR)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADCHARINSTRING)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_XMLDECLSYNTAX)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADCHARDATA)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGWHITESPACE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_EXPECTINGTAGEND)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGSEMICOLON)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNBALANCEDPAREN)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INTERNALERROR)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNEXPECTED_WHITESPACE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INCOMPLETE_ENCODING)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSING_PAREN)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_EXPECTINGCLOSEQUOTE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_MULTIPLE_COLONS)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_DECIMAL)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_HEXIDECIMAL)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_UNICODE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_WHITESPACEORQUESTIONMARK)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNEXPECTEDENDTAG)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDTAG)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_DUPLICATEATTRIBUTE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_MULTIPLEROOTS)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALIDATROOTLEVEL)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADXMLDECL)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGROOT)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNEXPECTEDEOF)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADPEREFINSUBSET)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDSTARTTAG)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDENDTAG)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDSTRING)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDCOMMENT)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDDECL)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDCDATA)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_RESERVEDNAMESPACE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALIDENCODING)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALIDSWITCH)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADXMLCASE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_STANDALONE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNEXPECTED_STANDALONE)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_VERSION)
+ CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGEQUALS)
+ CHK_ERR_WIN32A(ERROR_SXS_PROTECTION_RECOVERY_FAILED)
+ CHK_ERR_WIN32A(ERROR_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT)
+ CHK_ERR_WIN32A(ERROR_SXS_PROTECTION_CATALOG_NOT_VALID)
+ CHK_ERR_WIN32A(ERROR_SXS_UNTRANSLATABLE_HRESULT)
+ CHK_ERR_WIN32A(ERROR_SXS_PROTECTION_CATALOG_FILE_MISSING)
+ CHK_ERR_WIN32A(ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE)
+ CHK_ERR_WIN32A(ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME)
+ CHK_ERR_WIN32A(ERROR_IPSEC_QM_POLICY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_IPSEC_QM_POLICY_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_IPSEC_QM_POLICY_IN_USE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_POLICY_EXISTS)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_POLICY_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_POLICY_IN_USE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_FILTER_EXISTS)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_FILTER_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_IPSEC_TRANSPORT_FILTER_EXISTS)
+ CHK_ERR_WIN32A(ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_AUTH_EXISTS)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_AUTH_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_AUTH_IN_USE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_IPSEC_TUNNEL_FILTER_EXISTS)
+ CHK_ERR_WIN32A(ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_FILTER_PENDING_DELETION)
+ CHK_ERR_WIN32A(ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION)
+ CHK_ERR_WIN32A(ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_POLICY_PENDING_DELETION)
+ CHK_ERR_WIN32A(ERROR_IPSEC_MM_AUTH_PENDING_DELETION)
+ CHK_ERR_WIN32A(ERROR_IPSEC_QM_POLICY_PENDING_DELETION)
+// CHK_ERR_WIN32A(WARNING_IPSEC_MM_POLICY_PRUNED)
+// CHK_ERR_WIN32A(WARNING_IPSEC_QM_POLICY_PRUNED)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NEG_STATUS_BEGIN)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_AUTH_FAIL)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_ATTRIB_FAIL)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NEGOTIATION_PENDING)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_TIMED_OUT)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_CERT)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SA_DELETED)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SA_REAPED)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_MM_ACQUIRE_DROP)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_QM_ACQUIRE_DROP)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_QUEUE_DROP_MM)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_DROP_NO_RESPONSE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_MM_DELAY_DROP)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_QM_DELAY_DROP)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_ERROR)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_CRL_FAILED)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_KEY_USAGE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_CERT_TYPE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_PRIVATE_KEY)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_DH_FAIL)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_HEADER)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_POLICY)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_SIGNATURE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_KERBEROS_ERROR)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_PUBLIC_KEY)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_SA)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_PROP)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_TRANS)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_KE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_ID)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_CERT)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_HASH)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_SIG)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_NONCE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_DELETE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_PAYLOAD)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_LOAD_SOFT_SA)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_COOKIE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_PEER_CERT)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PEER_CRL_FAILED)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_POLICY_CHANGE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_MM_POLICY)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NOTCBPRIV)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SECLOADFAIL)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_FAILSSPINIT)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_FAILQUERYSSP)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SRVACQFAIL)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SRVQUERYCRED)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_GETSPIFAIL)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_FILTER)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_OUT_OF_MEMORY)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_POLICY)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_UNKNOWN_DOI)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_SITUATION)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_DH_FAILURE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_GROUP)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_ENCRYPT)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_DECRYPT)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_POLICY_MATCH)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_UNSUPPORTED_ID)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_HASH)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_HASH_ALG)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_HASH_SIZE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_AUTH_ALG)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_SIG)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_LOAD_FAILED)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_RPC_DELETE)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_BENIGN_REINIT)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_MM_LIMIT)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NEGOTIATION_DISABLED)
+ CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NEG_STATUS_END)
+
+#ifdef HAVE_DDRAW
+
+// -------------------------------------------------------------
+// ddraw.h error codes
+// -------------------------------------------------------------
+ CHK_ERRA(DDERR_ALREADYINITIALIZED)
+ CHK_ERRA(DDERR_CANNOTATTACHSURFACE)
+ CHK_ERRA(DDERR_CANNOTDETACHSURFACE)
+ CHK_ERRA(DDERR_CURRENTLYNOTAVAIL)
+ CHK_ERRA(DDERR_EXCEPTION)
+// CHK_ERRA(DDERR_GENERIC)
+ CHK_ERRA(DDERR_HEIGHTALIGN)
+ CHK_ERRA(DDERR_INCOMPATIBLEPRIMARY)
+ CHK_ERRA(DDERR_INVALIDCAPS)
+ CHK_ERRA(DDERR_INVALIDCLIPLIST)
+ CHK_ERRA(DDERR_INVALIDMODE)
+ CHK_ERRA(DDERR_INVALIDOBJECT)
+// CHK_ERRA(DDERR_INVALIDPARAMS)
+ CHK_ERRA(DDERR_INVALIDPIXELFORMAT)
+ CHK_ERRA(DDERR_INVALIDRECT)
+ CHK_ERRA(DDERR_LOCKEDSURFACES)
+ CHK_ERRA(DDERR_NO3D)
+ CHK_ERRA(DDERR_NOALPHAHW)
+ CHK_ERRA(DDERR_NOSTEREOHARDWARE)
+ CHK_ERRA(DDERR_NOSURFACELEFT)
+ CHK_ERRA(DDERR_NOCLIPLIST)
+ CHK_ERRA(DDERR_NOCOLORCONVHW)
+ CHK_ERRA(DDERR_NOCOOPERATIVELEVELSET)
+ CHK_ERRA(DDERR_NOCOLORKEY)
+ CHK_ERRA(DDERR_NOCOLORKEYHW)
+ CHK_ERRA(DDERR_NODIRECTDRAWSUPPORT)
+ CHK_ERRA(DDERR_NOEXCLUSIVEMODE)
+ CHK_ERRA(DDERR_NOFLIPHW)
+ CHK_ERRA(DDERR_NOGDI)
+ CHK_ERRA(DDERR_NOMIRRORHW)
+ CHK_ERRA(DDERR_NOTFOUND)
+ CHK_ERRA(DDERR_NOOVERLAYHW)
+ CHK_ERRA(DDERR_OVERLAPPINGRECTS)
+ CHK_ERRA(DDERR_NORASTEROPHW)
+ CHK_ERRA(DDERR_NOROTATIONHW)
+ CHK_ERRA(DDERR_NOSTRETCHHW)
+ CHK_ERRA(DDERR_NOT4BITCOLOR)
+ CHK_ERRA(DDERR_NOT4BITCOLORINDEX)
+ CHK_ERRA(DDERR_NOT8BITCOLOR)
+ CHK_ERRA(DDERR_NOTEXTUREHW)
+ CHK_ERRA(DDERR_NOVSYNCHW)
+ CHK_ERRA(DDERR_NOZBUFFERHW)
+ CHK_ERRA(DDERR_NOZOVERLAYHW)
+ CHK_ERRA(DDERR_OUTOFCAPS)
+// CHK_ERRA(DDERR_OUTOFMEMORY)
+// CHK_ERRA(DDERR_OUTOFVIDEOMEMORY)
+ CHK_ERRA(DDERR_OVERLAYCANTCLIP)
+ CHK_ERRA(DDERR_OVERLAYCOLORKEYONLYONEACTIVE)
+ CHK_ERRA(DDERR_PALETTEBUSY)
+ CHK_ERRA(DDERR_COLORKEYNOTSET)
+ CHK_ERRA(DDERR_SURFACEALREADYATTACHED)
+ CHK_ERRA(DDERR_SURFACEALREADYDEPENDENT)
+ CHK_ERRA(DDERR_SURFACEBUSY)
+ CHK_ERRA(DDERR_CANTLOCKSURFACE)
+ CHK_ERRA(DDERR_SURFACEISOBSCURED)
+ CHK_ERRA(DDERR_SURFACELOST)
+ CHK_ERRA(DDERR_SURFACENOTATTACHED)
+ CHK_ERRA(DDERR_TOOBIGHEIGHT)
+ CHK_ERRA(DDERR_TOOBIGSIZE)
+ CHK_ERRA(DDERR_TOOBIGWIDTH)
+// CHK_ERRA(DDERR_UNSUPPORTED)
+ CHK_ERRA(DDERR_UNSUPPORTEDFORMAT)
+ CHK_ERRA(DDERR_UNSUPPORTEDMASK)
+ CHK_ERRA(DDERR_INVALIDSTREAM)
+ CHK_ERRA(DDERR_VERTICALBLANKINPROGRESS)
+ CHK_ERRA(DDERR_WASSTILLDRAWING)
+ CHK_ERRA(DDERR_DDSCAPSCOMPLEXREQUIRED)
+ CHK_ERRA(DDERR_XALIGN)
+ CHK_ERRA(DDERR_INVALIDDIRECTDRAWGUID)
+ CHK_ERRA(DDERR_DIRECTDRAWALREADYCREATED)
+ CHK_ERRA(DDERR_NODIRECTDRAWHW)
+ CHK_ERRA(DDERR_PRIMARYSURFACEALREADYEXISTS)
+ CHK_ERRA(DDERR_NOEMULATION)
+ CHK_ERRA(DDERR_REGIONTOOSMALL)
+ CHK_ERRA(DDERR_CLIPPERISUSINGHWND)
+ CHK_ERRA(DDERR_NOCLIPPERATTACHED)
+ CHK_ERRA(DDERR_NOHWND)
+ CHK_ERRA(DDERR_HWNDSUBCLASSED)
+ CHK_ERRA(DDERR_HWNDALREADYSET)
+ CHK_ERRA(DDERR_NOPALETTEATTACHED)
+ CHK_ERRA(DDERR_NOPALETTEHW)
+ CHK_ERRA(DDERR_BLTFASTCANTCLIP)
+ CHK_ERRA(DDERR_NOBLTHW)
+ CHK_ERRA(DDERR_NODDROPSHW)
+ CHK_ERRA(DDERR_OVERLAYNOTVISIBLE)
+ CHK_ERRA(DDERR_NOOVERLAYDEST)
+ CHK_ERRA(DDERR_INVALIDPOSITION)
+ CHK_ERRA(DDERR_NOTAOVERLAYSURFACE)
+ CHK_ERRA(DDERR_EXCLUSIVEMODEALREADYSET)
+ CHK_ERRA(DDERR_NOTFLIPPABLE)
+ CHK_ERRA(DDERR_CANTDUPLICATE)
+ CHK_ERRA(DDERR_NOTLOCKED)
+ CHK_ERRA(DDERR_CANTCREATEDC)
+ CHK_ERRA(DDERR_NODC)
+ CHK_ERRA(DDERR_WRONGMODE)
+ CHK_ERRA(DDERR_IMPLICITLYCREATED)
+ CHK_ERRA(DDERR_NOTPALETTIZED)
+ CHK_ERRA(DDERR_UNSUPPORTEDMODE)
+ CHK_ERRA(DDERR_NOMIPMAPHW)
+ CHK_ERRA(DDERR_INVALIDSURFACETYPE)
+ CHK_ERRA(DDERR_NOOPTIMIZEHW)
+ CHK_ERRA(DDERR_NOTLOADED)
+ CHK_ERRA(DDERR_NOFOCUSWINDOW)
+ CHK_ERRA(DDERR_NOTONMIPMAPSUBLEVEL)
+ CHK_ERRA(DDERR_DCALREADYCREATED)
+ CHK_ERRA(DDERR_NONONLOCALVIDMEM)
+ CHK_ERRA(DDERR_CANTPAGELOCK)
+ CHK_ERRA(DDERR_CANTPAGEUNLOCK)
+ CHK_ERRA(DDERR_NOTPAGELOCKED)
+ CHK_ERRA(DDERR_MOREDATA)
+ CHK_ERRA(DDERR_EXPIRED)
+ CHK_ERRA(DDERR_TESTFINISHED)
+ CHK_ERRA(DDERR_NEWMODE)
+ CHK_ERRA(DDERR_D3DNOTINITIALIZED)
+ CHK_ERRA(DDERR_VIDEONOTACTIVE)
+ CHK_ERRA(DDERR_NOMONITORINFORMATION)
+ CHK_ERRA(DDERR_NODRIVERSUPPORT)
+ CHK_ERRA(DDERR_DEVICEDOESNTOWNSURFACE)
+
+#endif
+
+#ifdef HAVE_DINPUT
+
+// -------------------------------------------------------------
+// dinput.h error codes
+// -------------------------------------------------------------
+// CHK_ERRA(DI_OK)
+// CHK_ERRA(DI_NOTATTACHED)
+// CHK_ERRA(DI_BUFFEROVERFLOW)
+// CHK_ERRA(DI_PROPNOEFFECT)
+// CHK_ERRA(DI_NOEFFECT)
+// CHK_ERRA(DI_POLLEDDEVICE)
+// CHK_ERRA(DI_DOWNLOADSKIPPED)
+// CHK_ERRA(DI_EFFECTRESTARTED)
+// CHK_ERRA(DI_SETTINGSNOTSAVED_ACCESSDENIED)
+// CHK_ERRA(DI_SETTINGSNOTSAVED_DISKFULL)
+// CHK_ERRA(DI_TRUNCATED)
+// CHK_ERRA(DI_TRUNCATEDANDRESTARTED)
+// CHK_ERRA(DI_WRITEPROTECT)
+ CHK_ERR(DIERR_INSUFFICIENTPRIVS, "DIERR_INSUFFICIENTPRIVS & VFW_E_INVALIDMEDIATYPE")
+ CHK_ERR(DIERR_DEVICEFULL, "DIERR_DEVICEFULL & VFW_E_INVALIDSUBTYPE & DMO_E_INVALIDSTREAMINDEX")
+ CHK_ERR(DIERR_MOREDATA, "DIERR_MOREDATA & VFW_E_NEED_OWNER & DMO_E_INVALIDTYPE")
+ CHK_ERR(DIERR_NOTDOWNLOADED, "DIERR_NOTDOWNLOADED & VFW_E_ENUM_OUT_OF_SYNC & DMO_E_TYPE_NOT_SET")
+ CHK_ERR(DIERR_HASEFFECTS, "DIERR_HASEFFECTS & VFW_E_ALREADY_CONNECTED & DMO_E_NOTACCEPTING")
+ CHK_ERR(DIERR_NOTEXCLUSIVEACQUIRED, "DIERR_NOTEXCLUSIVEACQUIRED & VFW_E_FILTER_ACTIVE & DMO_E_TYPE_NOT_ACCEPTED")
+ CHK_ERR(DIERR_INCOMPLETEEFFECT, "DIERR_INCOMPLETEEFFECT & VFW_E_NO_TYPES & DMO_E_NO_MORE_ITEMS")
+ CHK_ERR(DIERR_NOTBUFFERED, "DIERR_NOTBUFFERED & VFW_E_NO_ACCEPTABLE_TYPES")
+ CHK_ERR(DIERR_EFFECTPLAYING, "DIERR_EFFECTPLAYING & VFW_E_INVALID_DIRECTION")
+ CHK_ERR(DIERR_UNPLUGGED, "DIERR_UNPLUGGED & VFW_E_NOT_CONNECTED")
+ CHK_ERR(DIERR_REPORTFULL, "DIERR_REPORTFULL & VFW_E_NO_ALLOCATOR")
+ CHK_ERR(DIERR_MAPFILEFAIL, "DIERR_MAPFILEFAIL & VFW_E_RUNTIME_ERROR")
+// CHK_ERRA(DIERR_OLDDIRECTINPUTVERSION)
+// CHK_ERRA(DIERR_GENERIC)
+// CHK_ERRA(DIERR_OLDDIRECTINPUTVERSION)
+// CHK_ERRA(DIERR_BETADIRECTINPUTVERSION)
+// CHK_ERRA(DIERR_BADDRIVERVER)
+// CHK_ERRA(DIERR_DEVICENOTREG)
+// CHK_ERRA(DIERR_NOTFOUND)
+// CHK_ERRA(DIERR_OBJECTNOTFOUND)
+// CHK_ERRA(DIERR_INVALIDPARAM)
+// CHK_ERRA(DIERR_NOINTERFACE)
+// CHK_ERRA(DIERR_GENERIC)
+// CHK_ERRA(DIERR_OUTOFMEMORY)
+// CHK_ERRA(DIERR_UNSUPPORTED)
+// CHK_ERRA(DIERR_NOTINITIALIZED)
+// CHK_ERRA(DIERR_ALREADYINITIALIZED)
+// CHK_ERRA(DIERR_NOAGGREGATION)
+// CHK_ERRA(DIERR_OTHERAPPHASPRIO)
+// CHK_ERRA(DIERR_INPUTLOST)
+// CHK_ERRA(DIERR_ACQUIRED)
+// CHK_ERRA(DIERR_NOTACQUIRED)
+// CHK_ERRA(DIERR_READONLY)
+// CHK_ERRA(DIERR_HANDLEEXISTS)
+
+
+// -------------------------------------------------------------
+// dinputd.h error
+// -------------------------------------------------------------
+// CHK_ERRA(DIERR_NOMOREITEMS)
+ CHK_ERRA(DIERR_DRIVERFIRST)
+ CHK_ERR(DIERR_DRIVERFIRST+1, "DIERR_DRIVERFIRST+1")
+ CHK_ERR(DIERR_DRIVERFIRST+2, "DIERR_DRIVERFIRST+2")
+ CHK_ERR(DIERR_DRIVERFIRST+3, "DIERR_DRIVERFIRST+3")
+ CHK_ERR(DIERR_DRIVERFIRST+4, "DIERR_DRIVERFIRST+4")
+ CHK_ERR(DIERR_DRIVERFIRST+5, "DIERR_DRIVERFIRST+5")
+ CHK_ERRA(DIERR_DRIVERLAST)
+ CHK_ERR(DIERR_INVALIDCLASSINSTALLER, "DIERR_INVALIDCLASSINSTALLER")
+ CHK_ERR(DIERR_CANCELLED, "DIERR_CANCELLED & MS_E_SAMPLEALLOC")
+ CHK_ERRA(DIERR_BADINF)
+
+#endif
+
+#ifdef HAVE_D3D9
+
+// -------------------------------------------------------------
+// d3d9.h error codes
+// -------------------------------------------------------------
+// CHK_ERRA(D3D_OK)
+ CHK_ERRA(D3DERR_WRONGTEXTUREFORMAT)
+ CHK_ERRA(D3DERR_UNSUPPORTEDCOLOROPERATION)
+ CHK_ERRA(D3DERR_UNSUPPORTEDCOLORARG)
+ CHK_ERRA(D3DERR_UNSUPPORTEDALPHAOPERATION)
+ CHK_ERRA(D3DERR_UNSUPPORTEDALPHAARG)
+ CHK_ERRA(D3DERR_TOOMANYOPERATIONS)
+ CHK_ERRA(D3DERR_CONFLICTINGTEXTUREFILTER)
+ CHK_ERRA(D3DERR_UNSUPPORTEDFACTORVALUE)
+ CHK_ERRA(D3DERR_CONFLICTINGRENDERSTATE)
+ CHK_ERRA(D3DERR_UNSUPPORTEDTEXTUREFILTER)
+ CHK_ERRA(D3DERR_CONFLICTINGTEXTUREPALETTE)
+ CHK_ERRA(D3DERR_DRIVERINTERNALERROR)
+ CHK_ERRA(D3DERR_NOTFOUND)
+ CHK_ERRA(D3DERR_MOREDATA)
+ CHK_ERRA(D3DERR_DEVICELOST)
+ CHK_ERRA(D3DERR_DEVICENOTRESET)
+ CHK_ERRA(D3DERR_NOTAVAILABLE)
+ CHK_ERRA(D3DERR_OUTOFVIDEOMEMORY)
+ CHK_ERRA(D3DERR_INVALIDDEVICE)
+ CHK_ERRA(D3DERR_INVALIDCALL)
+ CHK_ERRA(D3DERR_DRIVERINVALIDCALL)
+ //CHK_ERRA(D3DERR_WASSTILLDRAWING)
+ CHK_ERRA(D3DOK_NOAUTOGEN)
+
+ // Extended for Windows Vista
+ CHK_ERRA(D3DERR_DEVICEREMOVED)
+ CHK_ERRA(S_NOT_RESIDENT)
+ CHK_ERRA(S_RESIDENT_IN_SHARED_MEMORY)
+ CHK_ERRA(S_PRESENT_MODE_CHANGED)
+ CHK_ERRA(S_PRESENT_OCCLUDED)
+ CHK_ERRA(D3DERR_DEVICEHUNG)
+
+ // Extended for Windows 7
+ CHK_ERRA(D3DERR_UNSUPPORTEDOVERLAY)
+ CHK_ERRA(D3DERR_UNSUPPORTEDOVERLAYFORMAT)
+ CHK_ERRA(D3DERR_CANNOTPROTECTCONTENT)
+ CHK_ERRA(D3DERR_UNSUPPORTEDCRYPTO)
+ CHK_ERRA(D3DERR_PRESENT_STATISTICS_DISJOINT)
+
+#endif
+
+#ifdef HAVE_DSOUND
+
+// -------------------------------------------------------------
+// dsound.h error codes
+// -------------------------------------------------------------
+// CHK_ERRA(DS_OK)
+ CHK_ERRA(DS_NO_VIRTUALIZATION)
+ CHK_ERRA(DSERR_ALLOCATED)
+ CHK_ERRA(DSERR_CONTROLUNAVAIL)
+// CHK_ERRA(DSERR_INVALIDPARAM)
+ CHK_ERRA(DSERR_INVALIDCALL)
+// CHK_ERRA(DSERR_GENERIC)
+ CHK_ERRA(DSERR_PRIOLEVELNEEDED)
+// CHK_ERRA(DSERR_OUTOFMEMORY)
+ CHK_ERRA(DSERR_BADFORMAT)
+// CHK_ERRA(DSERR_UNSUPPORTED)
+ CHK_ERRA(DSERR_NODRIVER)
+ CHK_ERRA(DSERR_ALREADYINITIALIZED)
+// CHK_ERRA(DSERR_NOAGGREGATION)
+ CHK_ERRA(DSERR_BUFFERLOST)
+ CHK_ERRA(DSERR_OTHERAPPHASPRIO)
+ CHK_ERRA(DSERR_UNINITIALIZED)
+// CHK_ERRA(DSERR_NOINTERFACE)
+// CHK_ERRA(DSERR_ACCESSDENIED)
+ CHK_ERRA(DSERR_BUFFERTOOSMALL)
+ CHK_ERRA(DSERR_DS8_REQUIRED)
+ CHK_ERRA(DSERR_SENDLOOP)
+ CHK_ERRA(DSERR_BADSENDBUFFERGUID)
+ CHK_ERRA(DSERR_OBJECTNOTFOUND)
+
+ CHK_ERRA(DSERR_FXUNAVAILABLE)
+
+#endif
+
+#ifdef HAVE_D3D10_1
+
+// -------------------------------------------------------------
+// d3d10.h error codes
+// -------------------------------------------------------------
+ CHK_ERRA(D3D10_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS)
+ CHK_ERRA(D3D10_ERROR_FILE_NOT_FOUND)
+
+// -------------------------------------------------------------
+// dxgi.h error codes
+// -------------------------------------------------------------
+ CHK_ERRA(DXGI_STATUS_OCCLUDED)
+ CHK_ERRA(DXGI_STATUS_CLIPPED)
+ CHK_ERRA(DXGI_STATUS_NO_REDIRECTION)
+ CHK_ERRA(DXGI_STATUS_NO_DESKTOP_ACCESS)
+ CHK_ERRA(DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE)
+ CHK_ERRA(DXGI_STATUS_MODE_CHANGED)
+ CHK_ERRA(DXGI_STATUS_MODE_CHANGE_IN_PROGRESS)
+ CHK_ERRA(DXGI_ERROR_INVALID_CALL)
+ CHK_ERRA(DXGI_ERROR_NOT_FOUND)
+ CHK_ERRA(DXGI_ERROR_MORE_DATA)
+ CHK_ERRA(DXGI_ERROR_UNSUPPORTED)
+ CHK_ERRA(DXGI_ERROR_DEVICE_REMOVED)
+ CHK_ERRA(DXGI_ERROR_DEVICE_HUNG)
+ CHK_ERRA(DXGI_ERROR_DEVICE_RESET)
+ CHK_ERRA(DXGI_ERROR_WAS_STILL_DRAWING)
+ CHK_ERRA(DXGI_ERROR_FRAME_STATISTICS_DISJOINT)
+ CHK_ERRA(DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE)
+ CHK_ERRA(DXGI_ERROR_DRIVER_INTERNAL_ERROR)
+ CHK_ERRA(DXGI_ERROR_NONEXCLUSIVE)
+ CHK_ERRA(DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
+ CHK_ERRA(DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED)
+ CHK_ERRA(DXGI_ERROR_REMOTE_OUTOFMEMORY)
+
+#endif
+
+#ifdef HAVE_D3D11_1
+
+// -------------------------------------------------------------
+// d3d11.h error codes
+// -------------------------------------------------------------
+ CHK_ERRA(D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS)
+ CHK_ERRA(D3D11_ERROR_FILE_NOT_FOUND)
+ CHK_ERRA(D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS)
+ CHK_ERRA(D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD)
+
+#endif
+
+#ifdef HAVE_D2D
+
+// -------------------------------------------------------------
+// Direct2D error codes
+// -------------------------------------------------------------
+// CHK_ERRA(D2DERR_UNSUPPORTED_PIXEL_FORMAT)
+// CHK_ERRA(D2DERR_INSUFFICIENT_BUFFER)
+ CHK_ERRA(D2DERR_WRONG_STATE)
+ CHK_ERRA(D2DERR_NOT_INITIALIZED)
+ CHK_ERRA(D2DERR_UNSUPPORTED_OPERATION)
+ CHK_ERRA(D2DERR_SCANNER_FAILED)
+ CHK_ERRA(D2DERR_SCREEN_ACCESS_DENIED)
+ CHK_ERRA(D2DERR_DISPLAY_STATE_INVALID)
+ CHK_ERRA(D2DERR_ZERO_VECTOR)
+ CHK_ERRA(D2DERR_INTERNAL_ERROR)
+ CHK_ERRA(D2DERR_DISPLAY_FORMAT_NOT_SUPPORTED)
+ CHK_ERRA(D2DERR_INVALID_CALL)
+ CHK_ERRA(D2DERR_NO_HARDWARE_DEVICE)
+ CHK_ERRA(D2DERR_RECREATE_TARGET)
+ CHK_ERRA(D2DERR_TOO_MANY_SHADER_ELEMENTS)
+ CHK_ERRA(D2DERR_SHADER_COMPILE_FAILED)
+ CHK_ERRA(D2DERR_MAX_TEXTURE_SIZE_EXCEEDED)
+ CHK_ERRA(D2DERR_UNSUPPORTED_VERSION)
+ CHK_ERRA(D2DERR_BAD_NUMBER)
+ CHK_ERRA(D2DERR_WRONG_FACTORY)
+ CHK_ERRA(D2DERR_LAYER_ALREADY_IN_USE)
+ CHK_ERRA(D2DERR_POP_CALL_DID_NOT_MATCH_PUSH)
+// CHK_ERRA(D2DERR_WRONG_RESOURCE_DOMAIN)
+ CHK_ERRA(D2DERR_PUSH_POP_UNBALANCED)
+ CHK_ERRA(D2DERR_RENDER_TARGET_HAS_LAYER_OR_CLIPRECT)
+ CHK_ERRA(D2DERR_INCOMPATIBLE_BRUSH_TYPES)
+ CHK_ERRA(D2DERR_WIN32_ERROR)
+ CHK_ERRA(D2DERR_TARGET_NOT_GDI_COMPATIBLE)
+ CHK_ERRA(D2DERR_TEXT_EFFECT_IS_WRONG_TYPE)
+ CHK_ERRA(D2DERR_TEXT_RENDERER_NOT_RELEASED)
+// CHK_ERRA(D2DERR_EXCEEDS_MAX_BITMAP_SIZE)
+
+// -------------------------------------------------------------
+// DirectWrite error codes
+// -------------------------------------------------------------
+ CHK_ERRA(DWRITE_E_FILEFORMAT)
+ CHK_ERRA(DWRITE_E_UNEXPECTED)
+ CHK_ERRA(DWRITE_E_NOFONT)
+ CHK_ERRA(DWRITE_E_FILENOTFOUND)
+ CHK_ERRA(DWRITE_E_FILEACCESS)
+ CHK_ERRA(DWRITE_E_FONTCOLLECTIONOBSOLETE)
+ CHK_ERRA(DWRITE_E_ALREADYREGISTERED)
+
+// -------------------------------------------------------------
+// WIC error codes
+// -------------------------------------------------------------
+ CHK_ERRA(WINCODEC_ERR_WRONGSTATE)
+ CHK_ERRA(WINCODEC_ERR_VALUEOUTOFRANGE)
+ CHK_ERRA(WINCODEC_ERR_UNKNOWNIMAGEFORMAT)
+ CHK_ERRA(WINCODEC_ERR_UNSUPPORTEDVERSION)
+ CHK_ERRA(WINCODEC_ERR_NOTINITIALIZED)
+ CHK_ERRA(WINCODEC_ERR_ALREADYLOCKED)
+ CHK_ERRA(WINCODEC_ERR_PROPERTYNOTFOUND)
+ CHK_ERRA(WINCODEC_ERR_PROPERTYNOTSUPPORTED)
+ CHK_ERRA(WINCODEC_ERR_PROPERTYSIZE)
+ CHK_ERRA(WINCODEC_ERR_CODECPRESENT)
+ CHK_ERRA(WINCODEC_ERR_CODECNOTHUMBNAIL)
+ CHK_ERRA(WINCODEC_ERR_PALETTEUNAVAILABLE)
+ CHK_ERRA(WINCODEC_ERR_CODECTOOMANYSCANLINES)
+ CHK_ERRA(WINCODEC_ERR_INTERNALERROR)
+ CHK_ERRA(WINCODEC_ERR_SOURCERECTDOESNOTMATCHDIMENSIONS)
+ CHK_ERRA(WINCODEC_ERR_COMPONENTNOTFOUND)
+ CHK_ERRA(WINCODEC_ERR_IMAGESIZEOUTOFRANGE)
+ CHK_ERRA(WINCODEC_ERR_TOOMUCHMETADATA)
+ CHK_ERRA(WINCODEC_ERR_BADIMAGE)
+ CHK_ERRA(WINCODEC_ERR_BADHEADER)
+ CHK_ERRA(WINCODEC_ERR_FRAMEMISSING)
+ CHK_ERRA(WINCODEC_ERR_BADMETADATAHEADER)
+ CHK_ERRA(WINCODEC_ERR_BADSTREAMDATA)
+ CHK_ERRA(WINCODEC_ERR_STREAMWRITE)
+ CHK_ERRA(WINCODEC_ERR_STREAMREAD)
+ CHK_ERRA(WINCODEC_ERR_STREAMNOTAVAILABLE)
+ CHK_ERRA(WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT)
+ CHK_ERRA(WINCODEC_ERR_UNSUPPORTEDOPERATION)
+ CHK_ERRA(WINCODEC_ERR_INVALIDREGISTRATION)
+ CHK_ERRA(WINCODEC_ERR_COMPONENTINITIALIZEFAILURE)
+ CHK_ERRA(WINCODEC_ERR_INSUFFICIENTBUFFER)
+ CHK_ERRA(WINCODEC_ERR_DUPLICATEMETADATAPRESENT)
+ CHK_ERRA(WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE)
+ CHK_ERRA(WINCODEC_ERR_UNEXPECTEDSIZE)
+ CHK_ERRA(WINCODEC_ERR_INVALIDQUERYREQUEST)
+ CHK_ERRA(WINCODEC_ERR_UNEXPECTEDMETADATATYPE)
+ CHK_ERRA(WINCODEC_ERR_REQUESTONLYVALIDATMETADATAROOT)
+ CHK_ERRA(WINCODEC_ERR_INVALIDQUERYCHARACTER)
+ CHK_ERRA(WINCODEC_ERR_WIN32ERROR)
+ CHK_ERRA(WINCODEC_ERR_INVALIDPROGRESSIVELEVEL)
+
+#endif
+
+// -------------------------------------------------------------
+// DXUT error codes
+// -------------------------------------------------------------
+ CHK_ERRA(DXUTERR_NODIRECT3D)
+ CHK_ERRA(DXUTERR_NOCOMPATIBLEDEVICES)
+ CHK_ERRA(DXUTERR_MEDIANOTFOUND)
+ CHK_ERRA(DXUTERR_NONZEROREFCOUNT)
+ CHK_ERRA(DXUTERR_CREATINGDEVICE)
+ CHK_ERRA(DXUTERR_RESETTINGDEVICE)
+ CHK_ERRA(DXUTERR_CREATINGDEVICEOBJECTS)
+ CHK_ERRA(DXUTERR_RESETTINGDEVICEOBJECTS)
+ CHK_ERRA(DXUTERR_INCORRECTVERSION)
+ CHK_ERRA(DXUTERR_DEVICEREMOVED)
+
+// -------------------------------------------------------------
+// xaudio2.h error codes
+// -------------------------------------------------------------
+ CHK_ERRA(XAUDIO2_E_INVALID_CALL)
+ CHK_ERRA(XAUDIO2_E_XMA_DECODER_ERROR)
+ CHK_ERRA(XAUDIO2_E_XAPO_CREATION_FAILED)
+ CHK_ERRA(XAUDIO2_E_DEVICE_INVALIDATED)
+
+// -------------------------------------------------------------
+// xapo.h error codes
+// -------------------------------------------------------------
+ CHK_ERRA(XAPO_E_FORMAT_UNSUPPORTED)
+ }
+
+ return "Unknown";
+}
+
+//--------------------------------------------------------------------------------------
+#undef CHK_ERR
+#undef CHK_ERRA
+#undef HRESULT_FROM_WIN32b
+#undef CHK_ERR_WIN32A
+#undef CHK_ERR_WIN32_ONLY
+
+#define CHK_ERRA(hrchk) \
+ case hrchk: \
+ strcpy_s( desc, count, #hrchk ); \
+ break;
+
+#define CHK_ERR(hrchk, strOut) \
+ case hrchk: \
+ strcpy_s( desc, count, strOut ); \
+ break;
+
+
+//--------------------------------------------------------------------------------------
+void WINAPI DXGetErrorDescriptionA( HRESULT hr, char* desc, size_t count )
+{
+ if ( !count )
+ return;
+
+ *desc = 0;
+
+ // First try to see if FormatMessage knows this hr
+ UINT icount = static_cast<UINT>( std::min<size_t>( count, 32767 ) );
+
+ DWORD result = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), desc, icount, NULL );
+
+ if (result > 0)
+ return;
+
+ switch (hr)
+ {
+// Commmented out codes are actually alises for other codes
+
+#ifdef HAVE_DDRAW
+
+// -------------------------------------------------------------
+// ddraw.h error codes
+// -------------------------------------------------------------
+ CHK_ERR(DDERR_ALREADYINITIALIZED, "This object is already initialized")
+ CHK_ERR(DDERR_CANNOTATTACHSURFACE, "This surface can not be attached to the requested surface.")
+ CHK_ERR(DDERR_CANNOTDETACHSURFACE, "This surface can not be detached from the requested surface.")
+ CHK_ERR(DDERR_CURRENTLYNOTAVAIL, "Support is currently not available.")
+ CHK_ERR(DDERR_EXCEPTION, "An exception was encountered while performing the requested operation")
+// CHK_ERR(DDERR_GENERIC, "DDERR_GENERIC")
+ CHK_ERR(DDERR_HEIGHTALIGN, "Height of rectangle provided is not a multiple of reqd alignment")
+ CHK_ERR(DDERR_INCOMPATIBLEPRIMARY, "Unable to match primary surface creation request with existing primary surface.")
+ CHK_ERR(DDERR_INVALIDCAPS, "One or more of the caps bits passed to the callback are incorrect.")
+ CHK_ERR(DDERR_INVALIDCLIPLIST, "DirectDraw does not support provided Cliplist.")
+ CHK_ERR(DDERR_INVALIDMODE, "DirectDraw does not support the requested mode")
+ CHK_ERR(DDERR_INVALIDOBJECT, "DirectDraw received a pointer that was an invalid DIRECTDRAW object.")
+// CHK_ERR(DDERR_INVALIDPARAMS, "DDERR_INVALIDPARAMS")
+ CHK_ERR(DDERR_INVALIDPIXELFORMAT, "pixel format was invalid as specified")
+ CHK_ERR(DDERR_INVALIDRECT, "Rectangle provided was invalid.")
+ CHK_ERR(DDERR_LOCKEDSURFACES, "Operation could not be carried out because one or more surfaces are locked")
+ CHK_ERR(DDERR_NO3D, "There is no 3D present.")
+ CHK_ERR(DDERR_NOALPHAHW, "Operation could not be carried out because there is no alpha accleration hardware present or available.")
+ CHK_ERR(DDERR_NOSTEREOHARDWARE, "Operation could not be carried out because there is no stereo hardware present or available.")
+ CHK_ERR(DDERR_NOSURFACELEFT, "Operation could not be carried out because there is no hardware present which supports stereo surfaces")
+ CHK_ERR(DDERR_NOCLIPLIST, "no clip list available")
+ CHK_ERR(DDERR_NOCOLORCONVHW, "Operation could not be carried out because there is no color conversion hardware present or available.")
+ CHK_ERR(DDERR_NOCOOPERATIVELEVELSET, "Create function called without DirectDraw object method SetCooperativeLevel being called.")
+ CHK_ERR(DDERR_NOCOLORKEY, "Surface doesn't currently have a color key")
+ CHK_ERR(DDERR_NOCOLORKEYHW, "Operation could not be carried out because there is no hardware support of the dest color key.")
+ CHK_ERR(DDERR_NODIRECTDRAWSUPPORT, "No DirectDraw support possible with current display driver")
+ CHK_ERR(DDERR_NOEXCLUSIVEMODE, "Operation requires the application to have exclusive mode but the application does not have exclusive mode.")
+ CHK_ERR(DDERR_NOFLIPHW, "Flipping visible surfaces is not supported.")
+ CHK_ERR(DDERR_NOGDI, "There is no GDI present.")
+ CHK_ERR(DDERR_NOMIRRORHW, "Operation could not be carried out because there is no hardware present or available.")
+ CHK_ERR(DDERR_NOTFOUND, "Requested item was not found")
+ CHK_ERR(DDERR_NOOVERLAYHW, "Operation could not be carried out because there is no overlay hardware present or available.")
+ CHK_ERR(DDERR_OVERLAPPINGRECTS, "Operation could not be carried out because the source and destination rectangles are on the same surface and overlap each other.")
+ CHK_ERR(DDERR_NORASTEROPHW, "Operation could not be carried out because there is no appropriate raster op hardware present or available.")
+ CHK_ERR(DDERR_NOROTATIONHW, "Operation could not be carried out because there is no rotation hardware present or available.")
+ CHK_ERR(DDERR_NOSTRETCHHW, "Operation could not be carried out because there is no hardware support for stretching")
+ CHK_ERR(DDERR_NOT4BITCOLOR, "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.")
+ CHK_ERR(DDERR_NOT4BITCOLORINDEX, "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.")
+ CHK_ERR(DDERR_NOT8BITCOLOR, "DirectDraw Surface is not in 8 bit color mode and the requested operation requires 8 bit color.")
+ CHK_ERR(DDERR_NOTEXTUREHW, "Operation could not be carried out because there is no texture mapping hardware present or available.")
+ CHK_ERR(DDERR_NOVSYNCHW, "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.")
+ CHK_ERR(DDERR_NOZBUFFERHW, "Operation could not be carried out because there is no hardware support for zbuffer blting.")
+ CHK_ERR(DDERR_NOZOVERLAYHW, "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.")
+ CHK_ERR(DDERR_OUTOFCAPS, "The hardware needed for the requested operation has already been allocated.")
+// CHK_ERR(DDERR_OUTOFMEMORY, "DDERR_OUTOFMEMORY")
+// CHK_ERR(DDERR_OUTOFVIDEOMEMORY, "DDERR_OUTOFVIDEOMEMORY")
+ CHK_ERR(DDERR_OVERLAYCANTCLIP, "hardware does not support clipped overlays")
+ CHK_ERR(DDERR_OVERLAYCOLORKEYONLYONEACTIVE, "Can only have ony color key active at one time for overlays")
+ CHK_ERR(DDERR_PALETTEBUSY, "Access to this palette is being refused because the palette is already locked by another thread.")
+ CHK_ERR(DDERR_COLORKEYNOTSET, "No src color key specified for this operation.")
+ CHK_ERR(DDERR_SURFACEALREADYATTACHED, "This surface is already attached to the surface it is being attached to.")
+ CHK_ERR(DDERR_SURFACEALREADYDEPENDENT, "This surface is already a dependency of the surface it is being made a dependency of.")
+ CHK_ERR(DDERR_SURFACEBUSY, "Access to this surface is being refused because the surface is already locked by another thread.")
+ CHK_ERR(DDERR_CANTLOCKSURFACE, "Access to this surface is being refused because no driver exists which can supply a pointer to the surface. This is most likely to happen when attempting to lock the primary surface when no DCI provider is present. Will also happen on attempts to lock an optimized surface.")
+ CHK_ERR(DDERR_SURFACEISOBSCURED, "Access to Surface refused because Surface is obscured.")
+ CHK_ERR(DDERR_SURFACELOST, "Access to this surface is being refused because the surface is gone. The DIRECTDRAWSURFACE object representing this surface should have Restore called on it.")
+ CHK_ERR(DDERR_SURFACENOTATTACHED, "The requested surface is not attached.")
+ CHK_ERR(DDERR_TOOBIGHEIGHT, "Height requested by DirectDraw is too large.")
+ CHK_ERR(DDERR_TOOBIGSIZE, "Size requested by DirectDraw is too large -- The individual height and width are OK.")
+ CHK_ERR(DDERR_TOOBIGWIDTH, "Width requested by DirectDraw is too large.")
+// CHK_ERR(DDERR_UNSUPPORTED, "DDERR_UNSUPPORTED")
+ CHK_ERR(DDERR_UNSUPPORTEDFORMAT, "Pixel format requested is unsupported by DirectDraw")
+ CHK_ERR(DDERR_UNSUPPORTEDMASK, "Bitmask in the pixel format requested is unsupported by DirectDraw")
+ CHK_ERR(DDERR_INVALIDSTREAM, "The specified stream contains invalid data")
+ CHK_ERR(DDERR_VERTICALBLANKINPROGRESS, "vertical blank is in progress")
+ CHK_ERR(DDERR_WASSTILLDRAWING, "Was still drawing")
+ CHK_ERR(DDERR_DDSCAPSCOMPLEXREQUIRED, "The specified surface type requires specification of the COMPLEX flag")
+ CHK_ERR(DDERR_XALIGN, "Rectangle provided was not horizontally aligned on reqd. boundary")
+ CHK_ERR(DDERR_INVALIDDIRECTDRAWGUID, "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.")
+ CHK_ERR(DDERR_DIRECTDRAWALREADYCREATED, "A DirectDraw object representing this driver has already been created for this process.")
+ CHK_ERR(DDERR_NODIRECTDRAWHW, "A hardware only DirectDraw object creation was attempted but the driver did not support any hardware.")
+ CHK_ERR(DDERR_PRIMARYSURFACEALREADYEXISTS, "this process already has created a primary surface")
+ CHK_ERR(DDERR_NOEMULATION, "software emulation not available.")
+ CHK_ERR(DDERR_REGIONTOOSMALL, "region passed to Clipper::GetClipList is too small.")
+ CHK_ERR(DDERR_CLIPPERISUSINGHWND, "an attempt was made to set a clip list for a clipper objec that is already monitoring an hwnd.")
+ CHK_ERR(DDERR_NOCLIPPERATTACHED, "No clipper object attached to surface object")
+ CHK_ERR(DDERR_NOHWND, "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.")
+ CHK_ERR(DDERR_HWNDSUBCLASSED, "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.")
+ CHK_ERR(DDERR_HWNDALREADYSET, "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.")
+ CHK_ERR(DDERR_NOPALETTEATTACHED, "No palette object attached to this surface.")
+ CHK_ERR(DDERR_NOPALETTEHW, "No hardware support for 16 or 256 color palettes.")
+ CHK_ERR(DDERR_BLTFASTCANTCLIP, "If a clipper object is attached to the source surface passed into a BltFast call.")
+ CHK_ERR(DDERR_NOBLTHW, "No blter.")
+ CHK_ERR(DDERR_NODDROPSHW, "No DirectDraw ROP hardware.")
+ CHK_ERR(DDERR_OVERLAYNOTVISIBLE, "returned when GetOverlayPosition is called on a hidden overlay")
+ CHK_ERR(DDERR_NOOVERLAYDEST, "returned when GetOverlayPosition is called on a overlay that UpdateOverlay has never been called on to establish a destionation.")
+ CHK_ERR(DDERR_INVALIDPOSITION, "returned when the position of the overlay on the destionation is no longer legal for that destionation.")
+ CHK_ERR(DDERR_NOTAOVERLAYSURFACE, "returned when an overlay member is called for a non-overlay surface")
+ CHK_ERR(DDERR_EXCLUSIVEMODEALREADYSET, "An attempt was made to set the cooperative level when it was already set to exclusive.")
+ CHK_ERR(DDERR_NOTFLIPPABLE, "An attempt has been made to flip a surface that is not flippable.")
+ CHK_ERR(DDERR_CANTDUPLICATE, "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.")
+ CHK_ERR(DDERR_NOTLOCKED, "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.")
+ CHK_ERR(DDERR_CANTCREATEDC, "Windows can not create any more DCs, or a DC was requested for a paltte-indexed surface when the surface had no palette AND the display mode was not palette-indexed (in this case DirectDraw cannot select a proper palette into the DC)")
+ CHK_ERR(DDERR_NODC, "No DC was ever created for this surface.")
+ CHK_ERR(DDERR_WRONGMODE, "This surface can not be restored because it was created in a different mode.")
+ CHK_ERR(DDERR_IMPLICITLYCREATED, "This surface can not be restored because it is an implicitly created surface.")
+ CHK_ERR(DDERR_NOTPALETTIZED, "The surface being used is not a palette-based surface")
+ CHK_ERR(DDERR_UNSUPPORTEDMODE, "The display is currently in an unsupported mode")
+ CHK_ERR(DDERR_NOMIPMAPHW, "Operation could not be carried out because there is no mip-map texture mapping hardware present or available.")
+ CHK_ERR(DDERR_INVALIDSURFACETYPE, "The requested action could not be performed because the surface was of the wrong type.")
+ CHK_ERR(DDERR_NOOPTIMIZEHW, "Device does not support optimized surfaces, therefore no video memory optimized surfaces")
+ CHK_ERR(DDERR_NOTLOADED, "Surface is an optimized surface, but has not yet been allocated any memory")
+ CHK_ERR(DDERR_NOFOCUSWINDOW, "Attempt was made to create or set a device window without first setting the focus window")
+ CHK_ERR(DDERR_NOTONMIPMAPSUBLEVEL, "Attempt was made to set a palette on a mipmap sublevel")
+ CHK_ERR(DDERR_DCALREADYCREATED, "A DC has already been returned for this surface. Only one DC can be retrieved per surface.")
+ CHK_ERR(DDERR_NONONLOCALVIDMEM, "An attempt was made to allocate non-local video memory from a device that does not support non-local video memory.")
+ CHK_ERR(DDERR_CANTPAGELOCK, "The attempt to page lock a surface failed.")
+ CHK_ERR(DDERR_CANTPAGEUNLOCK, "The attempt to page unlock a surface failed.")
+ CHK_ERR(DDERR_NOTPAGELOCKED, "An attempt was made to page unlock a surface with no outstanding page locks.")
+ CHK_ERR(DDERR_MOREDATA, "There is more data available than the specified buffer size could hold")
+ CHK_ERR(DDERR_EXPIRED, "The data has expired and is therefore no longer valid.")
+ CHK_ERR(DDERR_TESTFINISHED, "The mode test has finished executing.")
+ CHK_ERR(DDERR_NEWMODE, "The mode test has switched to a new mode.")
+ CHK_ERR(DDERR_D3DNOTINITIALIZED, "D3D has not yet been initialized.")
+ CHK_ERR(DDERR_VIDEONOTACTIVE, "The video port is not active")
+ CHK_ERR(DDERR_NOMONITORINFORMATION, "The monitor does not have EDID data.")
+ CHK_ERR(DDERR_NODRIVERSUPPORT, "The driver does not enumerate display mode refresh rates.")
+ CHK_ERR(DDERR_DEVICEDOESNTOWNSURFACE, "Surfaces created by one direct draw device cannot be used directly by another direct draw device.")
+
+#endif
+
+#ifdef HAVE_DINPUT
+
+// -------------------------------------------------------------
+// dinput.h error codes
+// -------------------------------------------------------------
+// CHK_ERR(DI_OK, "DI_OK")
+// CHK_ERR(DI_NOTATTACHED, "DI_NOTATTACHED")
+// CHK_ERR(DI_BUFFEROVERFLOW, "DI_BUFFEROVERFLOW")
+// CHK_ERR(DI_PROPNOEFFECT, "DI_PROPNOEFFECT")
+// CHK_ERR(DI_NOEFFECT, "DI_NOEFFECT")
+// CHK_ERR(DI_POLLEDDEVICE, "DI_POLLEDDEVICE")
+// CHK_ERR(DI_DOWNLOADSKIPPED, "DI_DOWNLOADSKIPPED")
+// CHK_ERR(DI_EFFECTRESTARTED, "DI_EFFECTRESTARTED")
+// CHK_ERR(DI_SETTINGSNOTSAVED_ACCESSDENIED, "DI_SETTINGSNOTSAVED_ACCESSDENIED")
+// CHK_ERR(DI_SETTINGSNOTSAVED_DISKFULL, "DI_SETTINGSNOTSAVED_DISKFULL")
+// CHK_ERR(DI_TRUNCATED, "DI_TRUNCATED")
+// CHK_ERR(DI_TRUNCATEDANDRESTARTED, "DI_TRUNCATEDANDRESTARTED")
+// CHK_ERR(DI_WRITEPROTECT, "DI_WRITEPROTECT")
+ CHK_ERR(DIERR_OLDDIRECTINPUTVERSION, "The application requires a newer version of DirectInput.")
+// CHK_ERR(DIERR_GENERIC, "DIERR_GENERIC")
+// CHK_ERR(DIERR_OLDDIRECTINPUTVERSION, "DIERR_OLDDIRECTINPUTVERSION")
+ CHK_ERR(DIERR_BETADIRECTINPUTVERSION, "The application was written for an unsupported prerelease version of DirectInput.")
+ CHK_ERR(DIERR_BADDRIVERVER, "The object could not be created due to an incompatible driver version or mismatched or incomplete driver components.")
+// CHK_ERR(DIERR_DEVICENOTREG, "DIERR_DEVICENOTREG")
+// CHK_ERR(DIERR_NOTFOUND, "The requested object does not exist.")
+// CHK_ERR(DIERR_OBJECTNOTFOUND, "DIERR_OBJECTNOTFOUND")
+// CHK_ERR(DIERR_INVALIDPARAM, "DIERR_INVALIDPARAM")
+// CHK_ERR(DIERR_NOINTERFACE, "DIERR_NOINTERFACE")
+// CHK_ERR(DIERR_GENERIC, "DIERR_GENERIC")
+// CHK_ERR(DIERR_OUTOFMEMORY, "DIERR_OUTOFMEMORY")
+// CHK_ERR(DIERR_UNSUPPORTED, "DIERR_UNSUPPORTED")
+ CHK_ERR(DIERR_NOTINITIALIZED, "This object has not been initialized")
+ CHK_ERR(DIERR_ALREADYINITIALIZED, "This object is already initialized")
+// CHK_ERR(DIERR_NOAGGREGATION, "DIERR_NOAGGREGATION")
+// CHK_ERR(DIERR_OTHERAPPHASPRIO, "DIERR_OTHERAPPHASPRIO")
+ CHK_ERR(DIERR_INPUTLOST, "Access to the device has been lost. It must be re-acquired.")
+ CHK_ERR(DIERR_ACQUIRED, "The operation cannot be performed while the device is acquired.")
+ CHK_ERR(DIERR_NOTACQUIRED, "The operation cannot be performed unless the device is acquired.")
+// CHK_ERR(DIERR_READONLY, "DIERR_READONLY")
+// CHK_ERR(DIERR_HANDLEEXISTS, "DIERR_HANDLEEXISTS")
+ CHK_ERR(DIERR_INSUFFICIENTPRIVS, "Unable to IDirectInputJoyConfig_Acquire because the user does not have sufficient privileges to change the joystick configuration. & An invalid media type was specified")
+ CHK_ERR(DIERR_DEVICEFULL, "The device is full. & An invalid media subtype was specified.")
+ CHK_ERR(DIERR_MOREDATA, "Not all the requested information fit into the buffer. & This object can only be created as an aggregated object.")
+ CHK_ERR(DIERR_NOTDOWNLOADED, "The effect is not downloaded. & The enumerator has become invalid.")
+ CHK_ERR(DIERR_HASEFFECTS, "The device cannot be reinitialized because there are still effects attached to it. & At least one of the pins involved in the operation is already connected.")
+ CHK_ERR(DIERR_NOTEXCLUSIVEACQUIRED, "The operation cannot be performed unless the device is acquired in DISCL_EXCLUSIVE mode. & This operation cannot be performed because the filter is active.")
+ CHK_ERR(DIERR_INCOMPLETEEFFECT, "The effect could not be downloaded because essential information is missing. For example, no axes have been associated with the effect, or no type-specific information has been created. & One of the specified pins supports no media types.")
+ CHK_ERR(DIERR_NOTBUFFERED, "Attempted to read buffered device data from a device that is not buffered. & There is no common media type between these pins.")
+ CHK_ERR(DIERR_EFFECTPLAYING, "An attempt was made to modify parameters of an effect while it is playing. Not all hardware devices support altering the parameters of an effect while it is playing. & Two pins of the same direction cannot be connected together.")
+ CHK_ERR(DIERR_UNPLUGGED, "The operation could not be completed because the device is not plugged in. & The operation cannot be performed because the pins are not connected.")
+ CHK_ERR(DIERR_REPORTFULL, "SendDeviceData failed because more information was requested to be sent than can be sent to the device. Some devices have restrictions on how much data can be sent to them. (For example, there might be a limit on the number of buttons that can be pressed at once.) & No sample buffer allocator is available.")
+ CHK_ERR(DIERR_MAPFILEFAIL, "A mapper file function failed because reading or writing the user or IHV settings file failed. & A run-time error occurred.")
+
+// -------------------------------------------------------------
+// dinputd.h error codes
+// -------------------------------------------------------------
+ CHK_ERR(DIERR_NOMOREITEMS, "No more items.")
+ CHK_ERR(DIERR_DRIVERFIRST, "Device driver-specific codes. Unless the specific driver has been precisely identified, no meaning should be attributed to these values other than that the driver originated the error.")
+ CHK_ERR(DIERR_DRIVERFIRST+1, "DIERR_DRIVERFIRST+1")
+ CHK_ERR(DIERR_DRIVERFIRST+2, "DIERR_DRIVERFIRST+2")
+ CHK_ERR(DIERR_DRIVERFIRST+3, "DIERR_DRIVERFIRST+3")
+ CHK_ERR(DIERR_DRIVERFIRST+4, "DIERR_DRIVERFIRST+4")
+ CHK_ERR(DIERR_DRIVERFIRST+5, "DIERR_DRIVERFIRST+5")
+ CHK_ERR(DIERR_DRIVERLAST, "Device installer errors.")
+ CHK_ERR(DIERR_INVALIDCLASSINSTALLER, "Registry entry or DLL for class installer invalid or class installer not found.")
+ CHK_ERR(DIERR_CANCELLED, "The user cancelled the install operation. & The stream already has allocated samples and the surface doesn't match the sample format.")
+ CHK_ERR(DIERR_BADINF, "The INF file for the selected device could not be found or is invalid or is damaged. & The specified purpose ID can't be used for the call.")
+
+#endif
+
+#ifdef HAVE_D3D9
+
+// -------------------------------------------------------------
+// d3d9.h error codes
+// -------------------------------------------------------------
+// CHK_ERR(D3D_OK, "Ok")
+ CHK_ERR(D3DERR_WRONGTEXTUREFORMAT, "Wrong texture format")
+ CHK_ERR(D3DERR_UNSUPPORTEDCOLOROPERATION, "Unsupported color operation")
+ CHK_ERR(D3DERR_UNSUPPORTEDCOLORARG, "Unsupported color arg")
+ CHK_ERR(D3DERR_UNSUPPORTEDALPHAOPERATION, "Unsupported alpha operation")
+ CHK_ERR(D3DERR_UNSUPPORTEDALPHAARG, "Unsupported alpha arg")
+ CHK_ERR(D3DERR_TOOMANYOPERATIONS, "Too many operations")
+ CHK_ERR(D3DERR_CONFLICTINGTEXTUREFILTER, "Conflicting texture filter")
+ CHK_ERR(D3DERR_UNSUPPORTEDFACTORVALUE, "Unsupported factor value")
+ CHK_ERR(D3DERR_CONFLICTINGRENDERSTATE, "Conflicting render state")
+ CHK_ERR(D3DERR_UNSUPPORTEDTEXTUREFILTER, "Unsupported texture filter")
+ CHK_ERR(D3DERR_CONFLICTINGTEXTUREPALETTE, "Conflicting texture palette")
+ CHK_ERR(D3DERR_DRIVERINTERNALERROR, "Driver internal error")
+ CHK_ERR(D3DERR_NOTFOUND, "Not found")
+ CHK_ERR(D3DERR_MOREDATA, "More data")
+ CHK_ERR(D3DERR_DEVICELOST, "Device lost")
+ CHK_ERR(D3DERR_DEVICENOTRESET, "Device not reset")
+ CHK_ERR(D3DERR_NOTAVAILABLE, "Not available")
+ CHK_ERR(D3DERR_OUTOFVIDEOMEMORY, "Out of video memory")
+ CHK_ERR(D3DERR_INVALIDDEVICE, "Invalid device")
+ CHK_ERR(D3DERR_INVALIDCALL, "Invalid call")
+ CHK_ERR(D3DERR_DRIVERINVALIDCALL, "Driver invalid call")
+ //CHK_ERR(D3DERR_WASSTILLDRAWING, "Was Still Drawing")
+ CHK_ERR(D3DOK_NOAUTOGEN, "The call succeeded but there won't be any mipmaps generated")
+
+ // Extended for Windows Vista
+ CHK_ERR(D3DERR_DEVICEREMOVED, "Hardware device was removed")
+ CHK_ERR(S_NOT_RESIDENT, "Resource not resident in memory")
+ CHK_ERR(S_RESIDENT_IN_SHARED_MEMORY, "Resource resident in shared memory")
+ CHK_ERR(S_PRESENT_MODE_CHANGED, "Desktop display mode has changed")
+ CHK_ERR(S_PRESENT_OCCLUDED, "Client window is occluded (minimized or other fullscreen)")
+ CHK_ERR(D3DERR_DEVICEHUNG, "Hardware adapter reset by OS")
+
+ // Extended for Windows 7
+ CHK_ERR(D3DERR_UNSUPPORTEDOVERLAY, "Overlay is not supported" )
+ CHK_ERR(D3DERR_UNSUPPORTEDOVERLAYFORMAT, "Overlay format is not supported" )
+ CHK_ERR(D3DERR_CANNOTPROTECTCONTENT, "Contect protection not available" )
+ CHK_ERR(D3DERR_UNSUPPORTEDCRYPTO, "Unsupported cryptographic system" )
+ CHK_ERR(D3DERR_PRESENT_STATISTICS_DISJOINT, "Presentation statistics are disjoint" )
+
+#endif
+
+#ifdef HAVE_DSOUND
+
+// -------------------------------------------------------------
+// dsound.h error codes
+// -------------------------------------------------------------
+// CHK_ERR(DS_OK, "")
+ CHK_ERR(DS_NO_VIRTUALIZATION, "The call succeeded, but we had to substitute the 3D algorithm")
+ CHK_ERR(DSERR_ALLOCATED, "The call failed because resources (such as a priority level) were already being used by another caller")
+ CHK_ERR(DSERR_CONTROLUNAVAIL, "The control (vol, pan, etc.) requested by the caller is not available")
+// CHK_ERR(DSERR_INVALIDPARAM, "DSERR_INVALIDPARAM")
+ CHK_ERR(DSERR_INVALIDCALL, "This call is not valid for the current state of this object")
+// CHK_ERR(DSERR_GENERIC, "DSERR_GENERIC")
+ CHK_ERR(DSERR_PRIOLEVELNEEDED, "The caller does not have the priority level required for the function to succeed")
+// CHK_ERR(DSERR_OUTOFMEMORY, "Not enough free memory is available to complete the operation")
+ CHK_ERR(DSERR_BADFORMAT, "The specified WAVE format is not supported")
+// CHK_ERR(DSERR_UNSUPPORTED, "DSERR_UNSUPPORTED")
+ CHK_ERR(DSERR_NODRIVER, "No sound driver is available for use")
+ CHK_ERR(DSERR_ALREADYINITIALIZED, "This object is already initialized")
+// CHK_ERR(DSERR_NOAGGREGATION, "DSERR_NOAGGREGATION")
+ CHK_ERR(DSERR_BUFFERLOST, "The buffer memory has been lost, and must be restored")
+ CHK_ERR(DSERR_OTHERAPPHASPRIO, "Another app has a higher priority level, preventing this call from succeeding")
+ CHK_ERR(DSERR_UNINITIALIZED, "This object has not been initialized")
+// CHK_ERR(DSERR_NOINTERFACE, "DSERR_NOINTERFACE")
+// CHK_ERR(DSERR_ACCESSDENIED, "DSERR_ACCESSDENIED")
+ CHK_ERR(DSERR_BUFFERTOOSMALL, "Tried to create a DSBCAPS_CTRLFX buffer shorter than DSBSIZE_FX_MIN milliseconds")
+ CHK_ERR(DSERR_DS8_REQUIRED, "Attempt to use DirectSound 8 functionality on an older DirectSound object")
+ CHK_ERR(DSERR_SENDLOOP, "A circular loop of send effects was detected")
+ CHK_ERR(DSERR_BADSENDBUFFERGUID, "The GUID specified in an audiopath file does not match a valid MIXIN buffer")
+ CHK_ERR(DSERR_OBJECTNOTFOUND, "The object requested was not found (numerically equal to DMUS_E_NOT_FOUND)")
+
+ CHK_ERR(DSERR_FXUNAVAILABLE, "Requested effects are not available")
+
+#endif
+
+#ifdef HAVE_D3D10_1
+
+// -------------------------------------------------------------
+// d3d10.h error codes
+// -------------------------------------------------------------
+ CHK_ERR(D3D10_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS, "There are too many unique state objects.")
+ CHK_ERR(D3D10_ERROR_FILE_NOT_FOUND, "File not found")
+
+// -------------------------------------------------------------
+// dxgi.h error codes
+// -------------------------------------------------------------
+ CHK_ERR(DXGI_STATUS_OCCLUDED, "The target window or output has been occluded. The application should suspend rendering operations if possible.")
+ CHK_ERR(DXGI_STATUS_CLIPPED, "Target window is clipped.")
+ CHK_ERR(DXGI_STATUS_NO_REDIRECTION, "")
+ CHK_ERR(DXGI_STATUS_NO_DESKTOP_ACCESS, "No access to desktop.")
+ CHK_ERR(DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, "")
+ CHK_ERR(DXGI_STATUS_MODE_CHANGED, "Display mode has changed")
+ CHK_ERR(DXGI_STATUS_MODE_CHANGE_IN_PROGRESS, "Display mode is changing")
+ CHK_ERR(DXGI_ERROR_INVALID_CALL, "The application has made an erroneous API call that it had enough information to avoid. This error is intended to denote that the application should be altered to avoid the error. Use of the debug version of the DXGI.DLL will provide run-time debug output with further information.")
+ CHK_ERR(DXGI_ERROR_NOT_FOUND, "The item requested was not found. For GetPrivateData calls, this means that the specified GUID had not been previously associated with the object.")
+ CHK_ERR(DXGI_ERROR_MORE_DATA, "The specified size of the destination buffer is too small to hold the requested data.")
+ CHK_ERR(DXGI_ERROR_UNSUPPORTED, "Unsupported.")
+ CHK_ERR(DXGI_ERROR_DEVICE_REMOVED, "Hardware device removed.")
+ CHK_ERR(DXGI_ERROR_DEVICE_HUNG, "Device hung due to badly formed commands.")
+ CHK_ERR(DXGI_ERROR_DEVICE_RESET, "Device reset due to a badly formed commant.")
+ CHK_ERR(DXGI_ERROR_WAS_STILL_DRAWING, "Was still drawing.")
+ CHK_ERR(DXGI_ERROR_FRAME_STATISTICS_DISJOINT, "The requested functionality is not supported by the device or the driver.")
+ CHK_ERR(DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE, "The requested functionality is not supported by the device or the driver.")
+ CHK_ERR(DXGI_ERROR_DRIVER_INTERNAL_ERROR, "An internal driver error occurred.")
+ CHK_ERR(DXGI_ERROR_NONEXCLUSIVE, "The application attempted to perform an operation on an DXGI output that is only legal after the output has been claimed for exclusive owenership.")
+ CHK_ERR(DXGI_ERROR_NOT_CURRENTLY_AVAILABLE, "The requested functionality is not supported by the device or the driver.")
+ CHK_ERR(DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED, "Remote desktop client disconnected.")
+ CHK_ERR(DXGI_ERROR_REMOTE_OUTOFMEMORY, "Remote desktop client is out of memory.")
+
+#endif
+
+#ifdef HAVE_D3D11_1
+
+// -------------------------------------------------------------
+// d3d11.h error codes
+// -------------------------------------------------------------
+ CHK_ERR(D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS, "There are too many unique state objects.")
+ CHK_ERR(D3D11_ERROR_FILE_NOT_FOUND, "File not found")
+ CHK_ERR(D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS, "Therea are too many unique view objects.")
+ CHK_ERR(D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD, "Deferred context requires Map-Discard usage pattern")
+
+#endif
+
+#ifdef HAVE_D2D
+
+// -------------------------------------------------------------
+// Direct2D error codes
+// -------------------------------------------------------------
+// CHK_ERR(D2DERR_UNSUPPORTED_PIXEL_FORMAT, "The pixel format is not supported.")
+// CHK_ERR(D2DERR_INSUFFICIENT_BUFFER, "The supplied buffer was too small to accomodate the data.")
+ CHK_ERR(D2DERR_WRONG_STATE, "The object was not in the correct state to process the method.")
+ CHK_ERR(D2DERR_NOT_INITIALIZED, "The object has not yet been initialized.")
+ CHK_ERR(D2DERR_UNSUPPORTED_OPERATION, "The requested opertion is not supported.")
+ CHK_ERR(D2DERR_SCANNER_FAILED, "The geomery scanner failed to process the data.")
+ CHK_ERR(D2DERR_SCREEN_ACCESS_DENIED, "D2D could not access the screen.")
+ CHK_ERR(D2DERR_DISPLAY_STATE_INVALID, "A valid display state could not be determined.")
+ CHK_ERR(D2DERR_ZERO_VECTOR, "The supplied vector is zero.")
+ CHK_ERR(D2DERR_INTERNAL_ERROR, "An internal error (D2D bug) occurred. On checked builds, we would assert.")
+ CHK_ERR(D2DERR_DISPLAY_FORMAT_NOT_SUPPORTED, "The display format we need to render is not supported by the hardware device.")
+ CHK_ERR(D2DERR_INVALID_CALL, "A call to this method is invalid.")
+ CHK_ERR(D2DERR_NO_HARDWARE_DEVICE, "No HW rendering device is available for this operation.")
+ CHK_ERR(D2DERR_RECREATE_TARGET, "here has been a presentation error that may be recoverable. The caller needs to recreate, rerender the entire frame, and reattempt present.")
+ CHK_ERR(D2DERR_TOO_MANY_SHADER_ELEMENTS, "Shader construction failed because it was too complex.")
+ CHK_ERR(D2DERR_SHADER_COMPILE_FAILED, "Shader compilation failed.")
+ CHK_ERR(D2DERR_MAX_TEXTURE_SIZE_EXCEEDED, "Requested DX surface size exceeded maximum texture size.")
+ CHK_ERR(D2DERR_UNSUPPORTED_VERSION, "The requested D2D version is not supported.")
+ CHK_ERR(D2DERR_BAD_NUMBER, "Invalid number.")
+ CHK_ERR(D2DERR_WRONG_FACTORY, "Objects used together must be created from the same factory instance.")
+ CHK_ERR(D2DERR_LAYER_ALREADY_IN_USE, "A layer resource can only be in use once at any point in time.")
+ CHK_ERR(D2DERR_POP_CALL_DID_NOT_MATCH_PUSH, "The pop call did not match the corresponding push call")
+// CHK_ERR(D2DERR_WRONG_RESOURCE_DOMAIN, "The resource was realized on the wrong render target")
+ CHK_ERR(D2DERR_PUSH_POP_UNBALANCED, "The push and pop calls were unbalanced")
+ CHK_ERR(D2DERR_RENDER_TARGET_HAS_LAYER_OR_CLIPRECT, "Attempt to copy from a render target while a layer or clip rect is applied")
+ CHK_ERR(D2DERR_INCOMPATIBLE_BRUSH_TYPES, "The brush types are incompatible for the call.")
+ CHK_ERR(D2DERR_WIN32_ERROR, "An unknown win32 failure occurred.")
+ CHK_ERR(D2DERR_TARGET_NOT_GDI_COMPATIBLE, "The render target is not compatible with GDI")
+ CHK_ERR(D2DERR_TEXT_EFFECT_IS_WRONG_TYPE, "A text client drawing effect object is of the wrong type")
+ CHK_ERR(D2DERR_TEXT_RENDERER_NOT_RELEASED, "The application is holding a reference to the IDWriteTextRenderer interface after the corresponding DrawText or DrawTextLayout call has returned. The IDWriteTextRenderer instance will be zombied.")
+// CHK_ERR(D2DERR_EXCEEDS_MAX_BITMAP_SIZE, "The requested size is larger than the guaranteed supported texture size.")
+
+// -------------------------------------------------------------
+// DirectWrite error codes
+// -------------------------------------------------------------
+ CHK_ERR(DWRITE_E_FILEFORMAT, "Indicates an error in an input file such as a font file.")
+ CHK_ERR(DWRITE_E_UNEXPECTED, "Indicates an error originating in DirectWrite code, which is not expected to occur but is safe to recover from.")
+ CHK_ERR(DWRITE_E_NOFONT, "Indicates the specified font does not exist.")
+ CHK_ERR(DWRITE_E_FILENOTFOUND, "A font file could not be opened because the file, directory, network location, drive, or other storage location does not exist or is unavailable.")
+ CHK_ERR(DWRITE_E_FILEACCESS, "A font file exists but could not be opened due to access denied, sharing violation, or similar error.")
+ CHK_ERR(DWRITE_E_FONTCOLLECTIONOBSOLETE, "A font collection is obsolete due to changes in the system.")
+ CHK_ERR(DWRITE_E_ALREADYREGISTERED, "The given interface is already registered.")
+
+// -------------------------------------------------------------
+// WIC error codes
+// -------------------------------------------------------------
+ CHK_ERR(WINCODEC_ERR_WRONGSTATE, "WIC object in incorrect state.")
+ CHK_ERR(WINCODEC_ERR_VALUEOUTOFRANGE, "WIC Value out of range.")
+ CHK_ERR(WINCODEC_ERR_UNKNOWNIMAGEFORMAT, "Encountered unexpected value or setting in WIC image format.")
+ CHK_ERR(WINCODEC_ERR_UNSUPPORTEDVERSION, "Unsupported WINCODEC_SD_VERSION passed to WIC factory.")
+ CHK_ERR(WINCODEC_ERR_NOTINITIALIZED, "WIC component not initialized.")
+ CHK_ERR(WINCODEC_ERR_ALREADYLOCKED, "WIC bitmap object already locked.")
+ CHK_ERR(WINCODEC_ERR_PROPERTYNOTFOUND, "WIC property not found.")
+ CHK_ERR(WINCODEC_ERR_PROPERTYNOTSUPPORTED, "WIC property not supported.")
+ CHK_ERR(WINCODEC_ERR_PROPERTYSIZE, "Invalid property size")
+ CHK_ERRA(WINCODEC_ERR_CODECPRESENT) // not currently used by WIC
+ CHK_ERRA(WINCODEC_ERR_CODECNOTHUMBNAIL) // not currently used by WIC
+ CHK_ERR(WINCODEC_ERR_PALETTEUNAVAILABLE, "Required palette data not available.")
+ CHK_ERR(WINCODEC_ERR_CODECTOOMANYSCANLINES, "More scanlines requested than are available in WIC bitmap.")
+ CHK_ERR(WINCODEC_ERR_INTERNALERROR, "Unexpected internal error in WIC.")
+ CHK_ERR(WINCODEC_ERR_SOURCERECTDOESNOTMATCHDIMENSIONS, "Source WIC rectangle does not match bitmap dimensions.")
+ CHK_ERR(WINCODEC_ERR_COMPONENTNOTFOUND, "WIC component not found.")
+ CHK_ERR(WINCODEC_ERR_IMAGESIZEOUTOFRANGE, "Image size beyond expected boundaries for WIC codec." )
+ CHK_ERR(WINCODEC_ERR_TOOMUCHMETADATA, "Image metadata size beyond expected boundaries for WIC codec.")
+ CHK_ERR(WINCODEC_ERR_BADIMAGE, "WIC image is corrupted.")
+ CHK_ERR(WINCODEC_ERR_BADHEADER, "Invalid header found in WIC image.")
+ CHK_ERR(WINCODEC_ERR_FRAMEMISSING, "Expected bitmap frame data not found in WIC image." )
+ CHK_ERR(WINCODEC_ERR_BADMETADATAHEADER, "Invalid metadata header found in WIC image.")
+ CHK_ERR(WINCODEC_ERR_BADSTREAMDATA, "Invalid stream data found in WIC image.")
+ CHK_ERR(WINCODEC_ERR_STREAMWRITE, "WIC operation on write stream failed.")
+ CHK_ERR(WINCODEC_ERR_STREAMREAD, "WIC operation on read stream failed.")
+ CHK_ERR(WINCODEC_ERR_STREAMNOTAVAILABLE, "Required stream is not available." )
+ CHK_ERR(WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT, "The pixel format is not supported.")
+ CHK_ERR(WINCODEC_ERR_UNSUPPORTEDOPERATION, "This operation is not supported by WIC." )
+ CHK_ERR(WINCODEC_ERR_INVALIDREGISTRATION, "Error occurred reading WIC codec registry keys.")
+ CHK_ERR(WINCODEC_ERR_COMPONENTINITIALIZEFAILURE, "Failed initializing WIC codec.")
+ CHK_ERR(WINCODEC_ERR_INSUFFICIENTBUFFER, "Not enough buffer space available for WIC operation.")
+ CHK_ERR(WINCODEC_ERR_DUPLICATEMETADATAPRESENT, "Duplicate metadata detected in WIC image.")
+ CHK_ERR(WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE, "Unexpected property type in WIC image.")
+ CHK_ERR(WINCODEC_ERR_UNEXPECTEDSIZE, "Unexpected value size in WIC metadata.")
+ CHK_ERR(WINCODEC_ERR_INVALIDQUERYREQUEST, "Invalid metadata query.")
+ CHK_ERR(WINCODEC_ERR_UNEXPECTEDMETADATATYPE, "Unexpected metadata type encountered in WIC image.")
+ CHK_ERR(WINCODEC_ERR_REQUESTONLYVALIDATMETADATAROOT, "Operation only valid on meatadata root.")
+ CHK_ERR(WINCODEC_ERR_INVALIDQUERYCHARACTER, "Invalid character in WIC metadata query.")
+ CHK_ERR(WINCODEC_ERR_WIN32ERROR, "General Win32 error encountered during WIC operation.")
+ CHK_ERR(WINCODEC_ERR_INVALIDPROGRESSIVELEVEL, "Invalid level for progressive WIC image decode.")
+
+#endif
+
+// -------------------------------------------------------------
+// DXUT error codes
+// -------------------------------------------------------------
+ CHK_ERR(DXUTERR_NODIRECT3D, "Could not initialize Direct3D.")
+ CHK_ERR(DXUTERR_NOCOMPATIBLEDEVICES, "No device could be found with the specified device settings.")
+ CHK_ERR(DXUTERR_MEDIANOTFOUND, "A media file could not be found.")
+ CHK_ERR(DXUTERR_NONZEROREFCOUNT, "The device interface has a non-zero reference count, meaning that some objects were not released.")
+ CHK_ERR(DXUTERR_CREATINGDEVICE, "An error occurred when attempting to create a device.")
+ CHK_ERR(DXUTERR_RESETTINGDEVICE, "An error occurred when attempting to reset a device.")
+ CHK_ERR(DXUTERR_CREATINGDEVICEOBJECTS, "An error occurred in the device create callback function.")
+ CHK_ERR(DXUTERR_RESETTINGDEVICEOBJECTS, "An error occurred in the device reset callback function.")
+ CHK_ERR(DXUTERR_INCORRECTVERSION, "Incorrect version of Direct3D or D3DX.")
+ CHK_ERR(DXUTERR_DEVICEREMOVED, "The device was removed.")
+
+// -------------------------------------------------------------
+// xaudio2.h error codes
+// -------------------------------------------------------------
+ CHK_ERR(XAUDIO2_E_INVALID_CALL, "Invalid XAudio2 API call or arguments")
+ CHK_ERR(XAUDIO2_E_XMA_DECODER_ERROR, "Hardware XMA decoder error")
+ CHK_ERR(XAUDIO2_E_XAPO_CREATION_FAILED, "Failed to create an audio effect")
+ CHK_ERR(XAUDIO2_E_DEVICE_INVALIDATED, "Device invalidated (unplugged, disabled, etc)")
+
+// -------------------------------------------------------------
+// xapo.h error codes
+// -------------------------------------------------------------
+ CHK_ERR(XAPO_E_FORMAT_UNSUPPORTED, "Requested audio format unsupported.")
+ }
+}
diff --git a/thirdparty/dxerr/dxerr.h b/thirdparty/dxerr/dxerr.h
new file mode 100644
index 00000000..b2c64ca1
--- /dev/null
+++ b/thirdparty/dxerr/dxerr.h
@@ -0,0 +1,45 @@
+//--------------------------------------------------------------------------------------
+// File: DXErr.h
+//
+// DirectX Error Library
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+
+// This version only supports UNICODE.
+
+#pragma once
+
+#if !defined(NOMINMAX)
+#define NOMINMAX
+#endif
+
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------------------------------------------
+// DXGetErrorString
+//--------------------------------------------------------------------------------------
+const char* WINAPI DXGetErrorStringA( HRESULT hr );
+
+#define DXGetErrorString DXGetErrorStringA
+
+//--------------------------------------------------------------------------------------
+// DXGetErrorDescription has to be modified to return a copy in a buffer rather than
+// the original static string.
+//--------------------------------------------------------------------------------------
+void WINAPI DXGetErrorDescriptionA( HRESULT hr, char* desc, size_t count );
+
+#define DXGetErrorDescription DXGetErrorDescriptionA
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
diff --git a/thirdparty/dxerr/license.txt b/thirdparty/dxerr/license.txt
new file mode 100644
index 00000000..a6ad5f24
--- /dev/null
+++ b/thirdparty/dxerr/license.txt
@@ -0,0 +1,61 @@
+ Microsoft Public License (Ms-PL)
+
+This license governs use of the accompanying software. If you use the
+software, you accept this license. If you do not accept the license, do not
+use the software.
+
+ 1. Definitions
+
+ The terms "reproduce," "reproduction," "derivative works," and
+ "distribution" have the same meaning here as under U.S. copyright law.
+
+ A "contribution" is the original software, or any additions or changes
+ to the software.
+
+ A "contributor" is any person that distributes its contribution under
+ this license.
+
+ "Licensed patents" are a contributor's patent claims that read directly
+ on its contribution.
+
+ 2. Grant of Rights
+
+ (A) Copyright Grant- Subject to the terms of this license, including
+ the license conditions and limitations in section 3, each contributor
+ grants you a non-exclusive, worldwide, royalty-free copyright license
+ to reproduce its contribution, prepare derivative works of its
+ contribution, and distribute its contribution or any derivative works
+ that you create.
+
+ (B) Patent Grant- Subject to the terms of this license, including the
+ license conditions and limitations in section 3, each contributor
+ grants you a non-exclusive, worldwide, royalty-free license under its
+ licensed patents to make, have made, use, sell, offer for sale, import,
+ and/or otherwise dispose of its contribution in the software or
+ derivative works of the contribution in the software.
+
+ 3. Conditions and Limitations
+
+ (A) No Trademark License- This license does not grant you rights to use
+ any contributors' name, logo, or trademarks.
+
+ (B) If you bring a patent claim against any contributor over patents
+ that you claim are infringed by the software, your patent license from
+ such contributor to the software ends automatically.
+
+ (C) If you distribute any portion of the software, you must retain all
+ copyright, patent, trademark, and attribution notices that are present
+ in the software.
+
+ (D) If you distribute any portion of the software in source code form,
+ you may do so only under this license by including a complete copy of
+ this license with your distribution. If you distribute any portion of
+ the software in compiled or object code form, you may only do so under
+ a license that complies with this license.
+
+ (E) The software is licensed "as-is." You bear the risk of using it.
+ The contributors give no express warranties, guarantees, or conditions.
+ You may have additional consumer rights under your local laws which
+ this license cannot change. To the extent permitted under your local
+ laws, the contributors exclude the implied warranties of
+ merchantability, fitness for a particular purpose and non-infringement.
diff --git a/thirdparty/gradlew/gradle/wrapper/gradle-wrapper.jar b/thirdparty/gradlew/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..8c0fb64a
--- /dev/null
+++ b/thirdparty/gradlew/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/thirdparty/gradlew/gradle/wrapper/gradle-wrapper.properties b/thirdparty/gradlew/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..0c71e760
--- /dev/null
+++ b/thirdparty/gradlew/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/thirdparty/gradlew/gradlew b/thirdparty/gradlew/gradlew
new file mode 100755
index 00000000..91a7e269
--- /dev/null
+++ b/thirdparty/gradlew/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/thirdparty/gradlew/gradlew.bat b/thirdparty/gradlew/gradlew.bat
new file mode 100644
index 00000000..aec99730
--- /dev/null
+++ b/thirdparty/gradlew/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/thirdparty/gtest/CHANGES b/thirdparty/gtest/CHANGES
new file mode 100644
index 00000000..05521324
--- /dev/null
+++ b/thirdparty/gtest/CHANGES
@@ -0,0 +1,157 @@
+Changes for 1.7.0:
+
+* New feature: death tests are supported on OpenBSD and in iOS
+ simulator now.
+* New feature: Google Test now implements a protocol to allow
+ a test runner to detect that a test program has exited
+ prematurely and report it as a failure (before it would be
+ falsely reported as a success if the exit code is 0).
+* New feature: Test::RecordProperty() can now be used outside of the
+ lifespan of a test method, in which case it will be attributed to
+ the current test case or the test program in the XML report.
+* New feature (potentially breaking): --gtest_list_tests now prints
+ the type parameters and value parameters for each test.
+* Improvement: char pointers and char arrays are now escaped properly
+ in failure messages.
+* Improvement: failure summary in XML reports now includes file and
+ line information.
+* Improvement: the <testsuites> XML element now has a timestamp attribute.
+* Improvement: When --gtest_filter is specified, XML report now doesn't
+ contain information about tests that are filtered out.
+* Fixed the bug where long --gtest_filter flag values are truncated in
+ death tests.
+* Potentially breaking change: RUN_ALL_TESTS() is now implemented as a
+ function instead of a macro in order to work better with Clang.
+* Compatibility fixes with C++ 11 and various platforms.
+* Bug/warning fixes.
+
+Changes for 1.6.0:
+
+* New feature: ADD_FAILURE_AT() for reporting a test failure at the
+ given source location -- useful for writing testing utilities.
+* New feature: the universal value printer is moved from Google Mock
+ to Google Test.
+* New feature: type parameters and value parameters are reported in
+ the XML report now.
+* A gtest_disable_pthreads CMake option.
+* Colored output works in GNU Screen sessions now.
+* Parameters of value-parameterized tests are now printed in the
+ textual output.
+* Failures from ad hoc test assertions run before RUN_ALL_TESTS() are
+ now correctly reported.
+* Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to
+ ostream.
+* More complete handling of exceptions.
+* GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter
+ name is already used by another library.
+* --gtest_catch_exceptions is now true by default, allowing a test
+ program to continue after an exception is thrown.
+* Value-parameterized test fixtures can now derive from Test and
+ WithParamInterface<T> separately, easing conversion of legacy tests.
+* Death test messages are clearly marked to make them more
+ distinguishable from other messages.
+* Compatibility fixes for Android, Google Native Client, MinGW, HP UX,
+ PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear),
+ IBM XL C++ (Visual Age C++), and C++0x.
+* Bug fixes and implementation clean-ups.
+* Potentially incompatible changes: disables the harmful 'make install'
+ command in autotools.
+
+Changes for 1.5.0:
+
+ * New feature: assertions can be safely called in multiple threads
+ where the pthreads library is available.
+ * New feature: predicates used inside EXPECT_TRUE() and friends
+ can now generate custom failure messages.
+ * New feature: Google Test can now be compiled as a DLL.
+ * New feature: fused source files are included.
+ * New feature: prints help when encountering unrecognized Google Test flags.
+ * Experimental feature: CMake build script (requires CMake 2.6.4+).
+ * Experimental feature: the Pump script for meta programming.
+ * double values streamed to an assertion are printed with enough precision
+ to differentiate any two different values.
+ * Google Test now works on Solaris and AIX.
+ * Build and test script improvements.
+ * Bug fixes and implementation clean-ups.
+
+ Potentially breaking changes:
+
+ * Stopped supporting VC++ 7.1 with exceptions disabled.
+ * Dropped support for 'make install'.
+
+Changes for 1.4.0:
+
+ * New feature: the event listener API
+ * New feature: test shuffling
+ * New feature: the XML report format is closer to junitreport and can
+ be parsed by Hudson now.
+ * New feature: when a test runs under Visual Studio, its failures are
+ integrated in the IDE.
+ * New feature: /MD(d) versions of VC++ projects.
+ * New feature: elapsed time for the tests is printed by default.
+ * New feature: comes with a TR1 tuple implementation such that Boost
+ is no longer needed for Combine().
+ * New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends.
+ * New feature: the Xcode project can now produce static gtest
+ libraries in addition to a framework.
+ * Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile,
+ Symbian, gcc, and C++Builder.
+ * Bug fixes and implementation clean-ups.
+
+Changes for 1.3.0:
+
+ * New feature: death tests on Windows, Cygwin, and Mac.
+ * New feature: ability to use Google Test assertions in other testing
+ frameworks.
+ * New feature: ability to run disabled test via
+ --gtest_also_run_disabled_tests.
+ * New feature: the --help flag for printing the usage.
+ * New feature: access to Google Test flag values in user code.
+ * New feature: a script that packs Google Test into one .h and one
+ .cc file for easy deployment.
+ * New feature: support for distributing test functions to multiple
+ machines (requires support from the test runner).
+ * Bug fixes and implementation clean-ups.
+
+Changes for 1.2.1:
+
+ * Compatibility fixes for Linux IA-64 and IBM z/OS.
+ * Added support for using Boost and other TR1 implementations.
+ * Changes to the build scripts to support upcoming release of Google C++
+ Mocking Framework.
+ * Added Makefile to the distribution package.
+ * Improved build instructions in README.
+
+Changes for 1.2.0:
+
+ * New feature: value-parameterized tests.
+ * New feature: the ASSERT/EXPECT_(NON)FATAL_FAILURE(_ON_ALL_THREADS)
+ macros.
+ * Changed the XML report format to match JUnit/Ant's.
+ * Added tests to the Xcode project.
+ * Added scons/SConscript for building with SCons.
+ * Added src/gtest-all.cc for building Google Test from a single file.
+ * Fixed compatibility with Solaris and z/OS.
+ * Enabled running Python tests on systems with python 2.3 installed,
+ e.g. Mac OS X 10.4.
+ * Bug fixes.
+
+Changes for 1.1.0:
+
+ * New feature: type-parameterized tests.
+ * New feature: exception assertions.
+ * New feature: printing elapsed time of tests.
+ * Improved the robustness of death tests.
+ * Added an Xcode project and samples.
+ * Adjusted the output format on Windows to be understandable by Visual Studio.
+ * Minor bug fixes.
+
+Changes for 1.0.1:
+
+ * Added project files for Visual Studio 7.1.
+ * Fixed issues with compiling on Mac OS X.
+ * Fixed issues with compiling on Cygwin.
+
+Changes for 1.0.0:
+
+ * Initial Open Source release of Google Test
diff --git a/thirdparty/gtest/CMakeLists.txt b/thirdparty/gtest/CMakeLists.txt
new file mode 100644
index 00000000..57470c84
--- /dev/null
+++ b/thirdparty/gtest/CMakeLists.txt
@@ -0,0 +1,252 @@
+########################################################################
+# CMake build script for Google Test.
+#
+# To run the tests for Google Test itself on Linux, use 'make test' or
+# ctest. You can select which tests to run using 'ctest -R regex'.
+# For more options, run 'ctest --help'.
+
+# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
+# make it prominent in the GUI.
+option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
+
+# When other libraries are using a shared version of runtime libraries,
+# Google Test also has to use one.
+option(
+ gtest_force_shared_crt
+ "Use shared (DLL) run-time lib even when Google Test is built as static lib."
+ OFF)
+
+option(gtest_build_tests "Build all of gtest's own tests." OFF)
+
+option(gtest_build_samples "Build gtest's sample programs." OFF)
+
+option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
+
+# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
+include(cmake/hermetic_build.cmake OPTIONAL)
+
+if (COMMAND pre_project_set_up_hermetic_build)
+ pre_project_set_up_hermetic_build()
+endif()
+
+########################################################################
+#
+# Project-wide settings
+
+# Name of the project.
+#
+# CMake files in this project can refer to the root source directory
+# as ${gtest_SOURCE_DIR} and to the root binary directory as
+# ${gtest_BINARY_DIR}.
+# Language "C" is required for find_package(Threads).
+project(gtest CXX C)
+cmake_minimum_required(VERSION 2.6.2)
+
+if (COMMAND set_up_hermetic_build)
+ set_up_hermetic_build()
+endif()
+
+# Define helper functions and macros used by Google Test.
+include(cmake/internal_utils.cmake)
+
+config_compiler_and_linker() # Defined in internal_utils.cmake.
+
+# Where Google Test's .h files can be found.
+include_directories(
+ ${gtest_SOURCE_DIR}/include
+ ${gtest_SOURCE_DIR})
+
+# Where Google Test's libraries can be found.
+link_directories(${gtest_BINARY_DIR}/src)
+
+########################################################################
+#
+# Defines the gtest & gtest_main libraries. User tests should link
+# with one of them.
+
+# Google Test libraries. We build them using more strict warnings than what
+# are used for other targets, to ensure that gtest can be compiled by a user
+# aggressive about warnings.
+cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
+cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
+target_link_libraries(gtest_main gtest)
+
+########################################################################
+#
+# Samples on how to link user tests with gtest or gtest_main.
+#
+# They are not built by default. To build them, set the
+# gtest_build_samples option to ON. You can do it by running ccmake
+# or specifying the -Dgtest_build_samples=ON flag when running cmake.
+
+if (gtest_build_samples)
+ cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
+ cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
+ cxx_executable(sample3_unittest samples gtest_main)
+ cxx_executable(sample4_unittest samples gtest_main samples/sample4.cc)
+ cxx_executable(sample5_unittest samples gtest_main samples/sample1.cc)
+ cxx_executable(sample6_unittest samples gtest_main)
+ cxx_executable(sample7_unittest samples gtest_main)
+ cxx_executable(sample8_unittest samples gtest_main)
+ cxx_executable(sample9_unittest samples gtest)
+ cxx_executable(sample10_unittest samples gtest)
+endif()
+
+########################################################################
+#
+# Google Test's own tests.
+#
+# You can skip this section if you aren't interested in testing
+# Google Test itself.
+#
+# The tests are not built by default. To build them, set the
+# gtest_build_tests option to ON. You can do it by running ccmake
+# or specifying the -Dgtest_build_tests=ON flag when running cmake.
+
+if (gtest_build_tests)
+ # This must be set in the root directory for the tests to be run by
+ # 'make test' or ctest.
+ enable_testing()
+
+ ############################################################
+ # C++ tests built with standard compiler flags.
+
+ cxx_test(gtest-death-test_test gtest_main)
+ cxx_test(gtest_environment_test gtest)
+ cxx_test(gtest-filepath_test gtest_main)
+ cxx_test(gtest-linked_ptr_test gtest_main)
+ cxx_test(gtest-listener_test gtest_main)
+ cxx_test(gtest_main_unittest gtest_main)
+ cxx_test(gtest-message_test gtest_main)
+ cxx_test(gtest_no_test_unittest gtest)
+ cxx_test(gtest-options_test gtest_main)
+ cxx_test(gtest-param-test_test gtest
+ test/gtest-param-test2_test.cc)
+ cxx_test(gtest-port_test gtest_main)
+ cxx_test(gtest_pred_impl_unittest gtest_main)
+ cxx_test(gtest_premature_exit_test gtest
+ test/gtest_premature_exit_test.cc)
+ cxx_test(gtest-printers_test gtest_main)
+ cxx_test(gtest_prod_test gtest_main
+ test/production.cc)
+ cxx_test(gtest_repeat_test gtest)
+ cxx_test(gtest_sole_header_test gtest_main)
+ cxx_test(gtest_stress_test gtest)
+ cxx_test(gtest-test-part_test gtest_main)
+ cxx_test(gtest_throw_on_failure_ex_test gtest)
+ cxx_test(gtest-typed-test_test gtest_main
+ test/gtest-typed-test2_test.cc)
+ cxx_test(gtest_unittest gtest_main)
+ cxx_test(gtest-unittest-api_test gtest)
+
+ ############################################################
+ # C++ tests built with non-standard compiler flags.
+
+ # MSVC 7.1 does not support STL with exceptions disabled.
+ if (NOT MSVC OR MSVC_VERSION GREATER 1310)
+ cxx_library(gtest_no_exception "${cxx_no_exception}"
+ src/gtest-all.cc)
+ cxx_library(gtest_main_no_exception "${cxx_no_exception}"
+ src/gtest-all.cc src/gtest_main.cc)
+ endif()
+ cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
+ src/gtest-all.cc src/gtest_main.cc)
+
+ cxx_test_with_flags(gtest-death-test_ex_nocatch_test
+ "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=0"
+ gtest test/gtest-death-test_ex_test.cc)
+ cxx_test_with_flags(gtest-death-test_ex_catch_test
+ "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=1"
+ gtest test/gtest-death-test_ex_test.cc)
+
+ cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
+ gtest_main_no_rtti test/gtest_unittest.cc)
+
+ cxx_shared_library(gtest_dll "${cxx_default}"
+ src/gtest-all.cc src/gtest_main.cc)
+
+ cxx_executable_with_flags(gtest_dll_test_ "${cxx_default}"
+ gtest_dll test/gtest_all_test.cc)
+ set_target_properties(gtest_dll_test_
+ PROPERTIES
+ COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+
+ if (NOT MSVC OR NOT MSVC_VERSION EQUAL 1600)
+ # The C++ Standard specifies tuple_element<int, class>.
+ # Yet MSVC 10's <utility> declares tuple_element<size_t, class>.
+ # That declaration conflicts with our own standard-conforming
+ # tuple implementation. Therefore using our own tuple with
+ # MSVC 10 doesn't compile.
+ cxx_library(gtest_main_use_own_tuple "${cxx_use_own_tuple}"
+ src/gtest-all.cc src/gtest_main.cc)
+
+ cxx_test_with_flags(gtest-tuple_test "${cxx_use_own_tuple}"
+ gtest_main_use_own_tuple test/gtest-tuple_test.cc)
+
+ cxx_test_with_flags(gtest_use_own_tuple_test "${cxx_use_own_tuple}"
+ gtest_main_use_own_tuple
+ test/gtest-param-test_test.cc test/gtest-param-test2_test.cc)
+ endif()
+
+ ############################################################
+ # Python tests.
+
+ cxx_executable(gtest_break_on_failure_unittest_ test gtest)
+ py_test(gtest_break_on_failure_unittest)
+
+ # MSVC 7.1 does not support STL with exceptions disabled.
+ if (NOT MSVC OR MSVC_VERSION GREATER 1310)
+ cxx_executable_with_flags(
+ gtest_catch_exceptions_no_ex_test_
+ "${cxx_no_exception}"
+ gtest_main_no_exception
+ test/gtest_catch_exceptions_test_.cc)
+ endif()
+
+ cxx_executable_with_flags(
+ gtest_catch_exceptions_ex_test_
+ "${cxx_exception}"
+ gtest_main
+ test/gtest_catch_exceptions_test_.cc)
+ py_test(gtest_catch_exceptions_test)
+
+ cxx_executable(gtest_color_test_ test gtest)
+ py_test(gtest_color_test)
+
+ cxx_executable(gtest_env_var_test_ test gtest)
+ py_test(gtest_env_var_test)
+
+ cxx_executable(gtest_filter_unittest_ test gtest)
+ py_test(gtest_filter_unittest)
+
+ cxx_executable(gtest_help_test_ test gtest_main)
+ py_test(gtest_help_test)
+
+ cxx_executable(gtest_list_tests_unittest_ test gtest)
+ py_test(gtest_list_tests_unittest)
+
+ cxx_executable(gtest_output_test_ test gtest)
+ py_test(gtest_output_test)
+
+ cxx_executable(gtest_shuffle_test_ test gtest)
+ py_test(gtest_shuffle_test)
+
+ # MSVC 7.1 does not support STL with exceptions disabled.
+ if (NOT MSVC OR MSVC_VERSION GREATER 1310)
+ cxx_executable(gtest_throw_on_failure_test_ test gtest_no_exception)
+ set_target_properties(gtest_throw_on_failure_test_
+ PROPERTIES
+ COMPILE_FLAGS "${cxx_no_exception}")
+ py_test(gtest_throw_on_failure_test)
+ endif()
+
+ cxx_executable(gtest_uninitialized_test_ test gtest)
+ py_test(gtest_uninitialized_test)
+
+ cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
+ cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
+ py_test(gtest_xml_outfiles_test)
+
+ cxx_executable(gtest_xml_output_unittest_ test gtest)
+ py_test(gtest_xml_output_unittest)
+endif()
diff --git a/thirdparty/gtest/CONTRIBUTORS b/thirdparty/gtest/CONTRIBUTORS
new file mode 100644
index 00000000..feae2fc0
--- /dev/null
+++ b/thirdparty/gtest/CONTRIBUTORS
@@ -0,0 +1,37 @@
+# This file contains a list of people who've made non-trivial
+# contribution to the Google C++ Testing Framework project. People
+# who commit code to the project are encouraged to add their names
+# here. Please keep the list sorted by first names.
+
+Ajay Joshi <jaj@google.com>
+Balázs Dán <balazs.dan@gmail.com>
+Bharat Mediratta <bharat@menalto.com>
+Chandler Carruth <chandlerc@google.com>
+Chris Prince <cprince@google.com>
+Chris Taylor <taylorc@google.com>
+Dan Egnor <egnor@google.com>
+Eric Roman <eroman@chromium.org>
+Hady Zalek <hady.zalek@gmail.com>
+Jeffrey Yasskin <jyasskin@google.com>
+Jói Sigurðsson <joi@google.com>
+Keir Mierle <mierle@gmail.com>
+Keith Ray <keith.ray@gmail.com>
+Kenton Varda <kenton@google.com>
+Manuel Klimek <klimek@google.com>
+Markus Heule <markus.heule@gmail.com>
+Mika Raento <mikie@iki.fi>
+Miklós Fazekas <mfazekas@szemafor.com>
+Pasi Valminen <pasi.valminen@gmail.com>
+Patrick Hanna <phanna@google.com>
+Patrick Riley <pfr@google.com>
+Peter Kaminski <piotrk@google.com>
+Preston Jackson <preston.a.jackson@gmail.com>
+Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
+Russ Cox <rsc@google.com>
+Russ Rufer <russ@pentad.com>
+Sean Mcafee <eefacm@gmail.com>
+Sigurður Ãsgeirsson <siggi@google.com>
+Tracy Bialik <tracy@pentad.com>
+Vadim Berman <vadimb@google.com>
+Vlad Losev <vladl@google.com>
+Zhanyong Wan <wan@google.com>
diff --git a/thirdparty/gtest/LICENSE b/thirdparty/gtest/LICENSE
new file mode 100644
index 00000000..1941a11f
--- /dev/null
+++ b/thirdparty/gtest/LICENSE
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/thirdparty/gtest/README b/thirdparty/gtest/README
new file mode 100644
index 00000000..26f35a84
--- /dev/null
+++ b/thirdparty/gtest/README
@@ -0,0 +1,435 @@
+Google C++ Testing Framework
+============================
+
+http://code.google.com/p/googletest/
+
+Overview
+--------
+
+Google's framework for writing C++ tests on a variety of platforms
+(Linux, Mac OS X, Windows, Windows CE, Symbian, etc). Based on the
+xUnit architecture. Supports automatic test discovery, a rich set of
+assertions, user-defined assertions, death tests, fatal and non-fatal
+failures, various options for running the tests, and XML test report
+generation.
+
+Please see the project page above for more information as well as the
+mailing list for questions, discussions, and development. There is
+also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please
+join us!
+
+Requirements for End Users
+--------------------------
+
+Google Test is designed to have fairly minimal requirements to build
+and use with your projects, but there are some. Currently, we support
+Linux, Windows, Mac OS X, and Cygwin. We will also make our best
+effort to support other platforms (e.g. Solaris, AIX, and z/OS).
+However, since core members of the Google Test project have no access
+to these platforms, Google Test may have outstanding issues there. If
+you notice any problems on your platform, please notify
+googletestframework@googlegroups.com. Patches for fixing them are
+even more welcome!
+
+### Linux Requirements ###
+
+These are the base requirements to build and use Google Test from a source
+package (as described below):
+ * GNU-compatible Make or gmake
+ * POSIX-standard shell
+ * POSIX(-2) Regular Expressions (regex.h)
+ * A C++98-standard-compliant compiler
+
+### Windows Requirements ###
+
+ * Microsoft Visual C++ 7.1 or newer
+
+### Cygwin Requirements ###
+
+ * Cygwin 1.5.25-14 or newer
+
+### Mac OS X Requirements ###
+
+ * Mac OS X 10.4 Tiger or newer
+ * Developer Tools Installed
+
+Also, you'll need CMake 2.6.4 or higher if you want to build the
+samples using the provided CMake script, regardless of the platform.
+
+Requirements for Contributors
+-----------------------------
+
+We welcome patches. If you plan to contribute a patch, you need to
+build Google Test and its own tests from an SVN checkout (described
+below), which has further requirements:
+
+ * Python version 2.3 or newer (for running some of the tests and
+ re-generating certain source files from templates)
+ * CMake 2.6.4 or newer
+
+Getting the Source
+------------------
+
+There are two primary ways of getting Google Test's source code: you
+can download a stable source release in your preferred archive format,
+or directly check out the source from our Subversion (SVN) repositary.
+The SVN checkout requires a few extra steps and some extra software
+packages on your system, but lets you track the latest development and
+make patches much more easily, so we highly encourage it.
+
+### Source Package ###
+
+Google Test is released in versioned source packages which can be
+downloaded from the download page [1]. Several different archive
+formats are provided, but the only difference is the tools used to
+manipulate them, and the size of the resulting file. Download
+whichever you are most comfortable with.
+
+ [1] http://code.google.com/p/googletest/downloads/list
+
+Once the package is downloaded, expand it using whichever tools you
+prefer for that type. This will result in a new directory with the
+name "gtest-X.Y.Z" which contains all of the source code. Here are
+some examples on Linux:
+
+ tar -xvzf gtest-X.Y.Z.tar.gz
+ tar -xvjf gtest-X.Y.Z.tar.bz2
+ unzip gtest-X.Y.Z.zip
+
+### SVN Checkout ###
+
+To check out the main branch (also known as the "trunk") of Google
+Test, run the following Subversion command:
+
+ svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
+
+Setting up the Build
+--------------------
+
+To build Google Test and your tests that use it, you need to tell your
+build system where to find its headers and source files. The exact
+way to do it depends on which build system you use, and is usually
+straightforward.
+
+### Generic Build Instructions ###
+
+Suppose you put Google Test in directory ${GTEST_DIR}. To build it,
+create a library build target (or a project as called by Visual Studio
+and Xcode) to compile
+
+ ${GTEST_DIR}/src/gtest-all.cc
+
+with ${GTEST_DIR}/include in the system header search path and ${GTEST_DIR}
+in the normal header search path. Assuming a Linux-like system and gcc,
+something like the following will do:
+
+ g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \
+ -pthread -c ${GTEST_DIR}/src/gtest-all.cc
+ ar -rv libgtest.a gtest-all.o
+
+(We need -pthread as Google Test uses threads.)
+
+Next, you should compile your test source file with
+${GTEST_DIR}/include in the system header search path, and link it
+with gtest and any other necessary libraries:
+
+ g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \
+ -o your_test
+
+As an example, the make/ directory contains a Makefile that you can
+use to build Google Test on systems where GNU make is available
+(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google
+Test's own tests. Instead, it just builds the Google Test library and
+a sample test. You can use it as a starting point for your own build
+script.
+
+If the default settings are correct for your environment, the
+following commands should succeed:
+
+ cd ${GTEST_DIR}/make
+ make
+ ./sample1_unittest
+
+If you see errors, try to tweak the contents of make/Makefile to make
+them go away. There are instructions in make/Makefile on how to do
+it.
+
+### Using CMake ###
+
+Google Test comes with a CMake build script (CMakeLists.txt) that can
+be used on a wide range of platforms ("C" stands for cross-platofrm.).
+If you don't have CMake installed already, you can download it for
+free from http://www.cmake.org/.
+
+CMake works by generating native makefiles or build projects that can
+be used in the compiler environment of your choice. The typical
+workflow starts with:
+
+ mkdir mybuild # Create a directory to hold the build output.
+ cd mybuild
+ cmake ${GTEST_DIR} # Generate native build scripts.
+
+If you want to build Google Test's samples, you should replace the
+last command with
+
+ cmake -Dgtest_build_samples=ON ${GTEST_DIR}
+
+If you are on a *nix system, you should now see a Makefile in the
+current directory. Just type 'make' to build gtest.
+
+If you use Windows and have Vistual Studio installed, a gtest.sln file
+and several .vcproj files will be created. You can then build them
+using Visual Studio.
+
+On Mac OS X with Xcode installed, a .xcodeproj file will be generated.
+
+### Legacy Build Scripts ###
+
+Before settling on CMake, we have been providing hand-maintained build
+projects/scripts for Visual Studio, Xcode, and Autotools. While we
+continue to provide them for convenience, they are not actively
+maintained any more. We highly recommend that you follow the
+instructions in the previous two sections to integrate Google Test
+with your existing build system.
+
+If you still need to use the legacy build scripts, here's how:
+
+The msvc\ folder contains two solutions with Visual C++ projects.
+Open the gtest.sln or gtest-md.sln file using Visual Studio, and you
+are ready to build Google Test the same way you build any Visual
+Studio project. Files that have names ending with -md use DLL
+versions of Microsoft runtime libraries (the /MD or the /MDd compiler
+option). Files without that suffix use static versions of the runtime
+libraries (the /MT or the /MTd option). Please note that one must use
+the same option to compile both gtest and the test code. If you use
+Visual Studio 2005 or above, we recommend the -md version as /MD is
+the default for new projects in these versions of Visual Studio.
+
+On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using
+Xcode. Build the "gtest" target. The universal binary framework will
+end up in your selected build directory (selected in the Xcode
+"Preferences..." -> "Building" pane and defaults to xcode/build).
+Alternatively, at the command line, enter:
+
+ xcodebuild
+
+This will build the "Release" configuration of gtest.framework in your
+default build location. See the "xcodebuild" man page for more
+information about building different configurations and building in
+different locations.
+
+If you wish to use the Google Test Xcode project with Xcode 4.x and
+above, you need to either:
+ * update the SDK configuration options in xcode/Config/General.xconfig.
+ Comment options SDKROOT, MACOS_DEPLOYMENT_TARGET, and GCC_VERSION. If
+ you choose this route you lose the ability to target earlier versions
+ of MacOS X.
+ * Install an SDK for an earlier version. This doesn't appear to be
+ supported by Apple, but has been reported to work
+ (http://stackoverflow.com/questions/5378518).
+
+Tweaking Google Test
+--------------------
+
+Google Test can be used in diverse environments. The default
+configuration may not work (or may not work well) out of the box in
+some environments. However, you can easily tweak Google Test by
+defining control macros on the compiler command line. Generally,
+these macros are named like GTEST_XYZ and you define them to either 1
+or 0 to enable or disable a certain feature.
+
+We list the most frequently used macros below. For a complete list,
+see file include/gtest/internal/gtest-port.h.
+
+### Choosing a TR1 Tuple Library ###
+
+Some Google Test features require the C++ Technical Report 1 (TR1)
+tuple library, which is not yet available with all compilers. The
+good news is that Google Test implements a subset of TR1 tuple that's
+enough for its own need, and will automatically use this when the
+compiler doesn't provide TR1 tuple.
+
+Usually you don't need to care about which tuple library Google Test
+uses. However, if your project already uses TR1 tuple, you need to
+tell Google Test to use the same TR1 tuple library the rest of your
+project uses, or the two tuple implementations will clash. To do
+that, add
+
+ -DGTEST_USE_OWN_TR1_TUPLE=0
+
+to the compiler flags while compiling Google Test and your tests. If
+you want to force Google Test to use its own tuple library, just add
+
+ -DGTEST_USE_OWN_TR1_TUPLE=1
+
+to the compiler flags instead.
+
+If you don't want Google Test to use tuple at all, add
+
+ -DGTEST_HAS_TR1_TUPLE=0
+
+and all features using tuple will be disabled.
+
+### Multi-threaded Tests ###
+
+Google Test is thread-safe where the pthread library is available.
+After #include "gtest/gtest.h", you can check the GTEST_IS_THREADSAFE
+macro to see whether this is the case (yes if the macro is #defined to
+1, no if it's undefined.).
+
+If Google Test doesn't correctly detect whether pthread is available
+in your environment, you can force it with
+
+ -DGTEST_HAS_PTHREAD=1
+
+or
+
+ -DGTEST_HAS_PTHREAD=0
+
+When Google Test uses pthread, you may need to add flags to your
+compiler and/or linker to select the pthread library, or you'll get
+link errors. If you use the CMake script or the deprecated Autotools
+script, this is taken care of for you. If you use your own build
+script, you'll need to read your compiler and linker's manual to
+figure out what flags to add.
+
+### As a Shared Library (DLL) ###
+
+Google Test is compact, so most users can build and link it as a
+static library for the simplicity. You can choose to use Google Test
+as a shared library (known as a DLL on Windows) if you prefer.
+
+To compile *gtest* as a shared library, add
+
+ -DGTEST_CREATE_SHARED_LIBRARY=1
+
+to the compiler flags. You'll also need to tell the linker to produce
+a shared library instead - consult your linker's manual for how to do
+it.
+
+To compile your *tests* that use the gtest shared library, add
+
+ -DGTEST_LINKED_AS_SHARED_LIBRARY=1
+
+to the compiler flags.
+
+Note: while the above steps aren't technically necessary today when
+using some compilers (e.g. GCC), they may become necessary in the
+future, if we decide to improve the speed of loading the library (see
+http://gcc.gnu.org/wiki/Visibility for details). Therefore you are
+recommended to always add the above flags when using Google Test as a
+shared library. Otherwise a future release of Google Test may break
+your build script.
+
+### Avoiding Macro Name Clashes ###
+
+In C++, macros don't obey namespaces. Therefore two libraries that
+both define a macro of the same name will clash if you #include both
+definitions. In case a Google Test macro clashes with another
+library, you can force Google Test to rename its macro to avoid the
+conflict.
+
+Specifically, if both Google Test and some other code define macro
+FOO, you can add
+
+ -DGTEST_DONT_DEFINE_FOO=1
+
+to the compiler flags to tell Google Test to change the macro's name
+from FOO to GTEST_FOO. Currently FOO can be FAIL, SUCCEED, or TEST.
+For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write
+
+ GTEST_TEST(SomeTest, DoesThis) { ... }
+
+instead of
+
+ TEST(SomeTest, DoesThis) { ... }
+
+in order to define a test.
+
+Upgrating from an Earlier Version
+---------------------------------
+
+We strive to keep Google Test releases backward compatible.
+Sometimes, though, we have to make some breaking changes for the
+users' long-term benefits. This section describes what you'll need to
+do if you are upgrading from an earlier version of Google Test.
+
+### Upgrading from 1.3.0 or Earlier ###
+
+You may need to explicitly enable or disable Google Test's own TR1
+tuple library. See the instructions in section "Choosing a TR1 Tuple
+Library".
+
+### Upgrading from 1.4.0 or Earlier ###
+
+The Autotools build script (configure + make) is no longer officially
+supportted. You are encouraged to migrate to your own build system or
+use CMake. If you still need to use Autotools, you can find
+instructions in the README file from Google Test 1.4.0.
+
+On platforms where the pthread library is available, Google Test uses
+it in order to be thread-safe. See the "Multi-threaded Tests" section
+for what this means to your build script.
+
+If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google
+Test will no longer compile. This should affect very few people, as a
+large portion of STL (including <string>) doesn't compile in this mode
+anyway. We decided to stop supporting it in order to greatly simplify
+Google Test's implementation.
+
+Developing Google Test
+----------------------
+
+This section discusses how to make your own changes to Google Test.
+
+### Testing Google Test Itself ###
+
+To make sure your changes work as intended and don't break existing
+functionality, you'll want to compile and run Google Test's own tests.
+For that you can use CMake:
+
+ mkdir mybuild
+ cd mybuild
+ cmake -Dgtest_build_tests=ON ${GTEST_DIR}
+
+Make sure you have Python installed, as some of Google Test's tests
+are written in Python. If the cmake command complains about not being
+able to find Python ("Could NOT find PythonInterp (missing:
+PYTHON_EXECUTABLE)"), try telling it explicitly where your Python
+executable can be found:
+
+ cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR}
+
+Next, you can build Google Test and all of its own tests. On *nix,
+this is usually done by 'make'. To run the tests, do
+
+ make test
+
+All tests should pass.
+
+### Regenerating Source Files ###
+
+Some of Google Test's source files are generated from templates (not
+in the C++ sense) using a script. A template file is named FOO.pump,
+where FOO is the name of the file it will generate. For example, the
+file include/gtest/internal/gtest-type-util.h.pump is used to generate
+gtest-type-util.h in the same directory.
+
+Normally you don't need to worry about regenerating the source files,
+unless you need to modify them. In that case, you should modify the
+corresponding .pump files instead and run the pump.py Python script to
+regenerate them. You can find pump.py in the scripts/ directory.
+Read the Pump manual [2] for how to use it.
+
+ [2] http://code.google.com/p/googletest/wiki/PumpManual
+
+### Contributing a Patch ###
+
+We welcome patches. Please read the Google Test developer's guide [3]
+for how you can contribute. In particular, make sure you have signed
+the Contributor License Agreement, or we won't be able to accept the
+patch.
+
+ [3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide
+
+Happy testing!
diff --git a/thirdparty/gtest/cmake/.gitignore b/thirdparty/gtest/cmake/.gitignore
new file mode 100644
index 00000000..4d7a2315
--- /dev/null
+++ b/thirdparty/gtest/cmake/.gitignore
@@ -0,0 +1 @@
+!*.cmake
diff --git a/thirdparty/gtest/cmake/internal_utils.cmake b/thirdparty/gtest/cmake/internal_utils.cmake
new file mode 100644
index 00000000..8cb21894
--- /dev/null
+++ b/thirdparty/gtest/cmake/internal_utils.cmake
@@ -0,0 +1,227 @@
+# Defines functions and macros useful for building Google Test and
+# Google Mock.
+#
+# Note:
+#
+# - This file will be run twice when building Google Mock (once via
+# Google Test's CMakeLists.txt, and once via Google Mock's).
+# Therefore it shouldn't have any side effects other than defining
+# the functions and macros.
+#
+# - The functions/macros defined in this file may depend on Google
+# Test and Google Mock's option() definitions, and thus must be
+# called *after* the options have been defined.
+
+# Tweaks CMake's default compiler/linker settings to suit Google Test's needs.
+#
+# This must be a macro(), as inside a function string() can only
+# update variables in the function scope.
+macro(fix_default_compiler_settings_)
+ if (MSVC)
+ # For MSVC, CMake sets certain flags to defaults we want to override.
+ # This replacement code is taken from sample in the CMake Wiki at
+ # http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace.
+ foreach (flag_var
+ CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
+ # When Google Test is built as a shared library, it should also use
+ # shared runtime libraries. Otherwise, it may end up with multiple
+ # copies of runtime library data in different modules, resulting in
+ # hard-to-find crashes. When it is built as a static library, it is
+ # preferable to use CRT as static libraries, as we don't have to rely
+ # on CRT DLLs being available. CMake always defaults to using shared
+ # CRT libraries, so we override that default here.
+ string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
+ endif()
+
+ # We prefer more strict warning checking for building Google Test.
+ # Replaces /W3 with /W4 in defaults.
+ string(REPLACE "/W3" "-W4" ${flag_var} "${${flag_var}}")
+ endforeach()
+ endif()
+endmacro()
+
+# Defines the compiler/linker flags used to build Google Test and
+# Google Mock. You can tweak these definitions to suit your need. A
+# variable's value is empty before it's explicitly assigned to.
+macro(config_compiler_and_linker)
+ if (NOT gtest_disable_pthreads)
+ # Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
+ find_package(Threads)
+ endif()
+
+ fix_default_compiler_settings_()
+ if (MSVC)
+ # Newlines inside flags variables break CMake's NMake generator.
+ # TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
+ set(cxx_base_flags "-GS -W4 -WX -wd4127 -wd4251 -wd4275 -nologo -J -Zi")
+ if (MSVC_VERSION LESS 1400)
+ # Suppress spurious warnings MSVC 7.1 sometimes issues.
+ # Forcing value to bool.
+ set(cxx_base_flags "${cxx_base_flags} -wd4800")
+ # Copy constructor and assignment operator could not be generated.
+ set(cxx_base_flags "${cxx_base_flags} -wd4511 -wd4512")
+ # Compatibility warnings not applicable to Google Test.
+ # Resolved overload was found by argument-dependent lookup.
+ set(cxx_base_flags "${cxx_base_flags} -wd4675")
+ endif()
+ set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
+ set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
+ set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
+ set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0")
+ set(cxx_no_rtti_flags "-GR-")
+ elseif (CMAKE_COMPILER_IS_GNUCXX)
+ set(cxx_base_flags "-Wall -Wshadow")
+ set(cxx_exception_flags "-fexceptions")
+ set(cxx_no_exception_flags "-fno-exceptions")
+ # Until version 4.3.2, GCC doesn't define a macro to indicate
+ # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
+ # explicitly.
+ set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
+ set(cxx_strict_flags
+ "-Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
+ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
+ set(cxx_exception_flags "-features=except")
+ # Sun Pro doesn't provide macros to indicate whether exceptions and
+ # RTTI are enabled, so we define GTEST_HAS_* explicitly.
+ set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
+ set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
+ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
+ CMAKE_CXX_COMPILER_ID STREQUAL "XL")
+ # CMake 2.8 changes Visual Age's compiler ID to "XL".
+ set(cxx_exception_flags "-qeh")
+ set(cxx_no_exception_flags "-qnoeh")
+ # Until version 9.0, Visual Age doesn't define a macro to indicate
+ # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
+ # explicitly.
+ set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
+ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP")
+ set(cxx_base_flags "-AA -mt")
+ set(cxx_exception_flags "-DGTEST_HAS_EXCEPTIONS=1")
+ set(cxx_no_exception_flags "+noeh -DGTEST_HAS_EXCEPTIONS=0")
+ # RTTI can not be disabled in HP aCC compiler.
+ set(cxx_no_rtti_flags "")
+ endif()
+
+ if (CMAKE_USE_PTHREADS_INIT) # The pthreads library is available and allowed.
+ set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=1")
+ else()
+ set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=0")
+ endif()
+
+ # For building gtest's own tests and samples.
+ set(cxx_exception "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_exception_flags}")
+ set(cxx_no_exception
+ "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
+ set(cxx_default "${cxx_exception}")
+ set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
+ set(cxx_use_own_tuple "${cxx_default} -DGTEST_USE_OWN_TR1_TUPLE=1")
+
+ # For building the gtest libraries.
+ set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
+endmacro()
+
+# Defines the gtest & gtest_main libraries. User tests should link
+# with one of them.
+function(cxx_library_with_type name type cxx_flags)
+ # type can be either STATIC or SHARED to denote a static or shared library.
+ # ARGN refers to additional arguments after 'cxx_flags'.
+ add_library(${name} ${type} ${ARGN})
+ set_target_properties(${name}
+ PROPERTIES
+ COMPILE_FLAGS "${cxx_flags}")
+ if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
+ set_target_properties(${name}
+ PROPERTIES
+ COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
+ endif()
+ if (CMAKE_USE_PTHREADS_INIT)
+ target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
+ endif()
+endfunction()
+
+########################################################################
+#
+# Helper functions for creating build targets.
+
+function(cxx_shared_library name cxx_flags)
+ cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
+endfunction()
+
+function(cxx_library name cxx_flags)
+ cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
+endfunction()
+
+# cxx_executable_with_flags(name cxx_flags libs srcs...)
+#
+# creates a named C++ executable that depends on the given libraries and
+# is built from the given source files with the given compiler flags.
+function(cxx_executable_with_flags name cxx_flags libs)
+ add_executable(${name} ${ARGN})
+ if (cxx_flags)
+ set_target_properties(${name}
+ PROPERTIES
+ COMPILE_FLAGS "${cxx_flags}")
+ endif()
+ if (BUILD_SHARED_LIBS)
+ set_target_properties(${name}
+ PROPERTIES
+ COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
+ endif()
+ # To support mixing linking in static and dynamic libraries, link each
+ # library in with an extra call to target_link_libraries.
+ foreach (lib "${libs}")
+ target_link_libraries(${name} ${lib})
+ endforeach()
+endfunction()
+
+# cxx_executable(name dir lib srcs...)
+#
+# creates a named target that depends on the given libs and is built
+# from the given source files. dir/name.cc is implicitly included in
+# the source file list.
+function(cxx_executable name dir libs)
+ cxx_executable_with_flags(
+ ${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
+endfunction()
+
+# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
+find_package(PythonInterp)
+
+# cxx_test_with_flags(name cxx_flags libs srcs...)
+#
+# creates a named C++ test that depends on the given libs and is built
+# from the given source files with the given compiler flags.
+function(cxx_test_with_flags name cxx_flags libs)
+ cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
+ add_test(${name} ${name})
+endfunction()
+
+# cxx_test(name libs srcs...)
+#
+# creates a named test target that depends on the given libs and is
+# built from the given source files. Unlike cxx_test_with_flags,
+# test/name.cc is already implicitly included in the source file list.
+function(cxx_test name libs)
+ cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
+ "test/${name}.cc" ${ARGN})
+endfunction()
+
+# py_test(name)
+#
+# creates a Python test with the given name whose main module is in
+# test/name.py. It does nothing if Python is not installed.
+function(py_test name)
+ # We are not supporting Python tests on Linux yet as they consider
+ # all Linux environments to be google3 and try to use google3 features.
+ if (PYTHONINTERP_FOUND)
+ # ${CMAKE_BINARY_DIR} is known at configuration time, so we can
+ # directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known
+ # only at ctest runtime (by calling ctest -c <Configuration>), so
+ # we have to escape $ to delay variable substitution here.
+ add_test(${name}
+ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
+ --build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE})
+ endif()
+endfunction()
diff --git a/thirdparty/gtest/include/gtest/gtest-death-test.h b/thirdparty/gtest/include/gtest/gtest-death-test.h
new file mode 100644
index 00000000..957a69c6
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest-death-test.h
@@ -0,0 +1,294 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for death tests. It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+#include "gtest/internal/gtest-death-test-internal.h"
+
+namespace testing {
+
+// This flag controls the style of death tests. Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process. Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests. IMPORTANT: This is an internal utility. Using it may break the
+// implementation of death tests. User code MUST NOT use it.
+GTEST_API_ bool InDeathTestChild();
+
+} // namespace internal
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+// 1. It generates a warning if there is more than one active
+// thread. This is because it's safe to fork() or clone() only
+// when there is a single thread.
+//
+// 2. The parent process clone()s a sub-process and runs the death
+// test in it; the sub-process exits with code 0 at the end of the
+// death test, if it hasn't exited already.
+//
+// 3. The parent process waits for the sub-process to terminate.
+//
+// 4. The parent process checks the exit code and error message of
+// the sub-process.
+//
+// Examples:
+//
+// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+// for (int i = 0; i < 5; i++) {
+// EXPECT_DEATH(server.ProcessRequest(i),
+// "Invalid request .* in ProcessRequest()")
+// << "Failed to die on request " << i;
+// }
+//
+// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+// bool KilledBySIGHUP(int exit_code) {
+// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+// }
+//
+// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// On the regular expressions used in death tests:
+//
+// On POSIX-compliant systems (*nix), we use the <regex.h> library,
+// which uses the POSIX extended regex syntax.
+//
+// On other platforms (e.g. Windows), we only support a simple regex
+// syntax implemented as part of Google Test. This limited
+// implementation should be enough most of the time when writing
+// death tests; though it lacks many features you can find in PCRE
+// or POSIX extended regex syntax. For example, we don't support
+// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+// repetition count ("x{5,7}"), among others.
+//
+// Below is the syntax that we do support. We chose it to be a
+// subset of both PCRE and POSIX extended regex, so it's easy to
+// learn wherever you come from. In the following: 'A' denotes a
+// literal character, period (.), or a single \\ escape sequence;
+// 'x' and 'y' denote regular expressions; 'm' and 'n' are for
+// natural numbers.
+//
+// c matches any literal character c
+// \\d matches any decimal digit
+// \\D matches any character that's not a decimal digit
+// \\f matches \f
+// \\n matches \n
+// \\r matches \r
+// \\s matches any ASCII whitespace, including \n
+// \\S matches any character that's not a whitespace
+// \\t matches \t
+// \\v matches \v
+// \\w matches any letter, _, or decimal digit
+// \\W matches any character that \\w doesn't match
+// \\c matches any literal character c, which must be a punctuation
+// . matches any single character except \n
+// A? matches 0 or 1 occurrences of A
+// A* matches 0 or many occurrences of A
+// A+ matches 1 or many occurrences of A
+// ^ matches the beginning of a string (not that of each line)
+// $ matches the end of a string (not that of each line)
+// xy matches x followed by y
+//
+// If you accidentally use PCRE or POSIX extended regex features
+// not implemented by us, you will get a run-time failure. In that
+// case, please try to rewrite your regular expression within the
+// above syntax.
+//
+// This implementation is *not* meant to be as highly tuned or robust
+// as a compiled regex library, but should perform well enough for a
+// death test, which already incurs significant overhead by launching
+// a child process.
+//
+// Known caveats:
+//
+// A "threadsafe" style death test obtains the path to the test
+// program from argv[0] and re-executes it in the sub-process. For
+// simplicity, the current implementation doesn't search the PATH
+// when launching the sub-process. This means that the user must
+// invoke the test program via a path that contains at least one
+// path separator (e.g. path/to/foo_test and
+// /absolute/path/to/bar_test are fine, but foo_test is not). This
+// is rarely a problem as people usually don't put the test binary
+// directory in PATH.
+//
+// TODO(wan@google.com): make thread-safe death tests search the PATH.
+
+// Asserts that a given statement causes the program to exit, with an
+// integer exit status that satisfies predicate, and emitting error output
+// that matches regex.
+# define ASSERT_EXIT(statement, predicate, regex) \
+ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+
+// Like ASSERT_EXIT, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_EXIT(statement, predicate, regex) \
+ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+
+// Asserts that a given statement causes the program to exit, either by
+// explicitly exiting with a nonzero exit code or being killed by a
+// signal, and emitting error output that matches regex.
+# define ASSERT_DEATH(statement, regex) \
+ ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Like ASSERT_DEATH, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_DEATH(statement, regex) \
+ EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+ explicit ExitedWithCode(int exit_code);
+ bool operator()(int exit_status) const;
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ExitedWithCode& other);
+
+ const int exit_code_;
+};
+
+# if !GTEST_OS_WINDOWS
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+class GTEST_API_ KilledBySignal {
+ public:
+ explicit KilledBySignal(int signum);
+ bool operator()(int exit_status) const;
+ private:
+ const int signum_;
+};
+# endif // !GTEST_OS_WINDOWS
+
+// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
+// The death testing framework causes this to have interesting semantics,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+// if (sideeffect) {
+// *sideeffect = 12;
+// }
+// LOG(DFATAL) << "death";
+// return 12;
+// }
+//
+// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
+// int sideeffect = 0;
+// // Only asserts in dbg.
+// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+// // opt-mode has sideeffect visible.
+// EXPECT_EQ(12, sideeffect);
+// #else
+// // dbg-mode no visible sideeffect.
+// EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects. A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+// // Side-effects here will have an effect after this statement in
+// // opt mode, but none in debug mode.
+// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+# ifdef NDEBUG
+
+# define EXPECT_DEBUG_DEATH(statement, regex) \
+ GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+# define ASSERT_DEBUG_DEATH(statement, regex) \
+ GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+# else
+
+# define EXPECT_DEBUG_DEATH(statement, regex) \
+ EXPECT_DEATH(statement, regex)
+
+# define ASSERT_DEBUG_DEATH(statement, regex) \
+ ASSERT_DEATH(statement, regex)
+
+# endif // NDEBUG for EXPECT_DEBUG_DEATH
+#endif // GTEST_HAS_DEATH_TEST
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning. This is
+// useful when you are combining death test assertions with normal test
+// assertions in one test.
+#if GTEST_HAS_DEATH_TEST
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+ EXPECT_DEATH(statement, regex)
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+ ASSERT_DEATH(statement, regex)
+#else
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+ GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+ GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
+#endif
+
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
diff --git a/thirdparty/gtest/include/gtest/gtest-message.h b/thirdparty/gtest/include/gtest/gtest-message.h
new file mode 100644
index 00000000..fe879bca
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest-message.h
@@ -0,0 +1,250 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+
+#include "gtest/internal/gtest-port.h"
+
+// Ensures that there is at least one operator<< in the global namespace.
+// See Message& operator<<(...) below for why.
+void operator<<(const testing::internal::Secret&, int);
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+// 1. You stream a bunch of values to a Message object.
+// It will remember the text in a stringstream.
+// 2. Then you stream the Message object to an ostream.
+// This causes the text in the Message to be streamed
+// to the ostream.
+//
+// For example;
+//
+// testing::Message foo;
+// foo << 1 << " != " << 2;
+// std::cout << foo;
+//
+// will print "1 != 2".
+//
+// Message is not intended to be inherited from. In particular, its
+// destructor is not virtual.
+//
+// Note that stringstream behaves differently in gcc and in MSVC. You
+// can stream a NULL char pointer to it in the former, but not in the
+// latter (it causes an access violation if you do). The Message
+// class hides this difference by treating a NULL char pointer as
+// "(null)".
+class GTEST_API_ Message {
+ private:
+ // The type of basic IO manipulators (endl, ends, and flush) for
+ // narrow streams.
+ typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+ // Constructs an empty Message.
+ Message();
+
+ // Copy constructor.
+ Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
+ *ss_ << msg.GetString();
+ }
+
+ // Constructs a Message from a C-string.
+ explicit Message(const char* str) : ss_(new ::std::stringstream) {
+ *ss_ << str;
+ }
+
+#if GTEST_OS_SYMBIAN
+ // Streams a value (either a pointer or not) to this object.
+ template <typename T>
+ inline Message& operator <<(const T& value) {
+ StreamHelper(typename internal::is_pointer<T>::type(), value);
+ return *this;
+ }
+#else
+ // Streams a non-pointer value to this object.
+ template <typename T>
+ inline Message& operator <<(const T& val) {
+ // Some libraries overload << for STL containers. These
+ // overloads are defined in the global namespace instead of ::std.
+ //
+ // C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+ // overloads are visible in either the std namespace or the global
+ // namespace, but not other namespaces, including the testing
+ // namespace which Google Test's Message class is in.
+ //
+ // To allow STL containers (and other types that has a << operator
+ // defined in the global namespace) to be used in Google Test
+ // assertions, testing::Message must access the custom << operator
+ // from the global namespace. With this using declaration,
+ // overloads of << defined in the global namespace and those
+ // visible via Koenig lookup are both exposed in this function.
+ using ::operator <<;
+ *ss_ << val;
+ return *this;
+ }
+
+ // Streams a pointer value to this object.
+ //
+ // This function is an overload of the previous one. When you
+ // stream a pointer to a Message, this definition will be used as it
+ // is more specialized. (The C++ Standard, section
+ // [temp.func.order].) If you stream a non-pointer, then the
+ // previous definition will be used.
+ //
+ // The reason for this overload is that streaming a NULL pointer to
+ // ostream is undefined behavior. Depending on the compiler, you
+ // may get "0", "(nil)", "(null)", or an access violation. To
+ // ensure consistent result across compilers, we always treat NULL
+ // as "(null)".
+ template <typename T>
+ inline Message& operator <<(T* const& pointer) { // NOLINT
+ if (pointer == NULL) {
+ *ss_ << "(null)";
+ } else {
+ *ss_ << pointer;
+ }
+ return *this;
+ }
+#endif // GTEST_OS_SYMBIAN
+
+ // Since the basic IO manipulators are overloaded for both narrow
+ // and wide streams, we have to provide this specialized definition
+ // of operator <<, even though its body is the same as the
+ // templatized version above. Without this definition, streaming
+ // endl or other basic IO manipulators to Message will confuse the
+ // compiler.
+ Message& operator <<(BasicNarrowIoManip val) {
+ *ss_ << val;
+ return *this;
+ }
+
+ // Instead of 1/0, we want to see true/false for bool values.
+ Message& operator <<(bool b) {
+ return *this << (b ? "true" : "false");
+ }
+
+ // These two overloads allow streaming a wide C string to a Message
+ // using the UTF-8 encoding.
+ Message& operator <<(const wchar_t* wide_c_str);
+ Message& operator <<(wchar_t* wide_c_str);
+
+#if GTEST_HAS_STD_WSTRING
+ // Converts the given wide string to a narrow string using the UTF-8
+ // encoding, and streams the result to this Message object.
+ Message& operator <<(const ::std::wstring& wstr);
+#endif // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+ // Converts the given wide string to a narrow string using the UTF-8
+ // encoding, and streams the result to this Message object.
+ Message& operator <<(const ::wstring& wstr);
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+ // Gets the text streamed to this object so far as an std::string.
+ // Each '\0' character in the buffer is replaced with "\\0".
+ //
+ // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+ std::string GetString() const;
+
+ private:
+
+#if GTEST_OS_SYMBIAN
+ // These are needed as the Nokia Symbian Compiler cannot decide between
+ // const T& and const T* in a function template. The Nokia compiler _can_
+ // decide between class template specializations for T and T*, so a
+ // tr1::type_traits-like is_pointer works, and we can overload on that.
+ template <typename T>
+ inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
+ if (pointer == NULL) {
+ *ss_ << "(null)";
+ } else {
+ *ss_ << pointer;
+ }
+ }
+ template <typename T>
+ inline void StreamHelper(internal::false_type /*is_pointer*/,
+ const T& value) {
+ // See the comments in Message& operator <<(const T&) above for why
+ // we need this using statement.
+ using ::operator <<;
+ *ss_ << value;
+ }
+#endif // GTEST_OS_SYMBIAN
+
+ // We'll hold the text streamed to this object here.
+ const internal::scoped_ptr< ::std::stringstream> ss_;
+
+ // We declare (but don't implement) this to prevent the compiler
+ // from implementing the assignment operator.
+ void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
+ return os << sb.GetString();
+}
+
+namespace internal {
+
+// Converts a streamable value to an std::string. A NULL pointer is
+// converted to "(null)". When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+template <typename T>
+std::string StreamableToString(const T& streamable) {
+ return (Message() << streamable).GetString();
+}
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
diff --git a/thirdparty/gtest/include/gtest/gtest-param-test.h b/thirdparty/gtest/include/gtest/gtest-param-test.h
new file mode 100644
index 00000000..d6702c8f
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest-param-test.h
@@ -0,0 +1,1421 @@
+// This file was GENERATED by command:
+// pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+ // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+ // Inside a test, access the test parameter with the GetParam() method
+ // of the TestWithParam<T> class:
+ EXPECT_TRUE(foo.Blah(GetParam()));
+ ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+ ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a summary of them, which
+// are all in the testing namespace:
+//
+//
+// Range(begin, end [, step]) - Yields values {begin, begin+step,
+// begin+step+step, ...}. The values do not
+// include end. step defaults to 1.
+// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}.
+// ValuesIn(container) - Yields values from a C-style array, an STL
+// ValuesIn(begin,end) container, or an iterator range [begin, end).
+// Bool() - Yields sequence {false, true}.
+// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product
+// for the math savvy) of the values generated
+// by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+ FooTest,
+ Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+// * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+// * InstantiationName/FooTest.DoesBlah/1 for "miny"
+// * InstantiationName/FooTest.DoesBlah/2 for "moe"
+// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+// * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+// * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+ // You can inherit all the usual members for a non-parameterized test
+ // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+ // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+ // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+ // GetParam works just the same here as if you inherit from TestWithParam.
+ EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*. Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+// - returns a generator producing a sequence of values {start, start+1,
+// start+2, ..., }.
+// Range(start, end, step)
+// - returns a generator producing a sequence of values {start, start+step,
+// start+step+step, ..., }.
+// Notes:
+// * The generated sequences never include end. For example, Range(1, 5)
+// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+// returns a generator producing {1, 3, 5, 7}.
+// * start and end must have the same type. That type may be any integral or
+// floating-point type or a user defined type satisfying these conditions:
+// * It must be assignable (have operator=() defined).
+// * It must have operator+() (operator+(int-compatible type) for
+// two-operand version).
+// * It must have operator<() defined.
+// Elements in the resulting sequences will also have that type.
+// * Condition start < end must be satisfied in order for resulting sequences
+// to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+ return internal::ParamGenerator<T>(
+ new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+ return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+// - returns a generator producing sequences with elements from
+// a C-style array.
+// ValuesIn(const Container& container)
+// - returns a generator producing sequences with elements from
+// an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+// - returns a generator producing sequences with elements from
+// a range [begin, end) defined by a pair of STL-style iterators. These
+// iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+// ::std::vector< ::std::string> v;
+// v.push_back("a");
+// v.push_back("b");
+// return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+// StlStringTest,
+// ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+// ::std::list<char> list;
+// list.push_back('a');
+// list.push_back('b');
+// return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+// CharTest,
+// ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+ typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+ ::value_type ParamType;
+ return internal::ParamGenerator<ParamType>(
+ new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+ return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+ const Container& container) {
+ return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+// - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to 50 parameters.
+//
+template <typename T1>
+internal::ValueArray1<T1> Values(T1 v1) {
+ return internal::ValueArray1<T1>(v1);
+}
+
+template <typename T1, typename T2>
+internal::ValueArray2<T1, T2> Values(T1 v1, T2 v2) {
+ return internal::ValueArray2<T1, T2>(v1, v2);
+}
+
+template <typename T1, typename T2, typename T3>
+internal::ValueArray3<T1, T2, T3> Values(T1 v1, T2 v2, T3 v3) {
+ return internal::ValueArray3<T1, T2, T3>(v1, v2, v3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+internal::ValueArray4<T1, T2, T3, T4> Values(T1 v1, T2 v2, T3 v3, T4 v4) {
+ return internal::ValueArray4<T1, T2, T3, T4>(v1, v2, v3, v4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+internal::ValueArray5<T1, T2, T3, T4, T5> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5) {
+ return internal::ValueArray5<T1, T2, T3, T4, T5>(v1, v2, v3, v4, v5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+internal::ValueArray6<T1, T2, T3, T4, T5, T6> Values(T1 v1, T2 v2, T3 v3,
+ T4 v4, T5 v5, T6 v6) {
+ return internal::ValueArray6<T1, T2, T3, T4, T5, T6>(v1, v2, v3, v4, v5, v6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7> Values(T1 v1, T2 v2, T3 v3,
+ T4 v4, T5 v5, T6 v6, T7 v7) {
+ return internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7>(v1, v2, v3, v4, v5,
+ v6, v7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) {
+ return internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8>(v1, v2, v3, v4,
+ v5, v6, v7, v8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) {
+ return internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(v1, v2, v3,
+ v4, v5, v6, v7, v8, v9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Values(T1 v1,
+ T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) {
+ return internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(v1,
+ v2, v3, v4, v5, v6, v7, v8, v9, v10);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11>
+internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+ T11> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11) {
+ return internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+ T11>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12>
+internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12) {
+ return internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13>
+internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13) {
+ return internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14>
+internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) {
+ return internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+ v14);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15>
+internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+ T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) {
+ return internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+ v13, v14, v15);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16>
+internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16) {
+ return internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+ v12, v13, v14, v15, v16);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17>
+internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17) {
+ return internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+ v11, v12, v13, v14, v15, v16, v17);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18>
+internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+ T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18) {
+ return internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+ v10, v11, v12, v13, v14, v15, v16, v17, v18);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19>
+internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+ T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+ T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) {
+ return internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19>(v1, v2, v3, v4, v5, v6, v7, v8,
+ v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20>
+internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) {
+ return internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20>(v1, v2, v3, v4, v5, v6, v7,
+ v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21>
+internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) {
+ return internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(v1, v2, v3, v4, v5, v6,
+ v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22>
+internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22> Values(T1 v1, T2 v2, T3 v3,
+ T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22) {
+ return internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(v1, v2, v3, v4,
+ v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23>
+internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23) {
+ return internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(v1, v2, v3,
+ v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22, v23);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24>
+internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23, T24 v24) {
+ return internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(v1, v2,
+ v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+ v19, v20, v21, v22, v23, v24);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25>
+internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Values(T1 v1,
+ T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+ T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+ T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) {
+ return internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25>(v1,
+ v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+ v18, v19, v20, v21, v22, v23, v24, v25);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26>
+internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26) {
+ return internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+ v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27>
+internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27) {
+ return internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+ v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28>
+internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28) {
+ return internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+ v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+ v28);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29>
+internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29) {
+ return internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+ v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+ v27, v28, v29);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30>
+internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+ T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+ T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+ T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) {
+ return internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+ v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+ v26, v27, v28, v29, v30);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31>
+internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) {
+ return internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+ v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+ v25, v26, v27, v28, v29, v30, v31);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32>
+internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32) {
+ return internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+ v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+ v24, v25, v26, v27, v28, v29, v30, v31, v32);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33>
+internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+ T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32, T33 v33) {
+ return internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33>(v1, v2, v3, v4, v5, v6, v7, v8,
+ v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+ v24, v25, v26, v27, v28, v29, v30, v31, v32, v33);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34>
+internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+ T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+ T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+ T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+ T31 v31, T32 v32, T33 v33, T34 v34) {
+ return internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34>(v1, v2, v3, v4, v5, v6, v7,
+ v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+ v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35>
+internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+ T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+ T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) {
+ return internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35>(v1, v2, v3, v4, v5, v6,
+ v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+ v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36>
+internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+ T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+ T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) {
+ return internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36>(v1, v2, v3, v4,
+ v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+ v34, v35, v36);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37>
+internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37> Values(T1 v1, T2 v2, T3 v3,
+ T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+ T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+ T37 v37) {
+ return internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37>(v1, v2, v3,
+ v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+ v34, v35, v36, v37);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38>
+internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+ T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+ T37 v37, T38 v38) {
+ return internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38>(v1, v2,
+ v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+ v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32,
+ v33, v34, v35, v36, v37, v38);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39>
+internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Values(T1 v1, T2 v2,
+ T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+ T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+ T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+ T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+ T37 v37, T38 v38, T39 v39) {
+ return internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39>(v1,
+ v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+ v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
+ v32, v33, v34, v35, v36, v37, v38, v39);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40>
+internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Values(T1 v1,
+ T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+ T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+ T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27,
+ T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35,
+ T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) {
+ return internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+ v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
+ v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41>
+internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) {
+ return internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+ v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28,
+ v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42>
+internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42) {
+ return internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+ v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+ v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41,
+ v42);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43>
+internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43) {
+ return internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+ v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+ v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+ v41, v42, v43);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44>
+internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44) {
+ return internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+ v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+ v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39,
+ v40, v41, v42, v43, v44);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45>
+internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+ T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+ T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+ T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+ T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+ T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) {
+ return internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+ v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+ v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38,
+ v39, v40, v41, v42, v43, v44, v45);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46>
+internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+ T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) {
+ return internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+ v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+ v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+ v38, v39, v40, v41, v42, v43, v44, v45, v46);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47>
+internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+ T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) {
+ return internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46, T47>(v1, v2, v3, v4, v5, v6, v7, v8,
+ v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+ v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+ v38, v39, v40, v41, v42, v43, v44, v45, v46, v47);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48>
+internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+ T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+ T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+ T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+ T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+ T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47,
+ T48 v48) {
+ return internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46, T47, T48>(v1, v2, v3, v4, v5, v6, v7,
+ v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+ v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36,
+ v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49>
+internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+ T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+ T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+ T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+ T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38,
+ T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46,
+ T47 v47, T48 v48, T49 v49) {
+ return internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46, T47, T48, T49>(v1, v2, v3, v4, v5, v6,
+ v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+ v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35,
+ v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49, typename T50>
+internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49, T50> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+ T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+ T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+ T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+ T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37,
+ T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45,
+ T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) {
+ return internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40, T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>(v1, v2, v3, v4,
+ v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+ v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+ v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47,
+ v48, v49, v50);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+// - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+// virtual void SetUp() {
+// external_flag = GetParam();
+// }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+ return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+// - returns a generator producing sequences with elements coming from
+// the Cartesian product of elements from the sequences generated by
+// gen1, gen2, ..., genN. The sequence elements will have a type of
+// tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+// of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to 10 arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+// : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+// Combine(Values("cat", "dog"),
+// Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+// : public testing::TestWithParam<tuple<bool, bool> > {
+// virtual void SetUp() {
+// // Assigns external_flag_1 and external_flag_2 values from the tuple.
+// tie(external_flag_1, external_flag_2) = GetParam();
+// }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+// // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+// Combine(Bool(), Bool()));
+//
+template <typename Generator1, typename Generator2>
+internal::CartesianProductHolder2<Generator1, Generator2> Combine(
+ const Generator1& g1, const Generator2& g2) {
+ return internal::CartesianProductHolder2<Generator1, Generator2>(
+ g1, g2);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3>
+internal::CartesianProductHolder3<Generator1, Generator2, Generator3> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3) {
+ return internal::CartesianProductHolder3<Generator1, Generator2, Generator3>(
+ g1, g2, g3);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4>
+internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+ Generator4> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4) {
+ return internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+ Generator4>(
+ g1, g2, g3, g4);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5>
+internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+ Generator4, Generator5> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5) {
+ return internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+ Generator4, Generator5>(
+ g1, g2, g3, g4, g5);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6>
+internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6) {
+ return internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6>(
+ g1, g2, g3, g4, g5, g6);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6,
+ typename Generator7>
+internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6,
+ const Generator7& g7) {
+ return internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7>(
+ g1, g2, g3, g4, g5, g6, g7);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6,
+ typename Generator7, typename Generator8>
+internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6,
+ const Generator7& g7, const Generator8& g8) {
+ return internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8>(
+ g1, g2, g3, g4, g5, g6, g7, g8);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6,
+ typename Generator7, typename Generator8, typename Generator9>
+internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8,
+ Generator9> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6,
+ const Generator7& g7, const Generator8& g8, const Generator9& g9) {
+ return internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8, Generator9>(
+ g1, g2, g3, g4, g5, g6, g7, g8, g9);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+ typename Generator4, typename Generator5, typename Generator6,
+ typename Generator7, typename Generator8, typename Generator9,
+ typename Generator10>
+internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+ Generator10> Combine(
+ const Generator1& g1, const Generator2& g2, const Generator3& g3,
+ const Generator4& g4, const Generator5& g5, const Generator6& g6,
+ const Generator7& g7, const Generator8& g8, const Generator9& g9,
+ const Generator10& g10) {
+ return internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+ Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+ Generator10>(
+ g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
+}
+# endif // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+ : public test_case_name { \
+ public: \
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+ virtual void TestBody(); \
+ private: \
+ static int AddToRegistry() { \
+ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+ GetTestCasePatternHolder<test_case_name>(\
+ #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+ #test_case_name, \
+ #test_name, \
+ new ::testing::internal::TestMetaFactory< \
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+ return 0; \
+ } \
+ static int gtest_registering_dummy_; \
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+ }; \
+ int GTEST_TEST_CLASS_NAME_(test_case_name, \
+ test_name)::gtest_registering_dummy_ = \
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+ void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+ ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+ gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+ int gtest_##prefix##test_case_name##_dummy_ = \
+ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+ GetTestCasePatternHolder<test_case_name>(\
+ #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+ #prefix, \
+ &gtest_##prefix##test_case_name##_EvalGenerator_, \
+ __FILE__, __LINE__)
+
+} // namespace testing
+
+#endif // GTEST_HAS_PARAM_TEST
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/thirdparty/gtest/include/gtest/gtest-param-test.h.pump b/thirdparty/gtest/include/gtest/gtest-param-test.h.pump
new file mode 100644
index 00000000..2dc9303b
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest-param-test.h.pump
@@ -0,0 +1,487 @@
+$$ -*- mode: c++; -*-
+$var n = 50 $$ Maximum length of Values arguments we want to support.
+$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+ // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+ // Inside a test, access the test parameter with the GetParam() method
+ // of the TestWithParam<T> class:
+ EXPECT_TRUE(foo.Blah(GetParam()));
+ ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+ ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a summary of them, which
+// are all in the testing namespace:
+//
+//
+// Range(begin, end [, step]) - Yields values {begin, begin+step,
+// begin+step+step, ...}. The values do not
+// include end. step defaults to 1.
+// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}.
+// ValuesIn(container) - Yields values from a C-style array, an STL
+// ValuesIn(begin,end) container, or an iterator range [begin, end).
+// Bool() - Yields sequence {false, true}.
+// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product
+// for the math savvy) of the values generated
+// by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+ FooTest,
+ Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+// * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+// * InstantiationName/FooTest.DoesBlah/1 for "miny"
+// * InstantiationName/FooTest.DoesBlah/2 for "moe"
+// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+// * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+// * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+ // You can inherit all the usual members for a non-parameterized test
+ // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+ // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+ // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+ // GetParam works just the same here as if you inherit from TestWithParam.
+ EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*. Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+// - returns a generator producing a sequence of values {start, start+1,
+// start+2, ..., }.
+// Range(start, end, step)
+// - returns a generator producing a sequence of values {start, start+step,
+// start+step+step, ..., }.
+// Notes:
+// * The generated sequences never include end. For example, Range(1, 5)
+// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+// returns a generator producing {1, 3, 5, 7}.
+// * start and end must have the same type. That type may be any integral or
+// floating-point type or a user defined type satisfying these conditions:
+// * It must be assignable (have operator=() defined).
+// * It must have operator+() (operator+(int-compatible type) for
+// two-operand version).
+// * It must have operator<() defined.
+// Elements in the resulting sequences will also have that type.
+// * Condition start < end must be satisfied in order for resulting sequences
+// to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+ return internal::ParamGenerator<T>(
+ new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+ return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+// - returns a generator producing sequences with elements from
+// a C-style array.
+// ValuesIn(const Container& container)
+// - returns a generator producing sequences with elements from
+// an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+// - returns a generator producing sequences with elements from
+// a range [begin, end) defined by a pair of STL-style iterators. These
+// iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+// ::std::vector< ::std::string> v;
+// v.push_back("a");
+// v.push_back("b");
+// return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+// StlStringTest,
+// ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+// ::std::list<char> list;
+// list.push_back('a');
+// list.push_back('b');
+// return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+// CharTest,
+// ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+ typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+ ::value_type ParamType;
+ return internal::ParamGenerator<ParamType>(
+ new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+ return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+ const Container& container) {
+ return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+// - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to $n parameters.
+//
+$range i 1..n
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename T$j]]>
+internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) {
+ return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]);
+}
+
+]]
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+// - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+// virtual void SetUp() {
+// external_flag = GetParam();
+// }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+ return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+// - returns a generator producing sequences with elements coming from
+// the Cartesian product of elements from the sequences generated by
+// gen1, gen2, ..., genN. The sequence elements will have a type of
+// tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+// of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to $maxtuple arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+// : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+// Combine(Values("cat", "dog"),
+// Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+// : public testing::TestWithParam<tuple<bool, bool> > {
+// virtual void SetUp() {
+// // Assigns external_flag_1 and external_flag_2 values from the tuple.
+// tie(external_flag_1, external_flag_2) = GetParam();
+// }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+// // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+// Combine(Bool(), Bool()));
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename Generator$j]]>
+internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
+ $for j, [[const Generator$j& g$j]]) {
+ return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>(
+ $for j, [[g$j]]);
+}
+
+]]
+# endif // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+ : public test_case_name { \
+ public: \
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+ virtual void TestBody(); \
+ private: \
+ static int AddToRegistry() { \
+ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+ GetTestCasePatternHolder<test_case_name>(\
+ #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+ #test_case_name, \
+ #test_name, \
+ new ::testing::internal::TestMetaFactory< \
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+ return 0; \
+ } \
+ static int gtest_registering_dummy_; \
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+ }; \
+ int GTEST_TEST_CLASS_NAME_(test_case_name, \
+ test_name)::gtest_registering_dummy_ = \
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+ void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+ ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+ gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+ int gtest_##prefix##test_case_name##_dummy_ = \
+ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+ GetTestCasePatternHolder<test_case_name>(\
+ #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+ #prefix, \
+ &gtest_##prefix##test_case_name##_EvalGenerator_, \
+ __FILE__, __LINE__)
+
+} // namespace testing
+
+#endif // GTEST_HAS_PARAM_TEST
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
diff --git a/thirdparty/gtest/include/gtest/gtest-printers.h b/thirdparty/gtest/include/gtest/gtest-printers.h
new file mode 100644
index 00000000..0639d9f5
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest-printers.h
@@ -0,0 +1,855 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T. More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+// 1. foo::PrintTo(const T&, ostream*)
+// 2. operator<<(ostream&, const T&) defined in either foo or the
+// global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+// // Prints a value to a string. For a (const or not) char
+// // pointer, the NUL-terminated string (but not the pointer) is
+// // printed.
+// std::string ::testing::PrintToString(const T& value);
+//
+// // Prints a value tersely: for a reference type, the referenced
+// // value (but not the address) is printed; for a (const or not) char
+// // pointer, the NUL-terminated string (but not the pointer) is
+// // printed.
+// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+// // Prints value using the type inferred by the compiler. The difference
+// // from UniversalTersePrint() is that this function prints both the
+// // pointer and the NUL-terminated string for a (const or not) char pointer.
+// void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+// // Prints the fields of a tuple tersely to a string vector, one
+// // element for each field. Tuple support must be enabled in
+// // gtest-port.h.
+// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+// const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container. When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect. In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator. We'll fix this if there's an
+// actual need for it. Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <ostream> // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// Definitions in the 'internal' and 'internal2' name spaces are
+// subject to change without notice. DO NOT USE THEM IN USER CODE!
+namespace internal2 {
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+ size_t count,
+ ::std::ostream* os);
+
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+ kProtobuf, // a protobuf type
+ kConvertibleToInteger, // a type implicitly convertible to BiggestInt
+ // (e.g. a named or unnamed enum type)
+ kOtherType // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
+// by the universal printer to print a value of type T when neither
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
+class TypeWithoutFormatter {
+ public:
+ // This default version is called when kTypeKind is kOtherType.
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+ sizeof(value), os);
+ }
+};
+
+// We print a protobuf using its ShortDebugString() when the string
+// doesn't exceed this many characters; otherwise we print it using
+// DebugString() for better readability.
+const size_t kProtobufOneLinerMaxLength = 50;
+
+template <typename T>
+class TypeWithoutFormatter<T, kProtobuf> {
+ public:
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ const ::testing::internal::string short_str = value.ShortDebugString();
+ const ::testing::internal::string pretty_str =
+ short_str.length() <= kProtobufOneLinerMaxLength ?
+ short_str : ("\n" + value.DebugString());
+ *os << ("<" + pretty_str + ">");
+ }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+ // Since T has no << operator or PrintTo() but can be implicitly
+ // converted to BiggestInt, we print it as a BiggestInt.
+ //
+ // Most likely T is an enum type (either named or unnamed), in which
+ // case printing it as an integer is the desired behavior. In case
+ // T is not an enum, printing it as an integer is the best we can do
+ // given that it has no user-defined printer.
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ const internal::BiggestInt kBigInt = value;
+ *os << kBigInt;
+ }
+};
+
+// Prints the given value to the given ostream. If the value is a
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed. This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
+//
+// A user can override this behavior for a class type Foo by defining
+// a << operator in the namespace where Foo is defined.
+//
+// We put this operator in namespace 'internal2' instead of 'internal'
+// to simplify the implementation, as much code in 'internal' needs to
+// use << in STL, which would conflict with our own << were it defined
+// in 'internal'.
+//
+// Note that this operator<< takes a generic std::basic_ostream<Char,
+// CharTraits> type instead of the more restricted std::ostream. If
+// we define it to take an std::ostream instead, we'll get an
+// "ambiguous overloads" compiler error when trying to print a type
+// Foo that supports streaming to std::basic_ostream<Char,
+// CharTraits>, as the compiler cannot tell whether
+// operator<<(std::ostream&, const T&) or
+// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
+// specific.
+template <typename Char, typename CharTraits, typename T>
+::std::basic_ostream<Char, CharTraits>& operator<<(
+ ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
+ TypeWithoutFormatter<T,
+ (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+ internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+ kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+ return os;
+}
+
+} // namespace internal2
+} // namespace testing
+
+// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
+// magic needed for implementing UniversalPrinter won't work.
+namespace testing_internal {
+
+// Used to print a value that is not an STL-style container when the
+// user doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
+ // With the following statement, during unqualified name lookup,
+ // testing::internal2::operator<< appears as if it was declared in
+ // the nearest enclosing namespace that contains both
+ // ::testing_internal and ::testing::internal2, i.e. the global
+ // namespace. For more details, refer to the C++ Standard section
+ // 7.3.4-1 [namespace.udir]. This allows us to fall back onto
+ // testing::internal2::operator<< in case T doesn't come with a <<
+ // operator.
+ //
+ // We cannot write 'using ::testing::internal2::operator<<;', which
+ // gcc 3.3 fails to compile due to a compiler bug.
+ using namespace ::testing::internal2; // NOLINT
+
+ // Assuming T is defined in namespace foo, in the next statement,
+ // the compiler will consider all of:
+ //
+ // 1. foo::operator<< (thanks to Koenig look-up),
+ // 2. ::operator<< (as the current namespace is enclosed in ::),
+ // 3. testing::internal2::operator<< (thanks to the using statement above).
+ //
+ // The operator<< whose type matches T best will be picked.
+ //
+ // We deliberately allow #2 to be a candidate, as sometimes it's
+ // impossible to define #1 (e.g. when foo is ::std, defining
+ // anything in it is undefined behavior unless you are a compiler
+ // vendor.).
+ *os << value;
+}
+
+} // namespace testing_internal
+
+namespace testing {
+namespace internal {
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream. The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+template <typename C>
+void DefaultPrintTo(IsContainer /* dummy */,
+ false_type /* is not a pointer */,
+ const C& container, ::std::ostream* os) {
+ const size_t kMaxCount = 32; // The maximum number of elements to print.
+ *os << '{';
+ size_t count = 0;
+ for (typename C::const_iterator it = container.begin();
+ it != container.end(); ++it, ++count) {
+ if (count > 0) {
+ *os << ',';
+ if (count == kMaxCount) { // Enough has been printed.
+ *os << " ...";
+ break;
+ }
+ }
+ *os << ' ';
+ // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+ // handle *it being a native array.
+ internal::UniversalPrint(*it, os);
+ }
+
+ if (count > 0) {
+ *os << ' ';
+ }
+ *os << '}';
+}
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it. (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space. Their representation is
+// implementation-defined. Therefore they will be printed as raw
+// bytes.)
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+ true_type /* is a pointer */,
+ T* p, ::std::ostream* os) {
+ if (p == NULL) {
+ *os << "NULL";
+ } else {
+ // C++ doesn't allow casting from a function pointer to any object
+ // pointer.
+ //
+ // IsTrue() silences warnings: "Condition is always true",
+ // "unreachable code".
+ if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
+ // T is not a function type. We just call << to print p,
+ // relying on ADL to pick up user-defined << for their pointer
+ // types, if any.
+ *os << p;
+ } else {
+ // T is a function type, so '*os << p' doesn't do what we want
+ // (it just prints p as bool). We want to print p as a const
+ // void*. However, we cannot cast it to const void* directly,
+ // even using reinterpret_cast, as earlier versions of gcc
+ // (e.g. 3.4.5) cannot compile the cast when p is a function
+ // pointer. Casting to UInt64 first solves the problem.
+ *os << reinterpret_cast<const void*>(
+ reinterpret_cast<internal::UInt64>(p));
+ }
+ }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+ false_type /* is not a pointer */,
+ const T& value, ::std::ostream* os) {
+ ::testing_internal::DefaultPrintNonContainerTo(value, os);
+}
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it. This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined. We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+ // DefaultPrintTo() is overloaded. The type of its first two
+ // arguments determine which version will be picked. If T is an
+ // STL-style container, the version for container will be called; if
+ // T is a pointer, the pointer version will be called; otherwise the
+ // generic version will be called.
+ //
+ // Note that we check for container types here, prior to we check
+ // for protocol message types in our operator<<. The rationale is:
+ //
+ // For protocol messages, we want to give people a chance to
+ // override Google Mock's format by defining a PrintTo() or
+ // operator<<. For STL containers, other formats can be
+ // incompatible with Google Mock's format for the container
+ // elements; therefore we check for container types here to ensure
+ // that our format is used.
+ //
+ // The second argument of DefaultPrintTo() is needed to bypass a bug
+ // in Symbian's C++ compiler that prevents it from picking the right
+ // overload between:
+ //
+ // PrintTo(const T& x, ...);
+ // PrintTo(T* x, ...);
+ DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+ // When printing a plain char, we always treat it as unsigned. This
+ // way, the output won't be affected by whether the compiler thinks
+ // char is signed or not.
+ PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+ *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type. When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays. Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+ UniversalPrint(a[0], os);
+ for (size_t i = 1; i != count; i++) {
+ *os << ", ";
+ UniversalPrint(a[i], os);
+ }
+}
+
+// Overloads for ::string and ::std::string.
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
+inline void PrintTo(const ::string& s, ::std::ostream* os) {
+ PrintStringTo(s, os);
+}
+#endif // GTEST_HAS_GLOBAL_STRING
+
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+ PrintStringTo(s, os);
+}
+
+// Overloads for ::wstring and ::std::wstring.
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
+ PrintWideStringTo(s, os);
+}
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+ PrintWideStringTo(s, os);
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_TR1_TUPLE
+// Overload for ::std::tr1::tuple. Needed for printing function arguments,
+// which are packed as tuples.
+
+// Helper function for printing a tuple. T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os);
+
+// Overloaded PrintTo() for tuples of various arities. We support
+// tuples of up-to 10 fields. The following implementation works
+// regardless of whether tr1::tuple is implemented using the
+// non-standard variadic template feature or not.
+
+inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1>
+void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2>
+void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+void PrintTo(
+ const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+#endif // GTEST_HAS_TR1_TUPLE
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+ *os << '(';
+ // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+ // a reference type. The same for printing value.second.
+ UniversalPrinter<T1>::Print(value.first, os);
+ *os << ", ";
+ UniversalPrinter<T2>::Print(value.second, os);
+ *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+ // MSVC warns about adding const to a function type, so we want to
+ // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4180) // Temporarily disables warning 4180.
+#endif // _MSC_VER
+
+ // Note: we deliberately don't call this PrintTo(), as that name
+ // conflicts with ::testing::internal::PrintTo in the body of the
+ // function.
+ static void Print(const T& value, ::std::ostream* os) {
+ // By default, ::testing::internal::PrintTo() is used for printing
+ // the value.
+ //
+ // Thanks to Koenig look-up, if T is a class and has its own
+ // PrintTo() function defined in its namespace, that function will
+ // be visible here. Since it is more specific than the generic ones
+ // in ::testing::internal, it will be picked by the compiler in the
+ // following statement - exactly what we want.
+ PrintTo(value, os);
+ }
+
+#ifdef _MSC_VER
+# pragma warning(pop) // Restores the warning state.
+#endif // _MSC_VER
+};
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+ if (len == 0) {
+ *os << "{}";
+ } else {
+ *os << "{ ";
+ const size_t kThreshold = 18;
+ const size_t kChunkSize = 8;
+ // If the array has more than kThreshold elements, we'll have to
+ // omit some details by printing only the first and the last
+ // kChunkSize elements.
+ // TODO(wan@google.com): let the user control the threshold using a flag.
+ if (len <= kThreshold) {
+ PrintRawArrayTo(begin, len, os);
+ } else {
+ PrintRawArrayTo(begin, kChunkSize, os);
+ *os << ", ..., ";
+ PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+ }
+ *os << " }";
+ }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(
+ const char* begin, size_t len, ::std::ostream* os);
+
+// This overload prints a (const) wchar_t array compactly.
+GTEST_API_ void UniversalPrintArray(
+ const wchar_t* begin, size_t len, ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+ // Prints the given array, omitting some elements when there are too
+ // many.
+ static void Print(const T (&a)[N], ::std::ostream* os) {
+ UniversalPrintArray(a, N, os);
+ }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+ // MSVC warns about adding const to a function type, so we want to
+ // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4180) // Temporarily disables warning 4180.
+#endif // _MSC_VER
+
+ static void Print(const T& value, ::std::ostream* os) {
+ // Prints the address of the value. We use reinterpret_cast here
+ // as static_cast doesn't compile when T is a function type.
+ *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+ // Then prints the value itself.
+ UniversalPrint(value, os);
+ }
+
+#ifdef _MSC_VER
+# pragma warning(pop) // Restores the warning state.
+#endif // _MSC_VER
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+
+template <typename T>
+class UniversalTersePrinter {
+ public:
+ static void Print(const T& value, ::std::ostream* os) {
+ UniversalPrint(value, os);
+ }
+};
+template <typename T>
+class UniversalTersePrinter<T&> {
+ public:
+ static void Print(const T& value, ::std::ostream* os) {
+ UniversalPrint(value, os);
+ }
+};
+template <typename T, size_t N>
+class UniversalTersePrinter<T[N]> {
+ public:
+ static void Print(const T (&value)[N], ::std::ostream* os) {
+ UniversalPrinter<T[N]>::Print(value, os);
+ }
+};
+template <>
+class UniversalTersePrinter<const char*> {
+ public:
+ static void Print(const char* str, ::std::ostream* os) {
+ if (str == NULL) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(string(str), os);
+ }
+ }
+};
+template <>
+class UniversalTersePrinter<char*> {
+ public:
+ static void Print(char* str, ::std::ostream* os) {
+ UniversalTersePrinter<const char*>::Print(str, os);
+ }
+};
+
+#if GTEST_HAS_STD_WSTRING
+template <>
+class UniversalTersePrinter<const wchar_t*> {
+ public:
+ static void Print(const wchar_t* str, ::std::ostream* os) {
+ if (str == NULL) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(::std::wstring(str), os);
+ }
+ }
+};
+#endif
+
+template <>
+class UniversalTersePrinter<wchar_t*> {
+ public:
+ static void Print(wchar_t* str, ::std::ostream* os) {
+ UniversalTersePrinter<const wchar_t*>::Print(str, os);
+ }
+};
+
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+ UniversalTersePrinter<T>::Print(value, os);
+}
+
+// Prints a value using the type inferred by the compiler. The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+ // A workarond for the bug in VC++ 7.1 that prevents us from instantiating
+ // UniversalPrinter with T directly.
+ typedef T T1;
+ UniversalPrinter<T1>::Print(value, os);
+}
+
+#if GTEST_HAS_TR1_TUPLE
+typedef ::std::vector<string> Strings;
+
+// This helper template allows PrintTo() for tuples and
+// UniversalTersePrintTupleFieldsToStrings() to be defined by
+// induction on the number of tuple fields. The idea is that
+// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
+// fields in tuple t, and can be defined in terms of
+// TuplePrefixPrinter<N - 1>.
+
+// The inductive case.
+template <size_t N>
+struct TuplePrefixPrinter {
+ // Prints the first N fields of a tuple.
+ template <typename Tuple>
+ static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+ TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
+ *os << ", ";
+ UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
+ ::Print(::std::tr1::get<N - 1>(t), os);
+ }
+
+ // Tersely prints the first N fields of a tuple to a string vector,
+ // one element for each field.
+ template <typename Tuple>
+ static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+ TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
+ ::std::stringstream ss;
+ UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
+ strings->push_back(ss.str());
+ }
+};
+
+// Base cases.
+template <>
+struct TuplePrefixPrinter<0> {
+ template <typename Tuple>
+ static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
+
+ template <typename Tuple>
+ static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
+};
+// We have to specialize the entire TuplePrefixPrinter<> class
+// template here, even though the definition of
+// TersePrintPrefixToStrings() is the same as the generic version, as
+// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
+// support specializing a method template of a class template.
+template <>
+struct TuplePrefixPrinter<1> {
+ template <typename Tuple>
+ static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+ UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
+ Print(::std::tr1::get<0>(t), os);
+ }
+
+ template <typename Tuple>
+ static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+ ::std::stringstream ss;
+ UniversalTersePrint(::std::tr1::get<0>(t), &ss);
+ strings->push_back(ss.str());
+ }
+};
+
+// Helper function for printing a tuple. T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os) {
+ *os << "(";
+ TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
+ PrintPrefixTo(t, os);
+ *os << ")";
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field. See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+ Strings result;
+ TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
+ TersePrintPrefixToStrings(value, &result);
+ return result;
+}
+#endif // GTEST_HAS_TR1_TUPLE
+
+} // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+ ::std::stringstream ss;
+ internal::UniversalTersePrinter<T>::Print(value, &ss);
+ return ss.str();
+}
+
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
diff --git a/thirdparty/gtest/include/gtest/gtest-spi.h b/thirdparty/gtest/include/gtest/gtest-spi.h
new file mode 100644
index 00000000..f63fa9a1
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest-spi.h
@@ -0,0 +1,232 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+ : public TestPartResultReporterInterface {
+ public:
+ // The two possible mocking modes of this object.
+ enum InterceptMode {
+ INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures.
+ INTERCEPT_ALL_THREADS // Intercepts all failures.
+ };
+
+ // The c'tor sets this object as the test part result reporter used
+ // by Google Test. The 'result' parameter specifies where to report the
+ // results. This reporter will only catch failures generated in the current
+ // thread. DEPRECATED
+ explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+ // Same as above, but you can choose the interception scope of this object.
+ ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+ TestPartResultArray* result);
+
+ // The d'tor restores the previous test part result reporter.
+ virtual ~ScopedFakeTestPartResultReporter();
+
+ // Appends the TestPartResult object to the TestPartResultArray
+ // received in the constructor.
+ //
+ // This method is from the TestPartResultReporterInterface
+ // interface.
+ virtual void ReportTestPartResult(const TestPartResult& result);
+ private:
+ void Init();
+
+ const InterceptMode intercept_mode_;
+ TestPartResultReporterInterface* old_reporter_;
+ TestPartResultArray* const result_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring. If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+ // The constructor remembers the arguments.
+ SingleFailureChecker(const TestPartResultArray* results,
+ TestPartResult::Type type,
+ const string& substr);
+ ~SingleFailureChecker();
+ private:
+ const TestPartResultArray* const results_;
+ const TestPartResult::Type type_;
+ const string substr_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
+};
+
+} // namespace internal
+
+} // namespace testing
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures. It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+// - 'statement' cannot reference local non-static variables or
+// non-static members of the current object.
+// - 'statement' cannot return a value.
+// - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr) \
+ do { \
+ class GTestExpectFatalFailureHelper {\
+ public:\
+ static void Execute() { statement; }\
+ };\
+ ::testing::TestPartResultArray gtest_failures;\
+ ::testing::internal::SingleFailureChecker gtest_checker(\
+ &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+ {\
+ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+ ::testing::ScopedFakeTestPartResultReporter:: \
+ INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+ GTestExpectFatalFailureHelper::Execute();\
+ }\
+ } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+ do { \
+ class GTestExpectFatalFailureHelper {\
+ public:\
+ static void Execute() { statement; }\
+ };\
+ ::testing::TestPartResultArray gtest_failures;\
+ ::testing::internal::SingleFailureChecker gtest_checker(\
+ &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+ {\
+ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+ ::testing::ScopedFakeTestPartResultReporter:: \
+ INTERCEPT_ALL_THREADS, &gtest_failures);\
+ GTestExpectFatalFailureHelper::Execute();\
+ }\
+ } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures. It asserts that the given
+// statement will cause exactly one non-fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+// - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works. If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma. The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+// if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr) \
+ do {\
+ ::testing::TestPartResultArray gtest_failures;\
+ ::testing::internal::SingleFailureChecker gtest_checker(\
+ &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+ (substr));\
+ {\
+ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+ ::testing::ScopedFakeTestPartResultReporter:: \
+ INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+ if (::testing::internal::AlwaysTrue()) { statement; }\
+ }\
+ } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+ do {\
+ ::testing::TestPartResultArray gtest_failures;\
+ ::testing::internal::SingleFailureChecker gtest_checker(\
+ &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+ (substr));\
+ {\
+ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+ ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
+ &gtest_failures);\
+ if (::testing::internal::AlwaysTrue()) { statement; }\
+ }\
+ } while (::testing::internal::AlwaysFalse())
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
diff --git a/thirdparty/gtest/include/gtest/gtest-test-part.h b/thirdparty/gtest/include/gtest/gtest-test-part.h
new file mode 100644
index 00000000..77eb8448
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest-test-part.h
@@ -0,0 +1,179 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <vector>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+ // The possible outcomes of a test part (i.e. an assertion or an
+ // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+ enum Type {
+ kSuccess, // Succeeded.
+ kNonFatalFailure, // Failed but the test can continue.
+ kFatalFailure // Failed and the test should be terminated.
+ };
+
+ // C'tor. TestPartResult does NOT have a default constructor.
+ // Always use this constructor (with parameters) to create a
+ // TestPartResult object.
+ TestPartResult(Type a_type,
+ const char* a_file_name,
+ int a_line_number,
+ const char* a_message)
+ : type_(a_type),
+ file_name_(a_file_name == NULL ? "" : a_file_name),
+ line_number_(a_line_number),
+ summary_(ExtractSummary(a_message)),
+ message_(a_message) {
+ }
+
+ // Gets the outcome of the test part.
+ Type type() const { return type_; }
+
+ // Gets the name of the source file where the test part took place, or
+ // NULL if it's unknown.
+ const char* file_name() const {
+ return file_name_.empty() ? NULL : file_name_.c_str();
+ }
+
+ // Gets the line in the source file where the test part took place,
+ // or -1 if it's unknown.
+ int line_number() const { return line_number_; }
+
+ // Gets the summary of the failure message.
+ const char* summary() const { return summary_.c_str(); }
+
+ // Gets the message associated with the test part.
+ const char* message() const { return message_.c_str(); }
+
+ // Returns true iff the test part passed.
+ bool passed() const { return type_ == kSuccess; }
+
+ // Returns true iff the test part failed.
+ bool failed() const { return type_ != kSuccess; }
+
+ // Returns true iff the test part non-fatally failed.
+ bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+ // Returns true iff the test part fatally failed.
+ bool fatally_failed() const { return type_ == kFatalFailure; }
+
+ private:
+ Type type_;
+
+ // Gets the summary of the failure message by omitting the stack
+ // trace in it.
+ static std::string ExtractSummary(const char* message);
+
+ // The name of the source file where the test part took place, or
+ // "" if the source file is unknown.
+ std::string file_name_;
+ // The line in the source file where the test part took place, or -1
+ // if the line number is unknown.
+ int line_number_;
+ std::string summary_; // The test failure summary.
+ std::string message_; // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+ TestPartResultArray() {}
+
+ // Appends the given TestPartResult to the array.
+ void Append(const TestPartResult& result);
+
+ // Returns the TestPartResult at the given index (0-based).
+ const TestPartResult& GetTestPartResult(int index) const;
+
+ // Returns the number of TestPartResult objects in the array.
+ int size() const;
+
+ private:
+ std::vector<TestPartResult> array_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
+};
+
+// This interface knows how to report a test part result.
+class TestPartResultReporterInterface {
+ public:
+ virtual ~TestPartResultReporterInterface() {}
+
+ virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+ : public TestPartResultReporterInterface {
+ public:
+ HasNewFatalFailureHelper();
+ virtual ~HasNewFatalFailureHelper();
+ virtual void ReportTestPartResult(const TestPartResult& result);
+ bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+ private:
+ bool has_new_fatal_failure_;
+ TestPartResultReporterInterface* original_reporter_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
+};
+
+} // namespace internal
+
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
diff --git a/thirdparty/gtest/include/gtest/gtest-typed-test.h b/thirdparty/gtest/include/gtest/gtest-typed-test.h
new file mode 100644
index 00000000..fe1e83b2
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest-typed-test.h
@@ -0,0 +1,259 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list. You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template. It should be parameterized
+// by a type. Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+ ...
+ typedef std::list<T> List;
+ static T shared_;
+ T value_;
+};
+
+// Next, associate a list of types with the test case, which will be
+// repeated for each type in the list. The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+// TYPED_TEST_CASE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test case as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+ // Inside a test, refer to TypeParam to get the type parameter.
+ // Since we are inside a derived class template, C++ requires use to
+ // visit the members of FooTest via 'this'.
+ TypeParam n = this->value_;
+
+ // To visit static members of the fixture, add the TestFixture::
+ // prefix.
+ n += TestFixture::shared_;
+
+ // To refer to typedefs in the fixture, add the "typename
+ // TestFixture::" prefix.
+ typename TestFixture::List values;
+ values.push_back(n);
+ ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+#endif // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type. Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are. The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have. Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly. Here's an example:
+
+#if 0
+
+// First, define a fixture class template. It should be parameterized
+// by a type. Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ ...
+};
+
+// Next, declare that you will define a type-parameterized test case
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_CASE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test case as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+ // Inside a test, refer to TypeParam to get the type parameter.
+ TypeParam n = 0;
+ ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them. The first argument of the macro is the
+// test case name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+ DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want. If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test case name. Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+
+#endif // 0
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Implements typed tests.
+
+#if GTEST_HAS_TYPED_TEST
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the typedef for the type parameters of the
+// given test case.
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define TYPED_TEST_CASE(CaseName, Types) \
+ typedef ::testing::internal::TypeList< Types >::type \
+ GTEST_TYPE_PARAMS_(CaseName)
+
+# define TYPED_TEST(CaseName, TestName) \
+ template <typename gtest_TypeParam_> \
+ class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
+ : public CaseName<gtest_TypeParam_> { \
+ private: \
+ typedef CaseName<gtest_TypeParam_> TestFixture; \
+ typedef gtest_TypeParam_ TypeParam; \
+ virtual void TestBody(); \
+ }; \
+ bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
+ ::testing::internal::TypeParameterizedTest< \
+ CaseName, \
+ ::testing::internal::TemplateSel< \
+ GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
+ GTEST_TYPE_PARAMS_(CaseName)>::Register(\
+ "", #CaseName, #TestName, 0); \
+ template <typename gtest_TypeParam_> \
+ void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
+
+#endif // GTEST_HAS_TYPED_TEST
+
+// Implements type-parameterized tests.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the namespace name that the type-parameterized tests for
+// the given type-parameterized test case are defined in. The exact
+// name of the namespace is subject to change without notice.
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
+ gtest_case_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the variable used to remember the names of
+// the defined tests in the given test case.
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+ gtest_typed_test_case_p_state_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
+//
+// Expands to the name of the variable used to remember the names of
+// the registered tests in the given test case.
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+ gtest_registered_test_names_##TestCaseName##_
+
+// The variables defined in the type-parameterized test macros are
+// static as typically these macros are used in a .h file that can be
+// #included in multiple translation units linked together.
+# define TYPED_TEST_CASE_P(CaseName) \
+ static ::testing::internal::TypedTestCasePState \
+ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
+
+# define TYPED_TEST_P(CaseName, TestName) \
+ namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+ template <typename gtest_TypeParam_> \
+ class TestName : public CaseName<gtest_TypeParam_> { \
+ private: \
+ typedef CaseName<gtest_TypeParam_> TestFixture; \
+ typedef gtest_TypeParam_ TypeParam; \
+ virtual void TestBody(); \
+ }; \
+ static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
+ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
+ __FILE__, __LINE__, #CaseName, #TestName); \
+ } \
+ template <typename gtest_TypeParam_> \
+ void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
+
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+ namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+ typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
+ } \
+ static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
+ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
+ __FILE__, __LINE__, #__VA_ARGS__)
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+ bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
+ ::testing::internal::TypeParameterizedTestCase<CaseName, \
+ GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
+ ::testing::internal::TypeList< Types >::type>::Register(\
+ #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
+
+#endif // GTEST_HAS_TYPED_TEST_P
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
diff --git a/thirdparty/gtest/include/gtest/gtest.h b/thirdparty/gtest/include/gtest/gtest.h
new file mode 100644
index 00000000..6fa0a392
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest.h
@@ -0,0 +1,2291 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for Google Test. It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
+// easyUnit framework.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_H_
+
+#include <limits>
+#include <ostream>
+#include <vector>
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest_prod.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest-typed-test.h"
+
+// Depending on the platform, different string classes are available.
+// On Linux, in addition to ::std::string, Google also makes use of
+// class ::string, which has the same interface as ::std::string, but
+// has a different implementation.
+//
+// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
+// ::string is available AND is a distinct type to ::std::string, or
+// define it to 0 to indicate otherwise.
+//
+// If the user's ::std::string and ::string are the same class due to
+// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0.
+//
+// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined
+// heuristically.
+
+namespace testing {
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class StreamingListenerTest;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class UnitTestRecordPropertyTestHelper;
+class WindowsDeathTest;
+class UnitTestImpl* GetUnitTestImpl();
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+ const std::string& message);
+
+} // namespace internal
+
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
+// A class for indicating whether an assertion was successful. When
+// the assertion wasn't successful, the AssertionResult object
+// remembers a non-empty message that describes how it failed.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+// 1. Defining predicate functions to be used with Boolean test assertions
+// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+// 2. Defining predicate-format functions to be
+// used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+// testing::AssertionResult IsEven(int n) {
+// if ((n % 2) == 0)
+// return testing::AssertionSuccess();
+// else
+// return testing::AssertionFailure() << n << " is odd";
+// }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+// Value of: IsEven(Fib(5))
+// Actual: false (5 is odd)
+// Expected: true
+//
+// instead of a more opaque
+//
+// Value of: IsEven(Fib(5))
+// Actual: false
+// Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+// testing::AssertionResult IsEven(int n) {
+// if ((n % 2) == 0)
+// return testing::AssertionSuccess() << n << " is even";
+// else
+// return testing::AssertionFailure() << n << " is odd";
+// }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+// Value of: IsEven(Fib(6))
+// Actual: true (8 is even)
+// Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+// // Verifies that Foo() returns an even number.
+// EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+// testing::AssertionResult IsEven(const char* expr, int n) {
+// if ((n % 2) == 0)
+// return testing::AssertionSuccess();
+// else
+// return testing::AssertionFailure()
+// << "Expected: " << expr << " is even\n Actual: it's " << n;
+// }
+//
+// If Foo() returns 5, you will see the following message:
+//
+// Expected: Foo() is even
+// Actual: it's 5
+//
+class GTEST_API_ AssertionResult {
+ public:
+ // Copy constructor.
+ // Used in EXPECT_TRUE/FALSE(assertion_result).
+ AssertionResult(const AssertionResult& other);
+ // Used in the EXPECT_TRUE/FALSE(bool_expression).
+ explicit AssertionResult(bool success) : success_(success) {}
+
+ // Returns true iff the assertion succeeded.
+ operator bool() const { return success_; } // NOLINT
+
+ // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+ AssertionResult operator!() const;
+
+ // Returns the text streamed into this AssertionResult. Test assertions
+ // use it when they fail (i.e., the predicate's outcome doesn't match the
+ // assertion's expectation). When nothing has been streamed into the
+ // object, returns an empty string.
+ const char* message() const {
+ return message_.get() != NULL ? message_->c_str() : "";
+ }
+ // TODO(vladl@google.com): Remove this after making sure no clients use it.
+ // Deprecated; please use message() instead.
+ const char* failure_message() const { return message(); }
+
+ // Streams a custom failure message into this object.
+ template <typename T> AssertionResult& operator<<(const T& value) {
+ AppendMessage(Message() << value);
+ return *this;
+ }
+
+ // Allows streaming basic output manipulators such as endl or flush into
+ // this object.
+ AssertionResult& operator<<(
+ ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+ AppendMessage(Message() << basic_manipulator);
+ return *this;
+ }
+
+ private:
+ // Appends the contents of message to message_.
+ void AppendMessage(const Message& a_message) {
+ if (message_.get() == NULL)
+ message_.reset(new ::std::string);
+ message_->append(a_message.GetString().c_str());
+ }
+
+ // Stores result of the assertion predicate.
+ bool success_;
+ // Stores the message describing the condition in case the expectation
+ // construct is not satisfied with the predicate's outcome.
+ // Referenced via a pointer to avoid taking too much stack frame space
+ // with test assertions.
+ internal::scoped_ptr< ::std::string> message_;
+
+ GTEST_DISALLOW_ASSIGN_(AssertionResult);
+};
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestCases, and
+// each TestCase contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used a TEST_F. For example:
+//
+// class FooTest : public testing::Test {
+// protected:
+// virtual void SetUp() { ... }
+// virtual void TearDown() { ... }
+// ...
+// };
+//
+// TEST_F(FooTest, Bar) { ... }
+// TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+ friend class TestInfo;
+
+ // Defines types for pointers to functions that set up and tear down
+ // a test case.
+ typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc;
+ typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc;
+
+ // The d'tor is virtual as we intend to inherit from Test.
+ virtual ~Test();
+
+ // Sets up the stuff shared by all tests in this test case.
+ //
+ // Google Test will call Foo::SetUpTestCase() before running the first
+ // test in test case Foo. Hence a sub-class can define its own
+ // SetUpTestCase() method to shadow the one defined in the super
+ // class.
+ static void SetUpTestCase() {}
+
+ // Tears down the stuff shared by all tests in this test case.
+ //
+ // Google Test will call Foo::TearDownTestCase() after running the last
+ // test in test case Foo. Hence a sub-class can define its own
+ // TearDownTestCase() method to shadow the one defined in the super
+ // class.
+ static void TearDownTestCase() {}
+
+ // Returns true iff the current test has a fatal failure.
+ static bool HasFatalFailure();
+
+ // Returns true iff the current test has a non-fatal failure.
+ static bool HasNonfatalFailure();
+
+ // Returns true iff the current test has a (either fatal or
+ // non-fatal) failure.
+ static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+ // Logs a property for the current test, test case, or for the entire
+ // invocation of the test program when used outside of the context of a
+ // test case. Only the last value for a given key is remembered. These
+ // are public static so they can be called from utility functions that are
+ // not members of the test fixture. Calls to RecordProperty made during
+ // lifespan of the test (from the moment its constructor starts to the
+ // moment its destructor finishes) will be output in XML as attributes of
+ // the <testcase> element. Properties recorded from fixture's
+ // SetUpTestCase or TearDownTestCase are logged as attributes of the
+ // corresponding <testsuite> element. Calls to RecordProperty made in the
+ // global context (before or after invocation of RUN_ALL_TESTS and from
+ // SetUp/TearDown method of Environment objects registered with Google
+ // Test) will be output as attributes of the <testsuites> element.
+ static void RecordProperty(const std::string& key, const std::string& value);
+ static void RecordProperty(const std::string& key, int value);
+
+ protected:
+ // Creates a Test object.
+ Test();
+
+ // Sets up the test fixture.
+ virtual void SetUp();
+
+ // Tears down the test fixture.
+ virtual void TearDown();
+
+ private:
+ // Returns true iff the current test has the same fixture class as
+ // the first test in the current test case.
+ static bool HasSameFixtureClass();
+
+ // Runs the test after the test fixture has been set up.
+ //
+ // A sub-class must implement this to define the test logic.
+ //
+ // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+ // Instead, use the TEST or TEST_F macro.
+ virtual void TestBody() = 0;
+
+ // Sets up, executes, and tears down the test.
+ void Run();
+
+ // Deletes self. We deliberately pick an unusual name for this
+ // internal method to avoid clashing with names used in user TESTs.
+ void DeleteSelf_() { delete this; }
+
+ // Uses a GTestFlagSaver to save and restore all Google Test flags.
+ const internal::GTestFlagSaver* const gtest_flag_saver_;
+
+ // Often a user mis-spells SetUp() as Setup() and spends a long time
+ // wondering why it is never called by Google Test. The declaration of
+ // the following method is solely for catching such an error at
+ // compile time:
+ //
+ // - The return type is deliberately chosen to be not void, so it
+ // will be a conflict if a user declares void Setup() in his test
+ // fixture.
+ //
+ // - This method is private, so it will be another compiler error
+ // if a user calls it from his test fixture.
+ //
+ // DO NOT OVERRIDE THIS FUNCTION.
+ //
+ // If you see an error about overriding the following function or
+ // about it being private, you have mis-spelled SetUp() as Setup().
+ struct Setup_should_be_spelled_SetUp {};
+ virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+
+ // We disallow copying Tests.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+ // C'tor. TestProperty does NOT have a default constructor.
+ // Always use this constructor (with parameters) to create a
+ // TestProperty object.
+ TestProperty(const std::string& a_key, const std::string& a_value) :
+ key_(a_key), value_(a_value) {
+ }
+
+ // Gets the user supplied key.
+ const char* key() const {
+ return key_.c_str();
+ }
+
+ // Gets the user supplied value.
+ const char* value() const {
+ return value_.c_str();
+ }
+
+ // Sets a new value, overriding the one supplied in the constructor.
+ void SetValue(const std::string& new_value) {
+ value_ = new_value;
+ }
+
+ private:
+ // The key supplied by the user.
+ std::string key_;
+ // The value supplied by the user.
+ std::string value_;
+};
+
+// The result of a single Test. This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+ // Creates an empty TestResult.
+ TestResult();
+
+ // D'tor. Do not inherit from TestResult.
+ ~TestResult();
+
+ // Gets the number of all test parts. This is the sum of the number
+ // of successful test parts and the number of failed test parts.
+ int total_part_count() const;
+
+ // Returns the number of the test properties.
+ int test_property_count() const;
+
+ // Returns true iff the test passed (i.e. no test part failed).
+ bool Passed() const { return !Failed(); }
+
+ // Returns true iff the test failed.
+ bool Failed() const;
+
+ // Returns true iff the test fatally failed.
+ bool HasFatalFailure() const;
+
+ // Returns true iff the test has a non-fatal failure.
+ bool HasNonfatalFailure() const;
+
+ // Returns the elapsed time, in milliseconds.
+ TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+ // Returns the i-th test part result among all the results. i can range
+ // from 0 to test_property_count() - 1. If i is not in that range, aborts
+ // the program.
+ const TestPartResult& GetTestPartResult(int i) const;
+
+ // Returns the i-th test property. i can range from 0 to
+ // test_property_count() - 1. If i is not in that range, aborts the
+ // program.
+ const TestProperty& GetTestProperty(int i) const;
+
+ private:
+ friend class TestInfo;
+ friend class TestCase;
+ friend class UnitTest;
+ friend class internal::DefaultGlobalTestPartResultReporter;
+ friend class internal::ExecDeathTest;
+ friend class internal::TestResultAccessor;
+ friend class internal::UnitTestImpl;
+ friend class internal::WindowsDeathTest;
+
+ // Gets the vector of TestPartResults.
+ const std::vector<TestPartResult>& test_part_results() const {
+ return test_part_results_;
+ }
+
+ // Gets the vector of TestProperties.
+ const std::vector<TestProperty>& test_properties() const {
+ return test_properties_;
+ }
+
+ // Sets the elapsed time.
+ void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+ // Adds a test property to the list. The property is validated and may add
+ // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+ // key names). If a property is already recorded for the same key, the
+ // value will be updated, rather than storing multiple values for the same
+ // key. xml_element specifies the element for which the property is being
+ // recorded and is used for validation.
+ void RecordProperty(const std::string& xml_element,
+ const TestProperty& test_property);
+
+ // Adds a failure if the key is a reserved attribute of Google Test
+ // testcase tags. Returns true if the property is valid.
+ // TODO(russr): Validate attribute names are legal and human readable.
+ static bool ValidateTestProperty(const std::string& xml_element,
+ const TestProperty& test_property);
+
+ // Adds a test part result to the list.
+ void AddTestPartResult(const TestPartResult& test_part_result);
+
+ // Returns the death test count.
+ int death_test_count() const { return death_test_count_; }
+
+ // Increments the death test count, returning the new count.
+ int increment_death_test_count() { return ++death_test_count_; }
+
+ // Clears the test part results.
+ void ClearTestPartResults();
+
+ // Clears the object.
+ void Clear();
+
+ // Protects mutable state of the property vector and of owned
+ // properties, whose values may be updated.
+ internal::Mutex test_properites_mutex_;
+
+ // The vector of TestPartResults
+ std::vector<TestPartResult> test_part_results_;
+ // The vector of TestProperties
+ std::vector<TestProperty> test_properties_;
+ // Running count of death tests.
+ int death_test_count_;
+ // The elapsed time, in milliseconds.
+ TimeInMillis elapsed_time_;
+
+ // We disallow copying TestResult.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
+}; // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+// Test case name
+// Test name
+// Whether the test should be run
+// A function pointer that creates the test object when invoked
+// Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+ // Destructs a TestInfo object. This function is not virtual, so
+ // don't inherit from TestInfo.
+ ~TestInfo();
+
+ // Returns the test case name.
+ const char* test_case_name() const { return test_case_name_.c_str(); }
+
+ // Returns the test name.
+ const char* name() const { return name_.c_str(); }
+
+ // Returns the name of the parameter type, or NULL if this is not a typed
+ // or a type-parameterized test.
+ const char* type_param() const {
+ if (type_param_.get() != NULL)
+ return type_param_->c_str();
+ return NULL;
+ }
+
+ // Returns the text representation of the value parameter, or NULL if this
+ // is not a value-parameterized test.
+ const char* value_param() const {
+ if (value_param_.get() != NULL)
+ return value_param_->c_str();
+ return NULL;
+ }
+
+ // Returns true if this test should run, that is if the test is not
+ // disabled (or it is disabled but the also_run_disabled_tests flag has
+ // been specified) and its full name matches the user-specified filter.
+ //
+ // Google Test allows the user to filter the tests by their full names.
+ // The full name of a test Bar in test case Foo is defined as
+ // "Foo.Bar". Only the tests that match the filter will run.
+ //
+ // A filter is a colon-separated list of glob (not regex) patterns,
+ // optionally followed by a '-' and a colon-separated list of
+ // negative patterns (tests to exclude). A test is run if it
+ // matches one of the positive patterns and does not match any of
+ // the negative patterns.
+ //
+ // For example, *A*:Foo.* is a filter that matches any string that
+ // contains the character 'A' or starts with "Foo.".
+ bool should_run() const { return should_run_; }
+
+ // Returns true iff this test will appear in the XML report.
+ bool is_reportable() const {
+ // For now, the XML report includes all tests matching the filter.
+ // In the future, we may trim tests that are excluded because of
+ // sharding.
+ return matches_filter_;
+ }
+
+ // Returns the result of the test.
+ const TestResult* result() const { return &result_; }
+
+ private:
+#if GTEST_HAS_DEATH_TEST
+ friend class internal::DefaultDeathTestFactory;
+#endif // GTEST_HAS_DEATH_TEST
+ friend class Test;
+ friend class TestCase;
+ friend class internal::UnitTestImpl;
+ friend class internal::StreamingListenerTest;
+ friend TestInfo* internal::MakeAndRegisterTestInfo(
+ const char* test_case_name,
+ const char* name,
+ const char* type_param,
+ const char* value_param,
+ internal::TypeId fixture_class_id,
+ Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc,
+ internal::TestFactoryBase* factory);
+
+ // Constructs a TestInfo object. The newly constructed instance assumes
+ // ownership of the factory object.
+ TestInfo(const std::string& test_case_name,
+ const std::string& name,
+ const char* a_type_param, // NULL if not a type-parameterized test
+ const char* a_value_param, // NULL if not a value-parameterized test
+ internal::TypeId fixture_class_id,
+ internal::TestFactoryBase* factory);
+
+ // Increments the number of death tests encountered in this test so
+ // far.
+ int increment_death_test_count() {
+ return result_.increment_death_test_count();
+ }
+
+ // Creates the test object, runs it, records its result, and then
+ // deletes it.
+ void Run();
+
+ static void ClearTestResult(TestInfo* test_info) {
+ test_info->result_.Clear();
+ }
+
+ // These fields are immutable properties of the test.
+ const std::string test_case_name_; // Test case name
+ const std::string name_; // Test name
+ // Name of the parameter type, or NULL if this is not a typed or a
+ // type-parameterized test.
+ const internal::scoped_ptr<const ::std::string> type_param_;
+ // Text representation of the value parameter, or NULL if this is not a
+ // value-parameterized test.
+ const internal::scoped_ptr<const ::std::string> value_param_;
+ const internal::TypeId fixture_class_id_; // ID of the test fixture class
+ bool should_run_; // True iff this test should run
+ bool is_disabled_; // True iff this test is disabled
+ bool matches_filter_; // True if this test matches the
+ // user-specified filter.
+ internal::TestFactoryBase* const factory_; // The factory that creates
+ // the test object
+
+ // This field is mutable and needs to be reset before running the
+ // test for the second time.
+ TestResult result_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
+};
+
+// A test case, which consists of a vector of TestInfos.
+//
+// TestCase is not copyable.
+class GTEST_API_ TestCase {
+ public:
+ // Creates a TestCase with the given name.
+ //
+ // TestCase does NOT have a default constructor. Always use this
+ // constructor to create a TestCase object.
+ //
+ // Arguments:
+ //
+ // name: name of the test case
+ // a_type_param: the name of the test's type parameter, or NULL if
+ // this is not a type-parameterized test.
+ // set_up_tc: pointer to the function that sets up the test case
+ // tear_down_tc: pointer to the function that tears down the test case
+ TestCase(const char* name, const char* a_type_param,
+ Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc);
+
+ // Destructor of TestCase.
+ virtual ~TestCase();
+
+ // Gets the name of the TestCase.
+ const char* name() const { return name_.c_str(); }
+
+ // Returns the name of the parameter type, or NULL if this is not a
+ // type-parameterized test case.
+ const char* type_param() const {
+ if (type_param_.get() != NULL)
+ return type_param_->c_str();
+ return NULL;
+ }
+
+ // Returns true if any test in this test case should run.
+ bool should_run() const { return should_run_; }
+
+ // Gets the number of successful tests in this test case.
+ int successful_test_count() const;
+
+ // Gets the number of failed tests in this test case.
+ int failed_test_count() const;
+
+ // Gets the number of disabled tests that will be reported in the XML report.
+ int reportable_disabled_test_count() const;
+
+ // Gets the number of disabled tests in this test case.
+ int disabled_test_count() const;
+
+ // Gets the number of tests to be printed in the XML report.
+ int reportable_test_count() const;
+
+ // Get the number of tests in this test case that should run.
+ int test_to_run_count() const;
+
+ // Gets the number of all tests in this test case.
+ int total_test_count() const;
+
+ // Returns true iff the test case passed.
+ bool Passed() const { return !Failed(); }
+
+ // Returns true iff the test case failed.
+ bool Failed() const { return failed_test_count() > 0; }
+
+ // Returns the elapsed time, in milliseconds.
+ TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+ // Returns the i-th test among all the tests. i can range from 0 to
+ // total_test_count() - 1. If i is not in that range, returns NULL.
+ const TestInfo* GetTestInfo(int i) const;
+
+ // Returns the TestResult that holds test properties recorded during
+ // execution of SetUpTestCase and TearDownTestCase.
+ const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; }
+
+ private:
+ friend class Test;
+ friend class internal::UnitTestImpl;
+
+ // Gets the (mutable) vector of TestInfos in this TestCase.
+ std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+ // Gets the (immutable) vector of TestInfos in this TestCase.
+ const std::vector<TestInfo*>& test_info_list() const {
+ return test_info_list_;
+ }
+
+ // Returns the i-th test among all the tests. i can range from 0 to
+ // total_test_count() - 1. If i is not in that range, returns NULL.
+ TestInfo* GetMutableTestInfo(int i);
+
+ // Sets the should_run member.
+ void set_should_run(bool should) { should_run_ = should; }
+
+ // Adds a TestInfo to this test case. Will delete the TestInfo upon
+ // destruction of the TestCase object.
+ void AddTestInfo(TestInfo * test_info);
+
+ // Clears the results of all tests in this test case.
+ void ClearResult();
+
+ // Clears the results of all tests in the given test case.
+ static void ClearTestCaseResult(TestCase* test_case) {
+ test_case->ClearResult();
+ }
+
+ // Runs every test in this TestCase.
+ void Run();
+
+ // Runs SetUpTestCase() for this TestCase. This wrapper is needed
+ // for catching exceptions thrown from SetUpTestCase().
+ void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+ // Runs TearDownTestCase() for this TestCase. This wrapper is
+ // needed for catching exceptions thrown from TearDownTestCase().
+ void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
+ // Returns true iff test passed.
+ static bool TestPassed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Passed();
+ }
+
+ // Returns true iff test failed.
+ static bool TestFailed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Failed();
+ }
+
+ // Returns true iff the test is disabled and will be reported in the XML
+ // report.
+ static bool TestReportableDisabled(const TestInfo* test_info) {
+ return test_info->is_reportable() && test_info->is_disabled_;
+ }
+
+ // Returns true iff test is disabled.
+ static bool TestDisabled(const TestInfo* test_info) {
+ return test_info->is_disabled_;
+ }
+
+ // Returns true iff this test will appear in the XML report.
+ static bool TestReportable(const TestInfo* test_info) {
+ return test_info->is_reportable();
+ }
+
+ // Returns true if the given test should run.
+ static bool ShouldRunTest(const TestInfo* test_info) {
+ return test_info->should_run();
+ }
+
+ // Shuffles the tests in this test case.
+ void ShuffleTests(internal::Random* random);
+
+ // Restores the test order to before the first shuffle.
+ void UnshuffleTests();
+
+ // Name of the test case.
+ std::string name_;
+ // Name of the parameter type, or NULL if this is not a typed or a
+ // type-parameterized test.
+ const internal::scoped_ptr<const ::std::string> type_param_;
+ // The vector of TestInfos in their original order. It owns the
+ // elements in the vector.
+ std::vector<TestInfo*> test_info_list_;
+ // Provides a level of indirection for the test list to allow easy
+ // shuffling and restoring the test order. The i-th element in this
+ // vector is the index of the i-th test in the shuffled test list.
+ std::vector<int> test_indices_;
+ // Pointer to the function that sets up the test case.
+ Test::SetUpTestCaseFunc set_up_tc_;
+ // Pointer to the function that tears down the test case.
+ Test::TearDownTestCaseFunc tear_down_tc_;
+ // True iff any test in this test case should run.
+ bool should_run_;
+ // Elapsed time, in milliseconds.
+ TimeInMillis elapsed_time_;
+ // Holds test properties recorded during execution of SetUpTestCase and
+ // TearDownTestCase.
+ TestResult ad_hoc_test_result_;
+
+ // We disallow copying TestCases.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase);
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment. The user should subclass this to define his own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+// 1. You cannot safely throw from a destructor. This is a problem
+// as in some cases Google Test is used where exceptions are enabled, and
+// we may want to implement ASSERT_* using exceptions where they are
+// available.
+// 2. You cannot use ASSERT_* directly in a constructor or
+// destructor.
+class Environment {
+ public:
+ // The d'tor is virtual as we need to subclass Environment.
+ virtual ~Environment() {}
+
+ // Override this to define how to set up the environment.
+ virtual void SetUp() {}
+
+ // Override this to define how to tear down the environment.
+ virtual void TearDown() {}
+ private:
+ // If you see an error about overriding the following function or
+ // about it being private, you have mis-spelled SetUp() as Setup().
+ struct Setup_should_be_spelled_SetUp {};
+ virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+};
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+ virtual ~TestEventListener() {}
+
+ // Fired before any test activity starts.
+ virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+ // Fired before each iteration of tests starts. There may be more than
+ // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+ // index, starting from 0.
+ virtual void OnTestIterationStart(const UnitTest& unit_test,
+ int iteration) = 0;
+
+ // Fired before environment set-up for each iteration of tests starts.
+ virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+ // Fired after environment set-up for each iteration of tests ends.
+ virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+ // Fired before the test case starts.
+ virtual void OnTestCaseStart(const TestCase& test_case) = 0;
+
+ // Fired before the test starts.
+ virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+ // Fired after a failed assertion or a SUCCEED() invocation.
+ virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+ // Fired after the test ends.
+ virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+ // Fired after the test case ends.
+ virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
+
+ // Fired before environment tear-down for each iteration of tests starts.
+ virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+ // Fired after environment tear-down for each iteration of tests ends.
+ virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+ // Fired after each iteration of tests finishes.
+ virtual void OnTestIterationEnd(const UnitTest& unit_test,
+ int iteration) = 0;
+
+ // Fired after all test activities have ended.
+ virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build. For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+ virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+ int /*iteration*/) {}
+ virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {}
+ virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+ virtual void OnTestStart(const TestInfo& /*test_info*/) {}
+ virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {}
+ virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
+ virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+ virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {}
+ virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+ int /*iteration*/) {}
+ virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+ TestEventListeners();
+ ~TestEventListeners();
+
+ // Appends an event listener to the end of the list. Google Test assumes
+ // the ownership of the listener (i.e. it will delete the listener when
+ // the test program finishes).
+ void Append(TestEventListener* listener);
+
+ // Removes the given event listener from the list and returns it. It then
+ // becomes the caller's responsibility to delete the listener. Returns
+ // NULL if the listener is not found in the list.
+ TestEventListener* Release(TestEventListener* listener);
+
+ // Returns the standard listener responsible for the default console
+ // output. Can be removed from the listeners list to shut down default
+ // console output. Note that removing this object from the listener list
+ // with Release transfers its ownership to the caller and makes this
+ // function return NULL the next time.
+ TestEventListener* default_result_printer() const {
+ return default_result_printer_;
+ }
+
+ // Returns the standard listener responsible for the default XML output
+ // controlled by the --gtest_output=xml flag. Can be removed from the
+ // listeners list by users who want to shut down the default XML output
+ // controlled by this flag and substitute it with custom one. Note that
+ // removing this object from the listener list with Release transfers its
+ // ownership to the caller and makes this function return NULL the next
+ // time.
+ TestEventListener* default_xml_generator() const {
+ return default_xml_generator_;
+ }
+
+ private:
+ friend class TestCase;
+ friend class TestInfo;
+ friend class internal::DefaultGlobalTestPartResultReporter;
+ friend class internal::NoExecDeathTest;
+ friend class internal::TestEventListenersAccessor;
+ friend class internal::UnitTestImpl;
+
+ // Returns repeater that broadcasts the TestEventListener events to all
+ // subscribers.
+ TestEventListener* repeater();
+
+ // Sets the default_result_printer attribute to the provided listener.
+ // The listener is also added to the listener list and previous
+ // default_result_printer is removed from it and deleted. The listener can
+ // also be NULL in which case it will not be added to the list. Does
+ // nothing if the previous and the current listener objects are the same.
+ void SetDefaultResultPrinter(TestEventListener* listener);
+
+ // Sets the default_xml_generator attribute to the provided listener. The
+ // listener is also added to the listener list and previous
+ // default_xml_generator is removed from it and deleted. The listener can
+ // also be NULL in which case it will not be added to the list. Does
+ // nothing if the previous and the current listener objects are the same.
+ void SetDefaultXmlGenerator(TestEventListener* listener);
+
+ // Controls whether events will be forwarded by the repeater to the
+ // listeners in the list.
+ bool EventForwardingEnabled() const;
+ void SuppressEventForwarding();
+
+ // The actual list of listeners.
+ internal::TestEventRepeater* repeater_;
+ // Listener responsible for the standard result output.
+ TestEventListener* default_result_printer_;
+ // Listener responsible for the creation of the XML output file.
+ TestEventListener* default_xml_generator_;
+
+ // We disallow copying TestEventListeners.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
+};
+
+// A UnitTest consists of a vector of TestCases.
+//
+// This is a singleton class. The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called. This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+ // Gets the singleton UnitTest object. The first time this method
+ // is called, a UnitTest object is constructed and returned.
+ // Consecutive calls will return the same object.
+ static UnitTest* GetInstance();
+
+ // Runs all tests in this UnitTest object and prints the result.
+ // Returns 0 if successful, or 1 otherwise.
+ //
+ // This method can only be called from the main thread.
+ //
+ // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+ int Run() GTEST_MUST_USE_RESULT_;
+
+ // Returns the working directory when the first TEST() or TEST_F()
+ // was executed. The UnitTest object owns the string.
+ const char* original_working_dir() const;
+
+ // Returns the TestCase object for the test that's currently running,
+ // or NULL if no test is running.
+ const TestCase* current_test_case() const
+ GTEST_LOCK_EXCLUDED_(mutex_);
+
+ // Returns the TestInfo object for the test that's currently running,
+ // or NULL if no test is running.
+ const TestInfo* current_test_info() const
+ GTEST_LOCK_EXCLUDED_(mutex_);
+
+ // Returns the random seed used at the start of the current test run.
+ int random_seed() const;
+
+#if GTEST_HAS_PARAM_TEST
+ // Returns the ParameterizedTestCaseRegistry object used to keep track of
+ // value-parameterized tests and instantiate and register them.
+ //
+ // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+ internal::ParameterizedTestCaseRegistry& parameterized_test_registry()
+ GTEST_LOCK_EXCLUDED_(mutex_);
+#endif // GTEST_HAS_PARAM_TEST
+
+ // Gets the number of successful test cases.
+ int successful_test_case_count() const;
+
+ // Gets the number of failed test cases.
+ int failed_test_case_count() const;
+
+ // Gets the number of all test cases.
+ int total_test_case_count() const;
+
+ // Gets the number of all test cases that contain at least one test
+ // that should run.
+ int test_case_to_run_count() const;
+
+ // Gets the number of successful tests.
+ int successful_test_count() const;
+
+ // Gets the number of failed tests.
+ int failed_test_count() const;
+
+ // Gets the number of disabled tests that will be reported in the XML report.
+ int reportable_disabled_test_count() const;
+
+ // Gets the number of disabled tests.
+ int disabled_test_count() const;
+
+ // Gets the number of tests to be printed in the XML report.
+ int reportable_test_count() const;
+
+ // Gets the number of all tests.
+ int total_test_count() const;
+
+ // Gets the number of tests that should run.
+ int test_to_run_count() const;
+
+ // Gets the time of the test program start, in ms from the start of the
+ // UNIX epoch.
+ TimeInMillis start_timestamp() const;
+
+ // Gets the elapsed time, in milliseconds.
+ TimeInMillis elapsed_time() const;
+
+ // Returns true iff the unit test passed (i.e. all test cases passed).
+ bool Passed() const;
+
+ // Returns true iff the unit test failed (i.e. some test case failed
+ // or something outside of all tests failed).
+ bool Failed() const;
+
+ // Gets the i-th test case among all the test cases. i can range from 0 to
+ // total_test_case_count() - 1. If i is not in that range, returns NULL.
+ const TestCase* GetTestCase(int i) const;
+
+ // Returns the TestResult containing information on test failures and
+ // properties logged outside of individual test cases.
+ const TestResult& ad_hoc_test_result() const;
+
+ // Returns the list of event listeners that can be used to track events
+ // inside Google Test.
+ TestEventListeners& listeners();
+
+ private:
+ // Registers and returns a global test environment. When a test
+ // program is run, all global test environments will be set-up in
+ // the order they were registered. After all tests in the program
+ // have finished, all global test environments will be torn-down in
+ // the *reverse* order they were registered.
+ //
+ // The UnitTest object takes ownership of the given environment.
+ //
+ // This method can only be called from the main thread.
+ Environment* AddEnvironment(Environment* env);
+
+ // Adds a TestPartResult to the current TestResult object. All
+ // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
+ // eventually call this to report their results. The user code
+ // should use the assertion macros instead of calling this directly.
+ void AddTestPartResult(TestPartResult::Type result_type,
+ const char* file_name,
+ int line_number,
+ const std::string& message,
+ const std::string& os_stack_trace)
+ GTEST_LOCK_EXCLUDED_(mutex_);
+
+ // Adds a TestProperty to the current TestResult object when invoked from
+ // inside a test, to current TestCase's ad_hoc_test_result_ when invoked
+ // from SetUpTestCase or TearDownTestCase, or to the global property set
+ // when invoked elsewhere. If the result already contains a property with
+ // the same key, the value will be updated.
+ void RecordProperty(const std::string& key, const std::string& value);
+
+ // Gets the i-th test case among all the test cases. i can range from 0 to
+ // total_test_case_count() - 1. If i is not in that range, returns NULL.
+ TestCase* GetMutableTestCase(int i);
+
+ // Accessors for the implementation object.
+ internal::UnitTestImpl* impl() { return impl_; }
+ const internal::UnitTestImpl* impl() const { return impl_; }
+
+ // These classes and funcions are friends as they need to access private
+ // members of UnitTest.
+ friend class Test;
+ friend class internal::AssertHelper;
+ friend class internal::ScopedTrace;
+ friend class internal::StreamingListenerTest;
+ friend class internal::UnitTestRecordPropertyTestHelper;
+ friend Environment* AddGlobalTestEnvironment(Environment* env);
+ friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+ friend void internal::ReportFailureInUnknownLocation(
+ TestPartResult::Type result_type,
+ const std::string& message);
+
+ // Creates an empty UnitTest.
+ UnitTest();
+
+ // D'tor
+ virtual ~UnitTest();
+
+ // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+ // Google Test trace stack.
+ void PushGTestTrace(const internal::TraceInfo& trace)
+ GTEST_LOCK_EXCLUDED_(mutex_);
+
+ // Pops a trace from the per-thread Google Test trace stack.
+ void PopGTestTrace()
+ GTEST_LOCK_EXCLUDED_(mutex_);
+
+ // Protects mutable state in *impl_. This is mutable as some const
+ // methods need to lock it too.
+ mutable internal::Mutex mutex_;
+
+ // Opaque implementation object. This field is never changed once
+ // the object is constructed. We don't mark it as const here, as
+ // doing so will cause a warning in the constructor of UnitTest.
+ // Mutable state in *impl_ is protected by mutex_.
+ internal::UnitTestImpl* impl_;
+
+ // We disallow copying UnitTest.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main(). If you use gtest_main, you need to call this before main()
+// starts for it to take effect. For example, you can define a global
+// variable like this:
+//
+// testing::Environment* const foo_env =
+// testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+ return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test. This must be called before calling
+// RUN_ALL_TESTS(). In particular, it parses a command line for the
+// flags that Google Test recognizes. Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned. Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+namespace internal {
+
+// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
+// value of type ToPrint that is an operand of a comparison assertion
+// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in
+// the comparison, and is used to help determine the best way to
+// format the value. In particular, when the value is a C string
+// (char pointer) and the other operand is an STL string object, we
+// want to format the C string as a string, since we know it is
+// compared by value with the string object. If the value is a char
+// pointer but the other operand is not an STL string object, we don't
+// know whether the pointer is supposed to point to a NUL-terminated
+// string, and thus want to print it as a pointer to be safe.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// The default case.
+template <typename ToPrint, typename OtherOperand>
+class FormatForComparison {
+ public:
+ static ::std::string Format(const ToPrint& value) {
+ return ::testing::PrintToString(value);
+ }
+};
+
+// Array.
+template <typename ToPrint, size_t N, typename OtherOperand>
+class FormatForComparison<ToPrint[N], OtherOperand> {
+ public:
+ static ::std::string Format(const ToPrint* value) {
+ return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
+ }
+};
+
+// By default, print C string as pointers to be safe, as we don't know
+// whether they actually point to a NUL-terminated string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \
+ template <typename OtherOperand> \
+ class FormatForComparison<CharType*, OtherOperand> { \
+ public: \
+ static ::std::string Format(CharType* value) { \
+ return ::testing::PrintToString(static_cast<const void*>(value)); \
+ } \
+ }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_
+
+// If a C string is compared with an STL string object, we know it's meant
+// to point to a NUL-terminated string, and thus can print it as a string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
+ template <> \
+ class FormatForComparison<CharType*, OtherStringType> { \
+ public: \
+ static ::std::string Format(CharType* value) { \
+ return ::testing::PrintToString(value); \
+ } \
+ }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
+
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string);
+#endif
+
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring);
+#endif
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
+#endif
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_
+
+// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
+// operand to be used in a failure message. The type (but not value)
+// of the other operand may affect the format. This allows us to
+// print a char* as a raw pointer when it is compared against another
+// char* or void*, and print it as a C string when it is compared
+// against an std::string object, for example.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+std::string FormatForComparisonFailureMessage(
+ const T1& value, const T2& /* other_operand */) {
+ return FormatForComparison<T1, T2>::Format(value);
+}
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* expected_expression,
+ const char* actual_expression,
+ const T1& expected,
+ const T2& actual) {
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4389) // Temporarily disables warning on
+ // signed/unsigned mismatch.
+#endif
+
+ if (expected == actual) {
+ return AssertionSuccess();
+ }
+
+#ifdef _MSC_VER
+# pragma warning(pop) // Restores the warning state.
+#endif
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ FormatForComparisonFailureMessage(expected, actual),
+ FormatForComparisonFailureMessage(actual, expected),
+ false);
+}
+
+// With this overloaded version, we allow anonymous enums to be used
+// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
+// can be implicitly cast to BiggestInt.
+GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression,
+ const char* actual_expression,
+ BiggestInt expected,
+ BiggestInt actual);
+
+// The helper class for {ASSERT|EXPECT}_EQ. The template argument
+// lhs_is_null_literal is true iff the first argument to ASSERT_EQ()
+// is a null pointer literal. The following default implementation is
+// for lhs_is_null_literal being false.
+template <bool lhs_is_null_literal>
+class EqHelper {
+ public:
+ // This templatized version is for the general case.
+ template <typename T1, typename T2>
+ static AssertionResult Compare(const char* expected_expression,
+ const char* actual_expression,
+ const T1& expected,
+ const T2& actual) {
+ return CmpHelperEQ(expected_expression, actual_expression, expected,
+ actual);
+ }
+
+ // With this overloaded version, we allow anonymous enums to be used
+ // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+ // enums can be implicitly cast to BiggestInt.
+ //
+ // Even though its body looks the same as the above version, we
+ // cannot merge the two, as it will make anonymous enums unhappy.
+ static AssertionResult Compare(const char* expected_expression,
+ const char* actual_expression,
+ BiggestInt expected,
+ BiggestInt actual) {
+ return CmpHelperEQ(expected_expression, actual_expression, expected,
+ actual);
+ }
+};
+
+// This specialization is used when the first argument to ASSERT_EQ()
+// is a null pointer literal, like NULL, false, or 0.
+template <>
+class EqHelper<true> {
+ public:
+ // We define two overloaded versions of Compare(). The first
+ // version will be picked when the second argument to ASSERT_EQ() is
+ // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
+ // EXPECT_EQ(false, a_bool).
+ template <typename T1, typename T2>
+ static AssertionResult Compare(
+ const char* expected_expression,
+ const char* actual_expression,
+ const T1& expected,
+ const T2& actual,
+ // The following line prevents this overload from being considered if T2
+ // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr)
+ // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+ // to match the Secret* in the other overload, which would otherwise make
+ // this template match better.
+ typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
+ return CmpHelperEQ(expected_expression, actual_expression, expected,
+ actual);
+ }
+
+ // This version will be picked when the second argument to ASSERT_EQ() is a
+ // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+ template <typename T>
+ static AssertionResult Compare(
+ const char* expected_expression,
+ const char* actual_expression,
+ // We used to have a second template parameter instead of Secret*. That
+ // template parameter would deduce to 'long', making this a better match
+ // than the first overload even without the first overload's EnableIf.
+ // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+ // non-pointer argument" (even a deduced integral argument), so the old
+ // implementation caused warnings in user code.
+ Secret* /* expected (NULL) */,
+ T* actual) {
+ // We already know that 'expected' is a null pointer.
+ return CmpHelperEQ(expected_expression, actual_expression,
+ static_cast<T*>(NULL), actual);
+ }
+};
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste
+// of similar code.
+//
+// For each templatized helper function, we also define an overloaded
+// version for BiggestInt in order to reduce code bloat and allow
+// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
+// with gcc 4.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+template <typename T1, typename T2>\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+ const T1& val1, const T2& val2) {\
+ if (val1 op val2) {\
+ return AssertionSuccess();\
+ } else {\
+ return AssertionFailure() \
+ << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+ << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+ }\
+}\
+GTEST_API_ AssertionResult CmpHelper##op_name(\
+ const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=);
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=);
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, <);
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=);
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, >);
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+ const char* actual_expression,
+ const char* expected,
+ const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+ const char* actual_expression,
+ const char* expected,
+ const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+ const char* s2_expression,
+ const char* s1,
+ const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+ const char* s2_expression,
+ const char* s1,
+ const char* s2);
+
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+ const char* actual_expression,
+ const wchar_t* expected,
+ const wchar_t* actual);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+ const char* s2_expression,
+ const wchar_t* s1,
+ const wchar_t* s2);
+
+} // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves. They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::string& needle, const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::string& needle, const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::wstring& needle, const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::wstring& needle, const ::std::wstring& haystack);
+#endif // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+// RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
+ const char* actual_expression,
+ RawType expected,
+ RawType actual) {
+ const FloatingPoint<RawType> lhs(expected), rhs(actual);
+
+ if (lhs.AlmostEquals(rhs)) {
+ return AssertionSuccess();
+ }
+
+ ::std::stringstream expected_ss;
+ expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+ << expected;
+
+ ::std::stringstream actual_ss;
+ actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+ << actual;
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ StringStreamToString(&expected_ss),
+ StringStreamToString(&actual_ss),
+ false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+ const char* expr2,
+ const char* abs_error_expr,
+ double val1,
+ double val2,
+ double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+ // Constructor.
+ AssertHelper(TestPartResult::Type type,
+ const char* file,
+ int line,
+ const char* message);
+ ~AssertHelper();
+
+ // Message assignment is a semantic trick to enable assertion
+ // streaming; see the GTEST_MESSAGE_ macro below.
+ void operator=(const Message& message) const;
+
+ private:
+ // We put our data in a struct so that the size of the AssertHelper class can
+ // be as small as possible. This is important because gcc is incapable of
+ // re-using stack space even for temporary variables, so every EXPECT_EQ
+ // reserves stack space for another AssertHelper.
+ struct AssertHelperData {
+ AssertHelperData(TestPartResult::Type t,
+ const char* srcfile,
+ int line_num,
+ const char* msg)
+ : type(t), file(srcfile), line(line_num), message(msg) { }
+
+ TestPartResult::Type const type;
+ const char* const file;
+ int const line;
+ std::string const message;
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+ };
+
+ AssertHelperData* const data_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
+};
+
+} // namespace internal
+
+#if GTEST_HAS_PARAM_TEST
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
+//
+// This interface has support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), and Combine().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+// protected:
+// FooTest() {
+// // Can use GetParam() here.
+// }
+// virtual ~FooTest() {
+// // Can use GetParam() here.
+// }
+// virtual void SetUp() {
+// // Can use GetParam() here.
+// }
+// virtual void TearDown {
+// // Can use GetParam() here.
+// }
+// };
+// TEST_P(FooTest, DoesBar) {
+// // Can use GetParam() method here.
+// Foo foo;
+// ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class WithParamInterface {
+ public:
+ typedef T ParamType;
+ virtual ~WithParamInterface() {}
+
+ // The current parameter value. Is also available in the test fixture's
+ // constructor. This member function is non-static, even though it only
+ // references static data, to reduce the opportunity for incorrect uses
+ // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+ // uses a fixture whose parameter type is int.
+ const ParamType& GetParam() const {
+ GTEST_CHECK_(parameter_ != NULL)
+ << "GetParam() can only be called inside a value-parameterized test "
+ << "-- did you intend to write TEST_P instead of TEST_F?";
+ return *parameter_;
+ }
+
+ private:
+ // Sets parameter value. The caller is responsible for making sure the value
+ // remains alive and unchanged throughout the current test.
+ static void SetParam(const ParamType* parameter) {
+ parameter_ = parameter;
+ }
+
+ // Static value used for accessing parameter during a test lifetime.
+ static const ParamType* parameter_;
+
+ // TestClass must be a subclass of WithParamInterface<T> and Test.
+ template <class TestClass> friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
+
+#endif // GTEST_HAS_PARAM_TEST
+
+// Macros for indicating success/failure in test code.
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied. If not,
+// it behaves like ADD_FAILURE. In particular:
+//
+// EXPECT_TRUE verifies that a Boolean condition is true.
+// EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure. People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+ GTEST_MESSAGE_AT_(file, line, "Failed", \
+ ::testing::TestPartResult::kNonFatalFailure)
+
+// Generates a fatal failure with a generic message.
+#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
+
+// Define this macro to 1 to omit the definition of FAIL(), which is a
+// generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_FAIL
+# define FAIL() GTEST_FAIL()
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// Define this macro to 1 to omit the definition of SUCCEED(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_SUCCEED
+# define SUCCEED() GTEST_SUCCEED()
+#endif
+
+// Macros for testing exceptions.
+//
+// * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+// Tests that the statement throws the expected exception.
+// * {ASSERT|EXPECT}_NO_THROW(statement):
+// Tests that the statement doesn't throw any exception.
+// * {ASSERT|EXPECT}_ANY_THROW(statement):
+// Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+ GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+ GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+ GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+ GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+ GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+ GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// Boolean assertions. Condition can be either a Boolean expression or an
+// AssertionResult. For more information on how to use AssertionResult with
+// these macros see comments on that class.
+#define EXPECT_TRUE(condition) \
+ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+ GTEST_NONFATAL_FAILURE_)
+#define EXPECT_FALSE(condition) \
+ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+ GTEST_NONFATAL_FAILURE_)
+#define ASSERT_TRUE(condition) \
+ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+ GTEST_FATAL_FAILURE_)
+#define ASSERT_FALSE(condition) \
+ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+ GTEST_FATAL_FAILURE_)
+
+// Includes the auto-generated header that implements a family of
+// generic predicate assertion macros.
+#include "gtest/gtest_pred_impl.h"
+
+// Macros for testing equalities and inequalities.
+//
+// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
+// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2
+// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2
+// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2
+// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2
+// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values. The values must be compatible built-in types,
+// or you will get a compiler error. By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+// 1. It is possible to make a user-defined type work with
+// {ASSERT|EXPECT}_??(), but that requires overloading the
+// comparison operators and is thus discouraged by the Google C++
+// Usage Guide. Therefore, you are advised to use the
+// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+// equal.
+//
+// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+// pointers (in particular, C strings). Therefore, if you use it
+// with two C strings, you are testing how their locations in memory
+// are related, not how their content is related. To compare two C
+// strings by content, use {ASSERT|EXPECT}_STR*().
+//
+// 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to
+// {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you
+// what the actual value is when it fails, and similarly for the
+// other comparisons.
+//
+// 4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+// evaluate their arguments, which is undefined.
+//
+// 5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+// EXPECT_NE(5, Foo());
+// EXPECT_EQ(NULL, a_pointer);
+// ASSERT_LT(i, array_size);
+// ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(::testing::internal:: \
+ EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+ expected, actual)
+#define EXPECT_NE(expected, actual) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual)
+#define EXPECT_LE(val1, val2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define GTEST_ASSERT_EQ(expected, actual) \
+ ASSERT_PRED_FORMAT2(::testing::internal:: \
+ EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+ expected, actual)
+#define GTEST_ASSERT_NE(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define GTEST_ASSERT_LE(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define GTEST_ASSERT_LT(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define GTEST_ASSERT_GE(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define GTEST_ASSERT_GT(val1, val2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
+// C-string Comparisons. All tests treat NULL and any non-NULL string
+// as different. Two NULLs are equal.
+//
+// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2
+// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2
+// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define EXPECT_STRNE(s1, s2) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define EXPECT_STRCASENE(s1, s2)\
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(expected, actual) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define ASSERT_STRNE(s1, s2) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(expected, actual) \
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define ASSERT_STRCASENE(s1, s2)\
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual):
+// Tests that two float values are almost equal.
+// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual):
+// Tests that two double values are almost equal.
+// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+// Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands. See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(expected, actual)\
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+ expected, actual)
+
+#define EXPECT_DOUBLE_EQ(expected, actual)\
+ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+ expected, actual)
+
+#define ASSERT_FLOAT_EQ(expected, actual)\
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+ expected, actual)
+
+#define ASSERT_DOUBLE_EQ(expected, actual)\
+ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+ expected, actual)
+
+#define EXPECT_NEAR(val1, val2, abs_error)\
+ EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+ val1, val2, abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)\
+ ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+ val1, val2, abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2. Fails
+// otherwise. In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+ float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+ double val1, double val2);
+
+
+#if GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// expected result and the actual result with both a human-readable
+// string representation of the error, if available, as well as the
+// hex result code.
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
+ EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
+ ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define EXPECT_HRESULT_FAILED(expr) \
+ EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+# define ASSERT_HRESULT_FAILED(expr) \
+ ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+// EXPECT_NO_FATAL_FAILURE(Process());
+// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+ GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+ GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope. The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+#define SCOPED_TRACE(message) \
+ ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
+ __FILE__, __LINE__, ::testing::Message() << (message))
+
+// Compile-time assertion for type equality.
+// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
+// the same type. The value it returns is not interesting.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template. This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated. For example, given:
+//
+// template <typename T> class Foo {
+// public:
+// void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+// };
+//
+// the code:
+//
+// void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated. Instead, you need:
+//
+// void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+bool StaticAssertTypeEq() {
+ (void)internal::StaticAssertTypeEqHelper<T1, T2>();
+ return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test case, and the second
+// parameter is the name of the test within the test case.
+//
+// The convention is to end the test case name with "Test". For
+// example, a test case for the Foo class can be named FooTest.
+//
+// The user should put his test code between braces after using this
+// macro. Example:
+//
+// TEST(FooTest, InitializesCorrectly) {
+// Foo foo;
+// EXPECT_TRUE(foo.StatusIsOK());
+// }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test. This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X. The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code. GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_case_name, test_name)\
+ GTEST_TEST_(test_case_name, test_name, \
+ ::testing::Test, ::testing::internal::GetTestTypeId())
+
+// Define this macro to 1 to omit the definition of TEST(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_TEST
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name. The second parameter is the
+// name of the test within the test case.
+//
+// A test fixture class must be declared earlier. The user should put
+// his test code between braces after using this macro. Example:
+//
+// class FooTest : public testing::Test {
+// protected:
+// virtual void SetUp() { b_.AddElement(3); }
+//
+// Foo a_;
+// Foo b_;
+// };
+//
+// TEST_F(FooTest, InitializesCorrectly) {
+// EXPECT_TRUE(a_.StatusIsOK());
+// }
+//
+// TEST_F(FooTest, ReturnsElementCountCorrectly) {
+// EXPECT_EQ(0, a_.size());
+// EXPECT_EQ(1, b_.size());
+// }
+
+#define TEST_F(test_fixture, test_name)\
+ GTEST_TEST_(test_fixture, test_name, test_fixture, \
+ ::testing::internal::GetTypeId<test_fixture>())
+
+} // namespace testing
+
+// Use this function in main() to run all tests. It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest().
+//
+// This function was formerly a macro; thus, it is in the global
+// namespace and has an all-caps name.
+int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
+
+inline int RUN_ALL_TESTS() {
+ return ::testing::UnitTest::GetInstance()->Run();
+}
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_H_
diff --git a/thirdparty/gtest/include/gtest/gtest_pred_impl.h b/thirdparty/gtest/include/gtest/gtest_pred_impl.h
new file mode 100644
index 00000000..30ae712f
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest_pred_impl.h
@@ -0,0 +1,358 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command
+// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Makes sure this header is not included before gtest.h.
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+# error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
+#endif // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+// ASSERT_PRED_FORMAT1(pred_format, v1)
+// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+// ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult. See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+// ASSERT_PRED1(pred, v1)
+// ASSERT_PRED2(pred, v1, v2)
+// ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce. Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const ::testing::AssertionResult gtest_ar = (expression)) \
+ ; \
+ else \
+ on_failure(gtest_ar.failure_message())
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text,
+ const char* e1,
+ Pred pred,
+ const T1& v1) {
+ if (pred(v1)) return AssertionSuccess();
+
+ return AssertionFailure() << pred_text << "("
+ << e1 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, v1), \
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
+ #v1, \
+ pred, \
+ v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+ GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) \
+ GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+ GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) \
+ GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1,
+ typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text,
+ const char* e1,
+ const char* e2,
+ Pred pred,
+ const T1& v1,
+ const T2& v2) {
+ if (pred(v1, v2)) return AssertionSuccess();
+
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
+ #v1, \
+ #v2, \
+ pred, \
+ v1, \
+ v2), on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+ GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+ GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+ GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+ GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1,
+ typename T2,
+ typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text,
+ const char* e1,
+ const char* e2,
+ const char* e3,
+ Pred pred,
+ const T1& v1,
+ const T2& v2,
+ const T3& v3) {
+ if (pred(v1, v2, v3)) return AssertionSuccess();
+
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
+ #v1, \
+ #v2, \
+ #v3, \
+ pred, \
+ v1, \
+ v2, \
+ v3), on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+ GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+ GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+ GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+ GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1,
+ typename T2,
+ typename T3,
+ typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text,
+ const char* e1,
+ const char* e2,
+ const char* e3,
+ const char* e4,
+ Pred pred,
+ const T1& v1,
+ const T2& v2,
+ const T3& v3,
+ const T4& v4) {
+ if (pred(v1, v2, v3, v4)) return AssertionSuccess();
+
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ", "
+ << e4 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3
+ << "\n" << e4 << " evaluates to " << v4;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
+ #v1, \
+ #v2, \
+ #v3, \
+ #v4, \
+ pred, \
+ v1, \
+ v2, \
+ v3, \
+ v4), on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+ GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+ GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+ GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+ GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
+// this in your code.
+template <typename Pred,
+ typename T1,
+ typename T2,
+ typename T3,
+ typename T4,
+ typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text,
+ const char* e1,
+ const char* e2,
+ const char* e3,
+ const char* e4,
+ const char* e5,
+ Pred pred,
+ const T1& v1,
+ const T2& v2,
+ const T3& v3,
+ const T4& v4,
+ const T5& v5) {
+ if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
+
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ", "
+ << e4 << ", "
+ << e5 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3
+ << "\n" << e4 << " evaluates to " << v4
+ << "\n" << e5 << " evaluates to " << v5;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
+ GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
+ on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
+ GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
+ #v1, \
+ #v2, \
+ #v3, \
+ #v4, \
+ #v5, \
+ pred, \
+ v1, \
+ v2, \
+ v3, \
+ v4, \
+ v5), on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+ GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+ GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+ GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+ GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
diff --git a/thirdparty/gtest/include/gtest/gtest_prod.h b/thirdparty/gtest/include/gtest/gtest_prod.h
new file mode 100644
index 00000000..da80ddc6
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/gtest_prod.h
@@ -0,0 +1,58 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Testing Framework definitions useful in production code.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class. For example:
+//
+// class MyClass {
+// private:
+// void MyMethod();
+// FRIEND_TEST(MyClassTest, MyMethod);
+// };
+//
+// class MyClassTest : public testing::Test {
+// // ...
+// };
+//
+// TEST_F(MyClassTest, MyMethod) {
+// // Can call MyClass::MyMethod() here.
+// }
+
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-death-test-internal.h b/thirdparty/gtest/include/gtest/internal/gtest-death-test-internal.h
new file mode 100644
index 00000000..2b3a78f5
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-death-test-internal.h
@@ -0,0 +1,319 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests. They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-internal.h"
+
+#include <stdio.h>
+
+namespace testing {
+namespace internal {
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kDeathTestStyleFlag[] = "death_test_style";
+const char kDeathTestUseFork[] = "death_test_use_fork";
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+#if GTEST_HAS_DEATH_TEST
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status: The integer exit information in the format specified
+// by wait(2)
+// exit code: The integer code passed to exit(3), _exit(2), or
+// returned from main()
+class GTEST_API_ DeathTest {
+ public:
+ // Create returns false if there was an error determining the
+ // appropriate action to take for the current death test; for example,
+ // if the gtest_death_test_style flag is set to an invalid value.
+ // The LastMessage method will return a more detailed message in that
+ // case. Otherwise, the DeathTest pointer pointed to by the "test"
+ // argument is set. If the death test should be skipped, the pointer
+ // is set to NULL; otherwise, it is set to the address of a new concrete
+ // DeathTest object that controls the execution of the current test.
+ static bool Create(const char* statement, const RE* regex,
+ const char* file, int line, DeathTest** test);
+ DeathTest();
+ virtual ~DeathTest() { }
+
+ // A helper class that aborts a death test when it's deleted.
+ class ReturnSentinel {
+ public:
+ explicit ReturnSentinel(DeathTest* test) : test_(test) { }
+ ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+ private:
+ DeathTest* const test_;
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
+ } GTEST_ATTRIBUTE_UNUSED_;
+
+ // An enumeration of possible roles that may be taken when a death
+ // test is encountered. EXECUTE means that the death test logic should
+ // be executed immediately. OVERSEE means that the program should prepare
+ // the appropriate environment for a child process to execute the death
+ // test, then wait for it to complete.
+ enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
+
+ // An enumeration of the three reasons that a test might be aborted.
+ enum AbortReason {
+ TEST_ENCOUNTERED_RETURN_STATEMENT,
+ TEST_THREW_EXCEPTION,
+ TEST_DID_NOT_DIE
+ };
+
+ // Assumes one of the above roles.
+ virtual TestRole AssumeRole() = 0;
+
+ // Waits for the death test to finish and returns its status.
+ virtual int Wait() = 0;
+
+ // Returns true if the death test passed; that is, the test process
+ // exited during the test, its exit status matches a user-supplied
+ // predicate, and its stderr output matches a user-supplied regular
+ // expression.
+ // The user-supplied predicate may be a macro expression rather
+ // than a function pointer or functor, or else Wait and Passed could
+ // be combined.
+ virtual bool Passed(bool exit_status_ok) = 0;
+
+ // Signals that the death test did not die as expected.
+ virtual void Abort(AbortReason reason) = 0;
+
+ // Returns a human-readable outcome message regarding the outcome of
+ // the last death test.
+ static const char* LastMessage();
+
+ static void set_last_death_test_message(const std::string& message);
+
+ private:
+ // A string containing a description of the outcome of the last death test.
+ static std::string last_death_test_message_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
+};
+
+// Factory interface for death tests. May be mocked out for testing.
+class DeathTestFactory {
+ public:
+ virtual ~DeathTestFactory() { }
+ virtual bool Create(const char* statement, const RE* regex,
+ const char* file, int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+ virtual bool Create(const char* statement, const RE* regex,
+ const char* file, int line, DeathTest** test);
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } catch (const ::std::exception& gtest_exception) { \
+ fprintf(\
+ stderr, \
+ "\n%s: Caught std::exception-derived exception escaping the " \
+ "death test statement. Exception message: %s\n", \
+ ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+ gtest_exception.what()); \
+ fflush(stderr); \
+ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+ } catch (...) { \
+ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+ }
+
+# else
+# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::AlwaysTrue()) { \
+ const ::testing::internal::RE& gtest_regex = (regex); \
+ ::testing::internal::DeathTest* gtest_dt; \
+ if (!::testing::internal::DeathTest::Create(#statement, &gtest_regex, \
+ __FILE__, __LINE__, &gtest_dt)) { \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+ } \
+ if (gtest_dt != NULL) { \
+ ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
+ gtest_dt_ptr(gtest_dt); \
+ switch (gtest_dt->AssumeRole()) { \
+ case ::testing::internal::DeathTest::OVERSEE_TEST: \
+ if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+ } \
+ break; \
+ case ::testing::internal::DeathTest::EXECUTE_TEST: { \
+ ::testing::internal::DeathTest::ReturnSentinel \
+ gtest_sentinel(gtest_dt); \
+ GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
+ gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
+ break; \
+ } \
+ default: \
+ break; \
+ } \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
+ fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
+// NDEBUG mode. In this case we need the statements to be executed, the regex is
+// ignored, and the macro must accept a streamed message even though the message
+// is never printed.
+# define GTEST_EXECUTE_STATEMENT_(statement, regex) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::AlwaysTrue()) { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } else \
+ ::testing::Message()
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+ InternalRunDeathTestFlag(const std::string& a_file,
+ int a_line,
+ int an_index,
+ int a_write_fd)
+ : file_(a_file), line_(a_line), index_(an_index),
+ write_fd_(a_write_fd) {}
+
+ ~InternalRunDeathTestFlag() {
+ if (write_fd_ >= 0)
+ posix::Close(write_fd_);
+ }
+
+ const std::string& file() const { return file_; }
+ int line() const { return line_; }
+ int index() const { return index_; }
+ int write_fd() const { return write_fd_; }
+
+ private:
+ std::string file_;
+ int line_;
+ int index_;
+ int write_fd_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#else // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
+// systems that support death tests. This allows one to write such a macro
+// on a system that does not support death tests and be sure that it will
+// compile on a death-test supporting system.
+//
+// Parameters:
+// statement - A statement that a macro such as EXPECT_DEATH would test
+// for program termination. This macro has to make sure this
+// statement is compiled but not executed, to ensure that
+// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+// parameter iff EXPECT_DEATH compiles with it.
+// regex - A regex that a macro such as EXPECT_DEATH would use to test
+// the output of statement. This parameter has to be
+// compiled but not evaluated by this macro, to ensure that
+// this macro only accepts expressions that a macro such as
+// EXPECT_DEATH would accept.
+// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+// compile inside functions where ASSERT_DEATH doesn't
+// compile.
+//
+// The branch that has an always false condition is used to ensure that
+// statement and regex are compiled (and thus syntactically correct) but
+// never executed. The unreachable code macro protects the terminator
+// statement from generating an 'unreachable code' warning in case
+// statement unconditionally returns or throws. The Message constructor at
+// the end allows the syntax of streaming additional messages into the
+// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::AlwaysTrue()) { \
+ GTEST_LOG_(WARNING) \
+ << "Death tests are not supported on this platform.\n" \
+ << "Statement '" #statement "' cannot be verified."; \
+ } else if (::testing::internal::AlwaysFalse()) { \
+ ::testing::internal::RE::PartialMatch(".*", (regex)); \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ terminator; \
+ } else \
+ ::testing::Message()
+
+#endif // GTEST_HAS_DEATH_TEST
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-filepath.h b/thirdparty/gtest/include/gtest/internal/gtest-filepath.h
new file mode 100644
index 00000000..7a13b4b0
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-filepath.h
@@ -0,0 +1,206 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test. They are subject to change without notice.
+//
+// This file is #included in <gtest/internal/gtest-internal.h>.
+// Do not include this header file separately!
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+ FilePath() : pathname_("") { }
+ FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
+
+ explicit FilePath(const std::string& pathname) : pathname_(pathname) {
+ Normalize();
+ }
+
+ FilePath& operator=(const FilePath& rhs) {
+ Set(rhs);
+ return *this;
+ }
+
+ void Set(const FilePath& rhs) {
+ pathname_ = rhs.pathname_;
+ }
+
+ const std::string& string() const { return pathname_; }
+ const char* c_str() const { return pathname_.c_str(); }
+
+ // Returns the current working directory, or "" if unsuccessful.
+ static FilePath GetCurrentDir();
+
+ // Given directory = "dir", base_name = "test", number = 0,
+ // extension = "xml", returns "dir/test.xml". If number is greater
+ // than zero (e.g., 12), returns "dir/test_12.xml".
+ // On Windows platform, uses \ as the separator rather than /.
+ static FilePath MakeFileName(const FilePath& directory,
+ const FilePath& base_name,
+ int number,
+ const char* extension);
+
+ // Given directory = "dir", relative_path = "test.xml",
+ // returns "dir/test.xml".
+ // On Windows, uses \ as the separator rather than /.
+ static FilePath ConcatPaths(const FilePath& directory,
+ const FilePath& relative_path);
+
+ // Returns a pathname for a file that does not currently exist. The pathname
+ // will be directory/base_name.extension or
+ // directory/base_name_<number>.extension if directory/base_name.extension
+ // already exists. The number will be incremented until a pathname is found
+ // that does not already exist.
+ // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+ // There could be a race condition if two or more processes are calling this
+ // function at the same time -- they could both pick the same filename.
+ static FilePath GenerateUniqueFileName(const FilePath& directory,
+ const FilePath& base_name,
+ const char* extension);
+
+ // Returns true iff the path is "".
+ bool IsEmpty() const { return pathname_.empty(); }
+
+ // If input name has a trailing separator character, removes it and returns
+ // the name, otherwise return the name string unmodified.
+ // On Windows platform, uses \ as the separator, other platforms use /.
+ FilePath RemoveTrailingPathSeparator() const;
+
+ // Returns a copy of the FilePath with the directory part removed.
+ // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+ // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+ // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+ // returns an empty FilePath ("").
+ // On Windows platform, '\' is the path separator, otherwise it is '/'.
+ FilePath RemoveDirectoryName() const;
+
+ // RemoveFileName returns the directory path with the filename removed.
+ // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+ // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+ // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+ // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+ // On Windows platform, '\' is the path separator, otherwise it is '/'.
+ FilePath RemoveFileName() const;
+
+ // Returns a copy of the FilePath with the case-insensitive extension removed.
+ // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+ // FilePath("dir/file"). If a case-insensitive extension is not
+ // found, returns a copy of the original FilePath.
+ FilePath RemoveExtension(const char* extension) const;
+
+ // Creates directories so that path exists. Returns true if successful or if
+ // the directories already exist; returns false if unable to create
+ // directories for any reason. Will also return false if the FilePath does
+ // not represent a directory (that is, it doesn't end with a path separator).
+ bool CreateDirectoriesRecursively() const;
+
+ // Create the directory so that path exists. Returns true if successful or
+ // if the directory already exists; returns false if unable to create the
+ // directory for any reason, including if the parent directory does not
+ // exist. Not named "CreateDirectory" because that's a macro on Windows.
+ bool CreateFolder() const;
+
+ // Returns true if FilePath describes something in the file-system,
+ // either a file, directory, or whatever, and that something exists.
+ bool FileOrDirectoryExists() const;
+
+ // Returns true if pathname describes a directory in the file-system
+ // that exists.
+ bool DirectoryExists() const;
+
+ // Returns true if FilePath ends with a path separator, which indicates that
+ // it is intended to represent a directory. Returns false otherwise.
+ // This does NOT check that a directory (or file) actually exists.
+ bool IsDirectory() const;
+
+ // Returns true if pathname describes a root directory. (Windows has one
+ // root directory per disk drive.)
+ bool IsRootDirectory() const;
+
+ // Returns true if pathname describes an absolute path.
+ bool IsAbsolutePath() const;
+
+ private:
+ // Replaces multiple consecutive separators with a single separator.
+ // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+ // redundancies that might be in a pathname involving "." or "..".
+ //
+ // A pathname with multiple consecutive separators may occur either through
+ // user error or as a result of some scripts or APIs that generate a pathname
+ // with a trailing separator. On other platforms the same API or script
+ // may NOT generate a pathname with a trailing "/". Then elsewhere that
+ // pathname may have another "/" and pathname components added to it,
+ // without checking for the separator already being there.
+ // The script language and operating system may allow paths like "foo//bar"
+ // but some of the functions in FilePath will not handle that correctly. In
+ // particular, RemoveTrailingPathSeparator() only removes one separator, and
+ // it is called in CreateDirectoriesRecursively() assuming that it will change
+ // a pathname from directory syntax (trailing separator) to filename syntax.
+ //
+ // On Windows this method also replaces the alternate path separator '/' with
+ // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+ // "bar\\foo".
+
+ void Normalize();
+
+ // Returns a pointer to the last occurence of a valid path separator in
+ // the FilePath. On Windows, for example, both '/' and '\' are valid path
+ // separators. Returns NULL if no path separator was found.
+ const char* FindLastPathSeparator() const;
+
+ std::string pathname_;
+}; // class FilePath
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-internal.h b/thirdparty/gtest/include/gtest/internal/gtest-internal.h
new file mode 100644
index 00000000..0dcc3a31
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-internal.h
@@ -0,0 +1,1158 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test. They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_OS_LINUX
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+#endif // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#include <ctype.h>
+#include <float.h>
+#include <string.h>
+#include <iomanip>
+#include <limits>
+#include <set>
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__. Writing
+//
+// foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number. For more details, see
+// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
+
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
+namespace testing {
+
+// Forward declarations.
+
+class AssertionResult; // Result of an assertion.
+class Message; // Represents a failure message.
+class Test; // Represents a test.
+class TestInfo; // Information about a test.
+class TestPartResult; // Result of a test part.
+class UnitTest; // A collection of test cases.
+
+template <typename T>
+::std::string PrintToString(const T& value);
+
+namespace internal {
+
+struct TraceInfo; // Information about a trace point.
+class ScopedTrace; // Implements scoped trace.
+class TestInfoImpl; // Opaque implementation of TestInfo
+class UnitTestImpl; // Opaque implementation of UnitTest
+
+// How many times InitGoogleTest() has been called.
+GTEST_API_ extern int g_init_gtest_count;
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// Two overloaded helpers for checking at compile time whether an
+// expression is a null pointer literal (i.e. NULL or any 0-valued
+// compile-time integral constant). Their return values have
+// different sizes, so we can use sizeof() to test which version is
+// picked by the compiler. These helpers have no implementations, as
+// we only need their signatures.
+//
+// Given IsNullLiteralHelper(x), the compiler will pick the first
+// version if x can be implicitly converted to Secret*, and pick the
+// second version otherwise. Since Secret is a secret and incomplete
+// type, the only expression a user can write that has type Secret* is
+// a null pointer literal. Therefore, we know that x is a null
+// pointer literal if and only if the first version is picked by the
+// compiler.
+char IsNullLiteralHelper(Secret* p);
+char (&IsNullLiteralHelper(...))[2]; // NOLINT
+
+// A compile-time bool constant that is true if and only if x is a
+// null pointer literal (i.e. NULL or any 0-valued compile-time
+// integral constant).
+#ifdef GTEST_ELLIPSIS_NEEDS_POD_
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_IS_NULL_LITERAL_(x) false
+#else
+# define GTEST_IS_NULL_LITERAL_(x) \
+ (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
+#endif // GTEST_ELLIPSIS_NEEDS_POD_
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ std::string AppendUserMessage(
+ const std::string& gtest_msg, const Message& user_msg);
+
+#if GTEST_HAS_EXCEPTIONS
+
+// This exception is thrown by (and only by) a failed Google Test
+// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
+// are enabled). We derive it from std::runtime_error, which is for
+// errors presumably detectable only at run time. Since
+// std::runtime_error inherits from std::exception, many testing
+// frameworks know how to extract and print the message inside it.
+class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
+ public:
+ explicit GoogleTestFailureException(const TestPartResult& failure);
+};
+
+#endif // GTEST_HAS_EXCEPTIONS
+
+// A helper class for creating scoped traces in user programs.
+class GTEST_API_ ScopedTrace {
+ public:
+ // The c'tor pushes the given source file location and message onto
+ // a trace stack maintained by Google Test.
+ ScopedTrace(const char* file, int line, const Message& message);
+
+ // The d'tor pops the info pushed by the c'tor.
+ //
+ // Note that the d'tor is not virtual in order to be efficient.
+ // Don't inherit from ScopedTrace!
+ ~ScopedTrace();
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
+} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its
+ // c'tor and d'tor. Therefore it doesn't
+ // need to be used otherwise.
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings. For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+// expected_expression: "foo"
+// actual_expression: "bar"
+// expected_value: "5"
+// actual_value: "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+ const char* actual_expression,
+ const std::string& expected_value,
+ const std::string& actual_value,
+ bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ std::string GetBoolAssertionFailureMessage(
+ const AssertionResult& assertion_result,
+ const char* expression_text,
+ const char* actual_predicate_value,
+ const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison. (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly. Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+// The most-significant bit being the leftmost, an IEEE
+// floating-point looks like
+//
+// sign_bit exponent_bits fraction_bits
+//
+// Here, sign_bit is a single bit that designates the sign of the
+// number.
+//
+// For float, there are 8 exponent bits and 23 fraction bits.
+//
+// For double, there are 11 exponent bits and 52 fraction bits.
+//
+// More details can be found at
+// http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+// RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+ // Defines the unsigned integer type that has the same size as the
+ // floating point number.
+ typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+ // Constants.
+
+ // # of bits in a number.
+ static const size_t kBitCount = 8*sizeof(RawType);
+
+ // # of fraction bits in a number.
+ static const size_t kFractionBitCount =
+ std::numeric_limits<RawType>::digits - 1;
+
+ // # of exponent bits in a number.
+ static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+ // The mask for the sign bit.
+ static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+ // The mask for the fraction bits.
+ static const Bits kFractionBitMask =
+ ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+ // The mask for the exponent bits.
+ static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+ // How many ULP's (Units in the Last Place) we want to tolerate when
+ // comparing two numbers. The larger the value, the more error we
+ // allow. A 0 value means that two numbers must be exactly the same
+ // to be considered equal.
+ //
+ // The maximum error of a single floating-point operation is 0.5
+ // units in the last place. On Intel CPU's, all floating-point
+ // calculations are done with 80-bit precision, while double has 64
+ // bits. Therefore, 4 should be enough for ordinary use.
+ //
+ // See the following article for more details on ULP:
+ // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
+ static const size_t kMaxUlps = 4;
+
+ // Constructs a FloatingPoint from a raw floating-point number.
+ //
+ // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+ // around may change its bits, although the new value is guaranteed
+ // to be also a NAN. Therefore, don't expect this constructor to
+ // preserve the bits in x when x is a NAN.
+ explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+ // Static methods
+
+ // Reinterprets a bit pattern as a floating-point number.
+ //
+ // This function is needed to test the AlmostEquals() method.
+ static RawType ReinterpretBits(const Bits bits) {
+ FloatingPoint fp(0);
+ fp.u_.bits_ = bits;
+ return fp.u_.value_;
+ }
+
+ // Returns the floating-point number that represent positive infinity.
+ static RawType Infinity() {
+ return ReinterpretBits(kExponentBitMask);
+ }
+
+ // Returns the maximum representable finite floating-point number.
+ static RawType Max();
+
+ // Non-static methods
+
+ // Returns the bits that represents this number.
+ const Bits &bits() const { return u_.bits_; }
+
+ // Returns the exponent bits of this number.
+ Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+ // Returns the fraction bits of this number.
+ Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+ // Returns the sign bit of this number.
+ Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+ // Returns true iff this is NAN (not a number).
+ bool is_nan() const {
+ // It's a NAN if the exponent bits are all ones and the fraction
+ // bits are not entirely zeros.
+ return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+ }
+
+ // Returns true iff this number is at most kMaxUlps ULP's away from
+ // rhs. In particular, this function:
+ //
+ // - returns false if either number is (or both are) NAN.
+ // - treats really large numbers as almost equal to infinity.
+ // - thinks +0.0 and -0.0 are 0 DLP's apart.
+ bool AlmostEquals(const FloatingPoint& rhs) const {
+ // The IEEE standard says that any comparison operation involving
+ // a NAN must return false.
+ if (is_nan() || rhs.is_nan()) return false;
+
+ return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+ <= kMaxUlps;
+ }
+
+ private:
+ // The data type used to store the actual floating-point number.
+ union FloatingPointUnion {
+ RawType value_; // The raw floating-point number.
+ Bits bits_; // The bits that represent the number.
+ };
+
+ // Converts an integer from the sign-and-magnitude representation to
+ // the biased representation. More precisely, let N be 2 to the
+ // power of (kBitCount - 1), an integer x is represented by the
+ // unsigned number x + N.
+ //
+ // For instance,
+ //
+ // -N + 1 (the most negative number representable using
+ // sign-and-magnitude) is represented by 1;
+ // 0 is represented by N; and
+ // N - 1 (the biggest number representable using
+ // sign-and-magnitude) is represented by 2N - 1.
+ //
+ // Read http://en.wikipedia.org/wiki/Signed_number_representations
+ // for more details on signed number representations.
+ static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+ if (kSignBitMask & sam) {
+ // sam represents a negative number.
+ return ~sam + 1;
+ } else {
+ // sam represents a positive number.
+ return kSignBitMask | sam;
+ }
+ }
+
+ // Given two numbers in the sign-and-magnitude representation,
+ // returns the distance between them as an unsigned number.
+ static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+ const Bits &sam2) {
+ const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+ const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+ return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+ }
+
+ FloatingPointUnion u_;
+};
+
+// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
+// macro defined by <windows.h>.
+template <>
+inline float FloatingPoint<float>::Max() { return FLT_MAX; }
+template <>
+inline double FloatingPoint<double>::Max() { return DBL_MAX; }
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test case, we need to assign
+// unique IDs to fixture classes and compare them. The TypeId type is
+// used to hold such IDs. The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+ // dummy_ must not have a const type. Otherwise an overly eager
+ // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+ // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+ static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T. Different values will be
+// returned for different types. Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+ // The compiler is required to allocate a different
+ // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+ // the template. Therefore, the address of dummy_ is guaranteed to
+ // be unique.
+ return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test. Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+ virtual ~TestFactoryBase() {}
+
+ // Creates a test instance to run. The instance is both created and destroyed
+ // within TestInfoImpl::Run()
+ virtual Test* CreateTest() = 0;
+
+ protected:
+ TestFactoryBase() {}
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
+};
+
+// This class provides implementation of TeastFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+ virtual Test* CreateTest() { return new TestClass; }
+};
+
+#if GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+ long hr); // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+ long hr); // NOLINT
+
+#endif // GTEST_OS_WINDOWS
+
+// Types of SetUpTestCase() and TearDownTestCase() functions.
+typedef void (*SetUpTestCaseFunc)();
+typedef void (*TearDownTestCaseFunc)();
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+// test_case_name: name of the test case
+// name: name of the test
+// type_param the name of the test's type parameter, or NULL if
+// this is not a typed or a type-parameterized test.
+// value_param text representation of the test's value parameter,
+// or NULL if this is not a type-parameterized test.
+// fixture_class_id: ID of the test fixture class
+// set_up_tc: pointer to the function that sets up the test case
+// tear_down_tc: pointer to the function that tears down the test case
+// factory: pointer to the factory that creates a test object.
+// The newly created TestInfo instance will assume
+// ownership of the factory object.
+GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
+ const char* test_case_name,
+ const char* name,
+ const char* type_param,
+ const char* value_param,
+ TypeId fixture_class_id,
+ SetUpTestCaseFunc set_up_tc,
+ TearDownTestCaseFunc tear_down_tc,
+ TestFactoryBase* factory);
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false. None of pstr, *pstr, and prefix can be NULL.
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// State of the definition of a type-parameterized test case.
+class GTEST_API_ TypedTestCasePState {
+ public:
+ TypedTestCasePState() : registered_(false) {}
+
+ // Adds the given test name to defined_test_names_ and return true
+ // if the test case hasn't been registered; otherwise aborts the
+ // program.
+ bool AddTestName(const char* file, int line, const char* case_name,
+ const char* test_name) {
+ if (registered_) {
+ fprintf(stderr, "%s Test %s must be defined before "
+ "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
+ FormatFileLocation(file, line).c_str(), test_name, case_name);
+ fflush(stderr);
+ posix::Abort();
+ }
+ defined_test_names_.insert(test_name);
+ return true;
+ }
+
+ // Verifies that registered_tests match the test names in
+ // defined_test_names_; returns registered_tests if successful, or
+ // aborts the program otherwise.
+ const char* VerifyRegisteredTestNames(
+ const char* file, int line, const char* registered_tests);
+
+ private:
+ bool registered_;
+ ::std::set<const char*> defined_test_names_;
+};
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+ const char* comma = strchr(str, ',');
+ if (comma == NULL) {
+ return NULL;
+ }
+ while (IsSpace(*(++comma))) {}
+ return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline std::string GetPrefixUntilComma(const char* str) {
+ const char* comma = strchr(str, ',');
+ return comma == NULL ? str : std::string(str, comma);
+}
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test. The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter. It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+ // 'index' is the index of the test in the type list 'Types'
+ // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
+ // Types). Valid values for 'index' are [0, N - 1] where N is the
+ // length of Types.
+ static bool Register(const char* prefix, const char* case_name,
+ const char* test_names, int index) {
+ typedef typename Types::Head Type;
+ typedef Fixture<Type> FixtureClass;
+ typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+ // First, registers the first type-parameterized test in the type
+ // list.
+ MakeAndRegisterTestInfo(
+ (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/"
+ + StreamableToString(index)).c_str(),
+ GetPrefixUntilComma(test_names).c_str(),
+ GetTypeName<Type>().c_str(),
+ NULL, // No value parameter.
+ GetTypeId<FixtureClass>(),
+ TestClass::SetUpTestCase,
+ TestClass::TearDownTestCase,
+ new TestFactoryImpl<TestClass>);
+
+ // Next, recurses (at compile time) with the tail of the type list.
+ return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
+ ::Register(prefix, case_name, test_names, index + 1);
+ }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, Types0> {
+ public:
+ static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+ const char* /*test_names*/, int /*index*/) {
+ return true;
+ }
+};
+
+// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test. The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestCase {
+ public:
+ static bool Register(const char* prefix, const char* case_name,
+ const char* test_names) {
+ typedef typename Tests::Head Head;
+
+ // First, register the first test in 'Test' for each type in 'Types'.
+ TypeParameterizedTest<Fixture, Head, Types>::Register(
+ prefix, case_name, test_names, 0);
+
+ // Next, recurses (at compile time) with the tail of the test list.
+ return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
+ ::Register(prefix, case_name, SkipComma(test_names));
+ }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestCase<Fixture, Templates0, Types> {
+ public:
+ static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+ const char* /*test_names*/) {
+ return true;
+ }
+};
+
+#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag. The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(
+ UnitTest* unit_test, int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+ ConstCharPtr(const char* str) : value(str) {}
+ operator bool() const { return true; }
+ const char* value;
+};
+
+// A simple Linear Congruential Generator for generating random
+// numbers with a uniform distribution. Unlike rand() and srand(), it
+// doesn't use global state (and therefore can't interfere with user
+// code). Unlike rand_r(), it's portable. An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+ static const UInt32 kMaxRange = 1u << 31;
+
+ explicit Random(UInt32 seed) : state_(seed) {}
+
+ void Reseed(UInt32 seed) { state_ = seed; }
+
+ // Generates a random number from [0, range). Crashes if 'range' is
+ // 0 or greater than kMaxRange.
+ UInt32 Generate(UInt32 range);
+
+ private:
+ UInt32 state_;
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
+};
+
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged. This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; }; // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; }; // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+ typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged. This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; }; // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; }; // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'. The following specialization works around the bug.
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+ typedef typename RemoveConst<T>::type type[N];
+};
+
+#if defined(_MSC_VER) && _MSC_VER < 1400
+// This is the only specialization that allows VC++ 7.1 to remove const in
+// 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC
+// and thus needs to be conditionally compiled.
+template <typename T, size_t N>
+struct RemoveConst<T[N]> {
+ typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+ typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+ GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged. This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; }; // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+ typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary. For example,
+// it transforms
+//
+// char ==> const char&
+// const char ==> const char&
+// char& ==> const char&
+// const char& ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+ GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+ // We need the following helper functions only for their types.
+ // They have no implementations.
+
+ // MakeFrom() is an expression whose type is From. We cannot simply
+ // use From(), as the type From may not have a public default
+ // constructor.
+ static From MakeFrom();
+
+ // These two functions are overloaded. Given an expression
+ // Helper(x), the compiler will pick the first version if x can be
+ // implicitly converted to type To; otherwise it will pick the
+ // second version.
+ //
+ // The first version returns a value of size 1, and the second
+ // version returns a value of size 2. Therefore, by checking the
+ // size of Helper(x), which can be done at compile time, we can tell
+ // which version of Helper() is used, and hence whether x can be
+ // implicitly converted to type To.
+ static char Helper(To);
+ static char (&Helper(...))[2]; // NOLINT
+
+ // We have to put the 'public' section after the 'private' section,
+ // or MSVC refuses to compile the code.
+ public:
+ // MSVC warns about implicitly converting from double to int for
+ // possible loss of data, so we need to temporarily disable the
+ // warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4244) // Temporarily disables warning 4244.
+
+ static const bool value =
+ sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+# pragma warning(pop) // Restores the warning state.
+#elif defined(__BORLANDC__)
+ // C++Builder cannot use member overload resolution during template
+ // instantiation. The simplest workaround is to use its C++0x type traits
+ // functions (C++Builder 2009 and above only).
+ static const bool value = __is_convertible(From, To);
+#else
+ static const bool value =
+ sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+#endif // _MSV_VER
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+ : public bool_constant<
+ ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+ ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them). It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0. If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked. Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator. The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator'). If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+ typename C::iterator* /* it */ = NULL,
+ typename C::const_iterator* /* const_it */ = NULL) {
+ return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false. To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; }; // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0. When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+ return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat. If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+ for (size_t i = 0; i != size; i++) {
+ if (!internal::ArrayEq(lhs[i], rhs[i]))
+ return false;
+ }
+ return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem. Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+ for (Iter it = begin; it != end; ++it) {
+ if (internal::ArrayEq(*it, elem))
+ return it;
+ }
+ return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0. When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+ internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat. If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+ for (size_t i = 0; i != size; i++) {
+ internal::CopyArray(from[i], to + i);
+ }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+ kReference, // The NativeArray references the native array.
+ kCopy // The NativeArray makes a copy of the native array and
+ // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container. Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers. New members
+// should be added as needed. To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier). It's the client's responsibility to satisfy
+// this requirement. Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+ // STL-style container typedefs.
+ typedef Element value_type;
+ typedef Element* iterator;
+ typedef const Element* const_iterator;
+
+ // Constructs from a native array.
+ NativeArray(const Element* array, size_t count, RelationToSource relation) {
+ Init(array, count, relation);
+ }
+
+ // Copy constructor.
+ NativeArray(const NativeArray& rhs) {
+ Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+ }
+
+ ~NativeArray() {
+ // Ensures that the user doesn't instantiate NativeArray with a
+ // const or reference type.
+ static_cast<void>(StaticAssertTypeEqHelper<Element,
+ GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
+ if (relation_to_source_ == kCopy)
+ delete[] array_;
+ }
+
+ // STL-style container methods.
+ size_t size() const { return size_; }
+ const_iterator begin() const { return array_; }
+ const_iterator end() const { return array_ + size_; }
+ bool operator==(const NativeArray& rhs) const {
+ return size() == rhs.size() &&
+ ArrayEq(begin(), size(), rhs.begin());
+ }
+
+ private:
+ // Initializes this object; makes a copy of the input array if
+ // 'relation' is kCopy.
+ void Init(const Element* array, size_t a_size, RelationToSource relation) {
+ if (relation == kReference) {
+ array_ = array;
+ } else {
+ Element* const copy = new Element[a_size];
+ CopyArray(array, a_size, copy);
+ array_ = copy;
+ }
+ size_ = a_size;
+ relation_to_source_ = relation;
+ }
+
+ const Element* array_;
+ size_t size_;
+ RelationToSource relation_to_source_;
+
+ GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
+} // namespace internal
+} // namespace testing
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+ ::testing::internal::AssertHelper(result_type, file, line, message) \
+ = ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+ GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+ return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+ GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+ GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+// Suppresses MSVC warnings 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+ if (::testing::internal::AlwaysTrue()) { statement; }
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::ConstCharPtr gtest_msg = "") { \
+ bool gtest_caught_expected = false; \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } \
+ catch (expected_exception const&) { \
+ gtest_caught_expected = true; \
+ } \
+ catch (...) { \
+ gtest_msg.value = \
+ "Expected: " #statement " throws an exception of type " \
+ #expected_exception ".\n Actual: it throws a different type."; \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+ } \
+ if (!gtest_caught_expected) { \
+ gtest_msg.value = \
+ "Expected: " #statement " throws an exception of type " \
+ #expected_exception ".\n Actual: it throws nothing."; \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
+ fail(gtest_msg.value)
+
+#define GTEST_TEST_NO_THROW_(statement, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::AlwaysTrue()) { \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } \
+ catch (...) { \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
+ fail("Expected: " #statement " doesn't throw an exception.\n" \
+ " Actual: it throws.")
+
+#define GTEST_TEST_ANY_THROW_(statement, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::AlwaysTrue()) { \
+ bool gtest_caught_any = false; \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } \
+ catch (...) { \
+ gtest_caught_any = true; \
+ } \
+ if (!gtest_caught_any) { \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
+ fail("Expected: " #statement " throws an exception.\n" \
+ " Actual: it doesn't.")
+
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// represenation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const ::testing::AssertionResult gtest_ar_ = \
+ ::testing::AssertionResult(expression)) \
+ ; \
+ else \
+ fail(::testing::internal::GetBoolAssertionFailureMessage(\
+ gtest_ar_, text, #actual, #expected).c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::AlwaysTrue()) { \
+ ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
+ goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
+ } \
+ } else \
+ GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
+ fail("Expected: " #statement " doesn't generate new fatal " \
+ "failures in the current thread.\n" \
+ " Actual: it does.")
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+ test_case_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
+class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
+ public:\
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
+ private:\
+ virtual void TestBody();\
+ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
+};\
+\
+::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
+ ::test_info_ =\
+ ::testing::internal::MakeAndRegisterTestInfo(\
+ #test_case_name, #test_name, NULL, NULL, \
+ (parent_id), \
+ parent_class::SetUpTestCase, \
+ parent_class::TearDownTestCase, \
+ new ::testing::internal::TestFactoryImpl<\
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-linked_ptr.h b/thirdparty/gtest/include/gtest/internal/gtest-linked_ptr.h
new file mode 100644
index 00000000..b1362cd0
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-linked_ptr.h
@@ -0,0 +1,233 @@
+// Copyright 2003 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Dan Egnor (egnor@google.com)
+//
+// A "smart" pointer type with reference tracking. Every pointer to a
+// particular object is kept on a circular linked list. When the last pointer
+// to an object is destroyed or reassigned, the object is deleted.
+//
+// Used properly, this deletes the object when the last reference goes away.
+// There are several caveats:
+// - Like all reference counting schemes, cycles lead to leaks.
+// - Each smart pointer is actually two pointers (8 bytes instead of 4).
+// - Every time a pointer is assigned, the entire list of pointers to that
+// object is traversed. This class is therefore NOT SUITABLE when there
+// will often be more than two or three pointers to a particular object.
+// - References are only tracked as long as linked_ptr<> objects are copied.
+// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
+// will happen (double deletion).
+//
+// A good use of this class is storing object references in STL containers.
+// You can safely put linked_ptr<> in a vector<>.
+// Other uses may not be as good.
+//
+// Note: If you use an incomplete type with linked_ptr<>, the class
+// *containing* linked_ptr<> must have a constructor and destructor (even
+// if they do nothing!).
+//
+// Bill Gibbons suggested we use something like this.
+//
+// Thread Safety:
+// Unlike other linked_ptr implementations, in this implementation
+// a linked_ptr object is thread-safe in the sense that:
+// - it's safe to copy linked_ptr objects concurrently,
+// - it's safe to copy *from* a linked_ptr and read its underlying
+// raw pointer (e.g. via get()) concurrently, and
+// - it's safe to write to two linked_ptrs that point to the same
+// shared object concurrently.
+// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
+// confusion with normal linked_ptr.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// Protects copying of all linked_ptr objects.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// This is used internally by all instances of linked_ptr<>. It needs to be
+// a non-template class because different types of linked_ptr<> can refer to
+// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
+// So, it needs to be possible for different types of linked_ptr to participate
+// in the same circular linked list, so we need a single class type here.
+//
+// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>.
+class linked_ptr_internal {
+ public:
+ // Create a new circle that includes only this instance.
+ void join_new() {
+ next_ = this;
+ }
+
+ // Many linked_ptr operations may change p.link_ for some linked_ptr
+ // variable p in the same circle as this object. Therefore we need
+ // to prevent two such operations from occurring concurrently.
+ //
+ // Note that different types of linked_ptr objects can coexist in a
+ // circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
+ // linked_ptr<Derived2>). Therefore we must use a single mutex to
+ // protect all linked_ptr objects. This can create serious
+ // contention in production code, but is acceptable in a testing
+ // framework.
+
+ // Join an existing circle.
+ void join(linked_ptr_internal const* ptr)
+ GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
+ MutexLock lock(&g_linked_ptr_mutex);
+
+ linked_ptr_internal const* p = ptr;
+ while (p->next_ != ptr) p = p->next_;
+ p->next_ = this;
+ next_ = ptr;
+ }
+
+ // Leave whatever circle we're part of. Returns true if we were the
+ // last member of the circle. Once this is done, you can join() another.
+ bool depart()
+ GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
+ MutexLock lock(&g_linked_ptr_mutex);
+
+ if (next_ == this) return true;
+ linked_ptr_internal const* p = next_;
+ while (p->next_ != this) p = p->next_;
+ p->next_ = next_;
+ return false;
+ }
+
+ private:
+ mutable linked_ptr_internal const* next_;
+};
+
+template <typename T>
+class linked_ptr {
+ public:
+ typedef T element_type;
+
+ // Take over ownership of a raw pointer. This should happen as soon as
+ // possible after the object is created.
+ explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
+ ~linked_ptr() { depart(); }
+
+ // Copy an existing linked_ptr<>, adding ourselves to the list of references.
+ template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
+ linked_ptr(linked_ptr const& ptr) { // NOLINT
+ assert(&ptr != this);
+ copy(&ptr);
+ }
+
+ // Assignment releases the old value and acquires the new.
+ template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
+ depart();
+ copy(&ptr);
+ return *this;
+ }
+
+ linked_ptr& operator=(linked_ptr const& ptr) {
+ if (&ptr != this) {
+ depart();
+ copy(&ptr);
+ }
+ return *this;
+ }
+
+ // Smart pointer members.
+ void reset(T* ptr = NULL) {
+ depart();
+ capture(ptr);
+ }
+ T* get() const { return value_; }
+ T* operator->() const { return value_; }
+ T& operator*() const { return *value_; }
+
+ bool operator==(T* p) const { return value_ == p; }
+ bool operator!=(T* p) const { return value_ != p; }
+ template <typename U>
+ bool operator==(linked_ptr<U> const& ptr) const {
+ return value_ == ptr.get();
+ }
+ template <typename U>
+ bool operator!=(linked_ptr<U> const& ptr) const {
+ return value_ != ptr.get();
+ }
+
+ private:
+ template <typename U>
+ friend class linked_ptr;
+
+ T* value_;
+ linked_ptr_internal link_;
+
+ void depart() {
+ if (link_.depart()) delete value_;
+ }
+
+ void capture(T* ptr) {
+ value_ = ptr;
+ link_.join_new();
+ }
+
+ template <typename U> void copy(linked_ptr<U> const* ptr) {
+ value_ = ptr->get();
+ if (value_)
+ link_.join(&ptr->link_);
+ else
+ link_.join_new();
+ }
+};
+
+template<typename T> inline
+bool operator==(T* ptr, const linked_ptr<T>& x) {
+ return ptr == x.get();
+}
+
+template<typename T> inline
+bool operator!=(T* ptr, const linked_ptr<T>& x) {
+ return ptr != x.get();
+}
+
+// A function to convert T* into linked_ptr<T>
+// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+linked_ptr<T> make_linked_ptr(T* ptr) {
+ return linked_ptr<T>(ptr);
+}
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-param-util-generated.h b/thirdparty/gtest/include/gtest/internal/gtest-param-util-generated.h
new file mode 100644
index 00000000..e8054859
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-param-util-generated.h
@@ -0,0 +1,5143 @@
+// This file was GENERATED by command:
+// pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most 50 arguments in Values,
+// and at most 10 arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at 10.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*. Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+ const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+ explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray1& other);
+
+ const T1 v1_;
+};
+
+template <typename T1, typename T2>
+class ValueArray2 {
+ public:
+ ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray2& other);
+
+ const T1 v1_;
+ const T2 v2_;
+};
+
+template <typename T1, typename T2, typename T3>
+class ValueArray3 {
+ public:
+ ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray3& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ValueArray4 {
+ public:
+ ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray4& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ValueArray5 {
+ public:
+ ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray5& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+class ValueArray6 {
+ public:
+ ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray6& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+class ValueArray7 {
+ public:
+ ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray7& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+class ValueArray8 {
+ public:
+ ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+ T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray8& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+class ValueArray9 {
+ public:
+ ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+ T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray9& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+class ValueArray10 {
+ public:
+ ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray10& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11>
+class ValueArray11 {
+ public:
+ ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray11& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12>
+class ValueArray12 {
+ public:
+ ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray12& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13>
+class ValueArray13 {
+ public:
+ ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray13& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14>
+class ValueArray14 {
+ public:
+ ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray14& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15>
+class ValueArray15 {
+ public:
+ ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray15& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16>
+class ValueArray16 {
+ public:
+ ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray16& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17>
+class ValueArray17 {
+ public:
+ ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+ T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray17& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18>
+class ValueArray18 {
+ public:
+ ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray18& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19>
+class ValueArray19 {
+ public:
+ ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+ v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray19& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20>
+class ValueArray20 {
+ public:
+ ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+ v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+ v19_(v19), v20_(v20) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray20& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21>
+class ValueArray21 {
+ public:
+ ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+ v18_(v18), v19_(v19), v20_(v20), v21_(v21) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray21& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22>
+class ValueArray22 {
+ public:
+ ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray22& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23>
+class ValueArray23 {
+ public:
+ ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray23& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24>
+class ValueArray24 {
+ public:
+ ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+ v22_(v22), v23_(v23), v24_(v24) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray24& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25>
+class ValueArray25 {
+ public:
+ ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+ T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray25& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26>
+class ValueArray26 {
+ public:
+ ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray26& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27>
+class ValueArray27 {
+ public:
+ ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+ v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+ v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+ v26_(v26), v27_(v27) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray27& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28>
+class ValueArray28 {
+ public:
+ ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+ v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+ v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+ v25_(v25), v26_(v26), v27_(v27), v28_(v28) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray28& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29>
+class ValueArray29 {
+ public:
+ ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+ v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+ v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray29& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30>
+class ValueArray30 {
+ public:
+ ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray30& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31>
+class ValueArray31 {
+ public:
+ ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray31& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32>
+class ValueArray32 {
+ public:
+ ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+ v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+ v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray32& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33>
+class ValueArray33 {
+ public:
+ ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+ T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray33& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34>
+class ValueArray34 {
+ public:
+ ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray34& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35>
+class ValueArray35 {
+ public:
+ ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+ v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+ v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+ v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+ v32_(v32), v33_(v33), v34_(v34), v35_(v35) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray35& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36>
+class ValueArray36 {
+ public:
+ ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+ v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+ v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+ v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+ v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray36& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37>
+class ValueArray37 {
+ public:
+ ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+ v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+ v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+ v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+ v36_(v36), v37_(v37) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray37& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38>
+class ValueArray38 {
+ public:
+ ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+ v35_(v35), v36_(v36), v37_(v37), v38_(v38) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray38& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39>
+class ValueArray39 {
+ public:
+ ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+ v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray39& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40>
+class ValueArray40 {
+ public:
+ ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+ v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+ v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+ v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+ v40_(v40) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray40& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41>
+class ValueArray41 {
+ public:
+ ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+ T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+ v39_(v39), v40_(v40), v41_(v41) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray41& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42>
+class ValueArray42 {
+ public:
+ ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+ v39_(v39), v40_(v40), v41_(v41), v42_(v42) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+ static_cast<T>(v42_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray42& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43>
+class ValueArray43 {
+ public:
+ ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+ v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+ v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+ v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+ v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+ v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37),
+ v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+ static_cast<T>(v42_), static_cast<T>(v43_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray43& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44>
+class ValueArray44 {
+ public:
+ ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+ v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+ v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+ v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+ v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+ v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36),
+ v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42),
+ v43_(v43), v44_(v44) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+ static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray44& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45>
+class ValueArray45 {
+ public:
+ ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+ v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+ v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+ v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+ v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+ v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+ v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41),
+ v42_(v42), v43_(v43), v44_(v44), v45_(v45) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+ static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+ static_cast<T>(v45_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray45& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46>
+class ValueArray46 {
+ public:
+ ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3),
+ v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+ v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+ v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+ static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+ static_cast<T>(v45_), static_cast<T>(v46_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray46& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47>
+class ValueArray47 {
+ public:
+ ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2),
+ v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+ v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+ v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+ v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+ v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+ v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+ v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46),
+ v47_(v47) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+ static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+ static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray47& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+ const T47 v47_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48>
+class ValueArray48 {
+ public:
+ ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1),
+ v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+ v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+ v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+ v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+ v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+ v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+ v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45),
+ v46_(v46), v47_(v47), v48_(v48) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+ static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+ static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+ static_cast<T>(v48_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray48& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+ const T47 v47_;
+ const T48 v48_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49>
+class ValueArray49 {
+ public:
+ ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48,
+ T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+ v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+ v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+ static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+ static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+ static_cast<T>(v48_), static_cast<T>(v49_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray49& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+ const T47 v47_;
+ const T48 v48_;
+ const T49 v49_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49, typename T50>
+class ValueArray50 {
+ public:
+ ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+ T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+ T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+ T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+ T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+ T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49,
+ T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+ v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+ v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+ v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+ v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+ v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+ v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+ v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+ static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+ static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+ static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+ static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+ static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+ static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+ static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+ static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+ static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+ static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+ static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+ static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+ static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+ static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+ static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+ static_cast<T>(v48_), static_cast<T>(v49_), static_cast<T>(v50_)};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray50& other);
+
+ const T1 v1_;
+ const T2 v2_;
+ const T3 v3_;
+ const T4 v4_;
+ const T5 v5_;
+ const T6 v6_;
+ const T7 v7_;
+ const T8 v8_;
+ const T9 v9_;
+ const T10 v10_;
+ const T11 v11_;
+ const T12 v12_;
+ const T13 v13_;
+ const T14 v14_;
+ const T15 v15_;
+ const T16 v16_;
+ const T17 v17_;
+ const T18 v18_;
+ const T19 v19_;
+ const T20 v20_;
+ const T21 v21_;
+ const T22 v22_;
+ const T23 v23_;
+ const T24 v24_;
+ const T25 v25_;
+ const T26 v26_;
+ const T27 v27_;
+ const T28 v28_;
+ const T29 v29_;
+ const T30 v30_;
+ const T31 v31_;
+ const T32 v32_;
+ const T33 v33_;
+ const T34 v34_;
+ const T35 v35_;
+ const T36 v36_;
+ const T37 v37_;
+ const T38 v38_;
+ const T39 v39_;
+ const T40 v40_;
+ const T41 v41_;
+ const T42 v42_;
+ const T43 v43_;
+ const T44 v44_;
+ const T45 v45_;
+ const T46 v46_;
+ const T47 v47_;
+ const T48 v48_;
+ const T49 v49_;
+ const T50 v50_;
+};
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+template <typename T1, typename T2>
+class CartesianProductGenerator2
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2> ParamType;
+
+ CartesianProductGenerator2(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2)
+ : g1_(g1), g2_(g2) {}
+ virtual ~CartesianProductGenerator2() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current2_;
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator2::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator2& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+}; // class CartesianProductGenerator2
+
+
+template <typename T1, typename T2, typename T3>
+class CartesianProductGenerator3
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3> ParamType;
+
+ CartesianProductGenerator3(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
+ : g1_(g1), g2_(g2), g3_(g3) {}
+ virtual ~CartesianProductGenerator3() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current3_;
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator3::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator3& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+}; // class CartesianProductGenerator3
+
+
+template <typename T1, typename T2, typename T3, typename T4>
+class CartesianProductGenerator4
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4> ParamType;
+
+ CartesianProductGenerator4(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+ virtual ~CartesianProductGenerator4() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current4_;
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator4::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator4& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+}; // class CartesianProductGenerator4
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class CartesianProductGenerator5
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5> ParamType;
+
+ CartesianProductGenerator5(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+ virtual ~CartesianProductGenerator5() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current5_;
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator5::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator5& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+}; // class CartesianProductGenerator5
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+class CartesianProductGenerator6
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5,
+ T6> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> ParamType;
+
+ CartesianProductGenerator6(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+ virtual ~CartesianProductGenerator6() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current6_;
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator6::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator6& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+}; // class CartesianProductGenerator6
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+class CartesianProductGenerator7
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
+
+ CartesianProductGenerator7(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+ virtual ~CartesianProductGenerator7() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+ g7_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6,
+ const ParamGenerator<T7>& g7,
+ const typename ParamGenerator<T7>::iterator& current7)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+ begin7_(g7.begin()), end7_(g7.end()), current7_(current7) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current7_;
+ if (current7_ == end7_) {
+ current7_ = begin7_;
+ ++current6_;
+ }
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_ &&
+ current7_ == typed_other->current7_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_),
+ begin7_(other.begin7_),
+ end7_(other.end7_),
+ current7_(other.current7_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_, *current7_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_ ||
+ current7_ == end7_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ const typename ParamGenerator<T7>::iterator begin7_;
+ const typename ParamGenerator<T7>::iterator end7_;
+ typename ParamGenerator<T7>::iterator current7_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator7::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator7& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+ const ParamGenerator<T7> g7_;
+}; // class CartesianProductGenerator7
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+class CartesianProductGenerator8
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7, T8> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
+
+ CartesianProductGenerator8(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+ const ParamGenerator<T8>& g8)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+ g8_(g8) {}
+ virtual ~CartesianProductGenerator8() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+ g7_.begin(), g8_, g8_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+ g8_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6,
+ const ParamGenerator<T7>& g7,
+ const typename ParamGenerator<T7>::iterator& current7,
+ const ParamGenerator<T8>& g8,
+ const typename ParamGenerator<T8>::iterator& current8)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+ begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+ begin8_(g8.begin()), end8_(g8.end()), current8_(current8) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current8_;
+ if (current8_ == end8_) {
+ current8_ = begin8_;
+ ++current7_;
+ }
+ if (current7_ == end7_) {
+ current7_ = begin7_;
+ ++current6_;
+ }
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_ &&
+ current7_ == typed_other->current7_ &&
+ current8_ == typed_other->current8_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_),
+ begin7_(other.begin7_),
+ end7_(other.end7_),
+ current7_(other.current7_),
+ begin8_(other.begin8_),
+ end8_(other.end8_),
+ current8_(other.current8_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_, *current7_, *current8_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_ ||
+ current7_ == end7_ ||
+ current8_ == end8_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ const typename ParamGenerator<T7>::iterator begin7_;
+ const typename ParamGenerator<T7>::iterator end7_;
+ typename ParamGenerator<T7>::iterator current7_;
+ const typename ParamGenerator<T8>::iterator begin8_;
+ const typename ParamGenerator<T8>::iterator end8_;
+ typename ParamGenerator<T8>::iterator current8_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator8::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator8& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+ const ParamGenerator<T7> g7_;
+ const ParamGenerator<T8> g8_;
+}; // class CartesianProductGenerator8
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+class CartesianProductGenerator9
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7, T8, T9> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
+
+ CartesianProductGenerator9(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+ const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+ g9_(g9) {}
+ virtual ~CartesianProductGenerator9() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+ g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+ g8_.end(), g9_, g9_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6,
+ const ParamGenerator<T7>& g7,
+ const typename ParamGenerator<T7>::iterator& current7,
+ const ParamGenerator<T8>& g8,
+ const typename ParamGenerator<T8>::iterator& current8,
+ const ParamGenerator<T9>& g9,
+ const typename ParamGenerator<T9>::iterator& current9)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+ begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+ begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+ begin9_(g9.begin()), end9_(g9.end()), current9_(current9) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current9_;
+ if (current9_ == end9_) {
+ current9_ = begin9_;
+ ++current8_;
+ }
+ if (current8_ == end8_) {
+ current8_ = begin8_;
+ ++current7_;
+ }
+ if (current7_ == end7_) {
+ current7_ = begin7_;
+ ++current6_;
+ }
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_ &&
+ current7_ == typed_other->current7_ &&
+ current8_ == typed_other->current8_ &&
+ current9_ == typed_other->current9_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_),
+ begin7_(other.begin7_),
+ end7_(other.end7_),
+ current7_(other.current7_),
+ begin8_(other.begin8_),
+ end8_(other.end8_),
+ current8_(other.current8_),
+ begin9_(other.begin9_),
+ end9_(other.end9_),
+ current9_(other.current9_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_, *current7_, *current8_,
+ *current9_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_ ||
+ current7_ == end7_ ||
+ current8_ == end8_ ||
+ current9_ == end9_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ const typename ParamGenerator<T7>::iterator begin7_;
+ const typename ParamGenerator<T7>::iterator end7_;
+ typename ParamGenerator<T7>::iterator current7_;
+ const typename ParamGenerator<T8>::iterator begin8_;
+ const typename ParamGenerator<T8>::iterator end8_;
+ typename ParamGenerator<T8>::iterator current8_;
+ const typename ParamGenerator<T9>::iterator begin9_;
+ const typename ParamGenerator<T9>::iterator end9_;
+ typename ParamGenerator<T9>::iterator current9_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator9::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator9& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+ const ParamGenerator<T7> g7_;
+ const ParamGenerator<T8> g8_;
+ const ParamGenerator<T9> g9_;
+}; // class CartesianProductGenerator9
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+class CartesianProductGenerator10
+ : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7, T8, T9, T10> > {
+ public:
+ typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
+
+ CartesianProductGenerator10(const ParamGenerator<T1>& g1,
+ const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+ const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+ const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+ const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9,
+ const ParamGenerator<T10>& g10)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+ g9_(g9), g10_(g10) {}
+ virtual ~CartesianProductGenerator10() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+ g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+ g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin());
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+ g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+ g8_.end(), g9_, g9_.end(), g10_, g10_.end());
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base,
+ const ParamGenerator<T1>& g1,
+ const typename ParamGenerator<T1>::iterator& current1,
+ const ParamGenerator<T2>& g2,
+ const typename ParamGenerator<T2>::iterator& current2,
+ const ParamGenerator<T3>& g3,
+ const typename ParamGenerator<T3>::iterator& current3,
+ const ParamGenerator<T4>& g4,
+ const typename ParamGenerator<T4>::iterator& current4,
+ const ParamGenerator<T5>& g5,
+ const typename ParamGenerator<T5>::iterator& current5,
+ const ParamGenerator<T6>& g6,
+ const typename ParamGenerator<T6>::iterator& current6,
+ const ParamGenerator<T7>& g7,
+ const typename ParamGenerator<T7>::iterator& current7,
+ const ParamGenerator<T8>& g8,
+ const typename ParamGenerator<T8>::iterator& current8,
+ const ParamGenerator<T9>& g9,
+ const typename ParamGenerator<T9>::iterator& current9,
+ const ParamGenerator<T10>& g10,
+ const typename ParamGenerator<T10>::iterator& current10)
+ : base_(base),
+ begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+ begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+ begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+ begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+ begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+ begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+ begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+ begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+ begin9_(g9.begin()), end9_(g9.end()), current9_(current9),
+ begin10_(g10.begin()), end10_(g10.end()), current10_(current10) {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current10_;
+ if (current10_ == end10_) {
+ current10_ = begin10_;
+ ++current9_;
+ }
+ if (current9_ == end9_) {
+ current9_ = begin9_;
+ ++current8_;
+ }
+ if (current8_ == end8_) {
+ current8_ = begin8_;
+ ++current7_;
+ }
+ if (current7_ == end7_) {
+ current7_ = begin7_;
+ ++current6_;
+ }
+ if (current6_ == end6_) {
+ current6_ = begin6_;
+ ++current5_;
+ }
+ if (current5_ == end5_) {
+ current5_ = begin5_;
+ ++current4_;
+ }
+ if (current4_ == end4_) {
+ current4_ = begin4_;
+ ++current3_;
+ }
+ if (current3_ == end3_) {
+ current3_ = begin3_;
+ ++current2_;
+ }
+ if (current2_ == end2_) {
+ current2_ = begin2_;
+ ++current1_;
+ }
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ (
+ current1_ == typed_other->current1_ &&
+ current2_ == typed_other->current2_ &&
+ current3_ == typed_other->current3_ &&
+ current4_ == typed_other->current4_ &&
+ current5_ == typed_other->current5_ &&
+ current6_ == typed_other->current6_ &&
+ current7_ == typed_other->current7_ &&
+ current8_ == typed_other->current8_ &&
+ current9_ == typed_other->current9_ &&
+ current10_ == typed_other->current10_);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_),
+ begin1_(other.begin1_),
+ end1_(other.end1_),
+ current1_(other.current1_),
+ begin2_(other.begin2_),
+ end2_(other.end2_),
+ current2_(other.current2_),
+ begin3_(other.begin3_),
+ end3_(other.end3_),
+ current3_(other.current3_),
+ begin4_(other.begin4_),
+ end4_(other.end4_),
+ current4_(other.current4_),
+ begin5_(other.begin5_),
+ end5_(other.end5_),
+ current5_(other.current5_),
+ begin6_(other.begin6_),
+ end6_(other.end6_),
+ current6_(other.current6_),
+ begin7_(other.begin7_),
+ end7_(other.end7_),
+ current7_(other.current7_),
+ begin8_(other.begin8_),
+ end8_(other.end8_),
+ current8_(other.current8_),
+ begin9_(other.begin9_),
+ end9_(other.end9_),
+ current9_(other.current9_),
+ begin10_(other.begin10_),
+ end10_(other.end10_),
+ current10_(other.current10_) {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType(*current1_, *current2_, *current3_,
+ *current4_, *current5_, *current6_, *current7_, *current8_,
+ *current9_, *current10_);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+ current1_ == end1_ ||
+ current2_ == end2_ ||
+ current3_ == end3_ ||
+ current4_ == end4_ ||
+ current5_ == end5_ ||
+ current6_ == end6_ ||
+ current7_ == end7_ ||
+ current8_ == end8_ ||
+ current9_ == end9_ ||
+ current10_ == end10_;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+ const typename ParamGenerator<T1>::iterator begin1_;
+ const typename ParamGenerator<T1>::iterator end1_;
+ typename ParamGenerator<T1>::iterator current1_;
+ const typename ParamGenerator<T2>::iterator begin2_;
+ const typename ParamGenerator<T2>::iterator end2_;
+ typename ParamGenerator<T2>::iterator current2_;
+ const typename ParamGenerator<T3>::iterator begin3_;
+ const typename ParamGenerator<T3>::iterator end3_;
+ typename ParamGenerator<T3>::iterator current3_;
+ const typename ParamGenerator<T4>::iterator begin4_;
+ const typename ParamGenerator<T4>::iterator end4_;
+ typename ParamGenerator<T4>::iterator current4_;
+ const typename ParamGenerator<T5>::iterator begin5_;
+ const typename ParamGenerator<T5>::iterator end5_;
+ typename ParamGenerator<T5>::iterator current5_;
+ const typename ParamGenerator<T6>::iterator begin6_;
+ const typename ParamGenerator<T6>::iterator end6_;
+ typename ParamGenerator<T6>::iterator current6_;
+ const typename ParamGenerator<T7>::iterator begin7_;
+ const typename ParamGenerator<T7>::iterator end7_;
+ typename ParamGenerator<T7>::iterator current7_;
+ const typename ParamGenerator<T8>::iterator begin8_;
+ const typename ParamGenerator<T8>::iterator end8_;
+ typename ParamGenerator<T8>::iterator current8_;
+ const typename ParamGenerator<T9>::iterator begin9_;
+ const typename ParamGenerator<T9>::iterator end9_;
+ typename ParamGenerator<T9>::iterator current9_;
+ const typename ParamGenerator<T10>::iterator begin10_;
+ const typename ParamGenerator<T10>::iterator end10_;
+ typename ParamGenerator<T10>::iterator current10_;
+ ParamType current_value_;
+ }; // class CartesianProductGenerator10::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator10& other);
+
+ const ParamGenerator<T1> g1_;
+ const ParamGenerator<T2> g2_;
+ const ParamGenerator<T3> g3_;
+ const ParamGenerator<T4> g4_;
+ const ParamGenerator<T5> g5_;
+ const ParamGenerator<T6> g6_;
+ const ParamGenerator<T7> g7_;
+ const ParamGenerator<T8> g8_;
+ const ParamGenerator<T9> g9_;
+ const ParamGenerator<T10> g10_;
+}; // class CartesianProductGenerator10
+
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+template <class Generator1, class Generator2>
+class CartesianProductHolder2 {
+ public:
+CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
+ : g1_(g1), g2_(g2) {}
+ template <typename T1, typename T2>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2> >(
+ new CartesianProductGenerator2<T1, T2>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder2& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+}; // class CartesianProductHolder2
+
+template <class Generator1, class Generator2, class Generator3>
+class CartesianProductHolder3 {
+ public:
+CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3)
+ : g1_(g1), g2_(g2), g3_(g3) {}
+ template <typename T1, typename T2, typename T3>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >(
+ new CartesianProductGenerator3<T1, T2, T3>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder3& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+}; // class CartesianProductHolder3
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4>
+class CartesianProductHolder4 {
+ public:
+CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+ template <typename T1, typename T2, typename T3, typename T4>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >(
+ new CartesianProductGenerator4<T1, T2, T3, T4>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder4& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+}; // class CartesianProductHolder4
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5>
+class CartesianProductHolder5 {
+ public:
+CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >(
+ new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder5& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+}; // class CartesianProductHolder5
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6>
+class CartesianProductHolder6 {
+ public:
+CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >(
+ new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder6& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+}; // class CartesianProductHolder6
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6, class Generator7>
+class CartesianProductHolder7 {
+ public:
+CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6, const Generator7& g7)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+ T7> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> >(
+ new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_),
+ static_cast<ParamGenerator<T7> >(g7_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder7& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+ const Generator7 g7_;
+}; // class CartesianProductHolder7
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6, class Generator7,
+ class Generator8>
+class CartesianProductHolder8 {
+ public:
+CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6, const Generator7& g7, const Generator8& g8)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+ g8_(g8) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7,
+ T8> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
+ new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_),
+ static_cast<ParamGenerator<T7> >(g7_),
+ static_cast<ParamGenerator<T8> >(g8_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder8& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+ const Generator7 g7_;
+ const Generator8 g8_;
+}; // class CartesianProductHolder8
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6, class Generator7,
+ class Generator8, class Generator9>
+class CartesianProductHolder9 {
+ public:
+CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6, const Generator7& g7, const Generator8& g8,
+ const Generator9& g9)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+ g9_(g9) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+ T9> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+ T9> >(
+ new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_),
+ static_cast<ParamGenerator<T7> >(g7_),
+ static_cast<ParamGenerator<T8> >(g8_),
+ static_cast<ParamGenerator<T9> >(g9_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder9& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+ const Generator7 g7_;
+ const Generator8 g8_;
+ const Generator9 g9_;
+}; // class CartesianProductHolder9
+
+template <class Generator1, class Generator2, class Generator3,
+ class Generator4, class Generator5, class Generator6, class Generator7,
+ class Generator8, class Generator9, class Generator10>
+class CartesianProductHolder10 {
+ public:
+CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
+ const Generator3& g3, const Generator4& g4, const Generator5& g5,
+ const Generator6& g6, const Generator7& g7, const Generator8& g8,
+ const Generator9& g9, const Generator10& g10)
+ : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+ g9_(g9), g10_(g10) {}
+ template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+ operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+ T9, T10> >() const {
+ return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+ T9, T10> >(
+ new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+ T10>(
+ static_cast<ParamGenerator<T1> >(g1_),
+ static_cast<ParamGenerator<T2> >(g2_),
+ static_cast<ParamGenerator<T3> >(g3_),
+ static_cast<ParamGenerator<T4> >(g4_),
+ static_cast<ParamGenerator<T5> >(g5_),
+ static_cast<ParamGenerator<T6> >(g6_),
+ static_cast<ParamGenerator<T7> >(g7_),
+ static_cast<ParamGenerator<T8> >(g8_),
+ static_cast<ParamGenerator<T9> >(g9_),
+ static_cast<ParamGenerator<T10> >(g10_)));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder10& other);
+
+ const Generator1 g1_;
+ const Generator2 g2_;
+ const Generator3 g3_;
+ const Generator4 g4_;
+ const Generator5 g5_;
+ const Generator6 g6_;
+ const Generator7 g7_;
+ const Generator8 g8_;
+ const Generator9 g9_;
+ const Generator10 g10_;
+}; // class CartesianProductHolder10
+
+# endif // GTEST_HAS_COMBINE
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_HAS_PARAM_TEST
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-param-util-generated.h.pump b/thirdparty/gtest/include/gtest/internal/gtest-param-util-generated.h.pump
new file mode 100644
index 00000000..009206fd
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-param-util-generated.h.pump
@@ -0,0 +1,301 @@
+$$ -*- mode: c++; -*-
+$var n = 50 $$ Maximum length of Values arguments we want to support.
+$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most $n arguments in Values,
+// and at most $maxtuple arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at $maxtuple.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*. Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+ const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+ explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray1& other);
+
+ const T1 v1_;
+};
+
+$range i 2..n
+$for i [[
+$range j 1..i
+
+template <$for j, [[typename T$j]]>
+class ValueArray$i {
+ public:
+ ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {}
+
+ template <typename T>
+ operator ParamGenerator<T>() const {
+ const T array[] = {$for j, [[static_cast<T>(v$(j)_)]]};
+ return ValuesIn(array);
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const ValueArray$i& other);
+
+$for j [[
+
+ const T$j v$(j)_;
+]]
+
+};
+
+]]
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+$range k 2..i
+
+template <$for j, [[typename T$j]]>
+class CartesianProductGenerator$i
+ : public ParamGeneratorInterface< ::std::tr1::tuple<$for j, [[T$j]]> > {
+ public:
+ typedef ::std::tr1::tuple<$for j, [[T$j]]> ParamType;
+
+ CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]])
+ : $for j, [[g$(j)_(g$j)]] {}
+ virtual ~CartesianProductGenerator$i() {}
+
+ virtual ParamIteratorInterface<ParamType>* Begin() const {
+ return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]);
+ }
+ virtual ParamIteratorInterface<ParamType>* End() const {
+ return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]);
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<ParamType> {
+ public:
+ Iterator(const ParamGeneratorInterface<ParamType>* base, $for j, [[
+
+ const ParamGenerator<T$j>& g$j,
+ const typename ParamGenerator<T$j>::iterator& current$(j)]])
+ : base_(base),
+$for j, [[
+
+ begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j)
+]] {
+ ComputeCurrentValue();
+ }
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+ return base_;
+ }
+ // Advance should not be called on beyond-of-range iterators
+ // so no component iterators must be beyond end of range, either.
+ virtual void Advance() {
+ assert(!AtEnd());
+ ++current$(i)_;
+
+$for k [[
+ if (current$(i+2-k)_ == end$(i+2-k)_) {
+ current$(i+2-k)_ = begin$(i+2-k)_;
+ ++current$(i+2-k-1)_;
+ }
+
+]]
+ ComputeCurrentValue();
+ }
+ virtual ParamIteratorInterface<ParamType>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const ParamType* Current() const { return &current_value_; }
+ virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const Iterator* typed_other =
+ CheckedDowncastToActualType<const Iterator>(&other);
+ // We must report iterators equal if they both point beyond their
+ // respective ranges. That can happen in a variety of fashions,
+ // so we have to consult AtEnd().
+ return (AtEnd() && typed_other->AtEnd()) ||
+ ($for j && [[
+
+ current$(j)_ == typed_other->current$(j)_
+]]);
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : base_(other.base_), $for j, [[
+
+ begin$(j)_(other.begin$(j)_),
+ end$(j)_(other.end$(j)_),
+ current$(j)_(other.current$(j)_)
+]] {
+ ComputeCurrentValue();
+ }
+
+ void ComputeCurrentValue() {
+ if (!AtEnd())
+ current_value_ = ParamType($for j, [[*current$(j)_]]);
+ }
+ bool AtEnd() const {
+ // We must report iterator past the end of the range when either of the
+ // component iterators has reached the end of its range.
+ return
+$for j || [[
+
+ current$(j)_ == end$(j)_
+]];
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<ParamType>* const base_;
+ // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+ // current[i]_ is the actual traversing iterator.
+$for j [[
+
+ const typename ParamGenerator<T$j>::iterator begin$(j)_;
+ const typename ParamGenerator<T$j>::iterator end$(j)_;
+ typename ParamGenerator<T$j>::iterator current$(j)_;
+]]
+
+ ParamType current_value_;
+ }; // class CartesianProductGenerator$i::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductGenerator$i& other);
+
+
+$for j [[
+ const ParamGenerator<T$j> g$(j)_;
+
+]]
+}; // class CartesianProductGenerator$i
+
+
+]]
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+$range i 2..maxtuple
+$for i [[
+$range j 1..i
+
+template <$for j, [[class Generator$j]]>
+class CartesianProductHolder$i {
+ public:
+CartesianProductHolder$i($for j, [[const Generator$j& g$j]])
+ : $for j, [[g$(j)_(g$j)]] {}
+ template <$for j, [[typename T$j]]>
+ operator ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >() const {
+ return ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >(
+ new CartesianProductGenerator$i<$for j, [[T$j]]>(
+$for j,[[
+
+ static_cast<ParamGenerator<T$j> >(g$(j)_)
+]]));
+ }
+
+ private:
+ // No implementation - assignment is unsupported.
+ void operator=(const CartesianProductHolder$i& other);
+
+
+$for j [[
+ const Generator$j g$(j)_;
+
+]]
+}; // class CartesianProductHolder$i
+
+]]
+
+# endif // GTEST_HAS_COMBINE
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_HAS_PARAM_TEST
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-param-util.h b/thirdparty/gtest/include/gtest/internal/gtest-param-util.h
new file mode 100644
index 00000000..d5e1028b
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-param-util.h
@@ -0,0 +1,619 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*. Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/gtest-printers.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test case. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
+ const char* file, int line);
+
+template <typename> class ParamGeneratorInterface;
+template <typename> class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+ virtual ~ParamIteratorInterface() {}
+ // A pointer to the base generator instance.
+ // Used only for the purposes of iterator comparison
+ // to make sure that two iterators belong to the same generator.
+ virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+ // Advances iterator to point to the next element
+ // provided by the generator. The caller is responsible
+ // for not calling Advance() on an iterator equal to
+ // BaseGenerator()->End().
+ virtual void Advance() = 0;
+ // Clones the iterator object. Used for implementing copy semantics
+ // of ParamIterator<T>.
+ virtual ParamIteratorInterface* Clone() const = 0;
+ // Dereferences the current iterator and provides (read-only) access
+ // to the pointed value. It is the caller's responsibility not to call
+ // Current() on an iterator equal to BaseGenerator()->End().
+ // Used for implementing ParamGenerator<T>::operator*().
+ virtual const T* Current() const = 0;
+ // Determines whether the given iterator and other point to the same
+ // element in the sequence generated by the generator.
+ // Used for implementing ParamGenerator<T>::operator==().
+ virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+ typedef T value_type;
+ typedef const T& reference;
+ typedef ptrdiff_t difference_type;
+
+ // ParamIterator assumes ownership of the impl_ pointer.
+ ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+ ParamIterator& operator=(const ParamIterator& other) {
+ if (this != &other)
+ impl_.reset(other.impl_->Clone());
+ return *this;
+ }
+
+ const T& operator*() const { return *impl_->Current(); }
+ const T* operator->() const { return impl_->Current(); }
+ // Prefix version of operator++.
+ ParamIterator& operator++() {
+ impl_->Advance();
+ return *this;
+ }
+ // Postfix version of operator++.
+ ParamIterator operator++(int /*unused*/) {
+ ParamIteratorInterface<T>* clone = impl_->Clone();
+ impl_->Advance();
+ return ParamIterator(clone);
+ }
+ bool operator==(const ParamIterator& other) const {
+ return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+ }
+ bool operator!=(const ParamIterator& other) const {
+ return !(*this == other);
+ }
+
+ private:
+ friend class ParamGenerator<T>;
+ explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+ scoped_ptr<ParamIteratorInterface<T> > impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+ typedef T ParamType;
+
+ virtual ~ParamGeneratorInterface() {}
+
+ // Generator interface definition
+ virtual ParamIteratorInterface<T>* Begin() const = 0;
+ virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template<typename T>
+class ParamGenerator {
+ public:
+ typedef ParamIterator<T> iterator;
+
+ explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+ ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+ ParamGenerator& operator=(const ParamGenerator& other) {
+ impl_ = other.impl_;
+ return *this;
+ }
+
+ iterator begin() const { return iterator(impl_->Begin()); }
+ iterator end() const { return iterator(impl_->End()); }
+
+ private:
+ linked_ptr<const ParamGeneratorInterface<T> > impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+ RangeGenerator(T begin, T end, IncrementT step)
+ : begin_(begin), end_(end),
+ step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
+ virtual ~RangeGenerator() {}
+
+ virtual ParamIteratorInterface<T>* Begin() const {
+ return new Iterator(this, begin_, 0, step_);
+ }
+ virtual ParamIteratorInterface<T>* End() const {
+ return new Iterator(this, end_, end_index_, step_);
+ }
+
+ private:
+ class Iterator : public ParamIteratorInterface<T> {
+ public:
+ Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+ IncrementT step)
+ : base_(base), value_(value), index_(index), step_(step) {}
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+ return base_;
+ }
+ virtual void Advance() {
+ value_ = value_ + step_;
+ index_++;
+ }
+ virtual ParamIteratorInterface<T>* Clone() const {
+ return new Iterator(*this);
+ }
+ virtual const T* Current() const { return &value_; }
+ virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ const int other_index =
+ CheckedDowncastToActualType<const Iterator>(&other)->index_;
+ return index_ == other_index;
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ : ParamIteratorInterface<T>(),
+ base_(other.base_), value_(other.value_), index_(other.index_),
+ step_(other.step_) {}
+
+ // No implementation - assignment is unsupported.
+ void operator=(const Iterator& other);
+
+ const ParamGeneratorInterface<T>* const base_;
+ T value_;
+ int index_;
+ const IncrementT step_;
+ }; // class RangeGenerator::Iterator
+
+ static int CalculateEndIndex(const T& begin,
+ const T& end,
+ const IncrementT& step) {
+ int end_index = 0;
+ for (T i = begin; i < end; i = i + step)
+ end_index++;
+ return end_index;
+ }
+
+ // No implementation - assignment is unsupported.
+ void operator=(const RangeGenerator& other);
+
+ const T begin_;
+ const T end_;
+ const IncrementT step_;
+ // The index for the end() iterator. All the elements in the generated
+ // sequence are indexed (0-based) to aid iterator comparison.
+ const int end_index_;
+}; // class RangeGenerator
+
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+ template <typename ForwardIterator>
+ ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+ : container_(begin, end) {}
+ virtual ~ValuesInIteratorRangeGenerator() {}
+
+ virtual ParamIteratorInterface<T>* Begin() const {
+ return new Iterator(this, container_.begin());
+ }
+ virtual ParamIteratorInterface<T>* End() const {
+ return new Iterator(this, container_.end());
+ }
+
+ private:
+ typedef typename ::std::vector<T> ContainerType;
+
+ class Iterator : public ParamIteratorInterface<T> {
+ public:
+ Iterator(const ParamGeneratorInterface<T>* base,
+ typename ContainerType::const_iterator iterator)
+ : base_(base), iterator_(iterator) {}
+ virtual ~Iterator() {}
+
+ virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+ return base_;
+ }
+ virtual void Advance() {
+ ++iterator_;
+ value_.reset();
+ }
+ virtual ParamIteratorInterface<T>* Clone() const {
+ return new Iterator(*this);
+ }
+ // We need to use cached value referenced by iterator_ because *iterator_
+ // can return a temporary object (and of type other then T), so just
+ // having "return &*iterator_;" doesn't work.
+ // value_ is updated here and not in Advance() because Advance()
+ // can advance iterator_ beyond the end of the range, and we cannot
+ // detect that fact. The client code, on the other hand, is
+ // responsible for not calling Current() on an out-of-range iterator.
+ virtual const T* Current() const {
+ if (value_.get() == NULL)
+ value_.reset(new T(*iterator_));
+ return value_.get();
+ }
+ virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+ // Having the same base generator guarantees that the other
+ // iterator is of the same type and we can downcast.
+ GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+ << "The program attempted to compare iterators "
+ << "from different generators." << std::endl;
+ return iterator_ ==
+ CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+ }
+
+ private:
+ Iterator(const Iterator& other)
+ // The explicit constructor call suppresses a false warning
+ // emitted by gcc when supplied with the -Wextra option.
+ : ParamIteratorInterface<T>(),
+ base_(other.base_),
+ iterator_(other.iterator_) {}
+
+ const ParamGeneratorInterface<T>* const base_;
+ typename ContainerType::const_iterator iterator_;
+ // A cached value of *iterator_. We keep it here to allow access by
+ // pointer in the wrapping iterator's operator->().
+ // value_ needs to be mutable to be accessed in Current().
+ // Use of scoped_ptr helps manage cached value's lifetime,
+ // which is bound by the lifespan of the iterator itself.
+ mutable scoped_ptr<const T> value_;
+ }; // class ValuesInIteratorRangeGenerator::Iterator
+
+ // No implementation - assignment is unsupported.
+ void operator=(const ValuesInIteratorRangeGenerator& other);
+
+ const ContainerType container_;
+}; // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+ typedef typename TestClass::ParamType ParamType;
+ explicit ParameterizedTestFactory(ParamType parameter) :
+ parameter_(parameter) {}
+ virtual Test* CreateTest() {
+ TestClass::SetParam(&parameter_);
+ return new TestClass();
+ }
+
+ private:
+ const ParamType parameter_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+ virtual ~TestMetaFactoryBase() {}
+
+ virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestCaseInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestCase>
+class TestMetaFactory
+ : public TestMetaFactoryBase<typename TestCase::ParamType> {
+ public:
+ typedef typename TestCase::ParamType ParamType;
+
+ TestMetaFactory() {}
+
+ virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
+ return new ParameterizedTestFactory<TestCase>(parameter);
+ }
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfoBase is a generic interface
+// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
+// a collection of pointers to the ParameterizedTestCaseInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestCaseInfoBase {
+ public:
+ virtual ~ParameterizedTestCaseInfoBase() {}
+
+ // Base part of test case name for display purposes.
+ virtual const string& GetTestCaseName() const = 0;
+ // Test case id to verify identity.
+ virtual TypeId GetTestCaseTypeId() const = 0;
+ // UnitTest class invokes this method to register tests in this
+ // test case right before running them in RUN_ALL_TESTS macro.
+ // This method should not be called more then once on any single
+ // instance of a ParameterizedTestCaseInfoBase derived class.
+ virtual void RegisterTests() = 0;
+
+ protected:
+ ParameterizedTestCaseInfoBase() {}
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test case and generators
+// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
+// test case. It registers tests with all values generated by all
+// generators when asked.
+template <class TestCase>
+class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
+ public:
+ // ParamType and GeneratorCreationFunc are private types but are required
+ // for declarations of public methods AddTestPattern() and
+ // AddTestCaseInstantiation().
+ typedef typename TestCase::ParamType ParamType;
+ // A function that returns an instance of appropriate generator type.
+ typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+
+ explicit ParameterizedTestCaseInfo(const char* name)
+ : test_case_name_(name) {}
+
+ // Test case base name for display purposes.
+ virtual const string& GetTestCaseName() const { return test_case_name_; }
+ // Test case id to verify identity.
+ virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
+ // TEST_P macro uses AddTestPattern() to record information
+ // about a single test in a LocalTestInfo structure.
+ // test_case_name is the base name of the test case (without invocation
+ // prefix). test_base_name is the name of an individual test without
+ // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+ // test case base name and DoBar is test base name.
+ void AddTestPattern(const char* test_case_name,
+ const char* test_base_name,
+ TestMetaFactoryBase<ParamType>* meta_factory) {
+ tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
+ test_base_name,
+ meta_factory)));
+ }
+ // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
+ // about a generator.
+ int AddTestCaseInstantiation(const string& instantiation_name,
+ GeneratorCreationFunc* func,
+ const char* /* file */,
+ int /* line */) {
+ instantiations_.push_back(::std::make_pair(instantiation_name, func));
+ return 0; // Return value used only to run this method in namespace scope.
+ }
+ // UnitTest class invokes this method to register tests in this test case
+ // test cases right before running tests in RUN_ALL_TESTS macro.
+ // This method should not be called more then once on any single
+ // instance of a ParameterizedTestCaseInfoBase derived class.
+ // UnitTest has a guard to prevent from calling this method more then once.
+ virtual void RegisterTests() {
+ for (typename TestInfoContainer::iterator test_it = tests_.begin();
+ test_it != tests_.end(); ++test_it) {
+ linked_ptr<TestInfo> test_info = *test_it;
+ for (typename InstantiationContainer::iterator gen_it =
+ instantiations_.begin(); gen_it != instantiations_.end();
+ ++gen_it) {
+ const string& instantiation_name = gen_it->first;
+ ParamGenerator<ParamType> generator((*gen_it->second)());
+
+ string test_case_name;
+ if ( !instantiation_name.empty() )
+ test_case_name = instantiation_name + "/";
+ test_case_name += test_info->test_case_base_name;
+
+ int i = 0;
+ for (typename ParamGenerator<ParamType>::iterator param_it =
+ generator.begin();
+ param_it != generator.end(); ++param_it, ++i) {
+ Message test_name_stream;
+ test_name_stream << test_info->test_base_name << "/" << i;
+ MakeAndRegisterTestInfo(
+ test_case_name.c_str(),
+ test_name_stream.GetString().c_str(),
+ NULL, // No type parameter.
+ PrintToString(*param_it).c_str(),
+ GetTestCaseTypeId(),
+ TestCase::SetUpTestCase,
+ TestCase::TearDownTestCase,
+ test_info->test_meta_factory->CreateTestFactory(*param_it));
+ } // for param_it
+ } // for gen_it
+ } // for test_it
+ } // RegisterTests
+
+ private:
+ // LocalTestInfo structure keeps information about a single test registered
+ // with TEST_P macro.
+ struct TestInfo {
+ TestInfo(const char* a_test_case_base_name,
+ const char* a_test_base_name,
+ TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
+ test_case_base_name(a_test_case_base_name),
+ test_base_name(a_test_base_name),
+ test_meta_factory(a_test_meta_factory) {}
+
+ const string test_case_base_name;
+ const string test_base_name;
+ const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
+ };
+ typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
+ // Keeps pairs of <Instantiation name, Sequence generator creation function>
+ // received from INSTANTIATE_TEST_CASE_P macros.
+ typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
+ InstantiationContainer;
+
+ const string test_case_name_;
+ TestInfoContainer tests_;
+ InstantiationContainer instantiations_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
+}; // class ParameterizedTestCaseInfo
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
+// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
+// macros use it to locate their corresponding ParameterizedTestCaseInfo
+// descriptors.
+class ParameterizedTestCaseRegistry {
+ public:
+ ParameterizedTestCaseRegistry() {}
+ ~ParameterizedTestCaseRegistry() {
+ for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+ it != test_case_infos_.end(); ++it) {
+ delete *it;
+ }
+ }
+
+ // Looks up or creates and returns a structure containing information about
+ // tests and instantiations of a particular test case.
+ template <class TestCase>
+ ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+ const char* test_case_name,
+ const char* file,
+ int line) {
+ ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
+ for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+ it != test_case_infos_.end(); ++it) {
+ if ((*it)->GetTestCaseName() == test_case_name) {
+ if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
+ // Complain about incorrect usage of Google Test facilities
+ // and terminate the program since we cannot guaranty correct
+ // test case setup and tear-down in this case.
+ ReportInvalidTestCaseType(test_case_name, file, line);
+ posix::Abort();
+ } else {
+ // At this point we are sure that the object we found is of the same
+ // type we are looking for, so we downcast it to that type
+ // without further checks.
+ typed_test_info = CheckedDowncastToActualType<
+ ParameterizedTestCaseInfo<TestCase> >(*it);
+ }
+ break;
+ }
+ }
+ if (typed_test_info == NULL) {
+ typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
+ test_case_infos_.push_back(typed_test_info);
+ }
+ return typed_test_info;
+ }
+ void RegisterTests() {
+ for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+ it != test_case_infos_.end(); ++it) {
+ (*it)->RegisterTests();
+ }
+ }
+
+ private:
+ typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
+
+ TestCaseInfoContainer test_case_infos_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
+};
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_HAS_PARAM_TEST
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-port.h b/thirdparty/gtest/include/gtest/internal/gtest-port.h
new file mode 100644
index 00000000..dc4fe0cb
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-port.h
@@ -0,0 +1,1947 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan)
+//
+// Low-level types and utilities for porting Google Test to various
+// platforms. They are subject to change without notice. DO NOT USE
+// THEM IN USER CODE.
+//
+// This file is fundamental to Google Test. All other Google Test source
+// files are expected to #include this. Therefore, it cannot #include
+// any other Google Test header.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+// The user can define the following macros in the build script to
+// control Google Test's behavior. If the user doesn't define a macro
+// in this list, Google Test will define it.
+//
+// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2)
+// is/isn't available.
+// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions
+// are enabled.
+// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string
+// is/isn't available (some systems define
+// ::string, which is different to std::string).
+// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
+// is/isn't available (some systems define
+// ::wstring, which is different to std::wstring).
+// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular
+// expressions are/aren't available.
+// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that <pthread.h>
+// is/isn't available.
+// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't
+// enabled.
+// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that
+// std::wstring does/doesn't work (Google Test can
+// be used where std::wstring is unavailable).
+// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple
+// is/isn't available.
+// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the
+// compiler supports Microsoft's "Structured
+// Exception Handling".
+// GTEST_HAS_STREAM_REDIRECTION
+// - Define it to 1/0 to indicate whether the
+// platform supports I/O stream redirection using
+// dup() and dup2().
+// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google
+// Test's own tr1 tuple implementation should be
+// used. Unused when the user sets
+// GTEST_HAS_TR1_TUPLE to 0.
+// GTEST_LANG_CXX11 - Define it to 1/0 to indicate that Google Test
+// is building in C++11/C++98 mode.
+// GTEST_LINKED_AS_SHARED_LIBRARY
+// - Define to 1 when compiling tests that use
+// Google Test as a shared library (known as
+// DLL on Windows).
+// GTEST_CREATE_SHARED_LIBRARY
+// - Define to 1 when compiling Google Test itself
+// as a shared library.
+
+// This header defines the following utilities:
+//
+// Macros indicating the current platform (defined to 1 if compiled on
+// the given platform; otherwise undefined):
+// GTEST_OS_AIX - IBM AIX
+// GTEST_OS_CYGWIN - Cygwin
+// GTEST_OS_HPUX - HP-UX
+// GTEST_OS_LINUX - Linux
+// GTEST_OS_LINUX_ANDROID - Google Android
+// GTEST_OS_MAC - Mac OS X
+// GTEST_OS_IOS - iOS
+// GTEST_OS_IOS_SIMULATOR - iOS simulator
+// GTEST_OS_NACL - Google Native Client (NaCl)
+// GTEST_OS_OPENBSD - OpenBSD
+// GTEST_OS_QNX - QNX
+// GTEST_OS_SOLARIS - Sun Solaris
+// GTEST_OS_SYMBIAN - Symbian
+// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
+// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop
+// GTEST_OS_WINDOWS_MINGW - MinGW
+// GTEST_OS_WINDOWS_MOBILE - Windows Mobile
+// GTEST_OS_ZOS - z/OS
+//
+// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
+// most stable support. Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable. If you notice any problems on your platform, please notify
+// googletestframework@googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// Note that it is possible that none of the GTEST_OS_* macros are defined.
+//
+// Macros indicating available Google Test features (defined to 1 if
+// the corresponding feature is supported; otherwise undefined):
+// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized
+// tests)
+// GTEST_HAS_DEATH_TEST - death tests
+// GTEST_HAS_PARAM_TEST - value-parameterized tests
+// GTEST_HAS_TYPED_TEST - typed tests
+// GTEST_HAS_TYPED_TEST_P - type-parameterized tests
+// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with
+// GTEST_HAS_POSIX_RE (see above) which users can
+// define themselves.
+// GTEST_USES_SIMPLE_RE - our own simple regex is used;
+// the above two are mutually exclusive.
+// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
+//
+// Macros for basic C++ coding:
+// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a
+// variable don't have to be used.
+// GTEST_DISALLOW_ASSIGN_ - disables operator=.
+// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
+// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used.
+//
+// Synchronization:
+// Mutex, MutexLock, ThreadLocal, GetThreadCount()
+// - synchronization primitives.
+// GTEST_IS_THREADSAFE - defined to 1 to indicate that the above
+// synchronization primitives have real implementations
+// and Google Test is thread-safe; or 0 otherwise.
+//
+// Template meta programming:
+// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only.
+// IteratorTraits - partial implementation of std::iterator_traits, which
+// is not available in libCstd when compiled with Sun C++.
+//
+// Smart pointers:
+// scoped_ptr - as in TR2.
+//
+// Regular expressions:
+// RE - a simple regular expression class using the POSIX
+// Extended Regular Expression syntax on UNIX-like
+// platforms, or a reduced regular exception syntax on
+// other platforms, including Windows.
+//
+// Logging:
+// GTEST_LOG_() - logs messages at the specified severity level.
+// LogToStderr() - directs all log messages to stderr.
+// FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+// CaptureStdout() - starts capturing stdout.
+// GetCapturedStdout() - stops capturing stdout and returns the captured
+// string.
+// CaptureStderr() - starts capturing stderr.
+// GetCapturedStderr() - stops capturing stderr and returns the captured
+// string.
+//
+// Integer types:
+// TypeWithSize - maps an integer to a int type.
+// Int32, UInt32, Int64, UInt64, TimeInMillis
+// - integers of known sizes.
+// BiggestInt - the biggest signed integer type.
+//
+// Command-line utilities:
+// GTEST_FLAG() - references a flag.
+// GTEST_DECLARE_*() - declares a flag.
+// GTEST_DEFINE_*() - defines a flag.
+// GetInjectableArgvs() - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+// GetEnv() - gets the value of an environment variable.
+// BoolFromGTestEnv() - parses a bool environment variable.
+// Int32FromGTestEnv() - parses an Int32 environment variable.
+// StringFromGTestEnv() - parses a string environment variable.
+
+#include <ctype.h> // for isspace, etc
+#include <stddef.h> // for ptrdiff_t
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32_WCE
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif // !_WIN32_WCE
+
+#if defined __APPLE__
+# include <AvailabilityMacros.h>
+# include <TargetConditionals.h>
+#endif
+
+#include <iostream> // NOLINT
+#include <sstream> // NOLINT
+#include <string> // NOLINT
+
+#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+#define GTEST_FLAG_PREFIX_ "gtest_"
+#define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+#define GTEST_NAME_ "Google Test"
+#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/"
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+# define GTEST_GCC_VER_ \
+ (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
+#endif // __GNUC__
+
+// Determines the platform on which Google Test is compiled.
+#ifdef __CYGWIN__
+# define GTEST_OS_CYGWIN 1
+#elif defined __SYMBIAN32__
+# define GTEST_OS_SYMBIAN 1
+#elif defined _WIN32
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+# define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+# define GTEST_OS_WINDOWS_MINGW 1
+# else
+# define GTEST_OS_WINDOWS_DESKTOP 1
+# endif // _WIN32_WCE
+#elif defined __APPLE__
+# define GTEST_OS_MAC 1
+# if TARGET_OS_IPHONE
+# define GTEST_OS_IOS 1
+# if TARGET_IPHONE_SIMULATOR
+# define GTEST_OS_IOS_SIMULATOR 1
+# endif
+# endif
+#elif defined __linux__
+# define GTEST_OS_LINUX 1
+# if defined __ANDROID__
+# define GTEST_OS_LINUX_ANDROID 1
+# endif
+#elif defined __MVS__
+# define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+# define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
+#elif defined __OpenBSD__
+# define GTEST_OS_OPENBSD 1
+#elif defined __QNX__
+# define GTEST_OS_QNX 1
+#endif // __CYGWIN__
+
+#ifndef GTEST_LANG_CXX11
+// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when
+// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a
+// value for __cplusplus, and recent versions of clang, gcc, and
+// probably other compilers set that too in C++11 mode.
+# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L
+// Compiling in at least C++11 mode.
+# define GTEST_LANG_CXX11 1
+# else
+# define GTEST_LANG_CXX11 0
+# endif
+#endif
+
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if !GTEST_OS_WINDOWS
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# include <strings.h>
+#elif !GTEST_OS_WINDOWS_MOBILE
+# include <direct.h>
+# include <io.h>
+#endif
+
+#if GTEST_OS_LINUX_ANDROID
+// Used to define __ANDROID_API__ matching the target NDK API level.
+# include <android/api-level.h> // NOLINT
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# if GTEST_OS_LINUX_ANDROID
+// On Android, <regex.h> is only available starting with Gingerbread.
+# define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9)
+# else
+# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+# endif
+#endif
+
+#if GTEST_HAS_POSIX_RE
+
+// On some platforms, <regex.h> needs someone to define size_t, and
+// won't compile otherwise. We can #include it here as we already
+// included <stdlib.h>, which is guaranteed to define size_t through
+// <stddef.h>.
+# include <regex.h> // NOLINT
+
+# define GTEST_USES_POSIX_RE 1
+
+#elif GTEST_OS_WINDOWS
+
+// <regex.h> is not available on Windows. Use our own simple regex
+// implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#else
+
+// <regex.h> may not be available on this platform. Use our own
+// simple regex implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#endif // GTEST_HAS_POSIX_RE
+
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
+// macro to enable exceptions, so we'll do the same.
+// Assumes that exceptions are enabled by default.
+# ifndef _HAS_EXCEPTIONS
+# define _HAS_EXCEPTIONS 1
+# endif // _HAS_EXCEPTIONS
+# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__GNUC__) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions. However, there is no compile-time way of
+// detecting whether they are enabled or not. Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
+// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+# define GTEST_HAS_EXCEPTIONS 1
+# else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
+# define GTEST_HAS_EXCEPTIONS 0
+# endif // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif // GTEST_HAS_EXCEPTIONS
+
+#if !defined(GTEST_HAS_STD_STRING)
+// Even though we don't use this macro any longer, we keep it in case
+// some clients still depend on it.
+# define GTEST_HAS_STD_STRING 1
+#elif !GTEST_HAS_STD_STRING
+// The user told us that ::std::string isn't available.
+# error "Google Test cannot be used where ::std::string isn't available."
+#endif // !defined(GTEST_HAS_STD_STRING)
+
+#ifndef GTEST_HAS_GLOBAL_STRING
+// The user didn't tell us whether ::string is available, so we need
+// to figure it out.
+
+# define GTEST_HAS_GLOBAL_STRING 0
+
+#endif // GTEST_HAS_GLOBAL_STRING
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring
+// is available.
+
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either. Android has
+// no support for it at least as recent as Froyo (2.2).
+# define GTEST_HAS_STD_WSTRING \
+ (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS))
+
+#endif // GTEST_HAS_STD_WSTRING
+
+#ifndef GTEST_HAS_GLOBAL_WSTRING
+// The user didn't tell us whether ::wstring is available, so we need
+// to figure it out.
+# define GTEST_HAS_GLOBAL_WSTRING \
+ (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+# ifdef _MSC_VER
+
+# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled.
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+
+# ifdef __GXX_RTTI
+// When building against STLport with the Android NDK and with
+// -frtti -fno-exceptions, the build fails at link time with undefined
+// references to __cxa_bad_typeid. Note sure if STL or toolchain bug,
+// so disable RTTI when detected.
+# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \
+ !defined(__EXCEPTIONS)
+# define GTEST_HAS_RTTI 0
+# else
+# define GTEST_HAS_RTTI 1
+# endif // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS
+# else
+# define GTEST_HAS_RTTI 0
+# endif // __GXX_RTTI
+
+// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends
+// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the
+// first version with C++ support.
+# elif defined(__clang__)
+
+# define GTEST_HAS_RTTI __has_feature(cxx_rtti)
+
+// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
+// both the typeid and dynamic_cast features are present.
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+
+# ifdef __RTTI_ALL__
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif
+
+# else
+
+// For all other compilers, we assume RTTI is enabled.
+# define GTEST_HAS_RTTI 1
+
+# endif // _MSC_VER
+
+#endif // GTEST_HAS_RTTI
+
+// It's this header's responsibility to #include <typeinfo> when RTTI
+// is enabled.
+#if GTEST_HAS_RTTI
+# include <typeinfo>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we assume pthreads support is
+// available on Linux and Mac.
+//
+// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
+// to your compiler flags.
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \
+ || GTEST_OS_QNX)
+#endif // GTEST_HAS_PTHREAD
+
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h> // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h> // NOLINT
+#endif
+
+// Determines whether Google Test can use tr1/tuple. You can define
+// this macro to 0 to prevent Google Test from using tuple (any
+// feature depending on tuple with be disabled in this mode).
+#ifndef GTEST_HAS_TR1_TUPLE
+# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR)
+// STLport, provided with the Android NDK, has neither <tr1/tuple> or <tuple>.
+# define GTEST_HAS_TR1_TUPLE 0
+# else
+// The user didn't tell us not to do it, so we assume it's OK.
+# define GTEST_HAS_TR1_TUPLE 1
+# endif
+#endif // GTEST_HAS_TR1_TUPLE
+
+// Determines whether Google Test's own tr1 tuple implementation
+// should be used.
+#ifndef GTEST_USE_OWN_TR1_TUPLE
+// The user didn't tell us, so we need to figure it out.
+
+// We use our own TR1 tuple if we aren't sure the user has an
+// implementation of it already. At this time, libstdc++ 4.0.0+ and
+// MSVC 2010 are the only mainstream standard libraries that come
+// with a TR1 tuple implementation. NVIDIA's CUDA NVCC compiler
+// pretends to be GCC by defining __GNUC__ and friends, but cannot
+// compile GCC's tuple implementation. MSVC 2008 (9.0) provides TR1
+// tuple in a 323 MB Feature Pack download, which we cannot assume the
+// user has. QNX's QCC compiler is a modified GCC but it doesn't
+// support TR1 tuple. libc++ only provides std::tuple, in C++11 mode,
+// and it can be used with some compilers that define __GNUC__.
+# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \
+ && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600
+# define GTEST_ENV_HAS_TR1_TUPLE_ 1
+# endif
+
+// C++11 specifies that <tuple> provides std::tuple. Use that if gtest is used
+// in C++11 mode and libstdc++ isn't very old (binaries targeting OS X 10.6
+// can build with clang but need to use gcc4.2's libstdc++).
+# if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325)
+# define GTEST_ENV_HAS_STD_TUPLE_ 1
+# endif
+
+# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_
+# define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+# define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
+
+#endif // GTEST_USE_OWN_TR1_TUPLE
+
+// To avoid conditional compilation everywhere, we make it
+// gtest-port.h's responsibility to #include the header implementing
+// tr1/tuple.
+#if GTEST_HAS_TR1_TUPLE
+
+# if GTEST_USE_OWN_TR1_TUPLE
+# include "gtest/internal/gtest-tuple.h"
+# elif GTEST_ENV_HAS_STD_TUPLE_
+# include <tuple>
+// C++11 puts its tuple into the ::std namespace rather than
+// ::std::tr1. gtest expects tuple to live in ::std::tr1, so put it there.
+// This causes undefined behavior, but supported compilers react in
+// the way we intend.
+namespace std {
+namespace tr1 {
+using ::std::get;
+using ::std::make_tuple;
+using ::std::tuple;
+using ::std::tuple_element;
+using ::std::tuple_size;
+}
+}
+
+# elif GTEST_OS_SYMBIAN
+
+// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
+// use STLport's tuple implementation, which unfortunately doesn't
+// work as the copy of STLport distributed with Symbian is incomplete.
+// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
+// use its own tuple implementation.
+# ifdef BOOST_HAS_TR1_TUPLE
+# undef BOOST_HAS_TR1_TUPLE
+# endif // BOOST_HAS_TR1_TUPLE
+
+// This prevents <boost/tr1/detail/config.hpp>, which defines
+// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
+# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+# include <tuple>
+
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does
+// not conform to the TR1 spec, which requires the header to be <tuple>.
+
+# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
+// which is #included by <tr1/tuple>, to not compile when RTTI is
+// disabled. _TR1_FUNCTIONAL is the header guard for
+// <tr1/functional>. Hence the following #define is a hack to prevent
+// <tr1/functional> from being included.
+# define _TR1_FUNCTIONAL 1
+# include <tr1/tuple>
+# undef _TR1_FUNCTIONAL // Allows the user to #include
+ // <tr1/functional> if he chooses to.
+# else
+# include <tr1/tuple> // NOLINT
+# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+
+# else
+// If the compiler is not GCC 4.0+, we assume the user is using a
+// spec-conforming TR1 implementation.
+# include <tuple> // NOLINT
+# endif // GTEST_USE_OWN_TR1_TUPLE
+
+#endif // GTEST_HAS_TR1_TUPLE
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see http://linux.die.net/man/2/clone.
+#ifndef GTEST_HAS_CLONE
+// The user didn't tell us, so we need to figure it out.
+
+# if GTEST_OS_LINUX && !defined(__ia64__)
+# if GTEST_OS_LINUX_ANDROID
+// On Android, clone() is only available on ARM starting with Gingerbread.
+# if defined(__arm__) && __ANDROID_API__ >= 9
+# define GTEST_HAS_CLONE 1
+# else
+# define GTEST_HAS_CLONE 0
+# endif
+# else
+# define GTEST_HAS_CLONE 1
+# endif
+# else
+# define GTEST_HAS_CLONE 0
+# endif // GTEST_OS_LINUX && !defined(__ia64__)
+
+#endif // GTEST_HAS_CLONE
+
+// Determines whether to support stream redirection. This is used to test
+// output correctness and to implement death tests.
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
+# define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+# define GTEST_HAS_STREAM_REDIRECTION 1
+# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif // GTEST_HAS_STREAM_REDIRECTION
+
+// Determines whether to support death tests.
+// Google Test does not support death tests for VC 7.1 and earlier as
+// abort() in a VC 7.1 application compiled as GUI in debug config
+// pops up a dialog window that cannot be suppressed programmatically.
+#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
+ (GTEST_OS_MAC && !GTEST_OS_IOS) || GTEST_OS_IOS_SIMULATOR || \
+ (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
+ GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \
+ GTEST_OS_OPENBSD || GTEST_OS_QNX)
+# define GTEST_HAS_DEATH_TEST 1
+# include <vector> // NOLINT
+#endif
+
+// We don't support MSVC 7.1 with exceptions disabled now. Therefore
+// all the compilers we care about are adequate for supporting
+// value-parameterized tests.
+#define GTEST_HAS_PARAM_TEST 1
+
+// Determines whether to support type-driven tests.
+
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
+#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
+ defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether to support Combine(). This only makes sense when
+// value-parameterized tests are enabled. The implementation doesn't
+// work on Sun Studio since it doesn't understand templated conversion
+// operators.
+#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
+# define GTEST_HAS_COMBINE 1
+#endif
+
+// Determines whether the system compiler uses UTF-16 for encoding wide strings.
+#define GTEST_WIDE_STRING_USES_UTF16_ \
+ (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding. This leads to problems with code like:
+//
+// if (gate)
+// ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT
+#endif
+
+// Use this annotation at the end of a struct/class definition to
+// prevent the compiler from optimizing away instances that are never
+// used. This is useful when all interesting logic happens inside the
+// c'tor and / or d'tor. Example:
+//
+// struct Foo {
+// Foo() { ... }
+// } GTEST_ATTRIBUTE_UNUSED_;
+//
+// Also use it after a variable or parameter declaration to tell the
+// compiler the variable/parameter does not have to be used.
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+#else
+# define GTEST_ATTRIBUTE_UNUSED_
+#endif
+
+// A macro to disallow operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_ASSIGN_(type)\
+ void operator=(type const &)
+
+// A macro to disallow copy constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
+ type(type const &);\
+ GTEST_DISALLOW_ASSIGN_(type)
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro. The macro should be used on function declarations
+// following the argument list:
+//
+// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
+#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+#else
+# define GTEST_MUST_USE_RESULT_
+#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling. This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+# define GTEST_HAS_SEH 1
+# else
+// Assume no SEH.
+# define GTEST_HAS_SEH 0
+# endif
+
+#endif // GTEST_HAS_SEH
+
+#ifdef _MSC_VER
+
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+# define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+# define GTEST_API_ __declspec(dllexport)
+# endif
+
+#endif // _MSC_VER
+
+#ifndef GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
+#endif
+
+// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project.
+#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
+# define GTEST_HAS_CXXABI_H_ 1
+#else
+# define GTEST_HAS_CXXABI_H_ 0
+#endif
+
+namespace testing {
+
+class Message;
+
+namespace internal {
+
+// A secret type that Google Test users don't know about. It has no
+// definition on purpose. Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+// content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define GTEST_COMPILE_ASSERT_(expr, msg) \
+ typedef ::testing::internal::CompileAssert<(static_cast<bool>(expr))> \
+ msg[static_cast<bool>(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+// elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+// does not work, as gcc supports variable-length arrays whose sizes
+// are determined at run-time (this is gcc's extension and not part
+// of the C++ standard). As a result, gcc fails to reject the
+// following code with the simple definition:
+//
+// int foo;
+// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+// // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+// expr is a compile-time constant. (Template arguments must be
+// determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
+//
+// CompileAssert<bool(expr)>
+//
+// instead, these compilers will refuse to compile
+//
+// GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+// (They seem to think the ">" in "5 > 0" marks the end of the
+// template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+// ((expr) ? 1 : -1).
+//
+// This is to avoid running into a bug in MS VC 7.1, which
+// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {};
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+// A helper for suppressing warnings on constant condition. It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines scoped_ptr.
+
+// This implementation of scoped_ptr is PARTIAL - it only contains
+// enough stuff to satisfy Google Test's need.
+template <typename T>
+class scoped_ptr {
+ public:
+ typedef T element_type;
+
+ explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
+ ~scoped_ptr() { reset(); }
+
+ T& operator*() const { return *ptr_; }
+ T* operator->() const { return ptr_; }
+ T* get() const { return ptr_; }
+
+ T* release() {
+ T* const ptr = ptr_;
+ ptr_ = NULL;
+ return ptr;
+ }
+
+ void reset(T* p = NULL) {
+ if (p != ptr_) {
+ if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type.
+ delete ptr_;
+ }
+ ptr_ = p;
+ }
+ }
+
+ private:
+ T* ptr_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr);
+};
+
+// Defines RE.
+
+// A simple C++ wrapper for <regex.h>. It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+ // A copy constructor is required by the Standard to initialize object
+ // references from r-values.
+ RE(const RE& other) { Init(other.pattern()); }
+
+ // Constructs an RE from a string.
+ RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT
+
+#if GTEST_HAS_GLOBAL_STRING
+
+ RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT
+
+#endif // GTEST_HAS_GLOBAL_STRING
+
+ RE(const char* regex) { Init(regex); } // NOLINT
+ ~RE();
+
+ // Returns the string representation of the regex.
+ const char* pattern() const { return pattern_; }
+
+ // FullMatch(str, re) returns true iff regular expression re matches
+ // the entire str.
+ // PartialMatch(str, re) returns true iff regular expression re
+ // matches a substring of str (including str itself).
+ //
+ // TODO(wan@google.com): make FullMatch() and PartialMatch() work
+ // when str contains NUL characters.
+ static bool FullMatch(const ::std::string& str, const RE& re) {
+ return FullMatch(str.c_str(), re);
+ }
+ static bool PartialMatch(const ::std::string& str, const RE& re) {
+ return PartialMatch(str.c_str(), re);
+ }
+
+#if GTEST_HAS_GLOBAL_STRING
+
+ static bool FullMatch(const ::string& str, const RE& re) {
+ return FullMatch(str.c_str(), re);
+ }
+ static bool PartialMatch(const ::string& str, const RE& re) {
+ return PartialMatch(str.c_str(), re);
+ }
+
+#endif // GTEST_HAS_GLOBAL_STRING
+
+ static bool FullMatch(const char* str, const RE& re);
+ static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+ void Init(const char* regex);
+
+ // We use a const char* instead of an std::string, as Google Test used to be
+ // used where std::string is not available. TODO(wan@google.com): change to
+ // std::string.
+ const char* pattern_;
+ bool is_valid_;
+
+#if GTEST_USES_POSIX_RE
+
+ regex_t full_regex_; // For FullMatch().
+ regex_t partial_regex_; // For PartialMatch().
+
+#else // GTEST_USES_SIMPLE_RE
+
+ const char* full_pattern_; // For FullMatch();
+
+#endif
+
+ GTEST_DISALLOW_ASSIGN_(RE);
+};
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+ int line);
+
+// Defines logging utilities:
+// GTEST_LOG_(severity) - logs messages at the specified severity level. The
+// message itself is streamed into the macro.
+// LogToStderr() - directs all log messages to stderr.
+// FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity {
+ GTEST_INFO,
+ GTEST_WARNING,
+ GTEST_ERROR,
+ GTEST_FATAL
+};
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+ GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+ // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+ ~GTestLog();
+
+ ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+ const GTestLogSeverity severity_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
+};
+
+#define GTEST_LOG_(severity) \
+ ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+ __FILE__, __LINE__).GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(NULL); }
+
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+// Synopsys:
+// GTEST_CHECK_(boolean_condition);
+// or
+// GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+// This checks the condition and if the condition is not satisfied
+// it prints message about the condition violation, including the
+// condition itself, plus additional message streamed into it, if any,
+// and then it aborts the program. It aborts the program irrespective of
+// whether it is built in the debug mode or not.
+#define GTEST_CHECK_(condition) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (::testing::internal::IsTrue(condition)) \
+ ; \
+ else \
+ GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success). Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+ if (const int gtest_error = (posix_call)) \
+ GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
+ << gtest_error
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*). When you use ImplicitCast_, the compiler checks that
+// the cast is safe. Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+// ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late. It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed. When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo? It
+// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
+// when you downcast, you should use this macro. In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not). In normal mode, we do the efficient static_cast<>
+// instead. Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+// This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From> // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) { // so we only accept pointers
+ // Ensures that To is a sub-type of From *. This test is here only
+ // for compile-time type checking, and has no overhead in an
+ // optimized build at run-time, as it will be optimized away
+ // completely.
+ if (false) {
+ const To to = NULL;
+ ::testing::internal::ImplicitCast_<From*>(to);
+ }
+
+#if GTEST_HAS_RTTI
+ // RTTI: debug mode only!
+ GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+ return static_cast<To>(f);
+}
+
+// Downcasts the pointer of type Base to Derived.
+// Derived must be a subclass of Base. The parameter MUST
+// point to a class of type Derived, not any subclass of it.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+#if GTEST_HAS_RTTI
+ GTEST_CHECK_(typeid(*base) == typeid(Derived));
+ return dynamic_cast<Derived*>(base); // NOLINT
+#else
+ return static_cast<Derived*>(base); // Poor man's downcast.
+#endif
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Defines the stderr capturer:
+// CaptureStdout - starts capturing stdout.
+// GetCapturedStdout - stops capturing stdout and returns the captured string.
+// CaptureStderr - starts capturing stderr.
+// GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ std::string GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ std::string GetCapturedStderr();
+
+#endif // GTEST_HAS_STREAM_REDIRECTION
+
+
+#if GTEST_HAS_DEATH_TEST
+
+const ::std::vector<testing::internal::string>& GetInjectableArgvs();
+void SetInjectableArgvs(const ::std::vector<testing::internal::string>*
+ new_argvs);
+
+// A copy of all command line arguments. Set by InitGoogleTest().
+extern ::std::vector<testing::internal::string> g_argvs;
+
+#endif // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+
+#if GTEST_HAS_PTHREAD
+
+// Sleeps for (roughly) n milli-seconds. This function is only for
+// testing Google Test's own constructs. Don't use it in user tests,
+// either directly or indirectly.
+inline void SleepMilliseconds(int n) {
+ const timespec time = {
+ 0, // 0 seconds.
+ n * 1000L * 1000L, // And n ms.
+ };
+ nanosleep(&time, NULL);
+}
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified. Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class Notification {
+ public:
+ Notification() : notified_(false) {
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+ }
+ ~Notification() {
+ pthread_mutex_destroy(&mutex_);
+ }
+
+ // Notifies all threads created with this notification to start. Must
+ // be called from the controller thread.
+ void Notify() {
+ pthread_mutex_lock(&mutex_);
+ notified_ = true;
+ pthread_mutex_unlock(&mutex_);
+ }
+
+ // Blocks until the controller thread notifies. Must be called from a test
+ // thread.
+ void WaitForNotification() {
+ for (;;) {
+ pthread_mutex_lock(&mutex_);
+ const bool notified = notified_;
+ pthread_mutex_unlock(&mutex_);
+ if (notified)
+ break;
+ SleepMilliseconds(10);
+ }
+ }
+
+ private:
+ pthread_mutex_t mutex_;
+ bool notified_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+ virtual ~ThreadWithParamBase() {}
+ virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical. Some compilers (for
+// example, SunStudio) treat them as different types. Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+ static_cast<ThreadWithParamBase*>(thread)->Run();
+ return NULL;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+// void ThreadFunc(int param) { /* Do things with param */ }
+// Notification thread_can_start;
+// ...
+// // The thread_can_start parameter is optional; you can supply NULL.
+// ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+// thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+ typedef void (*UserThreadFunc)(T);
+
+ ThreadWithParam(
+ UserThreadFunc func, T param, Notification* thread_can_start)
+ : func_(func),
+ param_(param),
+ thread_can_start_(thread_can_start),
+ finished_(false) {
+ ThreadWithParamBase* const base = this;
+ // The thread can be created only after all fields except thread_
+ // have been initialized.
+ GTEST_CHECK_POSIX_SUCCESS_(
+ pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base));
+ }
+ ~ThreadWithParam() { Join(); }
+
+ void Join() {
+ if (!finished_) {
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
+ finished_ = true;
+ }
+ }
+
+ virtual void Run() {
+ if (thread_can_start_ != NULL)
+ thread_can_start_->WaitForNotification();
+ func_(param_);
+ }
+
+ private:
+ const UserThreadFunc func_; // User-supplied thread function.
+ const T param_; // User-supplied parameter to the thread function.
+ // When non-NULL, used to block execution until the controller thread
+ // notifies.
+ Notification* const thread_can_start_;
+ bool finished_; // true iff we know that the thread function has finished.
+ pthread_t thread_; // The native thread object.
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+
+// MutexBase and Mutex implement mutex on pthreads-based platforms. They
+// are used in conjunction with class MutexLock:
+//
+// Mutex mutex;
+// ...
+// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end
+// // of the current scope.
+//
+// MutexBase implements behavior for both statically and dynamically
+// allocated mutexes. Do not use MutexBase directly. Instead, write
+// the following to define a static mutex:
+//
+// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//
+// You can forward declare a static mutex like this:
+//
+// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// To create a dynamic mutex, just define an object of type Mutex.
+class MutexBase {
+ public:
+ // Acquires this mutex.
+ void Lock() {
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+ owner_ = pthread_self();
+ has_owner_ = true;
+ }
+
+ // Releases this mutex.
+ void Unlock() {
+ // Since the lock is being released the owner_ field should no longer be
+ // considered valid. We don't protect writing to has_owner_ here, as it's
+ // the caller's responsibility to ensure that the current thread holds the
+ // mutex when this is called.
+ has_owner_ = false;
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+ }
+
+ // Does nothing if the current thread holds the mutex. Otherwise, crashes
+ // with high probability.
+ void AssertHeld() const {
+ GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self()))
+ << "The current thread is not holding the mutex @" << this;
+ }
+
+ // A static mutex may be used before main() is entered. It may even
+ // be used before the dynamic initialization stage. Therefore we
+ // must be able to initialize a static mutex object at link time.
+ // This means MutexBase has to be a POD and its member variables
+ // have to be public.
+ public:
+ pthread_mutex_t mutex_; // The underlying pthread mutex.
+ // has_owner_ indicates whether the owner_ field below contains a valid thread
+ // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All
+ // accesses to the owner_ field should be protected by a check of this field.
+ // An alternative might be to memset() owner_ to all zeros, but there's no
+ // guarantee that a zero'd pthread_t is necessarily invalid or even different
+ // from pthread_self().
+ bool has_owner_;
+ pthread_t owner_; // The thread holding the mutex.
+};
+
+// Forward-declares a static mutex.
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+ extern ::testing::internal::MutexBase mutex
+
+// Defines and statically (i.e. at link time) initializes a static mutex.
+// The initialization list here does not explicitly initialize each field,
+// instead relying on default initialization for the unspecified fields. In
+// particular, the owner_ field (a pthread_t) is not explicitly initialized.
+// This allows initialization to work whether pthread_t is a scalar or struct.
+// The flag -Wmissing-field-initializers must not be specified for this to work.
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+ ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false }
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+ Mutex() {
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+ has_owner_ = false;
+ }
+ ~Mutex() {
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
+ }
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+// We cannot name this class MutexLock as the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms. Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+ explicit GTestMutexLock(MutexBase* mutex)
+ : mutex_(mutex) { mutex_->Lock(); }
+
+ ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+ MutexBase* const mutex_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage. Therefore it cannot be templatized to access
+// ThreadLocal<T>. Hence the need for class
+// ThreadLocalValueHolderBase.
+class ThreadLocalValueHolderBase {
+ public:
+ virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+ delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+//
+// // Thread 1
+// ThreadLocal<int> tl(100); // 100 is the default value for each thread.
+//
+// // Thread 2
+// tl.set(150); // Changes the value for thread 2 only.
+// EXPECT_EQ(150, tl.get());
+//
+// // Thread 1
+// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value.
+// tl.set(200);
+// EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// An object managed for a thread by a ThreadLocal instance is deleted
+// when the thread exits. Or, if the ThreadLocal instance dies in
+// that thread, when the ThreadLocal dies. It's the user's
+// responsibility to ensure that all other threads using a ThreadLocal
+// have exited when it dies, or the per-thread objects for those
+// threads will not be deleted.
+//
+// Google Test only uses global ThreadLocal objects. That means they
+// will die after main() has returned. Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal {
+ public:
+ ThreadLocal() : key_(CreateKey()),
+ default_() {}
+ explicit ThreadLocal(const T& value) : key_(CreateKey()),
+ default_(value) {}
+
+ ~ThreadLocal() {
+ // Destroys the managed object for the current thread, if any.
+ DeleteThreadLocalValue(pthread_getspecific(key_));
+
+ // Releases resources associated with the key. This will *not*
+ // delete managed objects for other threads.
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+ }
+
+ T* pointer() { return GetOrCreateValue(); }
+ const T* pointer() const { return GetOrCreateValue(); }
+ const T& get() const { return *pointer(); }
+ void set(const T& value) { *pointer() = value; }
+
+ private:
+ // Holds a value of type T.
+ class ValueHolder : public ThreadLocalValueHolderBase {
+ public:
+ explicit ValueHolder(const T& value) : value_(value) {}
+
+ T* pointer() { return &value_; }
+
+ private:
+ T value_;
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+ };
+
+ static pthread_key_t CreateKey() {
+ pthread_key_t key;
+ // When a thread exits, DeleteThreadLocalValue() will be called on
+ // the object managed for that thread.
+ GTEST_CHECK_POSIX_SUCCESS_(
+ pthread_key_create(&key, &DeleteThreadLocalValue));
+ return key;
+ }
+
+ T* GetOrCreateValue() const {
+ ThreadLocalValueHolderBase* const holder =
+ static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+ if (holder != NULL) {
+ return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+ }
+
+ ValueHolder* const new_holder = new ValueHolder(default_);
+ ThreadLocalValueHolderBase* const holder_base = new_holder;
+ GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+ return new_holder->pointer();
+ }
+
+ // A key pthreads uses for looking up per-thread values.
+ const pthread_key_t key_;
+ const T default_; // The default value for each thread.
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# define GTEST_IS_THREADSAFE 1
+
+#else // GTEST_HAS_PTHREAD
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable). Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+ Mutex() {}
+ void Lock() {}
+ void Unlock() {}
+ void AssertHeld() const {}
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+ extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+class GTestMutexLock {
+ public:
+ explicit GTestMutexLock(Mutex*) {} // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class ThreadLocal {
+ public:
+ ThreadLocal() : value_() {}
+ explicit ThreadLocal(const T& value) : value_(value) {}
+ T* pointer() { return &value_; }
+ const T* pointer() const { return &value_; }
+ const T& get() const { return value_; }
+ void set(const T& value) { value_ = value; }
+ private:
+ T value_;
+};
+
+// The above synchronization primitives have dummy implementations.
+// Therefore Google Test is not thread-safe.
+# define GTEST_IS_THREADSAFE 0
+
+#endif // GTEST_HAS_PTHREAD
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+// Passing non-POD classes through ellipsis (...) crashes the ARM
+// compiler and generates a warning in Sun Studio. The Nokia Symbian
+// and the IBM XL C/C++ compiler try to instantiate a copy constructor
+// for objects passed through ellipsis (...), failing for uncopyable
+// objects. We define this to ensure that only POD is passed through
+// ellipsis on these systems.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
+#else
+# define GTEST_CAN_COMPARE_NULL 1
+#endif
+
+// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
+// const T& and const T* in a function template. These compilers
+// _can_ decide between class template specializations for T and T*,
+// so a tr1::type_traits-like is_pointer works.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
+# define GTEST_NEEDS_IS_POINTER_ 1
+#endif
+
+template <bool bool_value>
+struct bool_constant {
+ typedef bool_constant<bool_value> type;
+ static const bool value = bool_value;
+};
+template <bool bool_value> const bool bool_constant<bool_value>::value;
+
+typedef bool_constant<false> false_type;
+typedef bool_constant<true> true_type;
+
+template <typename T>
+struct is_pointer : public false_type {};
+
+template <typename T>
+struct is_pointer<T*> : public true_type {};
+
+template <typename Iterator>
+struct IteratorTraits {
+ typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+ typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+ typedef T value_type;
+};
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
+// The biggest signed integer type the compiler supports.
+typedef __int64 BiggestInt;
+#else
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
+typedef long long BiggestInt; // NOLINT
+#endif // GTEST_OS_WINDOWS
+
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF. char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+ return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+ return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+ return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+ return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+ return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+ return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+ return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(wchar_t ch) {
+ const unsigned char low_byte = static_cast<unsigned char>(ch);
+ return ch == low_byte && isxdigit(low_byte) != 0;
+}
+
+inline char ToLower(char ch) {
+ return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+ return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
+// The testing::internal::posix namespace holds wrappers for common
+// POSIX functions. These wrappers hide the differences between
+// Windows/MSVC and POSIX systems. Since some compilers define these
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// Functions with a different name on Windows.
+
+#if GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+# ifdef __BORLANDC__
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+ return stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+# else // !__BORLANDC__
+# if GTEST_OS_WINDOWS_MOBILE
+inline int IsATTY(int /* fd */) { return 0; }
+# else
+inline int IsATTY(int fd) { return _isatty(fd); }
+# endif // GTEST_OS_WINDOWS_MOBILE
+inline int StrCaseCmp(const char* s1, const char* s2) {
+ return _stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return _strdup(src); }
+# endif // __BORLANDC__
+
+# if GTEST_OS_WINDOWS_MOBILE
+inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
+// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
+// time and thus not defined there.
+# else
+inline int FileNo(FILE* file) { return _fileno(file); }
+inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
+inline int RmDir(const char* dir) { return _rmdir(dir); }
+inline bool IsDir(const StatStruct& st) {
+ return (_S_IFDIR & st.st_mode) != 0;
+}
+# endif // GTEST_OS_WINDOWS_MOBILE
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+ return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#endif // GTEST_OS_WINDOWS
+
+// Functions deprecated by MSVC 8.0.
+
+#ifdef _MSC_VER
+// Temporarily disable warning 4996 (deprecated function).
+# pragma warning(push)
+# pragma warning(disable:4996)
+#endif
+
+inline const char* StrNCpy(char* dest, const char* src, size_t n) {
+ return strncpy(dest, src, n);
+}
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+ return fopen(path, mode);
+}
+#if !GTEST_OS_WINDOWS_MOBILE
+inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
+ return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int Read(int fd, void* buf, unsigned int count) {
+ return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+ return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif
+inline const char* GetEnv(const char* name) {
+#if GTEST_OS_WINDOWS_MOBILE
+ // We are on Windows CE, which has no environment variables.
+ return NULL;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+ // Environment variables which we programmatically clear will be set to the
+ // empty string rather than unset (NULL). Handle that case.
+ const char* const env = getenv(name);
+ return (env != NULL && env[0] != '\0') ? env : NULL;
+#else
+ return getenv(name);
+#endif
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop) // Restores the warning state.
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+void Abort();
+#else
+inline void Abort() { abort(); }
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+} // namespace posix
+
+// MSVC "deprecates" snprintf and issues warnings wherever it is used. In
+// order to avoid these warnings, we need to use _snprintf or _snprintf_s on
+// MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate
+// function in order to achieve that. We use macro definition here because
+// snprintf is a variadic function.
+#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+// MSVC 2005 and above support variadic macros.
+# define GTEST_SNPRINTF_(buffer, size, format, ...) \
+ _snprintf_s(buffer, size, size, format, __VA_ARGS__)
+#elif defined(_MSC_VER)
+// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't
+// complain about _snprintf.
+# define GTEST_SNPRINTF_ _snprintf
+#else
+# define GTEST_SNPRINTF_ snprintf
+#endif
+
+// The maximum number a BiggestInt can represent. This definition
+// works no matter BiggestInt is represented in one's complement or
+// two's complement.
+//
+// We cannot rely on numeric_limits in STL, as __int64 and long long
+// are not part of standard C++ and numeric_limits doesn't need to be
+// defined for them.
+const BiggestInt kMaxBiggestInt =
+ ~(static_cast<BiggestInt>(1) << (8*sizeof(BiggestInt) - 1));
+
+// This template class serves as a compile-time function from size to
+// type. It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+// TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs. Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+ // This prevents the user from using TypeWithSize<N> with incorrect
+ // values of N.
+ typedef void UInt;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+ // unsigned int has size 4 in both gcc and MSVC.
+ //
+ // As base/basictypes.h doesn't compile on Windows, we cannot use
+ // uint32, uint64, and etc here.
+ typedef int Int;
+ typedef unsigned int UInt;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+#if GTEST_OS_WINDOWS
+ typedef __int64 Int;
+ typedef unsigned __int64 UInt;
+#else
+ typedef long long Int; // NOLINT
+ typedef unsigned long long UInt; // NOLINT
+#endif // GTEST_OS_WINDOWS
+};
+
+// Integer types of known sizes.
+typedef TypeWithSize<4>::Int Int32;
+typedef TypeWithSize<4>::UInt UInt32;
+typedef TypeWithSize<8>::Int Int64;
+typedef TypeWithSize<8>::UInt UInt64;
+typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#define GTEST_FLAG(name) FLAGS_gtest_##name
+
+// Macros for declaring flags.
+#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
+#define GTEST_DECLARE_int32_(name) \
+ GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
+#define GTEST_DECLARE_string_(name) \
+ GTEST_API_ extern ::std::string GTEST_FLAG(name)
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc) \
+ GTEST_API_ bool GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_int32_(name, default_val, doc) \
+ GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_string_(name, default_val, doc) \
+ GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val)
+
+// Thread annotations
+#define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
+#define GTEST_LOCK_EXCLUDED_(locks)
+
+// Parses 'str' for a 32-bit signed integer. If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+// TODO(chandlerc): Find a better way to refactor flag and environment parsing
+// out of both gtest-port.cc and gtest.cc to avoid exporting this utility
+// function.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value);
+
+// Parses a bool/Int32/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-string.h b/thirdparty/gtest/include/gtest/internal/gtest-string.h
new file mode 100644
index 00000000..97f1a7fd
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-string.h
@@ -0,0 +1,167 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test. They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by <gtest/internal/gtest-internal.h>.
+// It should not be #included by other files.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+# include <mem.h>
+#endif
+
+#include <string.h>
+#include <string>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// String - an abstract class holding static string utilities.
+class GTEST_API_ String {
+ public:
+ // Static utility methods
+
+ // Clones a 0-terminated C string, allocating memory using new. The
+ // caller is responsible for deleting the return value using
+ // delete[]. Returns the cloned string, or NULL if the input is
+ // NULL.
+ //
+ // This is different from strdup() in string.h, which allocates
+ // memory using malloc().
+ static const char* CloneCString(const char* c_str);
+
+#if GTEST_OS_WINDOWS_MOBILE
+ // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+ // able to pass strings to Win32 APIs on CE we need to convert them
+ // to 'Unicode', UTF-16.
+
+ // Creates a UTF-16 wide string from the given ANSI string, allocating
+ // memory using new. The caller is responsible for deleting the return
+ // value using delete[]. Returns the wide string, or NULL if the
+ // input is NULL.
+ //
+ // The wide string is created using the ANSI codepage (CP_ACP) to
+ // match the behaviour of the ANSI versions of Win32 calls and the
+ // C runtime.
+ static LPCWSTR AnsiToUtf16(const char* c_str);
+
+ // Creates an ANSI string from the given wide string, allocating
+ // memory using new. The caller is responsible for deleting the return
+ // value using delete[]. Returns the ANSI string, or NULL if the
+ // input is NULL.
+ //
+ // The returned string is created using the ANSI codepage (CP_ACP) to
+ // match the behaviour of the ANSI versions of Win32 calls and the
+ // C runtime.
+ static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+ // Compares two C strings. Returns true iff they have the same content.
+ //
+ // Unlike strcmp(), this function can handle NULL argument(s). A
+ // NULL C string is considered different to any non-NULL C string,
+ // including the empty string.
+ static bool CStringEquals(const char* lhs, const char* rhs);
+
+ // Converts a wide C string to a String using the UTF-8 encoding.
+ // NULL will be converted to "(null)". If an error occurred during
+ // the conversion, "(failed to convert from wide string)" is
+ // returned.
+ static std::string ShowWideCString(const wchar_t* wide_c_str);
+
+ // Compares two wide C strings. Returns true iff they have the same
+ // content.
+ //
+ // Unlike wcscmp(), this function can handle NULL argument(s). A
+ // NULL C string is considered different to any non-NULL C string,
+ // including the empty string.
+ static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+ // Compares two C strings, ignoring case. Returns true iff they
+ // have the same content.
+ //
+ // Unlike strcasecmp(), this function can handle NULL argument(s).
+ // A NULL C string is considered different to any non-NULL C string,
+ // including the empty string.
+ static bool CaseInsensitiveCStringEquals(const char* lhs,
+ const char* rhs);
+
+ // Compares two wide C strings, ignoring case. Returns true iff they
+ // have the same content.
+ //
+ // Unlike wcscasecmp(), this function can handle NULL argument(s).
+ // A NULL C string is considered different to any non-NULL wide C string,
+ // including the empty string.
+ // NB: The implementations on different platforms slightly differ.
+ // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+ // environment variable. On GNU platform this method uses wcscasecmp
+ // which compares according to LC_CTYPE category of the current locale.
+ // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+ // current locale.
+ static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+ const wchar_t* rhs);
+
+ // Returns true iff the given string ends with the given suffix, ignoring
+ // case. Any string is considered to end with an empty suffix.
+ static bool EndsWithCaseInsensitive(
+ const std::string& str, const std::string& suffix);
+
+ // Formats an int value as "%02d".
+ static std::string FormatIntWidth2(int value); // "%02d" for width == 2
+
+ // Formats an int value as "%X".
+ static std::string FormatHexInt(int value);
+
+ // Formats a byte as "%02X".
+ static std::string FormatByte(unsigned char value);
+
+ private:
+ String(); // Not meant to be instantiated.
+}; // class String
+
+// Gets the content of the stringstream's buffer as an std::string. Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-tuple.h b/thirdparty/gtest/include/gtest/internal/gtest-tuple.h
new file mode 100644
index 00000000..7b3dfc31
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-tuple.h
@@ -0,0 +1,1012 @@
+// This file was GENERATED by command:
+// pump.py gtest-tuple.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility> // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined). This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+ template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
+ private:
+#endif
+
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
+ void, void, void>
+#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \
+ void, void, void>
+#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \
+ void, void, void>
+#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \
+ void, void, void>
+#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \
+ void, void, void>
+#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \
+ void, void, void>
+#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ void, void, void>
+#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ T##7, void, void>
+#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ T##7, T##8, void>
+#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+ T##7, T##8, T##9>
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+#define GTEST_0_TYPENAMES_(T)
+#define GTEST_1_TYPENAMES_(T) typename T##0
+#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
+#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
+#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3
+#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4
+#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5
+#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6
+#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
+#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6, \
+ typename T##7, typename T##8
+#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+ typename T##3, typename T##4, typename T##5, typename T##6, \
+ typename T##7, typename T##8, typename T##9
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior. We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <typename T0 = void, typename T1 = void, typename T2 = void,
+ typename T3 = void, typename T4 = void, typename T5 = void,
+ typename T6 = void, typename T7 = void, typename T8 = void,
+ typename T9 = void>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; }; // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&. This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; }; // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>. kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 0, GTEST_10_TUPLE_(T) > {
+ typedef T0 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 1, GTEST_10_TUPLE_(T) > {
+ typedef T1 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 2, GTEST_10_TUPLE_(T) > {
+ typedef T2 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 3, GTEST_10_TUPLE_(T) > {
+ typedef T3 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 4, GTEST_10_TUPLE_(T) > {
+ typedef T4 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 5, GTEST_10_TUPLE_(T) > {
+ typedef T5 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 6, GTEST_10_TUPLE_(T) > {
+ typedef T6 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 7, GTEST_10_TUPLE_(T) > {
+ typedef T7 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 8, GTEST_10_TUPLE_(T) > {
+ typedef T8 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 9, GTEST_10_TUPLE_(T) > {
+ typedef T9 type;
+};
+
+} // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+ tuple() {}
+ tuple(const tuple& /* t */) {}
+ tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+class GTEST_1_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
+
+ tuple(const tuple& t) : f0_(t.f0_) {}
+
+ template <GTEST_1_TYPENAMES_(U)>
+ tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_1_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_1_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ return *this;
+ }
+
+ T0 f0_;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+class GTEST_2_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
+ f1_(f1) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
+
+ template <GTEST_2_TYPENAMES_(U)>
+ tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
+ template <typename U0, typename U1>
+ tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_2_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+ template <typename U0, typename U1>
+ tuple& operator=(const ::std::pair<U0, U1>& p) {
+ f0_ = p.first;
+ f1_ = p.second;
+ return *this;
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_2_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+class GTEST_3_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+ template <GTEST_3_TYPENAMES_(U)>
+ tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_3_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_3_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+class GTEST_4_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
+ f3_(f3) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
+
+ template <GTEST_4_TYPENAMES_(U)>
+ tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_4_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_4_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+class GTEST_5_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
+ GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_) {}
+
+ template <GTEST_5_TYPENAMES_(U)>
+ tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_5_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_5_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+class GTEST_6_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+ f5_(f5) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_) {}
+
+ template <GTEST_6_TYPENAMES_(U)>
+ tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_6_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_6_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+class GTEST_7_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
+ f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+ template <GTEST_7_TYPENAMES_(U)>
+ tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_7_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_7_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+class GTEST_8_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
+ GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+ f5_(f5), f6_(f6), f7_(f7) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+ template <GTEST_8_TYPENAMES_(U)>
+ tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_8_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_8_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ f7_ = t.f7_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+ T7 f7_;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+class GTEST_9_TUPLE_(T) {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+ GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+ f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+ template <GTEST_9_TYPENAMES_(U)>
+ tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_9_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_9_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ f7_ = t.f7_;
+ f8_ = t.f8_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+ T7 f7_;
+ T8 f8_;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+class tuple {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
+ f9_() {}
+
+ explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+ GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+ GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+ GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
+ f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
+
+ tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+ f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
+
+ template <GTEST_10_TYPENAMES_(U)>
+ tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+ f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
+ f9_(t.f9_) {}
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_10_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_10_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
+ f0_ = t.f0_;
+ f1_ = t.f1_;
+ f2_ = t.f2_;
+ f3_ = t.f3_;
+ f4_ = t.f4_;
+ f5_ = t.f5_;
+ f6_ = t.f6_;
+ f7_ = t.f7_;
+ f8_ = t.f8_;
+ f9_ = t.f9_;
+ return *this;
+ }
+
+ T0 f0_;
+ T1 f1_;
+ T2 f2_;
+ T3 f3_;
+ T4 f4_;
+ T5 f5_;
+ T6 f6_;
+ T7 f7_;
+ T8 f8_;
+ T9 f9_;
+};
+
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple(). And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+template <GTEST_1_TYPENAMES_(T)>
+inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
+ return GTEST_1_TUPLE_(T)(f0);
+}
+
+template <GTEST_2_TYPENAMES_(T)>
+inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
+ return GTEST_2_TUPLE_(T)(f0, f1);
+}
+
+template <GTEST_3_TYPENAMES_(T)>
+inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
+ return GTEST_3_TUPLE_(T)(f0, f1, f2);
+}
+
+template <GTEST_4_TYPENAMES_(T)>
+inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3) {
+ return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
+}
+
+template <GTEST_5_TYPENAMES_(T)>
+inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4) {
+ return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
+}
+
+template <GTEST_6_TYPENAMES_(T)>
+inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5) {
+ return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
+}
+
+template <GTEST_7_TYPENAMES_(T)>
+inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
+ return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
+}
+
+template <GTEST_8_TYPENAMES_(T)>
+inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
+ return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
+}
+
+template <GTEST_9_TYPENAMES_(T)>
+inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+ const T8& f8) {
+ return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
+}
+
+template <GTEST_10_TYPENAMES_(T)>
+inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+ const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+ const T8& f8, const T9& f9) {
+ return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
+}
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+template <GTEST_0_TYPENAMES_(T)>
+struct tuple_size<GTEST_0_TUPLE_(T) > {
+ static const int value = 0;
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+struct tuple_size<GTEST_1_TUPLE_(T) > {
+ static const int value = 1;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+struct tuple_size<GTEST_2_TUPLE_(T) > {
+ static const int value = 2;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+struct tuple_size<GTEST_3_TUPLE_(T) > {
+ static const int value = 3;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+struct tuple_size<GTEST_4_TUPLE_(T) > {
+ static const int value = 4;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+struct tuple_size<GTEST_5_TUPLE_(T) > {
+ static const int value = 5;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+struct tuple_size<GTEST_6_TUPLE_(T) > {
+ static const int value = 6;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+struct tuple_size<GTEST_7_TUPLE_(T) > {
+ static const int value = 7;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+struct tuple_size<GTEST_8_TUPLE_(T) > {
+ static const int value = 8;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+struct tuple_size<GTEST_9_TUPLE_(T) > {
+ static const int value = 9;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct tuple_size<GTEST_10_TUPLE_(T) > {
+ static const int value = 10;
+};
+
+template <int k, class Tuple>
+struct tuple_element {
+ typedef typename gtest_internal::TupleElement<
+ k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+template <>
+class Get<0> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+ Field(Tuple& t) { return t.f0_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+ ConstField(const Tuple& t) { return t.f0_; }
+};
+
+template <>
+class Get<1> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+ Field(Tuple& t) { return t.f1_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+ ConstField(const Tuple& t) { return t.f1_; }
+};
+
+template <>
+class Get<2> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+ Field(Tuple& t) { return t.f2_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+ ConstField(const Tuple& t) { return t.f2_; }
+};
+
+template <>
+class Get<3> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+ Field(Tuple& t) { return t.f3_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+ ConstField(const Tuple& t) { return t.f3_; }
+};
+
+template <>
+class Get<4> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+ Field(Tuple& t) { return t.f4_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+ ConstField(const Tuple& t) { return t.f4_; }
+};
+
+template <>
+class Get<5> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+ Field(Tuple& t) { return t.f5_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+ ConstField(const Tuple& t) { return t.f5_; }
+};
+
+template <>
+class Get<6> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+ Field(Tuple& t) { return t.f6_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+ ConstField(const Tuple& t) { return t.f6_; }
+};
+
+template <>
+class Get<7> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+ Field(Tuple& t) { return t.f7_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+ ConstField(const Tuple& t) { return t.f7_; }
+};
+
+template <>
+class Get<8> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+ Field(Tuple& t) { return t.f8_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+ ConstField(const Tuple& t) { return t.f8_; }
+};
+
+template <>
+class Get<9> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+ Field(Tuple& t) { return t.f9_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+ ConstField(const Tuple& t) { return t.f9_; }
+};
+
+} // namespace gtest_internal
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(GTEST_10_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(const GTEST_10_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+ return true;
+ }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+ return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+ ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+ }
+};
+
+} // namespace gtest_internal
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator==(const GTEST_10_TUPLE_(T)& t,
+ const GTEST_10_TUPLE_(U)& u) {
+ return gtest_internal::SameSizeTuplePrefixComparator<
+ tuple_size<GTEST_10_TUPLE_(T) >::value,
+ tuple_size<GTEST_10_TUPLE_(U) >::value>::Eq(t, u);
+}
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
+ const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+} // namespace tr1
+} // namespace std
+
+#undef GTEST_0_TUPLE_
+#undef GTEST_1_TUPLE_
+#undef GTEST_2_TUPLE_
+#undef GTEST_3_TUPLE_
+#undef GTEST_4_TUPLE_
+#undef GTEST_5_TUPLE_
+#undef GTEST_6_TUPLE_
+#undef GTEST_7_TUPLE_
+#undef GTEST_8_TUPLE_
+#undef GTEST_9_TUPLE_
+#undef GTEST_10_TUPLE_
+
+#undef GTEST_0_TYPENAMES_
+#undef GTEST_1_TYPENAMES_
+#undef GTEST_2_TYPENAMES_
+#undef GTEST_3_TYPENAMES_
+#undef GTEST_4_TYPENAMES_
+#undef GTEST_5_TYPENAMES_
+#undef GTEST_6_TYPENAMES_
+#undef GTEST_7_TYPENAMES_
+#undef GTEST_8_TYPENAMES_
+#undef GTEST_9_TYPENAMES_
+#undef GTEST_10_TYPENAMES_
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-tuple.h.pump b/thirdparty/gtest/include/gtest/internal/gtest-tuple.h.pump
new file mode 100644
index 00000000..c7d9e039
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-tuple.h.pump
@@ -0,0 +1,339 @@
+$$ -*- mode: c++; -*-
+$var n = 10 $$ Maximum number of tuple fields we want to support.
+$$ This meta comment fixes auto-indentation in Emacs. }}
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility> // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined). This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+ template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
+ private:
+#endif
+
+
+$range i 0..n-1
+$range j 0..n
+$range k 1..n
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+
+$for k [[
+$range m 0..k-1
+$range m2 k..n-1
+#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
+
+]]
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+
+$for j [[
+$range m 0..j-1
+#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
+
+
+]]
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior. We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <$for i, [[typename T$i = void]]>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; }; // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&. This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; }; // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>. kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+
+$for i [[
+template <GTEST_$(n)_TYPENAMES_(T)>
+struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T) > {
+ typedef T$i type;
+};
+
+
+]]
+} // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+ tuple() {}
+ tuple(const tuple& /* t */) {}
+ tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+
+$for k [[
+$range m 0..k-1
+template <GTEST_$(k)_TYPENAMES_(T)>
+class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
+ public:
+ template <int k> friend class gtest_internal::Get;
+
+ tuple() : $for m, [[f$(m)_()]] {}
+
+ explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
+$for m, [[f$(m)_(f$m)]] {}
+
+ tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+ template <GTEST_$(k)_TYPENAMES_(U)>
+ tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
+
+$if k == 2 [[
+ template <typename U0, typename U1>
+ tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+]]
+
+ tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+ template <GTEST_$(k)_TYPENAMES_(U)>
+ tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
+ return CopyFrom(t);
+ }
+
+$if k == 2 [[
+ template <typename U0, typename U1>
+ tuple& operator=(const ::std::pair<U0, U1>& p) {
+ f0_ = p.first;
+ f1_ = p.second;
+ return *this;
+ }
+
+]]
+
+ GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+ template <GTEST_$(k)_TYPENAMES_(U)>
+ tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
+
+$for m [[
+ f$(m)_ = t.f$(m)_;
+
+]]
+ return *this;
+ }
+
+
+$for m [[
+ T$m f$(m)_;
+
+]]
+};
+
+
+]]
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple(). And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+$for k [[
+$range m 0..k-1
+
+template <GTEST_$(k)_TYPENAMES_(T)>
+inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
+ return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
+}
+
+]]
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+
+$for j [[
+template <GTEST_$(j)_TYPENAMES_(T)>
+struct tuple_size<GTEST_$(j)_TUPLE_(T) > {
+ static const int value = $j;
+};
+
+
+]]
+template <int k, class Tuple>
+struct tuple_element {
+ typedef typename gtest_internal::TupleElement<
+ k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+
+$for i [[
+template <>
+class Get<$i> {
+ public:
+ template <class Tuple>
+ static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+ Field(Tuple& t) { return t.f$(i)_; } // NOLINT
+
+ template <class Tuple>
+ static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
+ ConstField(const Tuple& t) { return t.f$(i)_; }
+};
+
+
+]]
+} // namespace gtest_internal
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
+get(GTEST_$(n)_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_$(n)_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
+get(const GTEST_$(n)_TUPLE_(T)& t) {
+ return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+ return true;
+ }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+ template <class Tuple1, class Tuple2>
+ static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+ return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+ ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+ }
+};
+
+} // namespace gtest_internal
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
+ const GTEST_$(n)_TUPLE_(U)& u) {
+ return gtest_internal::SameSizeTuplePrefixComparator<
+ tuple_size<GTEST_$(n)_TUPLE_(T) >::value,
+ tuple_size<GTEST_$(n)_TUPLE_(U) >::value>::Eq(t, u);
+}
+
+template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
+ const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+} // namespace tr1
+} // namespace std
+
+
+$for j [[
+#undef GTEST_$(j)_TUPLE_
+
+]]
+
+
+$for j [[
+#undef GTEST_$(j)_TYPENAMES_
+
+]]
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-type-util.h b/thirdparty/gtest/include/gtest/internal/gtest-type-util.h
new file mode 100644
index 00000000..e46f7cfc
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-type-util.h
@@ -0,0 +1,3331 @@
+// This file was GENERATED by command:
+// pump.py gtest-type-util.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
+//
+// Currently we support at most 50 types in a list, and at most 50
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# if GTEST_HAS_CXXABI_H_
+# include <cxxabi.h>
+# elif defined(__HP_aCC)
+# include <acxx_demangle.h>
+# endif // GTEST_HASH_CXXABI_H_
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+# if GTEST_HAS_RTTI
+
+ const char* const name = typeid(T).name();
+# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+ int status = 0;
+ // gcc's implementation of typeid(T).name() mangles the type name,
+ // so we have to demangle it.
+# if GTEST_HAS_CXXABI_H_
+ using abi::__cxa_demangle;
+# endif // GTEST_HAS_CXXABI_H_
+ char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+ const std::string name_str(status == 0 ? readable_name : name);
+ free(readable_name);
+ return name_str;
+# else
+ return name;
+# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
+
+# else
+
+ return "<type>";
+
+# endif // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type. This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+ typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types. This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists. In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+ typedef T1 Head;
+ typedef Types0 Tail;
+};
+template <typename T1, typename T2>
+struct Types2 {
+ typedef T1 Head;
+ typedef Types1<T2> Tail;
+};
+
+template <typename T1, typename T2, typename T3>
+struct Types3 {
+ typedef T1 Head;
+ typedef Types2<T2, T3> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types4 {
+ typedef T1 Head;
+ typedef Types3<T2, T3, T4> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types5 {
+ typedef T1 Head;
+ typedef Types4<T2, T3, T4, T5> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+struct Types6 {
+ typedef T1 Head;
+ typedef Types5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+struct Types7 {
+ typedef T1 Head;
+ typedef Types6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+struct Types8 {
+ typedef T1 Head;
+ typedef Types7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+struct Types9 {
+ typedef T1 Head;
+ typedef Types8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types10 {
+ typedef T1 Head;
+ typedef Types9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11>
+struct Types11 {
+ typedef T1 Head;
+ typedef Types10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12>
+struct Types12 {
+ typedef T1 Head;
+ typedef Types11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13>
+struct Types13 {
+ typedef T1 Head;
+ typedef Types12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14>
+struct Types14 {
+ typedef T1 Head;
+ typedef Types13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types15 {
+ typedef T1 Head;
+ typedef Types14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16>
+struct Types16 {
+ typedef T1 Head;
+ typedef Types15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17>
+struct Types17 {
+ typedef T1 Head;
+ typedef Types16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18>
+struct Types18 {
+ typedef T1 Head;
+ typedef Types17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19>
+struct Types19 {
+ typedef T1 Head;
+ typedef Types18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types20 {
+ typedef T1 Head;
+ typedef Types19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21>
+struct Types21 {
+ typedef T1 Head;
+ typedef Types20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22>
+struct Types22 {
+ typedef T1 Head;
+ typedef Types21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23>
+struct Types23 {
+ typedef T1 Head;
+ typedef Types22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24>
+struct Types24 {
+ typedef T1 Head;
+ typedef Types23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types25 {
+ typedef T1 Head;
+ typedef Types24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26>
+struct Types26 {
+ typedef T1 Head;
+ typedef Types25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27>
+struct Types27 {
+ typedef T1 Head;
+ typedef Types26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28>
+struct Types28 {
+ typedef T1 Head;
+ typedef Types27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29>
+struct Types29 {
+ typedef T1 Head;
+ typedef Types28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types30 {
+ typedef T1 Head;
+ typedef Types29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31>
+struct Types31 {
+ typedef T1 Head;
+ typedef Types30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32>
+struct Types32 {
+ typedef T1 Head;
+ typedef Types31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33>
+struct Types33 {
+ typedef T1 Head;
+ typedef Types32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34>
+struct Types34 {
+ typedef T1 Head;
+ typedef Types33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types35 {
+ typedef T1 Head;
+ typedef Types34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36>
+struct Types36 {
+ typedef T1 Head;
+ typedef Types35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37>
+struct Types37 {
+ typedef T1 Head;
+ typedef Types36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38>
+struct Types38 {
+ typedef T1 Head;
+ typedef Types37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39>
+struct Types39 {
+ typedef T1 Head;
+ typedef Types38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types40 {
+ typedef T1 Head;
+ typedef Types39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41>
+struct Types41 {
+ typedef T1 Head;
+ typedef Types40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42>
+struct Types42 {
+ typedef T1 Head;
+ typedef Types41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43>
+struct Types43 {
+ typedef T1 Head;
+ typedef Types42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44>
+struct Types44 {
+ typedef T1 Head;
+ typedef Types43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types45 {
+ typedef T1 Head;
+ typedef Types44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46>
+struct Types46 {
+ typedef T1 Head;
+ typedef Types45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47>
+struct Types47 {
+ typedef T1 Head;
+ typedef Types46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48>
+struct Types48 {
+ typedef T1 Head;
+ typedef Types47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49>
+struct Types49 {
+ typedef T1 Head;
+ typedef Types48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49, typename T50>
+struct Types50 {
+ typedef T1 Head;
+ typedef Types49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+} // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length. Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable. The translation is done by the 'type' member of the
+// Types template.
+template <typename T1 = internal::None, typename T2 = internal::None,
+ typename T3 = internal::None, typename T4 = internal::None,
+ typename T5 = internal::None, typename T6 = internal::None,
+ typename T7 = internal::None, typename T8 = internal::None,
+ typename T9 = internal::None, typename T10 = internal::None,
+ typename T11 = internal::None, typename T12 = internal::None,
+ typename T13 = internal::None, typename T14 = internal::None,
+ typename T15 = internal::None, typename T16 = internal::None,
+ typename T17 = internal::None, typename T18 = internal::None,
+ typename T19 = internal::None, typename T20 = internal::None,
+ typename T21 = internal::None, typename T22 = internal::None,
+ typename T23 = internal::None, typename T24 = internal::None,
+ typename T25 = internal::None, typename T26 = internal::None,
+ typename T27 = internal::None, typename T28 = internal::None,
+ typename T29 = internal::None, typename T30 = internal::None,
+ typename T31 = internal::None, typename T32 = internal::None,
+ typename T33 = internal::None, typename T34 = internal::None,
+ typename T35 = internal::None, typename T36 = internal::None,
+ typename T37 = internal::None, typename T38 = internal::None,
+ typename T39 = internal::None, typename T40 = internal::None,
+ typename T41 = internal::None, typename T42 = internal::None,
+ typename T43 = internal::None, typename T44 = internal::None,
+ typename T45 = internal::None, typename T46 = internal::None,
+ typename T47 = internal::None, typename T48 = internal::None,
+ typename T49 = internal::None, typename T50 = internal::None>
+struct Types {
+ typedef internal::Types50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Types<internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types0 type;
+};
+template <typename T1>
+struct Types<T1, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types1<T1> type;
+};
+template <typename T1, typename T2>
+struct Types<T1, T2, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types2<T1, T2> type;
+};
+template <typename T1, typename T2, typename T3>
+struct Types<T1, T2, T3, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types3<T1, T2, T3> type;
+};
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types<T1, T2, T3, T4, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types4<T1, T2, T3, T4> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types<T1, T2, T3, T4, T5, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types5<T1, T2, T3, T4, T5> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+struct Types<T1, T2, T3, T4, T5, T6, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types6<T1, T2, T3, T4, T5, T6> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+struct Types<T1, T2, T3, T4, T5, T6, T7, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+ T12> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+ T26> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+ T40> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, internal::None,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None, internal::None> {
+ typedef internal::Types43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None, internal::None> {
+ typedef internal::Types44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ internal::None, internal::None, internal::None, internal::None,
+ internal::None> {
+ typedef internal::Types45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ T46, internal::None, internal::None, internal::None, internal::None> {
+ typedef internal::Types46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ T46, T47, internal::None, internal::None, internal::None> {
+ typedef internal::Types47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ T46, T47, T48, internal::None, internal::None> {
+ typedef internal::Types48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+ T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+ T46, T47, T48, T49, internal::None> {
+ typedef internal::Types49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>. This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+ template <typename T>
+ struct Bind {
+ typedef Tmpl<T> type;
+ };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+ TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates. This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists. In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN). Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates0 Tail;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates2 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates1<T2> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates3 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates2<T2, T3> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4>
+struct Templates4 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates3<T2, T3, T4> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates5 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates4<T2, T3, T4, T5> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates6 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7>
+struct Templates7 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates8 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates9 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10>
+struct Templates10 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates11 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates12 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13>
+struct Templates13 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates14 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates15 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16>
+struct Templates16 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates17 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates18 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19>
+struct Templates19 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates20 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates21 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22>
+struct Templates22 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates23 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates24 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25>
+struct Templates25 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates26 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates27 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28>
+struct Templates28 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates29 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates30 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31>
+struct Templates31 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates32 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates33 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34>
+struct Templates34 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates35 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates36 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37>
+struct Templates37 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates38 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates39 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40>
+struct Templates40 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates41 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates42 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43>
+struct Templates43 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates44 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates45 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46>
+struct Templates46 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates47 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46, T47> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates48 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46, T47, T48> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+ GTEST_TEMPLATE_ T49>
+struct Templates49 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+ GTEST_TEMPLATE_ T49, GTEST_TEMPLATE_ T50>
+struct Templates50 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+ T43, T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length. Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable. The translation is done by the 'type' member of the
+// Templates template.
+template <GTEST_TEMPLATE_ T1 = NoneT, GTEST_TEMPLATE_ T2 = NoneT,
+ GTEST_TEMPLATE_ T3 = NoneT, GTEST_TEMPLATE_ T4 = NoneT,
+ GTEST_TEMPLATE_ T5 = NoneT, GTEST_TEMPLATE_ T6 = NoneT,
+ GTEST_TEMPLATE_ T7 = NoneT, GTEST_TEMPLATE_ T8 = NoneT,
+ GTEST_TEMPLATE_ T9 = NoneT, GTEST_TEMPLATE_ T10 = NoneT,
+ GTEST_TEMPLATE_ T11 = NoneT, GTEST_TEMPLATE_ T12 = NoneT,
+ GTEST_TEMPLATE_ T13 = NoneT, GTEST_TEMPLATE_ T14 = NoneT,
+ GTEST_TEMPLATE_ T15 = NoneT, GTEST_TEMPLATE_ T16 = NoneT,
+ GTEST_TEMPLATE_ T17 = NoneT, GTEST_TEMPLATE_ T18 = NoneT,
+ GTEST_TEMPLATE_ T19 = NoneT, GTEST_TEMPLATE_ T20 = NoneT,
+ GTEST_TEMPLATE_ T21 = NoneT, GTEST_TEMPLATE_ T22 = NoneT,
+ GTEST_TEMPLATE_ T23 = NoneT, GTEST_TEMPLATE_ T24 = NoneT,
+ GTEST_TEMPLATE_ T25 = NoneT, GTEST_TEMPLATE_ T26 = NoneT,
+ GTEST_TEMPLATE_ T27 = NoneT, GTEST_TEMPLATE_ T28 = NoneT,
+ GTEST_TEMPLATE_ T29 = NoneT, GTEST_TEMPLATE_ T30 = NoneT,
+ GTEST_TEMPLATE_ T31 = NoneT, GTEST_TEMPLATE_ T32 = NoneT,
+ GTEST_TEMPLATE_ T33 = NoneT, GTEST_TEMPLATE_ T34 = NoneT,
+ GTEST_TEMPLATE_ T35 = NoneT, GTEST_TEMPLATE_ T36 = NoneT,
+ GTEST_TEMPLATE_ T37 = NoneT, GTEST_TEMPLATE_ T38 = NoneT,
+ GTEST_TEMPLATE_ T39 = NoneT, GTEST_TEMPLATE_ T40 = NoneT,
+ GTEST_TEMPLATE_ T41 = NoneT, GTEST_TEMPLATE_ T42 = NoneT,
+ GTEST_TEMPLATE_ T43 = NoneT, GTEST_TEMPLATE_ T44 = NoneT,
+ GTEST_TEMPLATE_ T45 = NoneT, GTEST_TEMPLATE_ T46 = NoneT,
+ GTEST_TEMPLATE_ T47 = NoneT, GTEST_TEMPLATE_ T48 = NoneT,
+ GTEST_TEMPLATE_ T49 = NoneT, GTEST_TEMPLATE_ T50 = NoneT>
+struct Templates {
+ typedef Templates50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Templates<NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT> {
+ typedef Templates0 type;
+};
+template <GTEST_TEMPLATE_ T1>
+struct Templates<T1, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT> {
+ typedef Templates1<T1> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates<T1, T2, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT> {
+ typedef Templates2<T1, T2> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates<T1, T2, T3, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates3<T1, T2, T3> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4>
+struct Templates<T1, T2, T3, T4, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates4<T1, T2, T3, T4> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates<T1, T2, T3, T4, T5, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates5<T1, T2, T3, T4, T5> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates<T1, T2, T3, T4, T5, T6, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates6<T1, T2, T3, T4, T5, T6> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT> {
+ typedef Templates22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT> {
+ typedef Templates23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT> {
+ typedef Templates24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT> {
+ typedef Templates25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT> {
+ typedef Templates26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT> {
+ typedef Templates27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT> {
+ typedef Templates28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT> {
+ typedef Templates29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, NoneT, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, NoneT, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, NoneT, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, NoneT, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, NoneT,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, NoneT, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, T46, NoneT, NoneT, NoneT, NoneT> {
+ typedef Templates46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, T46, T47, NoneT, NoneT, NoneT> {
+ typedef Templates47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46, T47> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, T46, T47, T48, NoneT, NoneT> {
+ typedef Templates48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+ GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+ GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+ GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+ GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+ GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+ GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+ GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+ GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+ GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+ GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+ GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+ GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+ GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+ GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+ GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+ GTEST_TEMPLATE_ T49>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+ T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+ T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+ T45, T46, T47, T48, T49, NoneT> {
+ typedef Templates49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+ T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+ T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList {
+ typedef Types1<T> type;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ typename T11, typename T12, typename T13, typename T14, typename T15,
+ typename T16, typename T17, typename T18, typename T19, typename T20,
+ typename T21, typename T22, typename T23, typename T24, typename T25,
+ typename T26, typename T27, typename T28, typename T29, typename T30,
+ typename T31, typename T32, typename T33, typename T34, typename T35,
+ typename T36, typename T37, typename T38, typename T39, typename T40,
+ typename T41, typename T42, typename T43, typename T44, typename T45,
+ typename T46, typename T47, typename T48, typename T49, typename T50>
+struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+ T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+ T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+ T44, T45, T46, T47, T48, T49, T50> > {
+ typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+ T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+ T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+ T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
+};
+
+#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/thirdparty/gtest/include/gtest/internal/gtest-type-util.h.pump b/thirdparty/gtest/include/gtest/internal/gtest-type-util.h.pump
new file mode 100644
index 00000000..251fdf02
--- /dev/null
+++ b/thirdparty/gtest/include/gtest/internal/gtest-type-util.h.pump
@@ -0,0 +1,297 @@
+$$ -*- mode: c++; -*-
+$var n = 50 $$ Maximum length of type lists we want to support.
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
+//
+// Currently we support at most $n types in a list, and at most $n
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# if GTEST_HAS_CXXABI_H_
+# include <cxxabi.h>
+# elif defined(__HP_aCC)
+# include <acxx_demangle.h>
+# endif // GTEST_HASH_CXXABI_H_
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+# if GTEST_HAS_RTTI
+
+ const char* const name = typeid(T).name();
+# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+ int status = 0;
+ // gcc's implementation of typeid(T).name() mangles the type name,
+ // so we have to demangle it.
+# if GTEST_HAS_CXXABI_H_
+ using abi::__cxa_demangle;
+# endif // GTEST_HAS_CXXABI_H_
+ char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+ const std::string name_str(status == 0 ? readable_name : name);
+ free(readable_name);
+ return name_str;
+# else
+ return name;
+# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
+
+# else
+
+ return "<type>";
+
+# endif // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type. This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+ typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types. This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists. In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+ typedef T1 Head;
+ typedef Types0 Tail;
+};
+
+$range i 2..n
+
+$for i [[
+$range j 1..i
+$range k 2..i
+template <$for j, [[typename T$j]]>
+struct Types$i {
+ typedef T1 Head;
+ typedef Types$(i-1)<$for k, [[T$k]]> Tail;
+};
+
+
+]]
+
+} // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length. Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable. The translation is done by the 'type' member of the
+// Types template.
+
+$range i 1..n
+template <$for i, [[typename T$i = internal::None]]>
+struct Types {
+ typedef internal::Types$n<$for i, [[T$i]]> type;
+};
+
+template <>
+struct Types<$for i, [[internal::None]]> {
+ typedef internal::Types0 type;
+};
+
+$range i 1..n-1
+$for i [[
+$range j 1..i
+$range k i+1..n
+template <$for j, [[typename T$j]]>
+struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
+ typedef internal::Types$i<$for j, [[T$j]]> type;
+};
+
+]]
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>. This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+ template <typename T>
+ struct Bind {
+ typedef Tmpl<T> type;
+ };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+ TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates. This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists. In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN). Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+ typedef TemplateSel<T1> Head;
+ typedef Templates0 Tail;
+};
+
+$range i 2..n
+
+$for i [[
+$range j 1..i
+$range k 2..i
+template <$for j, [[GTEST_TEMPLATE_ T$j]]>
+struct Templates$i {
+ typedef TemplateSel<T1> Head;
+ typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
+};
+
+
+]]
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length. Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable. The translation is done by the 'type' member of the
+// Templates template.
+
+$range i 1..n
+template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
+struct Templates {
+ typedef Templates$n<$for i, [[T$i]]> type;
+};
+
+template <>
+struct Templates<$for i, [[NoneT]]> {
+ typedef Templates0 type;
+};
+
+$range i 1..n-1
+$for i [[
+$range j 1..i
+$range k i+1..n
+template <$for j, [[GTEST_TEMPLATE_ T$j]]>
+struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
+ typedef Templates$i<$for j, [[T$j]]> type;
+};
+
+]]
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList {
+ typedef Types1<T> type;
+};
+
+
+$range i 1..n
+template <$for i, [[typename T$i]]>
+struct TypeList<Types<$for i, [[T$i]]> > {
+ typedef typename Types<$for i, [[T$i]]>::type type;
+};
+
+#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/thirdparty/gtest/src/gtest-all.cc b/thirdparty/gtest/src/gtest-all.cc
new file mode 100644
index 00000000..0a9cee52
--- /dev/null
+++ b/thirdparty/gtest/src/gtest-all.cc
@@ -0,0 +1,48 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// Google C++ Testing Framework (Google Test)
+//
+// Sometimes it's desirable to build Google Test by compiling a single file.
+// This file serves this purpose.
+
+// This line ensures that gtest.h can be compiled on its own, even
+// when it's fused.
+#include "gtest/gtest.h"
+
+// The following lines pull in the real gtest *.cc files.
+#include "src/gtest.cc"
+#include "src/gtest-death-test.cc"
+#include "src/gtest-filepath.cc"
+#include "src/gtest-port.cc"
+#include "src/gtest-printers.cc"
+#include "src/gtest-test-part.cc"
+#include "src/gtest-typed-test.cc"
diff --git a/thirdparty/gtest/src/gtest-death-test.cc b/thirdparty/gtest/src/gtest-death-test.cc
new file mode 100644
index 00000000..a6023fce
--- /dev/null
+++ b/thirdparty/gtest/src/gtest-death-test.cc
@@ -0,0 +1,1344 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
+//
+// This file implements death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_MAC
+# include <crt_externs.h>
+# endif // GTEST_OS_MAC
+
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+
+# if GTEST_OS_LINUX
+# include <signal.h>
+# endif // GTEST_OS_LINUX
+
+# include <stdarg.h>
+
+# if GTEST_OS_WINDOWS
+# include <windows.h>
+# else
+# include <sys/mman.h>
+# include <sys/wait.h>
+# endif // GTEST_OS_WINDOWS
+
+# if GTEST_OS_QNX
+# include <spawn.h>
+# endif // GTEST_OS_QNX
+
+#endif // GTEST_HAS_DEATH_TEST
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation. It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+static const char kDefaultDeathTestStyle[] = "fast";
+
+GTEST_DEFINE_string_(
+ death_test_style,
+ internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
+ "Indicates how to run a death test in a forked child process: "
+ "\"threadsafe\" (child process re-executes the test binary "
+ "from the beginning, running only the specific death test) or "
+ "\"fast\" (child process runs the death test immediately "
+ "after forking).");
+
+GTEST_DEFINE_bool_(
+ death_test_use_fork,
+ internal::BoolFromGTestEnv("death_test_use_fork", false),
+ "Instructs to use fork()/_exit() instead of clone() in death tests. "
+ "Ignored and always uses fork() on POSIX systems where clone() is not "
+ "implemented. Useful when running under valgrind or similar tools if "
+ "those do not support clone(). Valgrind 3.3.1 will just fail if "
+ "it sees an unsupported combination of clone() flags. "
+ "It is not recommended to use this flag w/o valgrind though it will "
+ "work in 99% of the cases. Once valgrind is fixed, this flag will "
+ "most likely be removed.");
+
+namespace internal {
+GTEST_DEFINE_string_(
+ internal_run_death_test, "",
+ "Indicates the file, line number, temporal index of "
+ "the single death test to run, and a file descriptor to "
+ "which a success code may be sent, all separated by "
+ "the '|' characters. This flag is specified if and only if the current "
+ "process is a sub-process launched for running a thread-safe "
+ "death test. FOR INTERNAL USE ONLY.");
+} // namespace internal
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Valid only for fast death tests. Indicates the code is running in the
+// child process of a fast style death test.
+static bool g_in_fast_death_test_child = false;
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process. Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests. IMPORTANT: This is an internal utility. Using it may break the
+// implementation of death tests. User code MUST NOT use it.
+bool InDeathTestChild() {
+# if GTEST_OS_WINDOWS
+
+ // On Windows, death tests are thread-safe regardless of the value of the
+ // death_test_style flag.
+ return !GTEST_FLAG(internal_run_death_test).empty();
+
+# else
+
+ if (GTEST_FLAG(death_test_style) == "threadsafe")
+ return !GTEST_FLAG(internal_run_death_test).empty();
+ else
+ return g_in_fast_death_test_child;
+#endif
+}
+
+} // namespace internal
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
+}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+# if GTEST_OS_WINDOWS
+
+ return exit_status == exit_code_;
+
+# else
+
+ return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+
+# endif // GTEST_OS_WINDOWS
+}
+
+# if !GTEST_OS_WINDOWS
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
+}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+ return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+# endif // !GTEST_OS_WINDOWS
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static std::string ExitSummary(int exit_code) {
+ Message m;
+
+# if GTEST_OS_WINDOWS
+
+ m << "Exited with exit status " << exit_code;
+
+# else
+
+ if (WIFEXITED(exit_code)) {
+ m << "Exited with exit status " << WEXITSTATUS(exit_code);
+ } else if (WIFSIGNALED(exit_code)) {
+ m << "Terminated by signal " << WTERMSIG(exit_code);
+ }
+# ifdef WCOREDUMP
+ if (WCOREDUMP(exit_code)) {
+ m << " (core dumped)";
+ }
+# endif
+# endif // GTEST_OS_WINDOWS
+
+ return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+ return !ExitedWithCode(0)(exit_status);
+}
+
+# if !GTEST_OS_WINDOWS
+// Generates a textual failure message when a death test finds more than
+// one thread running, or cannot determine the number of threads, prior
+// to executing the given statement. It is the responsibility of the
+// caller not to pass a thread_count of 1.
+static std::string DeathTestThreadWarning(size_t thread_count) {
+ Message msg;
+ msg << "Death tests use fork(), which is unsafe particularly"
+ << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+ if (thread_count == 0)
+ msg << "couldn't detect the number of threads.";
+ else
+ msg << "detected " << thread_count << " threads.";
+ return msg.GetString();
+}
+# endif // !GTEST_OS_WINDOWS
+
+// Flag characters for reporting a death test that did not die.
+static const char kDeathTestLived = 'L';
+static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
+static const char kDeathTestInternalError = 'I';
+
+// An enumeration describing all of the possible ways that a death test can
+// conclude. DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception. IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl@google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process. Otherwise, the
+// message is simply printed to stderr. In either case, the program
+// then exits with status 1.
+void DeathTestAbort(const std::string& message) {
+ // On a POSIX system, this function may be called from a threadsafe-style
+ // death test child process, which operates on a very small stack. Use
+ // the heap for any additional non-minuscule memory requirements.
+ const InternalRunDeathTestFlag* const flag =
+ GetUnitTestImpl()->internal_run_death_test_flag();
+ if (flag != NULL) {
+ FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+ fputc(kDeathTestInternalError, parent);
+ fprintf(parent, "%s", message.c_str());
+ fflush(parent);
+ _exit(1);
+ } else {
+ fprintf(stderr, "%s", message.c_str());
+ fflush(stderr);
+ posix::Abort();
+ }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+# define GTEST_DEATH_TEST_CHECK_(expression) \
+ do { \
+ if (!::testing::internal::IsTrue(expression)) { \
+ DeathTestAbort( \
+ ::std::string("CHECK failed: File ") + __FILE__ + ", line " \
+ + ::testing::internal::StreamableToString(__LINE__) + ": " \
+ + #expression); \
+ } \
+ } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again. The macro expands to a loop that repeatedly
+// evaluates the expression as long as it evaluates to -1 and sets
+// errno to EINTR. If the expression evaluates to -1 but errno is
+// something other than EINTR, DeathTestAbort is called.
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+ do { \
+ int gtest_retval; \
+ do { \
+ gtest_retval = (expression); \
+ } while (gtest_retval == -1 && errno == EINTR); \
+ if (gtest_retval == -1) { \
+ DeathTestAbort( \
+ ::std::string("CHECK failed: File ") + __FILE__ + ", line " \
+ + ::testing::internal::StreamableToString(__LINE__) + ": " \
+ + #expression + " != -1"); \
+ } \
+ } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+std::string GetLastErrnoDescription() {
+ return errno == 0 ? "" : posix::StrError(errno);
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+ Message error;
+ char buffer[256];
+ int num_read;
+
+ do {
+ while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+ buffer[num_read] = '\0';
+ error << buffer;
+ }
+ } while (num_read == -1 && errno == EINTR);
+
+ if (num_read == 0) {
+ GTEST_LOG_(FATAL) << error.GetString();
+ } else {
+ const int last_error = errno;
+ GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+ << GetLastErrnoDescription() << " [" << last_error << "]";
+ }
+}
+
+// Death test constructor. Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+ TestInfo* const info = GetUnitTestImpl()->current_test_info();
+ if (info == NULL) {
+ DeathTestAbort("Cannot run a death test outside of a TEST or "
+ "TEST_F construct");
+ }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement, const RE* regex,
+ const char* file, int line, DeathTest** test) {
+ return GetUnitTestImpl()->death_test_factory()->Create(
+ statement, regex, file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+ return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const std::string& message) {
+ last_death_test_message_ = message;
+}
+
+std::string DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+ DeathTestImpl(const char* a_statement, const RE* a_regex)
+ : statement_(a_statement),
+ regex_(a_regex),
+ spawned_(false),
+ status_(-1),
+ outcome_(IN_PROGRESS),
+ read_fd_(-1),
+ write_fd_(-1) {}
+
+ // read_fd_ is expected to be closed and cleared by a derived class.
+ ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+ void Abort(AbortReason reason);
+ virtual bool Passed(bool status_ok);
+
+ const char* statement() const { return statement_; }
+ const RE* regex() const { return regex_; }
+ bool spawned() const { return spawned_; }
+ void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+ int status() const { return status_; }
+ void set_status(int a_status) { status_ = a_status; }
+ DeathTestOutcome outcome() const { return outcome_; }
+ void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+ int read_fd() const { return read_fd_; }
+ void set_read_fd(int fd) { read_fd_ = fd; }
+ int write_fd() const { return write_fd_; }
+ void set_write_fd(int fd) { write_fd_ = fd; }
+
+ // Called in the parent process only. Reads the result code of the death
+ // test child process via a pipe, interprets it to set the outcome_
+ // member, and closes read_fd_. Outputs diagnostics and terminates in
+ // case of unexpected codes.
+ void ReadAndInterpretStatusByte();
+
+ private:
+ // The textual content of the code this object is testing. This class
+ // doesn't own this string and should not attempt to delete it.
+ const char* const statement_;
+ // The regular expression which test output must match. DeathTestImpl
+ // doesn't own this object and should not attempt to delete it.
+ const RE* const regex_;
+ // True if the death test child process has been successfully spawned.
+ bool spawned_;
+ // The exit status of the child process.
+ int status_;
+ // How the death test concluded.
+ DeathTestOutcome outcome_;
+ // Descriptor to the read end of the pipe to the child process. It is
+ // always -1 in the child process. The child keeps its write end of the
+ // pipe in write_fd_.
+ int read_fd_;
+ // Descriptor to the child's write end of the pipe to the parent process.
+ // It is always -1 in the parent process. The parent keeps its end of the
+ // pipe in read_fd_.
+ int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_. Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+ char flag;
+ int bytes_read;
+
+ // The read() here blocks until data is available (signifying the
+ // failure of the death test) or until the pipe is closed (signifying
+ // its success), so it's okay to call this in the parent before
+ // the child process has exited.
+ do {
+ bytes_read = posix::Read(read_fd(), &flag, 1);
+ } while (bytes_read == -1 && errno == EINTR);
+
+ if (bytes_read == 0) {
+ set_outcome(DIED);
+ } else if (bytes_read == 1) {
+ switch (flag) {
+ case kDeathTestReturned:
+ set_outcome(RETURNED);
+ break;
+ case kDeathTestThrew:
+ set_outcome(THREW);
+ break;
+ case kDeathTestLived:
+ set_outcome(LIVED);
+ break;
+ case kDeathTestInternalError:
+ FailFromInternalError(read_fd()); // Does not return.
+ break;
+ default:
+ GTEST_LOG_(FATAL) << "Death test child process reported "
+ << "unexpected status byte ("
+ << static_cast<unsigned int>(flag) << ")";
+ }
+ } else {
+ GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+ << GetLastErrnoDescription();
+ }
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+ set_read_fd(-1);
+}
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+ // The parent process considers the death test to be a failure if
+ // it finds any data in our pipe. So, here we write a single flag byte
+ // to the pipe, then exit.
+ const char status_ch =
+ reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+ reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+ // We are leaking the descriptor here because on some platforms (i.e.,
+ // when built as Windows DLL), destructors of global objects will still
+ // run after calling _exit(). On such systems, write_fd_ will be
+ // indirectly closed from the destructor of UnitTestImpl, causing double
+ // close if it is also closed here. On debug configurations, double close
+ // may assert. As there are no in-process buffers to flush here, we are
+ // relying on the OS to close the descriptor after the process terminates
+ // when the destructors are not run.
+ _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+ ::std::string ret;
+ for (size_t at = 0; ; ) {
+ const size_t line_end = output.find('\n', at);
+ ret += "[ DEATH ] ";
+ if (line_end == ::std::string::npos) {
+ ret += output.substr(at);
+ break;
+ }
+ ret += output.substr(at, line_end + 1 - at);
+ at = line_end + 1;
+ }
+ return ret;
+}
+
+// Assesses the success or failure of a death test, using both private
+// members which have previously been set, and one argument:
+//
+// Private data members:
+// outcome: An enumeration describing how the death test
+// concluded: DIED, LIVED, THREW, or RETURNED. The death test
+// fails in the latter three cases.
+// status: The exit status of the child process. On *nix, it is in the
+// in the format specified by wait(2). On Windows, this is the
+// value supplied to the ExitProcess() API or a numeric code
+// of the exception that terminated the program.
+// regex: A regular expression object to be applied to
+// the test's captured standard error output; the death test
+// fails if it does not match.
+//
+// Argument:
+// status_ok: true if exit_status is acceptable in the context of
+// this particular death test, which fails if it is false
+//
+// Returns true iff all of the above conditions are met. Otherwise, the
+// first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+ if (!spawned())
+ return false;
+
+ const std::string error_message = GetCapturedStderr();
+
+ bool success = false;
+ Message buffer;
+
+ buffer << "Death test: " << statement() << "\n";
+ switch (outcome()) {
+ case LIVED:
+ buffer << " Result: failed to die.\n"
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
+ break;
+ case THREW:
+ buffer << " Result: threw an exception.\n"
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
+ break;
+ case RETURNED:
+ buffer << " Result: illegal return in test statement.\n"
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
+ break;
+ case DIED:
+ if (status_ok) {
+ const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
+ if (matched) {
+ success = true;
+ } else {
+ buffer << " Result: died but not with expected error.\n"
+ << " Expected: " << regex()->pattern() << "\n"
+ << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+ }
+ } else {
+ buffer << " Result: died but not with expected exit code:\n"
+ << " " << ExitSummary(status()) << "\n"
+ << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+ }
+ break;
+ case IN_PROGRESS:
+ default:
+ GTEST_LOG_(FATAL)
+ << "DeathTest::Passed somehow called before conclusion of test";
+ }
+
+ DeathTest::set_last_death_test_message(buffer.GetString());
+ return success;
+}
+
+# if GTEST_OS_WINDOWS
+// WindowsDeathTest implements death tests on Windows. Due to the
+// specifics of starting new processes on Windows, death tests there are
+// always threadsafe, and Google Test considers the
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes: Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+// ends of it.
+// 2. The parent starts the child and provides it with the information
+// necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+// using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+// this is done before step 3, the object's reference count goes down to
+// 0 and it is destroyed, preventing the child from acquiring it. The
+// parent now has to release it, or read operations on the read end of
+// the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+// any possible error messages) from the pipe, and its stderr and then
+// determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+ WindowsDeathTest(const char* a_statement,
+ const RE* a_regex,
+ const char* file,
+ int line)
+ : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
+
+ // All of these virtual functions are inherited from DeathTest.
+ virtual int Wait();
+ virtual TestRole AssumeRole();
+
+ private:
+ // The name of the file in which the death test is located.
+ const char* const file_;
+ // The line number on which the death test is located.
+ const int line_;
+ // Handle to the write end of the pipe to the child process.
+ AutoHandle write_handle_;
+ // Child process handle.
+ AutoHandle child_handle_;
+ // Event the child process uses to signal the parent that it has
+ // acquired the handle to the write end of the pipe. After seeing this
+ // event the parent can release its own handles to make sure its
+ // ReadFile() calls return when the child terminates.
+ AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists. As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+ if (!spawned())
+ return 0;
+
+ // Wait until the child either signals that it has acquired the write end
+ // of the pipe or it dies.
+ const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
+ switch (::WaitForMultipleObjects(2,
+ wait_handles,
+ FALSE, // Waits for any of the handles.
+ INFINITE)) {
+ case WAIT_OBJECT_0:
+ case WAIT_OBJECT_0 + 1:
+ break;
+ default:
+ GTEST_DEATH_TEST_CHECK_(false); // Should not get here.
+ }
+
+ // The child has acquired the write end of the pipe or exited.
+ // We release the handle on our side and continue.
+ write_handle_.Reset();
+ event_handle_.Reset();
+
+ ReadAndInterpretStatusByte();
+
+ // Waits for the child process to exit if it haven't already. This
+ // returns immediately if the child has already exited, regardless of
+ // whether previous calls to WaitForMultipleObjects synchronized on this
+ // handle or not.
+ GTEST_DEATH_TEST_CHECK_(
+ WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
+ INFINITE));
+ DWORD status_code;
+ GTEST_DEATH_TEST_CHECK_(
+ ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
+ child_handle_.Reset();
+ set_status(static_cast<int>(status_code));
+ return status();
+}
+
+// The AssumeRole process for a Windows death test. It creates a child
+// process with the same executable as the current process to run the
+// death test. The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+ const UnitTestImpl* const impl = GetUnitTestImpl();
+ const InternalRunDeathTestFlag* const flag =
+ impl->internal_run_death_test_flag();
+ const TestInfo* const info = impl->current_test_info();
+ const int death_test_index = info->result()->death_test_count();
+
+ if (flag != NULL) {
+ // ParseInternalRunDeathTestFlag() has performed all the necessary
+ // processing.
+ set_write_fd(flag->write_fd());
+ return EXECUTE_TEST;
+ }
+
+ // WindowsDeathTest uses an anonymous pipe to communicate results of
+ // a death test.
+ SECURITY_ATTRIBUTES handles_are_inheritable = {
+ sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+ HANDLE read_handle, write_handle;
+ GTEST_DEATH_TEST_CHECK_(
+ ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
+ 0) // Default buffer size.
+ != FALSE);
+ set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
+ O_RDONLY));
+ write_handle_.Reset(write_handle);
+ event_handle_.Reset(::CreateEvent(
+ &handles_are_inheritable,
+ TRUE, // The event will automatically reset to non-signaled state.
+ FALSE, // The initial state is non-signalled.
+ NULL)); // The even is unnamed.
+ GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
+ const std::string filter_flag =
+ std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" +
+ info->test_case_name() + "." + info->name();
+ const std::string internal_flag =
+ std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
+ "=" + file_ + "|" + StreamableToString(line_) + "|" +
+ StreamableToString(death_test_index) + "|" +
+ StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
+ // size_t has the same width as pointers on both 32-bit and 64-bit
+ // Windows platforms.
+ // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+ "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) +
+ "|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
+
+ char executable_path[_MAX_PATH + 1]; // NOLINT
+ GTEST_DEATH_TEST_CHECK_(
+ _MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
+ executable_path,
+ _MAX_PATH));
+
+ std::string command_line =
+ std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
+ internal_flag + "\"";
+
+ DeathTest::set_last_death_test_message("");
+
+ CaptureStderr();
+ // Flush the log buffers since the log streams are shared with the child.
+ FlushInfoLog();
+
+ // The child process will share the standard handles with the parent.
+ STARTUPINFOA startup_info;
+ memset(&startup_info, 0, sizeof(STARTUPINFO));
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+ startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+ startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+ startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+ PROCESS_INFORMATION process_info;
+ GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
+ executable_path,
+ const_cast<char*>(command_line.c_str()),
+ NULL, // Retuned process handle is not inheritable.
+ NULL, // Retuned thread handle is not inheritable.
+ TRUE, // Child inherits all inheritable handles (for write_handle_).
+ 0x0, // Default creation flags.
+ NULL, // Inherit the parent's environment.
+ UnitTest::GetInstance()->original_working_dir(),
+ &startup_info,
+ &process_info) != FALSE);
+ child_handle_.Reset(process_info.hProcess);
+ ::CloseHandle(process_info.hThread);
+ set_spawned(true);
+ return OVERSEE_TEST;
+}
+# else // We are not on Windows.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface. Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+ ForkingDeathTest(const char* statement, const RE* regex);
+
+ // All of these virtual functions are inherited from DeathTest.
+ virtual int Wait();
+
+ protected:
+ void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+ // PID of child process during death test; 0 in the child process itself.
+ pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
+ : DeathTestImpl(a_statement, a_regex),
+ child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists. As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+ if (!spawned())
+ return 0;
+
+ ReadAndInterpretStatusByte();
+
+ int status_value;
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+ set_status(status_value);
+ return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+ NoExecDeathTest(const char* a_statement, const RE* a_regex) :
+ ForkingDeathTest(a_statement, a_regex) { }
+ virtual TestRole AssumeRole();
+};
+
+// The AssumeRole process for a fork-and-run death test. It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+ const size_t thread_count = GetThreadCount();
+ if (thread_count != 1) {
+ GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+ }
+
+ int pipe_fd[2];
+ GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+ DeathTest::set_last_death_test_message("");
+ CaptureStderr();
+ // When we fork the process below, the log file buffers are copied, but the
+ // file descriptors are shared. We flush all log files here so that closing
+ // the file descriptors in the child process doesn't throw off the
+ // synchronization between descriptors and buffers in the parent process.
+ // This is as close to the fork as possible to avoid a race condition in case
+ // there are multiple threads running before the death test, and another
+ // thread writes to the log file.
+ FlushInfoLog();
+
+ const pid_t child_pid = fork();
+ GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+ set_child_pid(child_pid);
+ if (child_pid == 0) {
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+ set_write_fd(pipe_fd[1]);
+ // Redirects all logging to stderr in the child process to prevent
+ // concurrent writes to the log files. We capture stderr in the parent
+ // process and append the child process' output to a log.
+ LogToStderr();
+ // Event forwarding to the listeners of event listener API mush be shut
+ // down in death test subprocesses.
+ GetUnitTestImpl()->listeners()->SuppressEventForwarding();
+ g_in_fast_death_test_child = true;
+ return EXECUTE_TEST;
+ } else {
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+ set_read_fd(pipe_fd[0]);
+ set_spawned(true);
+ return OVERSEE_TEST;
+ }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+ ExecDeathTest(const char* a_statement, const RE* a_regex,
+ const char* file, int line) :
+ ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
+ virtual TestRole AssumeRole();
+ private:
+ static ::std::vector<testing::internal::string>
+ GetArgvsForDeathTestChildProcess() {
+ ::std::vector<testing::internal::string> args = GetInjectableArgvs();
+ return args;
+ }
+ // The name of the file in which the death test is located.
+ const char* const file_;
+ // The line number on which the death test is located.
+ const int line_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+ Arguments() {
+ args_.push_back(NULL);
+ }
+
+ ~Arguments() {
+ for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+ ++i) {
+ free(*i);
+ }
+ }
+ void AddArgument(const char* argument) {
+ args_.insert(args_.end() - 1, posix::StrDup(argument));
+ }
+
+ template <typename Str>
+ void AddArguments(const ::std::vector<Str>& arguments) {
+ for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+ i != arguments.end();
+ ++i) {
+ args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+ }
+ }
+ char* const* Argv() {
+ return &args_[0];
+ }
+
+ private:
+ std::vector<char*> args_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+ char* const* argv; // Command-line arguments for the child's call to exec
+ int close_fd; // File descriptor to close; the read end of a pipe
+};
+
+# if GTEST_OS_MAC
+inline char** GetEnviron() {
+ // When Google Test is built as a framework on MacOS X, the environ variable
+ // is unavailable. Apple's documentation (man environ) recommends using
+ // _NSGetEnviron() instead.
+ return *_NSGetEnviron();
+}
+# else
+// Some POSIX platforms expect you to declare environ. extern "C" makes
+// it reside in the global namespace.
+extern "C" char** environ;
+inline char** GetEnviron() { return environ; }
+# endif // GTEST_OS_MAC
+
+# if !GTEST_OS_QNX
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+ ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+ // We need to execute the test program in the same environment where
+ // it was originally invoked. Therefore we change to the original
+ // working directory first.
+ const char* const original_dir =
+ UnitTest::GetInstance()->original_working_dir();
+ // We can safely call chdir() as it's a direct system call.
+ if (chdir(original_dir) != 0) {
+ DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+ GetLastErrnoDescription());
+ return EXIT_FAILURE;
+ }
+
+ // We can safely call execve() as it's a direct system call. We
+ // cannot use execvp() as it's a libc function and thus potentially
+ // unsafe. Since execve() doesn't search the PATH, the user must
+ // invoke the test program via a valid path that contains at least
+ // one path separator.
+ execve(args->argv[0], args->argv, GetEnviron());
+ DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " +
+ original_dir + " failed: " +
+ GetLastErrnoDescription());
+ return EXIT_FAILURE;
+}
+# endif // !GTEST_OS_QNX
+
+// Two utility routines that together determine the direction the stack
+// grows.
+// This could be accomplished more elegantly by a single recursive
+// function, but we want to guard against the unlikely possibility of
+// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_;
+void StackLowerThanAddress(const void* ptr, bool* result) {
+ int dummy;
+ *result = (&dummy < ptr);
+}
+
+bool StackGrowsDown() {
+ int dummy;
+ bool result;
+ StackLowerThanAddress(&dummy, &result);
+ return result;
+}
+
+// Spawns a child process with the same executable as the current process in
+// a thread-safe manner and instructs it to run the death test. The
+// implementation uses fork(2) + exec. On systems where clone(2) is
+// available, it is used instead, being slightly more thread-safe. On QNX,
+// fork supports only single-threaded environments, so this function uses
+// spawn(2) there instead. The function dies with an error message if
+// anything goes wrong.
+static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
+ ExecDeathTestArgs args = { argv, close_fd };
+ pid_t child_pid = -1;
+
+# if GTEST_OS_QNX
+ // Obtains the current directory and sets it to be closed in the child
+ // process.
+ const int cwd_fd = open(".", O_RDONLY);
+ GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
+ // We need to execute the test program in the same environment where
+ // it was originally invoked. Therefore we change to the original
+ // working directory first.
+ const char* const original_dir =
+ UnitTest::GetInstance()->original_working_dir();
+ // We can safely call chdir() as it's a direct system call.
+ if (chdir(original_dir) != 0) {
+ DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+ GetLastErrnoDescription());
+ return EXIT_FAILURE;
+ }
+
+ int fd_flags;
+ // Set close_fd to be closed after spawn.
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
+ fd_flags | FD_CLOEXEC));
+ struct inheritance inherit = {0};
+ // spawn is a system call.
+ child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
+ // Restores the current working directory.
+ GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
+
+# else // GTEST_OS_QNX
+# if GTEST_OS_LINUX
+ // When a SIGPROF signal is received while fork() or clone() are executing,
+ // the process may hang. To avoid this, we ignore SIGPROF here and re-enable
+ // it after the call to fork()/clone() is complete.
+ struct sigaction saved_sigprof_action;
+ struct sigaction ignore_sigprof_action;
+ memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
+ sigemptyset(&ignore_sigprof_action.sa_mask);
+ ignore_sigprof_action.sa_handler = SIG_IGN;
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
+ SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
+# endif // GTEST_OS_LINUX
+
+# if GTEST_HAS_CLONE
+ const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+ if (!use_fork) {
+ static const bool stack_grows_down = StackGrowsDown();
+ const size_t stack_size = getpagesize();
+ // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+ void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+
+ // Maximum stack alignment in bytes: For a downward-growing stack, this
+ // amount is subtracted from size of the stack space to get an address
+ // that is within the stack space and is aligned on all systems we care
+ // about. As far as I know there is no ABI with stack alignment greater
+ // than 64. We assume stack and stack_size already have alignment of
+ // kMaxStackAlignment.
+ const size_t kMaxStackAlignment = 64;
+ void* const stack_top =
+ static_cast<char*>(stack) +
+ (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
+ GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment &&
+ reinterpret_cast<intptr_t>(stack_top) % kMaxStackAlignment == 0);
+
+ child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+ GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+ }
+# else
+ const bool use_fork = true;
+# endif // GTEST_HAS_CLONE
+
+ if (use_fork && (child_pid = fork()) == 0) {
+ ExecDeathTestChildMain(&args);
+ _exit(0);
+ }
+# endif // GTEST_OS_QNX
+# if GTEST_OS_LINUX
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(
+ sigaction(SIGPROF, &saved_sigprof_action, NULL));
+# endif // GTEST_OS_LINUX
+
+ GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+ return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test. It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+ const UnitTestImpl* const impl = GetUnitTestImpl();
+ const InternalRunDeathTestFlag* const flag =
+ impl->internal_run_death_test_flag();
+ const TestInfo* const info = impl->current_test_info();
+ const int death_test_index = info->result()->death_test_count();
+
+ if (flag != NULL) {
+ set_write_fd(flag->write_fd());
+ return EXECUTE_TEST;
+ }
+
+ int pipe_fd[2];
+ GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+ // Clear the close-on-exec flag on the write end of the pipe, lest
+ // it be closed when the child process does an exec:
+ GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+ const std::string filter_flag =
+ std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
+ + info->test_case_name() + "." + info->name();
+ const std::string internal_flag =
+ std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
+ + file_ + "|" + StreamableToString(line_) + "|"
+ + StreamableToString(death_test_index) + "|"
+ + StreamableToString(pipe_fd[1]);
+ Arguments args;
+ args.AddArguments(GetArgvsForDeathTestChildProcess());
+ args.AddArgument(filter_flag.c_str());
+ args.AddArgument(internal_flag.c_str());
+
+ DeathTest::set_last_death_test_message("");
+
+ CaptureStderr();
+ // See the comment in NoExecDeathTest::AssumeRole for why the next line
+ // is necessary.
+ FlushInfoLog();
+
+ const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+ set_child_pid(child_pid);
+ set_read_fd(pipe_fd[0]);
+ set_spawned(true);
+ return OVERSEE_TEST;
+}
+
+# endif // !GTEST_OS_WINDOWS
+
+// Creates a concrete DeathTest-derived class that depends on the
+// --gtest_death_test_style flag, and sets the pointer pointed to
+// by the "test" argument to its address. If the test should be
+// skipped, sets that pointer to NULL. Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
+ const char* file, int line,
+ DeathTest** test) {
+ UnitTestImpl* const impl = GetUnitTestImpl();
+ const InternalRunDeathTestFlag* const flag =
+ impl->internal_run_death_test_flag();
+ const int death_test_index = impl->current_test_info()
+ ->increment_death_test_count();
+
+ if (flag != NULL) {
+ if (death_test_index > flag->index()) {
+ DeathTest::set_last_death_test_message(
+ "Death test count (" + StreamableToString(death_test_index)
+ + ") somehow exceeded expected maximum ("
+ + StreamableToString(flag->index()) + ")");
+ return false;
+ }
+
+ if (!(flag->file() == file && flag->line() == line &&
+ flag->index() == death_test_index)) {
+ *test = NULL;
+ return true;
+ }
+ }
+
+# if GTEST_OS_WINDOWS
+
+ if (GTEST_FLAG(death_test_style) == "threadsafe" ||
+ GTEST_FLAG(death_test_style) == "fast") {
+ *test = new WindowsDeathTest(statement, regex, file, line);
+ }
+
+# else
+
+ if (GTEST_FLAG(death_test_style) == "threadsafe") {
+ *test = new ExecDeathTest(statement, regex, file, line);
+ } else if (GTEST_FLAG(death_test_style) == "fast") {
+ *test = new NoExecDeathTest(statement, regex);
+ }
+
+# endif // GTEST_OS_WINDOWS
+
+ else { // NOLINT - this is more readable than unbalanced brackets inside #if.
+ DeathTest::set_last_death_test_message(
+ "Unknown death test style \"" + GTEST_FLAG(death_test_style)
+ + "\" encountered");
+ return false;
+ }
+
+ return true;
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have
+// ::std::string, so we can use it here.
+static void SplitString(const ::std::string& str, char delimiter,
+ ::std::vector< ::std::string>* dest) {
+ ::std::vector< ::std::string> parsed;
+ ::std::string::size_type pos = 0;
+ while (::testing::internal::AlwaysTrue()) {
+ const ::std::string::size_type colon = str.find(delimiter, pos);
+ if (colon == ::std::string::npos) {
+ parsed.push_back(str.substr(pos));
+ break;
+ } else {
+ parsed.push_back(str.substr(pos, colon - pos));
+ pos = colon + 1;
+ }
+ }
+ dest->swap(parsed);
+}
+
+# if GTEST_OS_WINDOWS
+// Recreates the pipe and event handles from the provided parameters,
+// signals the event, and returns a file descriptor wrapped around the pipe
+// handle. This function is called in the child process only.
+int GetStatusFileDescriptor(unsigned int parent_process_id,
+ size_t write_handle_as_size_t,
+ size_t event_handle_as_size_t) {
+ AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+ FALSE, // Non-inheritable.
+ parent_process_id));
+ if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+ DeathTestAbort("Unable to open parent process " +
+ StreamableToString(parent_process_id));
+ }
+
+ // TODO(vladl@google.com): Replace the following check with a
+ // compile-time assertion when available.
+ GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+ const HANDLE write_handle =
+ reinterpret_cast<HANDLE>(write_handle_as_size_t);
+ HANDLE dup_write_handle;
+
+ // The newly initialized handle is accessible only in in the parent
+ // process. To obtain one accessible within the child, we need to use
+ // DuplicateHandle.
+ if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+ ::GetCurrentProcess(), &dup_write_handle,
+ 0x0, // Requested privileges ignored since
+ // DUPLICATE_SAME_ACCESS is used.
+ FALSE, // Request non-inheritable handler.
+ DUPLICATE_SAME_ACCESS)) {
+ DeathTestAbort("Unable to duplicate the pipe handle " +
+ StreamableToString(write_handle_as_size_t) +
+ " from the parent process " +
+ StreamableToString(parent_process_id));
+ }
+
+ const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+ HANDLE dup_event_handle;
+
+ if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+ ::GetCurrentProcess(), &dup_event_handle,
+ 0x0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ DeathTestAbort("Unable to duplicate the event handle " +
+ StreamableToString(event_handle_as_size_t) +
+ " from the parent process " +
+ StreamableToString(parent_process_id));
+ }
+
+ const int write_fd =
+ ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+ if (write_fd == -1) {
+ DeathTestAbort("Unable to convert pipe handle " +
+ StreamableToString(write_handle_as_size_t) +
+ " to a file descriptor");
+ }
+
+ // Signals the parent that the write end of the pipe has been acquired
+ // so the parent can release its own write end.
+ ::SetEvent(dup_event_handle);
+
+ return write_fd;
+}
+# endif // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+ if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
+
+ // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+ // can use it here.
+ int line = -1;
+ int index = -1;
+ ::std::vector< ::std::string> fields;
+ SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
+ int write_fd = -1;
+
+# if GTEST_OS_WINDOWS
+
+ unsigned int parent_process_id = 0;
+ size_t write_handle_as_size_t = 0;
+ size_t event_handle_as_size_t = 0;
+
+ if (fields.size() != 6
+ || !ParseNaturalNumber(fields[1], &line)
+ || !ParseNaturalNumber(fields[2], &index)
+ || !ParseNaturalNumber(fields[3], &parent_process_id)
+ || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
+ || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+ DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
+ GTEST_FLAG(internal_run_death_test));
+ }
+ write_fd = GetStatusFileDescriptor(parent_process_id,
+ write_handle_as_size_t,
+ event_handle_as_size_t);
+# else
+
+ if (fields.size() != 4
+ || !ParseNaturalNumber(fields[1], &line)
+ || !ParseNaturalNumber(fields[2], &index)
+ || !ParseNaturalNumber(fields[3], &write_fd)) {
+ DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
+ + GTEST_FLAG(internal_run_death_test));
+ }
+
+# endif // GTEST_OS_WINDOWS
+
+ return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+} // namespace internal
+
+#endif // GTEST_HAS_DEATH_TEST
+
+} // namespace testing
diff --git a/thirdparty/gtest/src/gtest-filepath.cc b/thirdparty/gtest/src/gtest-filepath.cc
new file mode 100644
index 00000000..6be58b6f
--- /dev/null
+++ b/thirdparty/gtest/src/gtest-filepath.cc
@@ -0,0 +1,382 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-port.h"
+
+#include <stdlib.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN
+// Symbian OpenC has PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
+#else
+# include <limits.h>
+# include <climits> // Some Linux distributions define PATH_MAX here.
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_MAX_ _MAX_PATH
+#elif defined(PATH_MAX)
+# define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif // GTEST_OS_WINDOWS
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+const char kPathSeparatorString[] = "\\";
+const char kAlternatePathSeparatorString[] = "/";
+# if GTEST_OS_WINDOWS_MOBILE
+// Windows CE doesn't have a current directory. You should not use
+// the current directory in tests on Windows CE, but this at least
+// provides a reasonable fallback.
+const char kCurrentDirectoryString[] = "\\";
+// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
+const DWORD kInvalidFileAttributes = 0xffffffff;
+# else
+const char kCurrentDirectoryString[] = ".\\";
+# endif // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+const char kPathSeparatorString[] = "/";
+const char kCurrentDirectoryString[] = "./";
+#endif // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+ return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+ return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if GTEST_OS_WINDOWS_MOBILE
+ // Windows CE doesn't have a current directory, so we just return
+ // something reasonable.
+ return FilePath(kCurrentDirectoryString);
+#elif GTEST_OS_WINDOWS
+ char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+ return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#else
+ char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+ return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#endif // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+ const std::string dot_extension = std::string(".") + extension;
+ if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
+ return FilePath(pathname_.substr(
+ 0, pathname_.length() - dot_extension.length()));
+ }
+ return *this;
+}
+
+// Returns a pointer to the last occurence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+ const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+ const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+ // Comparing two pointers of which only one is NULL is undefined.
+ if (last_alt_sep != NULL &&
+ (last_sep == NULL || last_alt_sep > last_sep)) {
+ return last_alt_sep;
+ }
+#endif
+ return last_sep;
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+ const char* const last_sep = FindLastPathSeparator();
+ return last_sep ? FilePath(last_sep + 1) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+ const char* const last_sep = FindLastPathSeparator();
+ std::string dir;
+ if (last_sep) {
+ dir = std::string(c_str(), last_sep + 1 - c_str());
+ } else {
+ dir = kCurrentDirectoryString;
+ }
+ return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+ const FilePath& base_name,
+ int number,
+ const char* extension) {
+ std::string file;
+ if (number == 0) {
+ file = base_name.string() + "." + extension;
+ } else {
+ file = base_name.string() + "_" + StreamableToString(number)
+ + "." + extension;
+ }
+ return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+ const FilePath& relative_path) {
+ if (directory.IsEmpty())
+ return relative_path;
+ const FilePath dir(directory.RemoveTrailingPathSeparator());
+ return FilePath(dir.string() + kPathSeparator + relative_path.string());
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#if GTEST_OS_WINDOWS_MOBILE
+ LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+ const DWORD attributes = GetFileAttributes(unicode);
+ delete [] unicode;
+ return attributes != kInvalidFileAttributes;
+#else
+ posix::StatStruct file_stat;
+ return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+ bool result = false;
+#if GTEST_OS_WINDOWS
+ // Don't strip off trailing separator if path is a root directory on
+ // Windows (like "C:\\").
+ const FilePath& path(IsRootDirectory() ? *this :
+ RemoveTrailingPathSeparator());
+#else
+ const FilePath& path(*this);
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+ LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+ const DWORD attributes = GetFileAttributes(unicode);
+ delete [] unicode;
+ if ((attributes != kInvalidFileAttributes) &&
+ (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ result = true;
+ }
+#else
+ posix::StatStruct file_stat;
+ result = posix::Stat(path.c_str(), &file_stat) == 0 &&
+ posix::IsDir(file_stat);
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+ return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive.)
+bool FilePath::IsRootDirectory() const {
+#if GTEST_OS_WINDOWS
+ // TODO(wan@google.com): on Windows a network share like
+ // \\server\share can be a root directory, although it cannot be the
+ // current directory. Handle this properly.
+ return pathname_.length() == 3 && IsAbsolutePath();
+#else
+ return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
+#endif
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const {
+ const char* const name = pathname_.c_str();
+#if GTEST_OS_WINDOWS
+ return pathname_.length() >= 3 &&
+ ((name[0] >= 'a' && name[0] <= 'z') ||
+ (name[0] >= 'A' && name[0] <= 'Z')) &&
+ name[1] == ':' &&
+ IsPathSeparator(name[2]);
+#else
+ return IsPathSeparator(name[0]);
+#endif
+}
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+ const FilePath& base_name,
+ const char* extension) {
+ FilePath full_pathname;
+ int number = 0;
+ do {
+ full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+ } while (full_pathname.FileOrDirectoryExists());
+ return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+ return !pathname_.empty() &&
+ IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+ if (!this->IsDirectory()) {
+ return false;
+ }
+
+ if (pathname_.length() == 0 || this->DirectoryExists()) {
+ return true;
+ }
+
+ const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+ return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#if GTEST_OS_WINDOWS_MOBILE
+ FilePath removed_sep(this->RemoveTrailingPathSeparator());
+ LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+ int result = CreateDirectory(unicode, NULL) ? 0 : -1;
+ delete [] unicode;
+#elif GTEST_OS_WINDOWS
+ int result = _mkdir(pathname_.c_str());
+#else
+ int result = mkdir(pathname_.c_str(), 0777);
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+ if (result == -1) {
+ return this->DirectoryExists(); // An error is OK if the directory exists.
+ }
+ return true; // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+ return IsDirectory()
+ ? FilePath(pathname_.substr(0, pathname_.length() - 1))
+ : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
+void FilePath::Normalize() {
+ if (pathname_.c_str() == NULL) {
+ pathname_ = "";
+ return;
+ }
+ const char* src = pathname_.c_str();
+ char* const dest = new char[pathname_.length() + 1];
+ char* dest_ptr = dest;
+ memset(dest_ptr, 0, pathname_.length() + 1);
+
+ while (*src != '\0') {
+ *dest_ptr = *src;
+ if (!IsPathSeparator(*src)) {
+ src++;
+ } else {
+#if GTEST_HAS_ALT_PATH_SEP_
+ if (*dest_ptr == kAlternatePathSeparator) {
+ *dest_ptr = kPathSeparator;
+ }
+#endif
+ while (IsPathSeparator(*src))
+ src++;
+ }
+ dest_ptr++;
+ }
+ *dest_ptr = '\0';
+ pathname_ = dest;
+ delete[] dest;
+}
+
+} // namespace internal
+} // namespace testing
diff --git a/thirdparty/gtest/src/gtest-internal-inl.h b/thirdparty/gtest/src/gtest-internal-inl.h
new file mode 100644
index 00000000..35df303c
--- /dev/null
+++ b/thirdparty/gtest/src/gtest-internal-inl.h
@@ -0,0 +1,1218 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility functions and classes used by the Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// This file contains purely Google Test's internal implementation. Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
+#define GTEST_SRC_GTEST_INTERNAL_INL_H_
+
+// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
+// part of Google Test's implementation; otherwise it's undefined.
+#if !GTEST_IMPLEMENTATION_
+// A user is trying to include this from his code - just say no.
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
+#endif // GTEST_IMPLEMENTATION_
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
+#include <string.h> // For memmove.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h> // NOLINT
+# include <netdb.h> // NOLINT
+#endif
+
+#if GTEST_OS_WINDOWS
+# include <windows.h> // NOLINT
+#endif // GTEST_OS_WINDOWS
+
+#include "gtest/gtest.h" // NOLINT
+#include "gtest/gtest-spi.h"
+
+namespace testing {
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library. This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
+const char kBreakOnFailureFlag[] = "break_on_failure";
+const char kCatchExceptionsFlag[] = "catch_exceptions";
+const char kColorFlag[] = "color";
+const char kFilterFlag[] = "filter";
+const char kListTestsFlag[] = "list_tests";
+const char kOutputFlag[] = "output";
+const char kPrintTimeFlag[] = "print_time";
+const char kRandomSeedFlag[] = "random_seed";
+const char kRepeatFlag[] = "repeat";
+const char kShuffleFlag[] = "shuffle";
+const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true iff Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds.
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Converts the given time in milliseconds to a date string in the ISO 8601
+// format, without the timezone information. N.B.: due to the use the
+// non-reentrant localtime() function, this function is not thread safe. Do
+// not use it in any code that can be called from multiple threads.
+GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true. On failure, returns false without changing *value.
+GTEST_API_ bool ParseInt32Flag(
+ const char* str, const char* flag, Int32* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
+ const unsigned int raw_seed = (random_seed_flag == 0) ?
+ static_cast<unsigned int>(GetTimeInMillis()) :
+ static_cast<unsigned int>(random_seed_flag);
+
+ // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+ // it's easy to type.
+ const int normalized_seed =
+ static_cast<int>((raw_seed - 1U) %
+ static_cast<unsigned int>(kMaxRandomSeed)) + 1;
+ return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'. The behavior is
+// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+ GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+ << "Invalid random seed " << seed << " - must be in [1, "
+ << kMaxRandomSeed << "].";
+ const int next_seed = seed + 1;
+ return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+ // The c'tor.
+ GTestFlagSaver() {
+ also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
+ break_on_failure_ = GTEST_FLAG(break_on_failure);
+ catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+ color_ = GTEST_FLAG(color);
+ death_test_style_ = GTEST_FLAG(death_test_style);
+ death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
+ filter_ = GTEST_FLAG(filter);
+ internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
+ list_tests_ = GTEST_FLAG(list_tests);
+ output_ = GTEST_FLAG(output);
+ print_time_ = GTEST_FLAG(print_time);
+ random_seed_ = GTEST_FLAG(random_seed);
+ repeat_ = GTEST_FLAG(repeat);
+ shuffle_ = GTEST_FLAG(shuffle);
+ stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+ stream_result_to_ = GTEST_FLAG(stream_result_to);
+ throw_on_failure_ = GTEST_FLAG(throw_on_failure);
+ }
+
+ // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS.
+ ~GTestFlagSaver() {
+ GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
+ GTEST_FLAG(break_on_failure) = break_on_failure_;
+ GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+ GTEST_FLAG(color) = color_;
+ GTEST_FLAG(death_test_style) = death_test_style_;
+ GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
+ GTEST_FLAG(filter) = filter_;
+ GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
+ GTEST_FLAG(list_tests) = list_tests_;
+ GTEST_FLAG(output) = output_;
+ GTEST_FLAG(print_time) = print_time_;
+ GTEST_FLAG(random_seed) = random_seed_;
+ GTEST_FLAG(repeat) = repeat_;
+ GTEST_FLAG(shuffle) = shuffle_;
+ GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+ GTEST_FLAG(stream_result_to) = stream_result_to_;
+ GTEST_FLAG(throw_on_failure) = throw_on_failure_;
+ }
+
+ private:
+ // Fields for saving the original values of flags.
+ bool also_run_disabled_tests_;
+ bool break_on_failure_;
+ bool catch_exceptions_;
+ std::string color_;
+ std::string death_test_style_;
+ bool death_test_use_fork_;
+ std::string filter_;
+ std::string internal_run_death_test_;
+ bool list_tests_;
+ std::string output_;
+ bool print_time_;
+ internal::Int32 random_seed_;
+ internal::Int32 repeat_;
+ bool shuffle_;
+ internal::Int32 stack_trace_depth_;
+ std::string stream_result_to_;
+ bool throw_on_failure_;
+} GTEST_ATTRIBUTE_UNUSED_;
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+GTEST_API_ std::string CodePointToUtf8(UInt32 code_point);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+// UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+ const char* shard_index_str,
+ bool in_subprocess_for_death_test);
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error and
+// and aborts.
+GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(
+ int total_shards, int shard_index, int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// the given predicate.
+template <class Container, typename Predicate>
+inline int CountIf(const Container& c, Predicate predicate) {
+ // Implemented as an explicit loop since std::count_if() in libCstd on
+ // Solaris has a non-standard signature.
+ int count = 0;
+ for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+ if (predicate(*it))
+ ++count;
+ }
+ return count;
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+ std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+ return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+ std::vector<E>* v) {
+ const int size = static_cast<int>(v->size());
+ GTEST_CHECK_(0 <= begin && begin <= size)
+ << "Invalid shuffle range start " << begin << ": must be in range [0, "
+ << size << "].";
+ GTEST_CHECK_(begin <= end && end <= size)
+ << "Invalid shuffle range finish " << end << ": must be in range ["
+ << begin << ", " << size << "].";
+
+ // Fisher-Yates shuffle, from
+ // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+ for (int range_width = end - begin; range_width >= 2; range_width--) {
+ const int last_in_range = begin + range_width - 1;
+ const int selected = begin + random->Generate(range_width);
+ std::swap((*v)[selected], (*v)[last_in_range]);
+ }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+ ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object. Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+ delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+ // Constructor.
+ //
+ // TestPropertyKeyIs has NO default constructor.
+ explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
+
+ // Returns true iff the test name of test property matches on key_.
+ bool operator()(const TestProperty& test_property) const {
+ return test_property.key() == key_;
+ }
+
+ private:
+ std::string key_;
+};
+
+// Class UnitTestOptions.
+//
+// This class contains functions for processing options the user
+// specifies when running the tests. It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag. E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter. If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+ // Functions for processing the gtest_output flag.
+
+ // Returns the output format, or "" for normal printed output.
+ static std::string GetOutputFormat();
+
+ // Returns the absolute path of the requested output file, or the
+ // default (test_detail.xml in the original working directory) if
+ // none was explicitly specified.
+ static std::string GetAbsolutePathToOutputFile();
+
+ // Functions for processing the gtest_filter flag.
+
+ // Returns true iff the wildcard pattern matches the string. The
+ // first ':' or '\0' character in pattern marks the end of it.
+ //
+ // This recursive algorithm isn't very efficient, but is clear and
+ // works well enough for matching test names, which are short.
+ static bool PatternMatchesString(const char *pattern, const char *str);
+
+ // Returns true iff the user-specified filter matches the test case
+ // name and the test name.
+ static bool FilterMatchesTest(const std::string &test_case_name,
+ const std::string &test_name);
+
+#if GTEST_OS_WINDOWS
+ // Function for supporting the gtest_catch_exception flag.
+
+ // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+ // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+ // This function is useful as an __except condition.
+ static int GTestShouldProcessSEH(DWORD exception_code);
+#endif // GTEST_OS_WINDOWS
+
+ // Returns true if "name" matches the ':' separated list of glob-style
+ // filters in "filter".
+ static bool MatchesFilter(const std::string& name, const char* filter);
+};
+
+// Returns the current application's name, removing directory path if that
+// is present. Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+ OsStackTraceGetterInterface() {}
+ virtual ~OsStackTraceGetterInterface() {}
+
+ // Returns the current OS stack trace as an std::string. Parameters:
+ //
+ // max_depth - the maximum number of stack frames to be included
+ // in the trace.
+ // skip_count - the number of top frames to be skipped; doesn't count
+ // against max_depth.
+ virtual string CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+ // UponLeavingGTest() should be called immediately before Google Test calls
+ // user code. It saves some information about the current stack that
+ // CurrentStackTrace() will use to find and hide Google Test stack frames.
+ virtual void UponLeavingGTest() = 0;
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+ OsStackTraceGetter() : caller_frame_(NULL) {}
+
+ virtual string CurrentStackTrace(int max_depth, int skip_count)
+ GTEST_LOCK_EXCLUDED_(mutex_);
+
+ virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_);
+
+ // This string is inserted in place of stack frames that are part of
+ // Google Test's implementation.
+ static const char* const kElidedFramesMarker;
+
+ private:
+ Mutex mutex_; // protects all internal state
+
+ // We save the stack frame below the frame that calls user code.
+ // We do this because the address of the frame immediately below
+ // the user code changes between the call to UponLeavingGTest()
+ // and any calls to CurrentStackTrace() from within the user code.
+ void* caller_frame_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+ const char* file;
+ int line;
+ std::string message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+ : public TestPartResultReporterInterface {
+ public:
+ explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+ // Implements the TestPartResultReporterInterface. Reports the test part
+ // result in the current test.
+ virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+ UnitTestImpl* const unit_test_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+ : public TestPartResultReporterInterface {
+ public:
+ explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+ // Implements the TestPartResultReporterInterface. The implementation just
+ // delegates to the current global test part result reporter of *unit_test_.
+ virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+ UnitTestImpl* const unit_test_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
+};
+
+// The private implementation of the UnitTest class. We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+ explicit UnitTestImpl(UnitTest* parent);
+ virtual ~UnitTestImpl();
+
+ // There are two different ways to register your own TestPartResultReporter.
+ // You can register your own repoter to listen either only for test results
+ // from the current thread or for results from all threads.
+ // By default, each per-thread test result repoter just passes a new
+ // TestPartResult to the global test result reporter, which registers the
+ // test part result for the currently running test.
+
+ // Returns the global test part result reporter.
+ TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+ // Sets the global test part result reporter.
+ void SetGlobalTestPartResultReporter(
+ TestPartResultReporterInterface* reporter);
+
+ // Returns the test part result reporter for the current thread.
+ TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+ // Sets the test part result reporter for the current thread.
+ void SetTestPartResultReporterForCurrentThread(
+ TestPartResultReporterInterface* reporter);
+
+ // Gets the number of successful test cases.
+ int successful_test_case_count() const;
+
+ // Gets the number of failed test cases.
+ int failed_test_case_count() const;
+
+ // Gets the number of all test cases.
+ int total_test_case_count() const;
+
+ // Gets the number of all test cases that contain at least one test
+ // that should run.
+ int test_case_to_run_count() const;
+
+ // Gets the number of successful tests.
+ int successful_test_count() const;
+
+ // Gets the number of failed tests.
+ int failed_test_count() const;
+
+ // Gets the number of disabled tests that will be reported in the XML report.
+ int reportable_disabled_test_count() const;
+
+ // Gets the number of disabled tests.
+ int disabled_test_count() const;
+
+ // Gets the number of tests to be printed in the XML report.
+ int reportable_test_count() const;
+
+ // Gets the number of all tests.
+ int total_test_count() const;
+
+ // Gets the number of tests that should run.
+ int test_to_run_count() const;
+
+ // Gets the time of the test program start, in ms from the start of the
+ // UNIX epoch.
+ TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+ // Gets the elapsed time, in milliseconds.
+ TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+ // Returns true iff the unit test passed (i.e. all test cases passed).
+ bool Passed() const { return !Failed(); }
+
+ // Returns true iff the unit test failed (i.e. some test case failed
+ // or something outside of all tests failed).
+ bool Failed() const {
+ return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed();
+ }
+
+ // Gets the i-th test case among all the test cases. i can range from 0 to
+ // total_test_case_count() - 1. If i is not in that range, returns NULL.
+ const TestCase* GetTestCase(int i) const {
+ const int index = GetElementOr(test_case_indices_, i, -1);
+ return index < 0 ? NULL : test_cases_[i];
+ }
+
+ // Gets the i-th test case among all the test cases. i can range from 0 to
+ // total_test_case_count() - 1. If i is not in that range, returns NULL.
+ TestCase* GetMutableTestCase(int i) {
+ const int index = GetElementOr(test_case_indices_, i, -1);
+ return index < 0 ? NULL : test_cases_[index];
+ }
+
+ // Provides access to the event listener list.
+ TestEventListeners* listeners() { return &listeners_; }
+
+ // Returns the TestResult for the test that's currently running, or
+ // the TestResult for the ad hoc test if no test is running.
+ TestResult* current_test_result();
+
+ // Returns the TestResult for the ad hoc test.
+ const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+ // Sets the OS stack trace getter.
+ //
+ // Does nothing if the input and the current OS stack trace getter
+ // are the same; otherwise, deletes the old getter and makes the
+ // input the current getter.
+ void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+ // Returns the current OS stack trace getter if it is not NULL;
+ // otherwise, creates an OsStackTraceGetter, makes it the current
+ // getter, and returns it.
+ OsStackTraceGetterInterface* os_stack_trace_getter();
+
+ // Returns the current OS stack trace as an std::string.
+ //
+ // The maximum number of stack frames to be included is specified by
+ // the gtest_stack_trace_depth flag. The skip_count parameter
+ // specifies the number of top frames to be skipped, which doesn't
+ // count against the number of frames to be included.
+ //
+ // For example, if Foo() calls Bar(), which in turn calls
+ // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+ // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+ std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
+
+ // Finds and returns a TestCase with the given name. If one doesn't
+ // exist, creates one and returns it.
+ //
+ // Arguments:
+ //
+ // test_case_name: name of the test case
+ // type_param: the name of the test's type parameter, or NULL if
+ // this is not a typed or a type-parameterized test.
+ // set_up_tc: pointer to the function that sets up the test case
+ // tear_down_tc: pointer to the function that tears down the test case
+ TestCase* GetTestCase(const char* test_case_name,
+ const char* type_param,
+ Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc);
+
+ // Adds a TestInfo to the unit test.
+ //
+ // Arguments:
+ //
+ // set_up_tc: pointer to the function that sets up the test case
+ // tear_down_tc: pointer to the function that tears down the test case
+ // test_info: the TestInfo object
+ void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc,
+ TestInfo* test_info) {
+ // In order to support thread-safe death tests, we need to
+ // remember the original working directory when the test program
+ // was first invoked. We cannot do this in RUN_ALL_TESTS(), as
+ // the user may have changed the current directory before calling
+ // RUN_ALL_TESTS(). Therefore we capture the current directory in
+ // AddTestInfo(), which is called to register a TEST or TEST_F
+ // before main() is reached.
+ if (original_working_dir_.IsEmpty()) {
+ original_working_dir_.Set(FilePath::GetCurrentDir());
+ GTEST_CHECK_(!original_working_dir_.IsEmpty())
+ << "Failed to get the current working directory.";
+ }
+
+ GetTestCase(test_info->test_case_name(),
+ test_info->type_param(),
+ set_up_tc,
+ tear_down_tc)->AddTestInfo(test_info);
+ }
+
+#if GTEST_HAS_PARAM_TEST
+ // Returns ParameterizedTestCaseRegistry object used to keep track of
+ // value-parameterized tests and instantiate and register them.
+ internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
+ return parameterized_test_registry_;
+ }
+#endif // GTEST_HAS_PARAM_TEST
+
+ // Sets the TestCase object for the test that's currently running.
+ void set_current_test_case(TestCase* a_current_test_case) {
+ current_test_case_ = a_current_test_case;
+ }
+
+ // Sets the TestInfo object for the test that's currently running. If
+ // current_test_info is NULL, the assertion results will be stored in
+ // ad_hoc_test_result_.
+ void set_current_test_info(TestInfo* a_current_test_info) {
+ current_test_info_ = a_current_test_info;
+ }
+
+ // Registers all parameterized tests defined using TEST_P and
+ // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+ // combination. This method can be called more then once; it has guards
+ // protecting from registering the tests more then once. If
+ // value-parameterized tests are disabled, RegisterParameterizedTests is
+ // present but does nothing.
+ void RegisterParameterizedTests();
+
+ // Runs all tests in this UnitTest object, prints the result, and
+ // returns true if all tests are successful. If any exception is
+ // thrown during a test, this test is considered to be failed, but
+ // the rest of the tests will still be run.
+ bool RunAllTests();
+
+ // Clears the results of all tests, except the ad hoc tests.
+ void ClearNonAdHocTestResult() {
+ ForEach(test_cases_, TestCase::ClearTestCaseResult);
+ }
+
+ // Clears the results of ad-hoc test assertions.
+ void ClearAdHocTestResult() {
+ ad_hoc_test_result_.Clear();
+ }
+
+ // Adds a TestProperty to the current TestResult object when invoked in a
+ // context of a test or a test case, or to the global property set. If the
+ // result already contains a property with the same key, the value will be
+ // updated.
+ void RecordProperty(const TestProperty& test_property);
+
+ enum ReactionToSharding {
+ HONOR_SHARDING_PROTOCOL,
+ IGNORE_SHARDING_PROTOCOL
+ };
+
+ // Matches the full name of each test against the user-specified
+ // filter to decide whether the test should run, then records the
+ // result in each TestCase and TestInfo object.
+ // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+ // based on sharding variables in the environment.
+ // Returns the number of tests that should run.
+ int FilterTests(ReactionToSharding shard_tests);
+
+ // Prints the names of the tests matching the user-specified filter flag.
+ void ListTestsMatchingFilter();
+
+ const TestCase* current_test_case() const { return current_test_case_; }
+ TestInfo* current_test_info() { return current_test_info_; }
+ const TestInfo* current_test_info() const { return current_test_info_; }
+
+ // Returns the vector of environments that need to be set-up/torn-down
+ // before/after the tests are run.
+ std::vector<Environment*>& environments() { return environments_; }
+
+ // Getters for the per-thread Google Test trace stack.
+ std::vector<TraceInfo>& gtest_trace_stack() {
+ return *(gtest_trace_stack_.pointer());
+ }
+ const std::vector<TraceInfo>& gtest_trace_stack() const {
+ return gtest_trace_stack_.get();
+ }
+
+#if GTEST_HAS_DEATH_TEST
+ void InitDeathTestSubprocessControlInfo() {
+ internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+ }
+ // Returns a pointer to the parsed --gtest_internal_run_death_test
+ // flag, or NULL if that flag was not specified.
+ // This information is useful only in a death test child process.
+ // Must not be called before a call to InitGoogleTest.
+ const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+ return internal_run_death_test_flag_.get();
+ }
+
+ // Returns a pointer to the current death test factory.
+ internal::DeathTestFactory* death_test_factory() {
+ return death_test_factory_.get();
+ }
+
+ void SuppressTestEventsIfInSubprocess();
+
+ friend class ReplaceDeathTestFactory;
+#endif // GTEST_HAS_DEATH_TEST
+
+ // Initializes the event listener performing XML output as specified by
+ // UnitTestOptions. Must not be called before InitGoogleTest.
+ void ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+ // Initializes the event listener for streaming test results to a socket.
+ // Must not be called before InitGoogleTest.
+ void ConfigureStreamingOutput();
+#endif
+
+ // Performs initialization dependent upon flag values obtained in
+ // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
+ // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
+ // this function is also called from RunAllTests. Since this function can be
+ // called more than once, it has to be idempotent.
+ void PostFlagParsingInit();
+
+ // Gets the random seed used at the start of the current test iteration.
+ int random_seed() const { return random_seed_; }
+
+ // Gets the random number generator.
+ internal::Random* random() { return &random_; }
+
+ // Shuffles all test cases, and the tests within each test case,
+ // making sure that death tests are still run first.
+ void ShuffleTests();
+
+ // Restores the test cases and tests to their order before the first shuffle.
+ void UnshuffleTests();
+
+ // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+ // UnitTest::Run() starts.
+ bool catch_exceptions() const { return catch_exceptions_; }
+
+ private:
+ friend class ::testing::UnitTest;
+
+ // Used by UnitTest::Run() to capture the state of
+ // GTEST_FLAG(catch_exceptions) at the moment it starts.
+ void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
+ // The UnitTest object that owns this implementation object.
+ UnitTest* const parent_;
+
+ // The working directory when the first TEST() or TEST_F() was
+ // executed.
+ internal::FilePath original_working_dir_;
+
+ // The default test part result reporters.
+ DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+ DefaultPerThreadTestPartResultReporter
+ default_per_thread_test_part_result_reporter_;
+
+ // Points to (but doesn't own) the global test part result reporter.
+ TestPartResultReporterInterface* global_test_part_result_repoter_;
+
+ // Protects read and write access to global_test_part_result_reporter_.
+ internal::Mutex global_test_part_result_reporter_mutex_;
+
+ // Points to (but doesn't own) the per-thread test part result reporter.
+ internal::ThreadLocal<TestPartResultReporterInterface*>
+ per_thread_test_part_result_reporter_;
+
+ // The vector of environments that need to be set-up/torn-down
+ // before/after the tests are run.
+ std::vector<Environment*> environments_;
+
+ // The vector of TestCases in their original order. It owns the
+ // elements in the vector.
+ std::vector<TestCase*> test_cases_;
+
+ // Provides a level of indirection for the test case list to allow
+ // easy shuffling and restoring the test case order. The i-th
+ // element of this vector is the index of the i-th test case in the
+ // shuffled order.
+ std::vector<int> test_case_indices_;
+
+#if GTEST_HAS_PARAM_TEST
+ // ParameterizedTestRegistry object used to register value-parameterized
+ // tests.
+ internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
+
+ // Indicates whether RegisterParameterizedTests() has been called already.
+ bool parameterized_tests_registered_;
+#endif // GTEST_HAS_PARAM_TEST
+
+ // Index of the last death test case registered. Initially -1.
+ int last_death_test_case_;
+
+ // This points to the TestCase for the currently running test. It
+ // changes as Google Test goes through one test case after another.
+ // When no test is running, this is set to NULL and Google Test
+ // stores assertion results in ad_hoc_test_result_. Initially NULL.
+ TestCase* current_test_case_;
+
+ // This points to the TestInfo for the currently running test. It
+ // changes as Google Test goes through one test after another. When
+ // no test is running, this is set to NULL and Google Test stores
+ // assertion results in ad_hoc_test_result_. Initially NULL.
+ TestInfo* current_test_info_;
+
+ // Normally, a user only writes assertions inside a TEST or TEST_F,
+ // or inside a function called by a TEST or TEST_F. Since Google
+ // Test keeps track of which test is current running, it can
+ // associate such an assertion with the test it belongs to.
+ //
+ // If an assertion is encountered when no TEST or TEST_F is running,
+ // Google Test attributes the assertion result to an imaginary "ad hoc"
+ // test, and records the result in ad_hoc_test_result_.
+ TestResult ad_hoc_test_result_;
+
+ // The list of event listeners that can be used to track events inside
+ // Google Test.
+ TestEventListeners listeners_;
+
+ // The OS stack trace getter. Will be deleted when the UnitTest
+ // object is destructed. By default, an OsStackTraceGetter is used,
+ // but the user can set this field to use a custom getter if that is
+ // desired.
+ OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+ // True iff PostFlagParsingInit() has been called.
+ bool post_flag_parse_init_performed_;
+
+ // The random number seed used at the beginning of the test run.
+ int random_seed_;
+
+ // Our random number generator.
+ internal::Random random_;
+
+ // The time of the test program start, in ms from the start of the
+ // UNIX epoch.
+ TimeInMillis start_timestamp_;
+
+ // How long the test took to run, in milliseconds.
+ TimeInMillis elapsed_time_;
+
+#if GTEST_HAS_DEATH_TEST
+ // The decomposed components of the gtest_internal_run_death_test flag,
+ // parsed when RUN_ALL_TESTS is called.
+ internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+ internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif // GTEST_HAS_DEATH_TEST
+
+ // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+ internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+ // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+ // starts.
+ bool catch_exceptions_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
+}; // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+ return UnitTest::GetInstance()->impl();
+}
+
+#if GTEST_USES_SIMPLE_RE
+
+// Internal helper functions for implementing the simple regular
+// expression matcher.
+GTEST_API_ bool IsInSet(char ch, const char* str);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
+GTEST_API_ bool IsRepeat(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
+GTEST_API_ bool IsValidEscape(char ch);
+GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
+GTEST_API_ bool ValidateRegex(const char* regex);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(
+ bool escaped, char ch, char repeat, const char* regex, const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+#endif // GTEST_USES_SIMPLE_RE
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+GTEST_API_ std::string GetLastErrnoDescription();
+
+# if GTEST_OS_WINDOWS
+// Provides leak-safe Windows kernel handle ownership.
+class AutoHandle {
+ public:
+ AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
+ explicit AutoHandle(HANDLE handle) : handle_(handle) {}
+
+ ~AutoHandle() { Reset(); }
+
+ HANDLE Get() const { return handle_; }
+ void Reset() { Reset(INVALID_HANDLE_VALUE); }
+ void Reset(HANDLE handle) {
+ if (handle != handle_) {
+ if (handle_ != INVALID_HANDLE_VALUE)
+ ::CloseHandle(handle_);
+ handle_ = handle;
+ }
+ }
+
+ private:
+ HANDLE handle_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+# endif // GTEST_OS_WINDOWS
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter. Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+ // Fail fast if the given string does not begin with a digit;
+ // this bypasses strtoXXX's "optional leading whitespace and plus
+ // or minus sign" semantics, which are undesirable here.
+ if (str.empty() || !IsDigit(str[0])) {
+ return false;
+ }
+ errno = 0;
+
+ char* end;
+ // BiggestConvertible is the largest integer type that system-provided
+ // string-to-number conversion routines can return.
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+ // MSVC and C++ Builder define __int64 instead of the standard long long.
+ typedef unsigned __int64 BiggestConvertible;
+ const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
+
+# else
+
+ typedef unsigned long long BiggestConvertible; // NOLINT
+ const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
+
+# endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+ const bool parse_success = *end == '\0' && errno == 0;
+
+ // TODO(vladl@google.com): Convert this to compile time assertion when it is
+ // available.
+ GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+ const Integer result = static_cast<Integer>(parsed);
+ if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+ *number = result;
+ return true;
+ }
+ return false;
+}
+#endif // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+ static void RecordProperty(TestResult* test_result,
+ const std::string& xml_element,
+ const TestProperty& property) {
+ test_result->RecordProperty(xml_element, property);
+ }
+
+ static void ClearTestPartResults(TestResult* test_result) {
+ test_result->ClearTestPartResults();
+ }
+
+ static const std::vector<testing::TestPartResult>& test_part_results(
+ const TestResult& test_result) {
+ return test_result.test_part_results();
+ }
+};
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+ // Abstract base class for writing strings to a socket.
+ class AbstractSocketWriter {
+ public:
+ virtual ~AbstractSocketWriter() {}
+
+ // Sends a string to the socket.
+ virtual void Send(const string& message) = 0;
+
+ // Closes the socket.
+ virtual void CloseConnection() {}
+
+ // Sends a string and a newline to the socket.
+ void SendLn(const string& message) {
+ Send(message + "\n");
+ }
+ };
+
+ // Concrete class for actually writing strings to a socket.
+ class SocketWriter : public AbstractSocketWriter {
+ public:
+ SocketWriter(const string& host, const string& port)
+ : sockfd_(-1), host_name_(host), port_num_(port) {
+ MakeConnection();
+ }
+
+ virtual ~SocketWriter() {
+ if (sockfd_ != -1)
+ CloseConnection();
+ }
+
+ // Sends a string to the socket.
+ virtual void Send(const string& message) {
+ GTEST_CHECK_(sockfd_ != -1)
+ << "Send() can be called only when there is a connection.";
+
+ const int len = static_cast<int>(message.length());
+ if (write(sockfd_, message.c_str(), len) != len) {
+ GTEST_LOG_(WARNING)
+ << "stream_result_to: failed to stream to "
+ << host_name_ << ":" << port_num_;
+ }
+ }
+
+ private:
+ // Creates a client socket and connects to the server.
+ void MakeConnection();
+
+ // Closes the socket.
+ void CloseConnection() {
+ GTEST_CHECK_(sockfd_ != -1)
+ << "CloseConnection() can be called only when there is a connection.";
+
+ close(sockfd_);
+ sockfd_ = -1;
+ }
+
+ int sockfd_; // socket file descriptor
+ const string host_name_;
+ const string port_num_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
+ }; // class SocketWriter
+
+ // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+ static string UrlEncode(const char* str);
+
+ StreamingListener(const string& host, const string& port)
+ : socket_writer_(new SocketWriter(host, port)) { Start(); }
+
+ explicit StreamingListener(AbstractSocketWriter* socket_writer)
+ : socket_writer_(socket_writer) { Start(); }
+
+ void OnTestProgramStart(const UnitTest& /* unit_test */) {
+ SendLn("event=TestProgramStart");
+ }
+
+ void OnTestProgramEnd(const UnitTest& unit_test) {
+ // Note that Google Test current only report elapsed time for each
+ // test iteration, not for the entire test program.
+ SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
+
+ // Notify the streaming server to stop.
+ socket_writer_->CloseConnection();
+ }
+
+ void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+ SendLn("event=TestIterationStart&iteration=" +
+ StreamableToString(iteration));
+ }
+
+ void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+ SendLn("event=TestIterationEnd&passed=" +
+ FormatBool(unit_test.Passed()) + "&elapsed_time=" +
+ StreamableToString(unit_test.elapsed_time()) + "ms");
+ }
+
+ void OnTestCaseStart(const TestCase& test_case) {
+ SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
+ }
+
+ void OnTestCaseEnd(const TestCase& test_case) {
+ SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed())
+ + "&elapsed_time=" + StreamableToString(test_case.elapsed_time())
+ + "ms");
+ }
+
+ void OnTestStart(const TestInfo& test_info) {
+ SendLn(std::string("event=TestStart&name=") + test_info.name());
+ }
+
+ void OnTestEnd(const TestInfo& test_info) {
+ SendLn("event=TestEnd&passed=" +
+ FormatBool((test_info.result())->Passed()) +
+ "&elapsed_time=" +
+ StreamableToString((test_info.result())->elapsed_time()) + "ms");
+ }
+
+ void OnTestPartResult(const TestPartResult& test_part_result) {
+ const char* file_name = test_part_result.file_name();
+ if (file_name == NULL)
+ file_name = "";
+ SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
+ "&line=" + StreamableToString(test_part_result.line_number()) +
+ "&message=" + UrlEncode(test_part_result.message()));
+ }
+
+ private:
+ // Sends the given message and a newline to the socket.
+ void SendLn(const string& message) { socket_writer_->SendLn(message); }
+
+ // Called at the start of streaming to notify the receiver what
+ // protocol we are using.
+ void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
+
+ string FormatBool(bool value) { return value ? "1" : "0"; }
+
+ const scoped_ptr<AbstractSocketWriter> socket_writer_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+}; // class StreamingListener
+
+#endif // GTEST_CAN_STREAM_RESULTS_
+
+} // namespace internal
+} // namespace testing
+
+#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_
diff --git a/thirdparty/gtest/src/gtest-port.cc b/thirdparty/gtest/src/gtest-port.cc
new file mode 100644
index 00000000..0c4df5f2
--- /dev/null
+++ b/thirdparty/gtest/src/gtest-port.cc
@@ -0,0 +1,805 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/internal/gtest-port.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h> // For TerminateProcess()
+#elif GTEST_OS_WINDOWS
+# include <io.h>
+# include <sys/stat.h>
+#else
+# include <unistd.h>
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_MAC
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
+#endif // GTEST_OS_MAC
+
+#if GTEST_OS_QNX
+# include <devctl.h>
+# include <sys/procfs.h>
+#endif // GTEST_OS_QNX
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation. It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif // _MSC_VER
+
+#if GTEST_OS_MAC
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+ const task_t task = mach_task_self();
+ mach_msg_type_number_t thread_count;
+ thread_act_array_t thread_list;
+ const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+ if (status == KERN_SUCCESS) {
+ // task_threads allocates resources in thread_list and we need to free them
+ // to avoid leaks.
+ vm_deallocate(task,
+ reinterpret_cast<vm_address_t>(thread_list),
+ sizeof(thread_t) * thread_count);
+ return static_cast<size_t>(thread_count);
+ } else {
+ return 0;
+ }
+}
+
+#elif GTEST_OS_QNX
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+ const int fd = open("/proc/self/as", O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+ procfs_info process_info;
+ const int status =
+ devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
+ close(fd);
+ if (status == EOK) {
+ return static_cast<size_t>(process_info.num_threads);
+ } else {
+ return 0;
+ }
+}
+
+#else
+
+size_t GetThreadCount() {
+ // There's no portable way to detect the number of threads, so we just
+ // return 0 to indicate that we cannot detect it.
+ return 0;
+}
+
+#endif // GTEST_OS_MAC
+
+#if GTEST_USES_POSIX_RE
+
+// Implements RE. Currently only needed for death tests.
+
+RE::~RE() {
+ if (is_valid_) {
+ // regfree'ing an invalid regex might crash because the content
+ // of the regex is undefined. Since the regex's are essentially
+ // the same, one cannot be valid (or invalid) without the other
+ // being so too.
+ regfree(&partial_regex_);
+ regfree(&full_regex_);
+ }
+ free(const_cast<char*>(pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+ if (!re.is_valid_) return false;
+
+ regmatch_t match;
+ return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+ if (!re.is_valid_) return false;
+
+ regmatch_t match;
+ return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+ pattern_ = posix::StrDup(regex);
+
+ // Reserves enough bytes to hold the regular expression used for a
+ // full match.
+ const size_t full_regex_len = strlen(regex) + 10;
+ char* const full_pattern = new char[full_regex_len];
+
+ snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+ is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+ // We want to call regcomp(&partial_regex_, ...) even if the
+ // previous expression returns false. Otherwise partial_regex_ may
+ // not be properly initialized can may cause trouble when it's
+ // freed.
+ //
+ // Some implementation of POSIX regex (e.g. on at least some
+ // versions of Cygwin) doesn't accept the empty string as a valid
+ // regex. We change it to an equivalent form "()" to be safe.
+ if (is_valid_) {
+ const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+ is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+ }
+ EXPECT_TRUE(is_valid_)
+ << "Regular expression \"" << regex
+ << "\" is not a valid POSIX Extended regular expression.";
+
+ delete[] full_pattern;
+}
+
+#elif GTEST_USES_SIMPLE_RE
+
+// Returns true iff ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+ return ch != '\0' && strchr(str, ch) != NULL;
+}
+
+// Returns true iff ch belongs to the given classification. Unlike
+// similar functions in <ctype.h>, these aren't affected by the
+// current locale.
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
+ return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
+}
+bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
+ return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+ ('0' <= ch && ch <= '9') || ch == '_';
+}
+
+// Returns true iff "\\c" is a supported escape sequence.
+bool IsValidEscape(char c) {
+ return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+}
+
+// Returns true iff the given atom (specified by escaped and pattern)
+// matches ch. The result is undefined if the atom is invalid.
+bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
+ if (escaped) { // "\\p" where p is pattern_char.
+ switch (pattern_char) {
+ case 'd': return IsAsciiDigit(ch);
+ case 'D': return !IsAsciiDigit(ch);
+ case 'f': return ch == '\f';
+ case 'n': return ch == '\n';
+ case 'r': return ch == '\r';
+ case 's': return IsAsciiWhiteSpace(ch);
+ case 'S': return !IsAsciiWhiteSpace(ch);
+ case 't': return ch == '\t';
+ case 'v': return ch == '\v';
+ case 'w': return IsAsciiWordChar(ch);
+ case 'W': return !IsAsciiWordChar(ch);
+ }
+ return IsAsciiPunct(pattern_char) && pattern_char == ch;
+ }
+
+ return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+std::string FormatRegexSyntaxError(const char* regex, int index) {
+ return (Message() << "Syntax error at index " << index
+ << " in simple regular expression \"" << regex << "\": ").GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+ if (regex == NULL) {
+ // TODO(wan@google.com): fix the source file location in the
+ // assertion failures to match where the regex is used in user
+ // code.
+ ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+ return false;
+ }
+
+ bool is_valid = true;
+
+ // True iff ?, *, or + can follow the previous atom.
+ bool prev_repeatable = false;
+ for (int i = 0; regex[i]; i++) {
+ if (regex[i] == '\\') { // An escape sequence
+ i++;
+ if (regex[i] == '\0') {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+ << "'\\' cannot appear at the end.";
+ return false;
+ }
+
+ if (!IsValidEscape(regex[i])) {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+ << "invalid escape sequence \"\\" << regex[i] << "\".";
+ is_valid = false;
+ }
+ prev_repeatable = true;
+ } else { // Not an escape sequence.
+ const char ch = regex[i];
+
+ if (ch == '^' && i > 0) {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+ << "'^' can only appear at the beginning.";
+ is_valid = false;
+ } else if (ch == '$' && regex[i + 1] != '\0') {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+ << "'$' can only appear at the end.";
+ is_valid = false;
+ } else if (IsInSet(ch, "()[]{}|")) {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+ << "'" << ch << "' is unsupported.";
+ is_valid = false;
+ } else if (IsRepeat(ch) && !prev_repeatable) {
+ ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+ << "'" << ch << "' can only follow a repeatable token.";
+ is_valid = false;
+ }
+
+ prev_repeatable = !IsInSet(ch, "^$?*+");
+ }
+ }
+
+ return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression. The regex atom is defined as c if escaped is false,
+// or \c otherwise. repeat is the repetition meta character (?, *,
+// or +). The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway. We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(
+ bool escaped, char c, char repeat, const char* regex,
+ const char* str) {
+ const size_t min_count = (repeat == '+') ? 1 : 0;
+ const size_t max_count = (repeat == '?') ? 1 :
+ static_cast<size_t>(-1) - 1;
+ // We cannot call numeric_limits::max() as it conflicts with the
+ // max() macro on Windows.
+
+ for (size_t i = 0; i <= max_count; ++i) {
+ // We know that the atom matches each of the first i characters in str.
+ if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+ // We have enough matches at the head, and the tail matches too.
+ // Since we only care about *whether* the pattern matches str
+ // (as opposed to *how* it matches), there is no need to find a
+ // greedy match.
+ return true;
+ }
+ if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
+ return false;
+ }
+ return false;
+}
+
+// Returns true iff regex matches a prefix of str. regex must be a
+// valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+ if (*regex == '\0') // An empty regex matches a prefix of anything.
+ return true;
+
+ // "$" only matches the end of a string. Note that regex being
+ // valid guarantees that there's nothing after "$" in it.
+ if (*regex == '$')
+ return *str == '\0';
+
+ // Is the first thing in regex an escape sequence?
+ const bool escaped = *regex == '\\';
+ if (escaped)
+ ++regex;
+ if (IsRepeat(regex[1])) {
+ // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+ // here's an indirect recursion. It terminates as the regex gets
+ // shorter in each recursion.
+ return MatchRepetitionAndRegexAtHead(
+ escaped, regex[0], regex[1], regex + 2, str);
+ } else {
+ // regex isn't empty, isn't "$", and doesn't start with a
+ // repetition. We match the first atom of regex with the first
+ // character of str and recurse.
+ return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+ MatchRegexAtHead(regex + 1, str + 1);
+ }
+}
+
+// Returns true iff regex matches any substring of str. regex must be
+// a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally. In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+ if (regex == NULL || str == NULL)
+ return false;
+
+ if (*regex == '^')
+ return MatchRegexAtHead(regex + 1, str);
+
+ // A successful match can be anywhere in str.
+ do {
+ if (MatchRegexAtHead(regex, str))
+ return true;
+ } while (*str++ != '\0');
+ return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() {
+ free(const_cast<char*>(pattern_));
+ free(const_cast<char*>(full_pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+ return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+ return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+ pattern_ = full_pattern_ = NULL;
+ if (regex != NULL) {
+ pattern_ = posix::StrDup(regex);
+ }
+
+ is_valid_ = ValidateRegex(regex);
+ if (!is_valid_) {
+ // No need to calculate the full pattern when the regex is invalid.
+ return;
+ }
+
+ const size_t len = strlen(regex);
+ // Reserves enough bytes to hold the regular expression used for a
+ // full match: we need space to prepend a '^', append a '$', and
+ // terminate the string with '\0'.
+ char* buffer = static_cast<char*>(malloc(len + 3));
+ full_pattern_ = buffer;
+
+ if (*regex != '^')
+ *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'.
+
+ // We don't use snprintf or strncpy, as they trigger a warning when
+ // compiled with VC++ 8.0.
+ memcpy(buffer, regex, len);
+ buffer += len;
+
+ if (len == 0 || regex[len - 1] != '$')
+ *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'.
+
+ *buffer = '\0';
+}
+
+#endif // GTEST_USES_POSIX_RE
+
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+ const std::string file_name(file == NULL ? kUnknownFile : file);
+
+ if (line < 0) {
+ return file_name + ":";
+ }
+#ifdef _MSC_VER
+ return file_name + "(" + StreamableToString(line) + "):";
+#else
+ return file_name + ":" + StreamableToString(line) + ":";
+#endif // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+ const char* file, int line) {
+ const std::string file_name(file == NULL ? kUnknownFile : file);
+
+ if (line < 0)
+ return file_name;
+ else
+ return file_name + ":" + StreamableToString(line);
+}
+
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+ : severity_(severity) {
+ const char* const marker =
+ severity == GTEST_INFO ? "[ INFO ]" :
+ severity == GTEST_WARNING ? "[WARNING]" :
+ severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
+ GetStream() << ::std::endl << marker << " "
+ << FormatFileLocation(file, line).c_str() << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+ GetStream() << ::std::endl;
+ if (severity_ == GTEST_FATAL) {
+ fflush(stderr);
+ posix::Abort();
+ }
+}
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996)
+#endif // _MSC_VER
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Object that captures an output stream (stdout/stderr).
+class CapturedStream {
+ public:
+ // The ctor redirects the stream to a temporary file.
+ explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
+# if GTEST_OS_WINDOWS
+ char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
+ char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
+
+ ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+ const UINT success = ::GetTempFileNameA(temp_dir_path,
+ "gtest_redir",
+ 0, // Generate unique file name.
+ temp_file_path);
+ GTEST_CHECK_(success != 0)
+ << "Unable to create a temporary file in " << temp_dir_path;
+ const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+ GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
+ << temp_file_path;
+ filename_ = temp_file_path;
+# else
+ // There's no guarantee that a test has write access to the current
+ // directory, so we create the temporary file in the /tmp directory
+ // instead. We use /tmp on most systems, and /sdcard on Android.
+ // That's because Android doesn't have /tmp.
+# if GTEST_OS_LINUX_ANDROID
+ // Note: Android applications are expected to call the framework's
+ // Context.getExternalStorageDirectory() method through JNI to get
+ // the location of the world-writable SD Card directory. However,
+ // this requires a Context handle, which cannot be retrieved
+ // globally from native code. Doing so also precludes running the
+ // code as part of a regular standalone executable, which doesn't
+ // run in a Dalvik process (e.g. when running it through 'adb shell').
+ //
+ // The location /sdcard is directly accessible from native code
+ // and is the only location (unofficially) supported by the Android
+ // team. It's generally a symlink to the real SD Card mount point
+ // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or
+ // other OEM-customized locations. Never rely on these, and always
+ // use /sdcard.
+ char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
+# else
+ char name_template[] = "/tmp/captured_stream.XXXXXX";
+# endif // GTEST_OS_LINUX_ANDROID
+ const int captured_fd = mkstemp(name_template);
+ filename_ = name_template;
+# endif // GTEST_OS_WINDOWS
+ fflush(NULL);
+ dup2(captured_fd, fd_);
+ close(captured_fd);
+ }
+
+ ~CapturedStream() {
+ remove(filename_.c_str());
+ }
+
+ std::string GetCapturedString() {
+ if (uncaptured_fd_ != -1) {
+ // Restores the original stream.
+ fflush(NULL);
+ dup2(uncaptured_fd_, fd_);
+ close(uncaptured_fd_);
+ uncaptured_fd_ = -1;
+ }
+
+ FILE* const file = posix::FOpen(filename_.c_str(), "r");
+ const std::string content = ReadEntireFile(file);
+ posix::FClose(file);
+ return content;
+ }
+
+ private:
+ // Reads the entire content of a file as an std::string.
+ static std::string ReadEntireFile(FILE* file);
+
+ // Returns the size (in bytes) of a file.
+ static size_t GetFileSize(FILE* file);
+
+ const int fd_; // A stream to capture.
+ int uncaptured_fd_;
+ // Name of the temporary file holding the stderr output.
+ ::std::string filename_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
+};
+
+// Returns the size (in bytes) of a file.
+size_t CapturedStream::GetFileSize(FILE* file) {
+ fseek(file, 0, SEEK_END);
+ return static_cast<size_t>(ftell(file));
+}
+
+// Reads the entire content of a file as a string.
+std::string CapturedStream::ReadEntireFile(FILE* file) {
+ const size_t file_size = GetFileSize(file);
+ char* const buffer = new char[file_size];
+
+ size_t bytes_last_read = 0; // # of bytes read in the last fread()
+ size_t bytes_read = 0; // # of bytes read so far
+
+ fseek(file, 0, SEEK_SET);
+
+ // Keeps reading the file until we cannot read further or the
+ // pre-determined file size is reached.
+ do {
+ bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+ bytes_read += bytes_last_read;
+ } while (bytes_last_read > 0 && bytes_read < file_size);
+
+ const std::string content(buffer, bytes_read);
+ delete[] buffer;
+
+ return content;
+}
+
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif // _MSC_VER
+
+static CapturedStream* g_captured_stderr = NULL;
+static CapturedStream* g_captured_stdout = NULL;
+
+// Starts capturing an output stream (stdout/stderr).
+void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
+ if (*stream != NULL) {
+ GTEST_LOG_(FATAL) << "Only one " << stream_name
+ << " capturer can exist at a time.";
+ }
+ *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+std::string GetCapturedStream(CapturedStream** captured_stream) {
+ const std::string content = (*captured_stream)->GetCapturedString();
+
+ delete *captured_stream;
+ *captured_stream = NULL;
+
+ return content;
+}
+
+// Starts capturing stdout.
+void CaptureStdout() {
+ CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+ CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+std::string GetCapturedStdout() {
+ return GetCapturedStream(&g_captured_stdout);
+}
+
+// Stops capturing stderr and returns the captured string.
+std::string GetCapturedStderr() {
+ return GetCapturedStream(&g_captured_stderr);
+}
+
+#endif // GTEST_HAS_STREAM_REDIRECTION
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments. Set by InitGoogleTest().
+::std::vector<testing::internal::string> g_argvs;
+
+static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
+ NULL; // Owned.
+
+void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
+ if (g_injected_test_argvs != argvs)
+ delete g_injected_test_argvs;
+ g_injected_test_argvs = argvs;
+}
+
+const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
+ if (g_injected_test_argvs != NULL) {
+ return *g_injected_test_argvs;
+ }
+ return g_argvs;
+}
+#endif // GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+ DebugBreak();
+ TerminateProcess(GetCurrentProcess(), 1);
+}
+} // namespace posix
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag. For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static std::string FlagToEnvVar(const char* flag) {
+ const std::string full_flag =
+ (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+ Message env_var;
+ for (size_t i = 0; i != full_flag.length(); i++) {
+ env_var << ToUpper(full_flag.c_str()[i]);
+ }
+
+ return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer. If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
+ // Parses the environment variable as a decimal integer.
+ char* end = NULL;
+ const long long_value = strtol(str, &end, 10); // NOLINT
+
+ // Has strtol() consumed all characters in the string?
+ if (*end != '\0') {
+ // No - an invalid character was encountered.
+ Message msg;
+ msg << "WARNING: " << src_text
+ << " is expected to be a 32-bit integer, but actually"
+ << " has value \"" << str << "\".\n";
+ printf("%s", msg.GetString().c_str());
+ fflush(stdout);
+ return false;
+ }
+
+ // Is the parsed value in the range of an Int32?
+ const Int32 result = static_cast<Int32>(long_value);
+ if (long_value == LONG_MAX || long_value == LONG_MIN ||
+ // The parsed value overflows as a long. (strtol() returns
+ // LONG_MAX or LONG_MIN when the input overflows.)
+ result != long_value
+ // The parsed value overflows as an Int32.
+ ) {
+ Message msg;
+ msg << "WARNING: " << src_text
+ << " is expected to be a 32-bit integer, but actually"
+ << " has value " << str << ", which overflows.\n";
+ printf("%s", msg.GetString().c_str());
+ fflush(stdout);
+ return false;
+ }
+
+ *value = result;
+ return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true iff it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+ const std::string env_var = FlagToEnvVar(flag);
+ const char* const string_value = posix::GetEnv(env_var.c_str());
+ return string_value == NULL ?
+ default_value : strcmp(string_value, "0") != 0;
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
+ const std::string env_var = FlagToEnvVar(flag);
+ const char* const string_value = posix::GetEnv(env_var.c_str());
+ if (string_value == NULL) {
+ // The environment variable is not set.
+ return default_value;
+ }
+
+ Int32 result = default_value;
+ if (!ParseInt32(Message() << "Environment variable " << env_var,
+ string_value, &result)) {
+ printf("The default value %s is used.\n",
+ (Message() << default_value).GetString().c_str());
+ fflush(stdout);
+ return default_value;
+ }
+
+ return result;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+ const std::string env_var = FlagToEnvVar(flag);
+ const char* const value = posix::GetEnv(env_var.c_str());
+ return value == NULL ? default_value : value;
+}
+
+} // namespace internal
+} // namespace testing
diff --git a/thirdparty/gtest/src/gtest-printers.cc b/thirdparty/gtest/src/gtest-printers.cc
new file mode 100644
index 00000000..75fa4081
--- /dev/null
+++ b/thirdparty/gtest/src/gtest-printers.cc
@@ -0,0 +1,363 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise. A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include "gtest/gtest-printers.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <ostream> // NOLINT
+#include <string>
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+// Prints a segment of bytes in the given object.
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+ size_t count, ostream* os) {
+ char text[5] = "";
+ for (size_t i = 0; i != count; i++) {
+ const size_t j = start + i;
+ if (i != 0) {
+ // Organizes the bytes into groups of 2 for easy parsing by
+ // human.
+ if ((j % 2) == 0)
+ *os << ' ';
+ else
+ *os << '-';
+ }
+ GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
+ *os << text;
+ }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+ ostream* os) {
+ // Tells the user how big the object is.
+ *os << count << "-byte object <";
+
+ const size_t kThreshold = 132;
+ const size_t kChunkSize = 64;
+ // If the object size is bigger than kThreshold, we'll have to omit
+ // some details by printing only the first and the last kChunkSize
+ // bytes.
+ // TODO(wan): let the user control the threshold using a flag.
+ if (count < kThreshold) {
+ PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+ } else {
+ PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+ *os << " ... ";
+ // Rounds up to 2-byte boundary.
+ const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+ PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+ }
+ *os << ">";
+}
+
+} // namespace
+
+namespace internal2 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object. The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+ ostream* os) {
+ PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+} // namespace internal2
+
+namespace internal {
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+// - as a hexidecimal escape sequence (e.g. '\x7F'), or
+// - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+ kAsIs,
+ kHexEscape,
+ kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character. We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(wchar_t c) {
+ return 0x20 <= c && c <= 0x7E;
+}
+
+// Prints a wide or narrow char c as a character literal without the
+// quotes, escaping it when necessary; returns how c was formatted.
+// The template argument UnsignedChar is the unsigned version of Char,
+// which is the type of c.
+template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+ switch (static_cast<wchar_t>(c)) {
+ case L'\0':
+ *os << "\\0";
+ break;
+ case L'\'':
+ *os << "\\'";
+ break;
+ case L'\\':
+ *os << "\\\\";
+ break;
+ case L'\a':
+ *os << "\\a";
+ break;
+ case L'\b':
+ *os << "\\b";
+ break;
+ case L'\f':
+ *os << "\\f";
+ break;
+ case L'\n':
+ *os << "\\n";
+ break;
+ case L'\r':
+ *os << "\\r";
+ break;
+ case L'\t':
+ *os << "\\t";
+ break;
+ case L'\v':
+ *os << "\\v";
+ break;
+ default:
+ if (IsPrintableAscii(c)) {
+ *os << static_cast<char>(c);
+ return kAsIs;
+ } else {
+ *os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
+ return kHexEscape;
+ }
+ }
+ return kSpecialEscape;
+}
+
+// Prints a wchar_t c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
+ switch (c) {
+ case L'\'':
+ *os << "'";
+ return kAsIs;
+ case L'"':
+ *os << "\\\"";
+ return kSpecialEscape;
+ default:
+ return PrintAsCharLiteralTo<wchar_t>(c, os);
+ }
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
+ return PrintAsStringLiteralTo(
+ static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
+}
+
+// Prints a wide or narrow character c and its code. '\0' is printed
+// as "'\\0'", other unprintable characters are also properly escaped
+// using the standard C++ escape sequence. The template argument
+// UnsignedChar is the unsigned version of Char, which is the type of c.
+template <typename UnsignedChar, typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+ // First, print c as a literal in the most readable form we can find.
+ *os << ((sizeof(c) > 1) ? "L'" : "'");
+ const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+ *os << "'";
+
+ // To aid user debugging, we also print c's code in decimal, unless
+ // it's 0 (in which case c was printed as '\\0', making the code
+ // obvious).
+ if (c == 0)
+ return;
+ *os << " (" << static_cast<int>(c);
+
+ // For more convenience, we print c's code again in hexidecimal,
+ // unless c was already printed in the form '\x##' or the code is in
+ // [1, 9].
+ if (format == kHexEscape || (1 <= c && c <= 9)) {
+ // Do nothing.
+ } else {
+ *os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
+ }
+ *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) {
+ PrintCharAndCodeTo<unsigned char>(c, os);
+}
+void PrintTo(signed char c, ::std::ostream* os) {
+ PrintCharAndCodeTo<unsigned char>(c, os);
+}
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) {
+ PrintCharAndCodeTo<wchar_t>(wc, os);
+}
+
+// Prints the given array of characters to the ostream. CharType must be either
+// char or wchar_t.
+// The array starts at begin, the length is len, it may include '\0' characters
+// and may not be NUL-terminated.
+template <typename CharType>
+static void PrintCharsAsStringTo(
+ const CharType* begin, size_t len, ostream* os) {
+ const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
+ *os << kQuoteBegin;
+ bool is_previous_hex = false;
+ for (size_t index = 0; index < len; ++index) {
+ const CharType cur = begin[index];
+ if (is_previous_hex && IsXDigit(cur)) {
+ // Previous character is of '\x..' form and this character can be
+ // interpreted as another hexadecimal digit in its number. Break string to
+ // disambiguate.
+ *os << "\" " << kQuoteBegin;
+ }
+ is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
+ }
+ *os << "\"";
+}
+
+// Prints a (const) char/wchar_t array of 'len' elements, starting at address
+// 'begin'. CharType must be either char or wchar_t.
+template <typename CharType>
+static void UniversalPrintCharArray(
+ const CharType* begin, size_t len, ostream* os) {
+ // The code
+ // const char kFoo[] = "foo";
+ // generates an array of 4, not 3, elements, with the last one being '\0'.
+ //
+ // Therefore when printing a char array, we don't print the last element if
+ // it's '\0', such that the output matches the string literal as it's
+ // written in the source code.
+ if (len > 0 && begin[len - 1] == '\0') {
+ PrintCharsAsStringTo(begin, len - 1, os);
+ return;
+ }
+
+ // If, however, the last element in the array is not '\0', e.g.
+ // const char kFoo[] = { 'f', 'o', 'o' };
+ // we must print the entire array. We also print a message to indicate
+ // that the array is not NUL-terminated.
+ PrintCharsAsStringTo(begin, len, os);
+ *os << " (no terminating NUL)";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+ UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints a (const) wchar_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
+ UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints the given C string to the ostream.
+void PrintTo(const char* s, ostream* os) {
+ if (s == NULL) {
+ *os << "NULL";
+ } else {
+ *os << ImplicitCast_<const void*>(s) << " pointing to ";
+ PrintCharsAsStringTo(s, strlen(s), os);
+ }
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) {
+ if (s == NULL) {
+ *os << "NULL";
+ } else {
+ *os << ImplicitCast_<const void*>(s) << " pointing to ";
+ PrintCharsAsStringTo(s, wcslen(s), os);
+ }
+}
+#endif // wchar_t is native
+
+// Prints a ::string object.
+#if GTEST_HAS_GLOBAL_STRING
+void PrintStringTo(const ::string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif // GTEST_HAS_GLOBAL_STRING
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+// Prints a ::wstring object.
+#if GTEST_HAS_GLOBAL_WSTRING
+void PrintWideStringTo(const ::wstring& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+} // namespace internal
+
+} // namespace testing
diff --git a/thirdparty/gtest/src/gtest-test-part.cc b/thirdparty/gtest/src/gtest-test-part.cc
new file mode 100644
index 00000000..c60eef3a
--- /dev/null
+++ b/thirdparty/gtest/src/gtest-test-part.cc
@@ -0,0 +1,110 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest-test-part.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation. It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+using internal::GetUnitTestImpl;
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+std::string TestPartResult::ExtractSummary(const char* message) {
+ const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+ return stack_trace == NULL ? message :
+ std::string(message, stack_trace);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+ return os
+ << result.file_name() << ":" << result.line_number() << ": "
+ << (result.type() == TestPartResult::kSuccess ? "Success" :
+ result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
+ "Non-fatal failure") << ":\n"
+ << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+ array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+ if (index < 0 || index >= size()) {
+ printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+ internal::posix::Abort();
+ }
+
+ return array_[index];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+ return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+ : has_new_fatal_failure_(false),
+ original_reporter_(GetUnitTestImpl()->
+ GetTestPartResultReporterForCurrentThread()) {
+ GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+ GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+ original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+ const TestPartResult& result) {
+ if (result.fatally_failed())
+ has_new_fatal_failure_ = true;
+ original_reporter_->ReportTestPartResult(result);
+}
+
+} // namespace internal
+
+} // namespace testing
diff --git a/thirdparty/gtest/src/gtest-typed-test.cc b/thirdparty/gtest/src/gtest-typed-test.cc
new file mode 100644
index 00000000..f0079f40
--- /dev/null
+++ b/thirdparty/gtest/src/gtest-typed-test.cc
@@ -0,0 +1,110 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest-typed-test.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+ while (IsSpace(*str))
+ str++;
+ return str;
+}
+
+// Verifies that registered_tests match the test names in
+// defined_test_names_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestCasePState::VerifyRegisteredTestNames(
+ const char* file, int line, const char* registered_tests) {
+ typedef ::std::set<const char*>::const_iterator DefinedTestIter;
+ registered_ = true;
+
+ // Skip initial whitespace in registered_tests since some
+ // preprocessors prefix stringizied literals with whitespace.
+ registered_tests = SkipSpaces(registered_tests);
+
+ Message errors;
+ ::std::set<std::string> tests;
+ for (const char* names = registered_tests; names != NULL;
+ names = SkipComma(names)) {
+ const std::string name = GetPrefixUntilComma(names);
+ if (tests.count(name) != 0) {
+ errors << "Test " << name << " is listed more than once.\n";
+ continue;
+ }
+
+ bool found = false;
+ for (DefinedTestIter it = defined_test_names_.begin();
+ it != defined_test_names_.end();
+ ++it) {
+ if (name == *it) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ tests.insert(name);
+ } else {
+ errors << "No test named " << name
+ << " can be found in this test case.\n";
+ }
+ }
+
+ for (DefinedTestIter it = defined_test_names_.begin();
+ it != defined_test_names_.end();
+ ++it) {
+ if (tests.count(*it) == 0) {
+ errors << "You forgot to list test " << *it << ".\n";
+ }
+ }
+
+ const std::string& errors_str = errors.GetString();
+ if (errors_str != "") {
+ fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+ errors_str.c_str());
+ fflush(stderr);
+ posix::Abort();
+ }
+
+ return registered_tests;
+}
+
+#endif // GTEST_HAS_TYPED_TEST_P
+
+} // namespace internal
+} // namespace testing
diff --git a/thirdparty/gtest/src/gtest.cc b/thirdparty/gtest/src/gtest.cc
new file mode 100644
index 00000000..6de53dd0
--- /dev/null
+++ b/thirdparty/gtest/src/gtest.cc
@@ -0,0 +1,5015 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+#include <ctype.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <limits>
+#include <ostream> // NOLINT
+#include <sstream>
+#include <vector>
+
+#if GTEST_OS_LINUX
+
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+# include <fcntl.h> // NOLINT
+# include <limits.h> // NOLINT
+# include <sched.h> // NOLINT
+// Declares vsnprintf(). This header is not available on Windows.
+# include <strings.h> // NOLINT
+# include <sys/mman.h> // NOLINT
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
+# include <string>
+
+#elif GTEST_OS_SYMBIAN
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
+
+#elif GTEST_OS_ZOS
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+# include <strings.h> // NOLINT
+
+#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
+
+# include <windows.h> // NOLINT
+
+#elif GTEST_OS_WINDOWS // We are on Windows proper.
+
+# include <io.h> // NOLINT
+# include <sys/timeb.h> // NOLINT
+# include <sys/types.h> // NOLINT
+# include <sys/stat.h> // NOLINT
+
+# if GTEST_OS_WINDOWS_MINGW
+// MinGW has gettimeofday() but not _ftime64().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+// TODO(kenton@google.com): There are other ways to get the time on
+// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW
+// supports these. consider using them instead.
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
+# endif // GTEST_OS_WINDOWS_MINGW
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <windows.h> // NOLINT
+
+#else
+
+// Assume other platforms have gettimeofday().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
+
+#endif // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h> // NOLINT
+# include <netdb.h> // NOLINT
+#endif
+
+// Indicates that this translation unit is part of Google Test's
+// implementation. It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS
+# define vsnprintf _vsnprintf
+#endif // GTEST_OS_WINDOWS
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test case name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test case whose name matches this filter is considered a death
+// test case and will be run before test cases whose name doesn't
+// match this filter.
+static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output file for XML output.
+static const char kDefaultOutputFile[] = "test_detail.xml";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+bool g_help_flag = false;
+
+} // namespace internal
+
+static const char* GetDefaultFilter() {
+ return kUniversalFilter;
+}
+
+GTEST_DEFINE_bool_(
+ also_run_disabled_tests,
+ internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+ "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+ break_on_failure,
+ internal::BoolFromGTestEnv("break_on_failure", false),
+ "True iff a failed assertion should be a debugger break-point.");
+
+GTEST_DEFINE_bool_(
+ catch_exceptions,
+ internal::BoolFromGTestEnv("catch_exceptions", true),
+ "True iff " GTEST_NAME_
+ " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+ color,
+ internal::StringFromGTestEnv("color", "auto"),
+ "Whether to use colors in the output. Valid values: yes, no, "
+ "and auto. 'auto' means to use colors if the output is "
+ "being sent to a terminal and the TERM environment variable "
+ "is set to a terminal type that supports colors.");
+
+GTEST_DEFINE_string_(
+ filter,
+ internal::StringFromGTestEnv("filter", GetDefaultFilter()),
+ "A colon-separated list of glob (not regex) patterns "
+ "for filtering the tests to run, optionally followed by a "
+ "'-' and a : separated list of negative patterns (tests to "
+ "exclude). A test is run if it matches one of the positive "
+ "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(list_tests, false,
+ "List all tests without running them.");
+
+GTEST_DEFINE_string_(
+ output,
+ internal::StringFromGTestEnv("output", ""),
+ "A format (currently must be \"xml\"), optionally followed "
+ "by a colon and an output file name or directory. A directory "
+ "is indicated by a trailing pathname separator. "
+ "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+ "If a directory is specified, output files will be created "
+ "within that directory, with file-names based on the test "
+ "executable's name and, if necessary, made unique by adding "
+ "digits.");
+
+GTEST_DEFINE_bool_(
+ print_time,
+ internal::BoolFromGTestEnv("print_time", true),
+ "True iff " GTEST_NAME_
+ " should display elapsed time in text output.");
+
+GTEST_DEFINE_int32_(
+ random_seed,
+ internal::Int32FromGTestEnv("random_seed", 0),
+ "Random number seed to use when shuffling test orders. Must be in range "
+ "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+ repeat,
+ internal::Int32FromGTestEnv("repeat", 1),
+ "How many times to repeat each test. Specify a negative number "
+ "for repeating forever. Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(
+ show_internal_stack_frames, false,
+ "True iff " GTEST_NAME_ " should include internal stack frames when "
+ "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(
+ shuffle,
+ internal::BoolFromGTestEnv("shuffle", false),
+ "True iff " GTEST_NAME_
+ " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+ stack_trace_depth,
+ internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
+ "The maximum number of stack frames to print when an "
+ "assertion fails. The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_string_(
+ stream_result_to,
+ internal::StringFromGTestEnv("stream_result_to", ""),
+ "This flag specifies the host name and the port number on which to stream "
+ "test results. Example: \"localhost:555\". The flag is effective only on "
+ "Linux.");
+
+GTEST_DEFINE_bool_(
+ throw_on_failure,
+ internal::BoolFromGTestEnv("throw_on_failure", false),
+ "When this flag is specified, a failed assertion will throw an exception "
+ "if exceptions are enabled or exit the program with a non-zero code "
+ "otherwise.");
+
+namespace internal {
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG). Crashes if 'range' is 0 or greater
+// than kMaxRange.
+UInt32 Random::Generate(UInt32 range) {
+ // These constants are the same as are used in glibc's rand(3).
+ state_ = (1103515245U*state_ + 12345U) % kMaxRange;
+
+ GTEST_CHECK_(range > 0)
+ << "Cannot generate a number in the range [0, 0).";
+ GTEST_CHECK_(range <= kMaxRange)
+ << "Generation of a number in [0, " << range << ") was requested, "
+ << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+ // Converting via modulus introduces a bit of downward bias, but
+ // it's simple, and a linear congruential generator isn't too good
+ // to begin with.
+ return state_ % range;
+}
+
+// GTestIsInitialized() returns true iff the user has initialized
+// Google Test. Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+//
+// A user must call testing::InitGoogleTest() to initialize Google
+// Test. g_init_gtest_count is set to the number of times
+// InitGoogleTest() has been called. We don't protect this variable
+// under a mutex as it is only accessed in the main thread.
+GTEST_API_ int g_init_gtest_count = 0;
+static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
+
+// Iterates over a vector of TestCases, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestCaseList(const std::vector<TestCase*>& case_list,
+ int (TestCase::*method)() const) {
+ int sum = 0;
+ for (size_t i = 0; i < case_list.size(); i++) {
+ sum += (case_list[i]->*method)();
+ }
+ return sum;
+}
+
+// Returns true iff the test case passed.
+static bool TestCasePassed(const TestCase* test_case) {
+ return test_case->should_run() && test_case->Passed();
+}
+
+// Returns true iff the test case failed.
+static bool TestCaseFailed(const TestCase* test_case) {
+ return test_case->should_run() && test_case->Failed();
+}
+
+// Returns true iff test_case contains at least one test that should
+// run.
+static bool ShouldRunTestCase(const TestCase* test_case) {
+ return test_case->should_run();
+}
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type,
+ const char* file,
+ int line,
+ const char* message)
+ : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+ delete data_;
+}
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+ UnitTest::GetInstance()->
+ AddTestPartResult(data_->type, data_->file, data_->line,
+ AppendUserMessage(data_->message, message),
+ UnitTest::GetInstance()->impl()
+ ->CurrentOsStackTraceExceptTop(1)
+ // Skips the stack frame for this function itself.
+ ); // NOLINT
+}
+
+// Mutex for linked pointers.
+GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// Application pathname gotten in InitGoogleTest.
+std::string g_executable_path;
+
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+ FilePath result;
+
+#if GTEST_OS_WINDOWS
+ result.Set(FilePath(g_executable_path).RemoveExtension("exe"));
+#else
+ result.Set(FilePath(g_executable_path));
+#endif // GTEST_OS_WINDOWS
+
+ return result.RemoveDirectoryName();
+}
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+std::string UnitTestOptions::GetOutputFormat() {
+ const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+ if (gtest_output_flag == NULL) return std::string("");
+
+ const char* const colon = strchr(gtest_output_flag, ':');
+ return (colon == NULL) ?
+ std::string(gtest_output_flag) :
+ std::string(gtest_output_flag, colon - gtest_output_flag);
+}
+
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
+ const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+ if (gtest_output_flag == NULL)
+ return "";
+
+ const char* const colon = strchr(gtest_output_flag, ':');
+ if (colon == NULL)
+ return internal::FilePath::ConcatPaths(
+ internal::FilePath(
+ UnitTest::GetInstance()->original_working_dir()),
+ internal::FilePath(kDefaultOutputFile)).string();
+
+ internal::FilePath output_name(colon + 1);
+ if (!output_name.IsAbsolutePath())
+ // TODO(wan@google.com): on Windows \some\path is not an absolute
+ // path (as its meaning depends on the current drive), yet the
+ // following logic for turning it into an absolute path is wrong.
+ // Fix it.
+ output_name = internal::FilePath::ConcatPaths(
+ internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+ internal::FilePath(colon + 1));
+
+ if (!output_name.IsDirectory())
+ return output_name.string();
+
+ internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+ output_name, internal::GetCurrentExecutableName(),
+ GetOutputFormat().c_str()));
+ return result.string();
+}
+
+// Returns true iff the wildcard pattern matches the string. The
+// first ':' or '\0' character in pattern marks the end of it.
+//
+// This recursive algorithm isn't very efficient, but is clear and
+// works well enough for matching test names, which are short.
+bool UnitTestOptions::PatternMatchesString(const char *pattern,
+ const char *str) {
+ switch (*pattern) {
+ case '\0':
+ case ':': // Either ':' or '\0' marks the end of the pattern.
+ return *str == '\0';
+ case '?': // Matches any single character.
+ return *str != '\0' && PatternMatchesString(pattern + 1, str + 1);
+ case '*': // Matches any string (possibly empty) of characters.
+ return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
+ PatternMatchesString(pattern + 1, str);
+ default: // Non-special character. Matches itself.
+ return *pattern == *str &&
+ PatternMatchesString(pattern + 1, str + 1);
+ }
+}
+
+bool UnitTestOptions::MatchesFilter(
+ const std::string& name, const char* filter) {
+ const char *cur_pattern = filter;
+ for (;;) {
+ if (PatternMatchesString(cur_pattern, name.c_str())) {
+ return true;
+ }
+
+ // Finds the next pattern in the filter.
+ cur_pattern = strchr(cur_pattern, ':');
+
+ // Returns if no more pattern can be found.
+ if (cur_pattern == NULL) {
+ return false;
+ }
+
+ // Skips the pattern separater (the ':' character).
+ cur_pattern++;
+ }
+}
+
+// Returns true iff the user-specified filter matches the test case
+// name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name,
+ const std::string &test_name) {
+ const std::string& full_name = test_case_name + "." + test_name.c_str();
+
+ // Split --gtest_filter at '-', if there is one, to separate into
+ // positive filter and negative filter portions
+ const char* const p = GTEST_FLAG(filter).c_str();
+ const char* const dash = strchr(p, '-');
+ std::string positive;
+ std::string negative;
+ if (dash == NULL) {
+ positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter
+ negative = "";
+ } else {
+ positive = std::string(p, dash); // Everything up to the dash
+ negative = std::string(dash + 1); // Everything after the dash
+ if (positive.empty()) {
+ // Treat '-test1' as the same as '*-test1'
+ positive = kUniversalFilter;
+ }
+ }
+
+ // A filter is a colon-separated list of patterns. It matches a
+ // test if any pattern in it matches the test.
+ return (MatchesFilter(full_name, positive.c_str()) &&
+ !MatchesFilter(full_name, negative.c_str()));
+}
+
+#if GTEST_HAS_SEH
+// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+// This function is useful as an __except condition.
+int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+ // Google Test should handle a SEH exception if:
+ // 1. the user wants it to, AND
+ // 2. this is not a breakpoint exception, AND
+ // 3. this is not a C++ exception (VC++ implements them via SEH,
+ // apparently).
+ //
+ // SEH exception code for C++ exceptions.
+ // (see http://support.microsoft.com/kb/185294 for more information).
+ const DWORD kCxxExceptionCode = 0xe06d7363;
+
+ bool should_handle = true;
+
+ if (!GTEST_FLAG(catch_exceptions))
+ should_handle = false;
+ else if (exception_code == EXCEPTION_BREAKPOINT)
+ should_handle = false;
+ else if (exception_code == kCxxExceptionCode)
+ should_handle = false;
+
+ return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+#endif // GTEST_HAS_SEH
+
+} // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test. The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+ TestPartResultArray* result)
+ : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
+ result_(result) {
+ Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test. The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+ InterceptMode intercept_mode, TestPartResultArray* result)
+ : intercept_mode_(intercept_mode),
+ result_(result) {
+ Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+ old_reporter_ = impl->GetGlobalTestPartResultReporter();
+ impl->SetGlobalTestPartResultReporter(this);
+ } else {
+ old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+ impl->SetTestPartResultReporterForCurrentThread(this);
+ }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+ impl->SetGlobalTestPartResultReporter(old_reporter_);
+ } else {
+ impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+ }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+ const TestPartResult& result) {
+ result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test. We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test. This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X. The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code. GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() {
+ return GetTypeId<Test>();
+}
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library. This is solely for testing GetTestTypeId().
+extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+AssertionResult HasOneFailure(const char* /* results_expr */,
+ const char* /* type_expr */,
+ const char* /* substr_expr */,
+ const TestPartResultArray& results,
+ TestPartResult::Type type,
+ const string& substr) {
+ const std::string expected(type == TestPartResult::kFatalFailure ?
+ "1 fatal failure" :
+ "1 non-fatal failure");
+ Message msg;
+ if (results.size() != 1) {
+ msg << "Expected: " << expected << "\n"
+ << " Actual: " << results.size() << " failures";
+ for (int i = 0; i < results.size(); i++) {
+ msg << "\n" << results.GetTestPartResult(i);
+ }
+ return AssertionFailure() << msg;
+ }
+
+ const TestPartResult& r = results.GetTestPartResult(0);
+ if (r.type() != type) {
+ return AssertionFailure() << "Expected: " << expected << "\n"
+ << " Actual:\n"
+ << r;
+ }
+
+ if (strstr(r.message(), substr.c_str()) == NULL) {
+ return AssertionFailure() << "Expected: " << expected << " containing \""
+ << substr << "\"\n"
+ << " Actual:\n"
+ << r;
+ }
+
+ return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker:: SingleFailureChecker(
+ const TestPartResultArray* results,
+ TestPartResult::Type type,
+ const string& substr)
+ : results_(results),
+ type_(type),
+ substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring. If that's not the case, a
+// non-fatal failure will be generated.
+SingleFailureChecker::~SingleFailureChecker() {
+ EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+ UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+ const TestPartResult& result) {
+ unit_test_->current_test_result()->AddTestPartResult(result);
+ unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+ UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+ const TestPartResult& result) {
+ unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+ internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+ return global_test_part_result_repoter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+ TestPartResultReporterInterface* reporter) {
+ internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+ global_test_part_result_repoter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+ return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+ TestPartResultReporterInterface* reporter) {
+ per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test cases.
+int UnitTestImpl::successful_test_case_count() const {
+ return CountIf(test_cases_, TestCasePassed);
+}
+
+// Gets the number of failed test cases.
+int UnitTestImpl::failed_test_case_count() const {
+ return CountIf(test_cases_, TestCaseFailed);
+}
+
+// Gets the number of all test cases.
+int UnitTestImpl::total_test_case_count() const {
+ return static_cast<int>(test_cases_.size());
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTestImpl::test_case_to_run_count() const {
+ return CountIf(test_cases_, ShouldRunTestCase);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTestImpl::reportable_disabled_test_count() const {
+ return SumOverTestCaseList(test_cases_,
+ &TestCase::reportable_disabled_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTestImpl::reportable_test_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+ return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count);
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag. The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+ (void)skip_count;
+ return "";
+}
+
+// Returns the current time in milliseconds.
+TimeInMillis GetTimeInMillis() {
+#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
+ // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
+ // http://analogous.blogspot.com/2005/04/epoch.html
+ const TimeInMillis kJavaEpochToWinFileTimeDelta =
+ static_cast<TimeInMillis>(116444736UL) * 100000UL;
+ const DWORD kTenthMicrosInMilliSecond = 10000;
+
+ SYSTEMTIME now_systime;
+ FILETIME now_filetime;
+ ULARGE_INTEGER now_int64;
+ // TODO(kenton@google.com): Shouldn't this just use
+ // GetSystemTimeAsFileTime()?
+ GetSystemTime(&now_systime);
+ if (SystemTimeToFileTime(&now_systime, &now_filetime)) {
+ now_int64.LowPart = now_filetime.dwLowDateTime;
+ now_int64.HighPart = now_filetime.dwHighDateTime;
+ now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) -
+ kJavaEpochToWinFileTimeDelta;
+ return now_int64.QuadPart;
+ }
+ return 0;
+#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
+ __timeb64 now;
+
+# ifdef _MSC_VER
+
+ // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
+ // (deprecated function) there.
+ // TODO(kenton@google.com): Use GetTickCount()? Or use
+ // SystemTimeToFileTime()
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996.
+ _ftime64(&now);
+# pragma warning(pop) // Restores the warning state.
+# else
+
+ _ftime64(&now);
+
+# endif // _MSC_VER
+
+ return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
+#elif GTEST_HAS_GETTIMEOFDAY_
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
+#else
+# error "Don't know how to get the current time on your system."
+#endif
+}
+
+// Utilities
+
+// class String.
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+ if (!ansi) return NULL;
+ const int length = strlen(ansi);
+ const int unicode_length =
+ MultiByteToWideChar(CP_ACP, 0, ansi, length,
+ NULL, 0);
+ WCHAR* unicode = new WCHAR[unicode_length + 1];
+ MultiByteToWideChar(CP_ACP, 0, ansi, length,
+ unicode, unicode_length);
+ unicode[unicode_length] = 0;
+ return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str) {
+ if (!utf16_str) return NULL;
+ const int ansi_length =
+ WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+ NULL, 0, NULL, NULL);
+ char* ansi = new char[ansi_length + 1];
+ WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+ ansi, ansi_length, NULL, NULL);
+ ansi[ansi_length] = 0;
+ return ansi;
+}
+
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings. Returns true iff they have the same content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s). A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char * lhs, const char * rhs) {
+ if ( lhs == NULL ) return rhs == NULL;
+
+ if ( rhs == NULL ) return false;
+
+ return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+ Message* msg) {
+ for (size_t i = 0; i != length; ) { // NOLINT
+ if (wstr[i] != L'\0') {
+ *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+ while (i != length && wstr[i] != L'\0')
+ i++;
+ } else {
+ *msg << '\0';
+ i++;
+ }
+ }
+}
+
+#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+} // namespace internal
+
+// Constructs an empty Message.
+// We allocate the stringstream separately because otherwise each use of
+// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+// stack frame leading to huge stack frames in some cases; gcc does not reuse
+// the stack space.
+Message::Message() : ss_(new ::std::stringstream) {
+ // By default, we want there to be enough precision when printing
+ // a double to a Message.
+ *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+}
+
+// These two overloads allow streaming a wide C string to a Message
+// using the UTF-8 encoding.
+Message& Message::operator <<(const wchar_t* wide_c_str) {
+ return *this << internal::String::ShowWideCString(wide_c_str);
+}
+Message& Message::operator <<(wchar_t* wide_c_str) {
+ return *this << internal::String::ShowWideCString(wide_c_str);
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::std::wstring& wstr) {
+ internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+ return *this;
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::wstring& wstr) {
+ internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+ return *this;
+}
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+// Gets the text streamed to this object so far as an std::string.
+// Each '\0' character in the buffer is replaced with "\\0".
+std::string Message::GetString() const {
+ return internal::StringStreamToString(ss_.get());
+}
+
+// AssertionResult constructors.
+// Used in EXPECT_TRUE/FALSE(assertion_result).
+AssertionResult::AssertionResult(const AssertionResult& other)
+ : success_(other.success_),
+ message_(other.message_.get() != NULL ?
+ new ::std::string(*other.message_) :
+ static_cast< ::std::string*>(NULL)) {
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+ AssertionResult negation(!success_);
+ if (message_.get() != NULL)
+ negation << *message_;
+ return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() {
+ return AssertionResult(true);
+}
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() {
+ return AssertionResult(false);
+}
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+ return AssertionFailure() << message;
+}
+
+namespace internal {
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings. For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+// expected_expression: "foo"
+// actual_expression: "bar"
+// expected_value: "5"
+// actual_value: "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* expected_expression,
+ const char* actual_expression,
+ const std::string& expected_value,
+ const std::string& actual_value,
+ bool ignoring_case) {
+ Message msg;
+ msg << "Value of: " << actual_expression;
+ if (actual_value != actual_expression) {
+ msg << "\n Actual: " << actual_value;
+ }
+
+ msg << "\nExpected: " << expected_expression;
+ if (ignoring_case) {
+ msg << " (ignoring case)";
+ }
+ if (expected_value != expected_expression) {
+ msg << "\nWhich is: " << expected_value;
+ }
+
+ return AssertionFailure() << msg;
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+std::string GetBoolAssertionFailureMessage(
+ const AssertionResult& assertion_result,
+ const char* expression_text,
+ const char* actual_predicate_value,
+ const char* expected_predicate_value) {
+ const char* actual_message = assertion_result.message();
+ Message msg;
+ msg << "Value of: " << expression_text
+ << "\n Actual: " << actual_predicate_value;
+ if (actual_message[0] != '\0')
+ msg << " (" << actual_message << ")";
+ msg << "\nExpected: " << expected_predicate_value;
+ return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1,
+ const char* expr2,
+ const char* abs_error_expr,
+ double val1,
+ double val2,
+ double abs_error) {
+ const double diff = fabs(val1 - val2);
+ if (diff <= abs_error) return AssertionSuccess();
+
+ // TODO(wan): do not print the value of an expression if it's
+ // already a literal.
+ return AssertionFailure()
+ << "The difference between " << expr1 << " and " << expr2
+ << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
+ << expr1 << " evaluates to " << val1 << ",\n"
+ << expr2 << " evaluates to " << val2 << ", and\n"
+ << abs_error_expr << " evaluates to " << abs_error << ".";
+}
+
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1,
+ const char* expr2,
+ RawType val1,
+ RawType val2) {
+ // Returns success if val1 is less than val2,
+ if (val1 < val2) {
+ return AssertionSuccess();
+ }
+
+ // or if val1 is almost equal to val2.
+ const FloatingPoint<RawType> lhs(val1), rhs(val2);
+ if (lhs.AlmostEquals(rhs)) {
+ return AssertionSuccess();
+ }
+
+ // Note that the above two checks will both fail if either val1 or
+ // val2 is NaN, as the IEEE floating-point standard requires that
+ // any predicate involving a NaN must return false.
+
+ ::std::stringstream val1_ss;
+ val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+ << val1;
+
+ ::std::stringstream val2_ss;
+ val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+ << val2;
+
+ return AssertionFailure()
+ << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+ << " Actual: " << StringStreamToString(&val1_ss) << " vs "
+ << StringStreamToString(&val2_ss);
+}
+
+} // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2. Fails
+// otherwise. In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2,
+ float val1, float val2) {
+ return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2. Fails
+// otherwise. In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2,
+ double val1, double val2) {
+ return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_EQ with int or enum
+// arguments.
+AssertionResult CmpHelperEQ(const char* expected_expression,
+ const char* actual_expression,
+ BiggestInt expected,
+ BiggestInt actual) {
+ if (expected == actual) {
+ return AssertionSuccess();
+ }
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ FormatForComparisonFailureMessage(expected, actual),
+ FormatForComparisonFailureMessage(actual, expected),
+ false);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here
+// just to avoid copy-and-paste of similar code.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+ BiggestInt val1, BiggestInt val2) {\
+ if (val1 op val2) {\
+ return AssertionSuccess();\
+ } else {\
+ return AssertionFailure() \
+ << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+ << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+ }\
+}
+
+// Implements the helper function for {ASSERT|EXPECT}_NE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LT, < )
+// Implements the helper function for {ASSERT|EXPECT}_GE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GT, > )
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+ const char* actual_expression,
+ const char* expected,
+ const char* actual) {
+ if (String::CStringEquals(expected, actual)) {
+ return AssertionSuccess();
+ }
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ PrintToString(expected),
+ PrintToString(actual),
+ false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+ const char* actual_expression,
+ const char* expected,
+ const char* actual) {
+ if (String::CaseInsensitiveCStringEquals(expected, actual)) {
+ return AssertionSuccess();
+ }
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ PrintToString(expected),
+ PrintToString(actual),
+ true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+ const char* s2_expression,
+ const char* s1,
+ const char* s2) {
+ if (!String::CStringEquals(s1, s2)) {
+ return AssertionSuccess();
+ } else {
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: \""
+ << s1 << "\" vs \"" << s2 << "\"";
+ }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+ const char* s2_expression,
+ const char* s1,
+ const char* s2) {
+ if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+ return AssertionSuccess();
+ } else {
+ return AssertionFailure()
+ << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << ") (ignoring case), actual: \""
+ << s1 << "\" vs \"" << s2 << "\"";
+ }
+}
+
+} // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true iff needle is a
+// substring of haystack. NULL is considered a substring of itself
+// only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+ if (needle == NULL || haystack == NULL)
+ return needle == haystack;
+
+ return strstr(haystack, needle) != NULL;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+ if (needle == NULL || haystack == NULL)
+ return needle == haystack;
+
+ return wcsstr(haystack, needle) != NULL;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle,
+ const StringType& haystack) {
+ return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(
+ bool expected_to_be_substring,
+ const char* needle_expr, const char* haystack_expr,
+ const StringType& needle, const StringType& haystack) {
+ if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+ return AssertionSuccess();
+
+ const bool is_wide_string = sizeof(needle[0]) > 1;
+ const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+ return AssertionFailure()
+ << "Value of: " << needle_expr << "\n"
+ << " Actual: " << begin_string_quote << needle << "\"\n"
+ << "Expected: " << (expected_to_be_substring ? "" : "not ")
+ << "a substring of " << haystack_expr << "\n"
+ << "Which is: " << begin_string_quote << haystack << "\"";
+}
+
+} // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const char* needle, const char* haystack) {
+ return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const wchar_t* needle, const wchar_t* haystack) {
+ return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const char* needle, const char* haystack) {
+ return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const wchar_t* needle, const wchar_t* haystack) {
+ return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::string& needle, const ::std::string& haystack) {
+ return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::string& needle, const ::std::string& haystack) {
+ return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::wstring& needle, const ::std::wstring& haystack) {
+ return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+ const char* needle_expr, const char* haystack_expr,
+ const ::std::wstring& needle, const ::std::wstring& haystack) {
+ return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr,
+ const char* expected,
+ long hr) { // NOLINT
+# if GTEST_OS_WINDOWS_MOBILE
+
+ // Windows CE doesn't support FormatMessage.
+ const char error_text[] = "";
+
+# else
+
+ // Looks up the human-readable system message for the HRESULT code
+ // and since we're not passing any params to FormatMessage, we don't
+ // want inserts expanded.
+ const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS;
+ const DWORD kBufSize = 4096;
+ // Gets the system's human readable message string for this HRESULT.
+ char error_text[kBufSize] = { '\0' };
+ DWORD message_length = ::FormatMessageA(kFlags,
+ 0, // no source, we're asking system
+ hr, // the error
+ 0, // no line width restrictions
+ error_text, // output buffer
+ kBufSize, // buf size
+ NULL); // no arguments for inserts
+ // Trims tailing white space (FormatMessage leaves a trailing CR-LF)
+ for (; message_length && IsSpace(error_text[message_length - 1]);
+ --message_length) {
+ error_text[message_length - 1] = '\0';
+ }
+
+# endif // GTEST_OS_WINDOWS_MOBILE
+
+ const std::string error_hex("0x" + String::FormatHexInt(hr));
+ return ::testing::AssertionFailure()
+ << "Expected: " << expr << " " << expected << ".\n"
+ << " Actual: " << error_hex << " " << error_text << "\n";
+}
+
+} // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT
+ if (SUCCEEDED(hr)) {
+ return AssertionSuccess();
+ }
+ return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT
+ if (FAILED(hr)) {
+ return AssertionSuccess();
+ }
+ return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length Encoding
+// 0 - 7 bits 0xxxxxxx
+// 8 - 11 bits 110xxxxx 10xxxxxx
+// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx
+// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint1 = (static_cast<UInt32>(1) << 7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint2 = (static_cast<UInt32>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint3 = (static_cast<UInt32>(1) << (4 + 2*6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint4 = (static_cast<UInt32>(1) << (3 + 3*6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern. Returns the n
+// lowest bits. As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline UInt32 ChopLowBits(UInt32* bits, int n) {
+ const UInt32 low_bits = *bits & ((static_cast<UInt32>(1) << n) - 1);
+ *bits >>= n;
+ return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+std::string CodePointToUtf8(UInt32 code_point) {
+ if (code_point > kMaxCodePoint4) {
+ return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")";
+ }
+
+ char str[5]; // Big enough for the largest valid code point.
+ if (code_point <= kMaxCodePoint1) {
+ str[1] = '\0';
+ str[0] = static_cast<char>(code_point); // 0xxxxxxx
+ } else if (code_point <= kMaxCodePoint2) {
+ str[2] = '\0';
+ str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[0] = static_cast<char>(0xC0 | code_point); // 110xxxxx
+ } else if (code_point <= kMaxCodePoint3) {
+ str[3] = '\0';
+ str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[0] = static_cast<char>(0xE0 | code_point); // 1110xxxx
+ } else { // code_point <= kMaxCodePoint4
+ str[4] = '\0';
+ str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
+ str[0] = static_cast<char>(0xF0 | code_point); // 11110xxx
+ }
+ return str;
+}
+
+// The following two functions only make sense if the the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+ return sizeof(wchar_t) == 2 &&
+ (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+ wchar_t second) {
+ const UInt32 mask = (1 << 10) - 1;
+ return (sizeof(wchar_t) == 2) ?
+ (((first & mask) << 10) | (second & mask)) + 0x10000 :
+ // This function should not be called when the condition is
+ // false, but we provide a sensible default in case it is.
+ static_cast<UInt32>(first);
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+// UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+std::string WideStringToUtf8(const wchar_t* str, int num_chars) {
+ if (num_chars == -1)
+ num_chars = static_cast<int>(wcslen(str));
+
+ ::std::stringstream stream;
+ for (int i = 0; i < num_chars; ++i) {
+ UInt32 unicode_code_point;
+
+ if (str[i] == L'\0') {
+ break;
+ } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+ unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
+ str[i + 1]);
+ i++;
+ } else {
+ unicode_code_point = static_cast<UInt32>(str[i]);
+ }
+
+ stream << CodePointToUtf8(unicode_code_point);
+ }
+ return StringStreamToString(&stream);
+}
+
+// Converts a wide C string to an std::string using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+std::string String::ShowWideCString(const wchar_t * wide_c_str) {
+ if (wide_c_str == NULL) return "(null)";
+
+ return internal::WideStringToUtf8(wide_c_str, -1);
+}
+
+// Compares two wide C strings. Returns true iff they have the same
+// content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s). A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
+ if (lhs == NULL) return rhs == NULL;
+
+ if (rhs == NULL) return false;
+
+ return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+ const char* actual_expression,
+ const wchar_t* expected,
+ const wchar_t* actual) {
+ if (String::WideCStringEquals(expected, actual)) {
+ return AssertionSuccess();
+ }
+
+ return EqFailure(expected_expression,
+ actual_expression,
+ PrintToString(expected),
+ PrintToString(actual),
+ false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+ const char* s2_expression,
+ const wchar_t* s1,
+ const wchar_t* s2) {
+ if (!String::WideCStringEquals(s1, s2)) {
+ return AssertionSuccess();
+ }
+
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: "
+ << PrintToString(s1)
+ << " vs " << PrintToString(s2);
+}
+
+// Compares two C strings, ignoring case. Returns true iff they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s). A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
+ if (lhs == NULL)
+ return rhs == NULL;
+ if (rhs == NULL)
+ return false;
+ return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+ // Compares two wide C strings, ignoring case. Returns true iff they
+ // have the same content.
+ //
+ // Unlike wcscasecmp(), this function can handle NULL argument(s).
+ // A NULL C string is considered different to any non-NULL wide C string,
+ // including the empty string.
+ // NB: The implementations on different platforms slightly differ.
+ // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+ // environment variable. On GNU platform this method uses wcscasecmp
+ // which compares according to LC_CTYPE category of the current locale.
+ // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+ // current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+ const wchar_t* rhs) {
+ if (lhs == NULL) return rhs == NULL;
+
+ if (rhs == NULL) return false;
+
+#if GTEST_OS_WINDOWS
+ return _wcsicmp(lhs, rhs) == 0;
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
+ return wcscasecmp(lhs, rhs) == 0;
+#else
+ // Android, Mac OS X and Cygwin don't define wcscasecmp.
+ // Other unknown OSes may not define it either.
+ wint_t left, right;
+ do {
+ left = towlower(*lhs++);
+ right = towlower(*rhs++);
+ } while (left && left == right);
+ return left == right;
+#endif // OS selector
+}
+
+// Returns true iff str ends with the given suffix, ignoring case.
+// Any string is considered to end with an empty suffix.
+bool String::EndsWithCaseInsensitive(
+ const std::string& str, const std::string& suffix) {
+ const size_t str_len = str.length();
+ const size_t suffix_len = suffix.length();
+ return (str_len >= suffix_len) &&
+ CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len,
+ suffix.c_str());
+}
+
+// Formats an int value as "%02d".
+std::string String::FormatIntWidth2(int value) {
+ std::stringstream ss;
+ ss << std::setfill('0') << std::setw(2) << value;
+ return ss.str();
+}
+
+// Formats an int value as "%X".
+std::string String::FormatHexInt(int value) {
+ std::stringstream ss;
+ ss << std::hex << std::uppercase << value;
+ return ss.str();
+}
+
+// Formats a byte as "%02X".
+std::string String::FormatByte(unsigned char value) {
+ std::stringstream ss;
+ ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase
+ << static_cast<unsigned int>(value);
+ return ss.str();
+}
+
+// Converts the buffer in a stringstream to an std::string, converting NUL
+// bytes to "\\0" along the way.
+std::string StringStreamToString(::std::stringstream* ss) {
+ const ::std::string& str = ss->str();
+ const char* const start = str.c_str();
+ const char* const end = start + str.length();
+
+ std::string result;
+ result.reserve(2 * (end - start));
+ for (const char* ch = start; ch != end; ++ch) {
+ if (*ch == '\0') {
+ result += "\\0"; // Replaces NUL with "\\0";
+ } else {
+ result += *ch;
+ }
+ }
+
+ return result;
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+std::string AppendUserMessage(const std::string& gtest_msg,
+ const Message& user_msg) {
+ // Appends the user message if it's non-empty.
+ const std::string user_msg_string = user_msg.GetString();
+ if (user_msg_string.empty()) {
+ return gtest_msg;
+ }
+
+ return gtest_msg + "\n" + user_msg_string;
+}
+
+} // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+ : death_test_count_(0),
+ elapsed_time_(0) {
+}
+
+// D'tor.
+TestResult::~TestResult() {
+}
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+ if (i < 0 || i >= total_part_count())
+ internal::posix::Abort();
+ return test_part_results_.at(i);
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+ if (i < 0 || i >= test_property_count())
+ internal::posix::Abort();
+ return test_properties_.at(i);
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+ test_part_results_.clear();
+}
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+ test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const std::string& xml_element,
+ const TestProperty& test_property) {
+ if (!ValidateTestProperty(xml_element, test_property)) {
+ return;
+ }
+ internal::MutexLock lock(&test_properites_mutex_);
+ const std::vector<TestProperty>::iterator property_with_matching_key =
+ std::find_if(test_properties_.begin(), test_properties_.end(),
+ internal::TestPropertyKeyIs(test_property.key()));
+ if (property_with_matching_key == test_properties_.end()) {
+ test_properties_.push_back(test_property);
+ return;
+ }
+ property_with_matching_key->SetValue(test_property.value());
+}
+
+// The list of reserved attributes used in the <testsuites> element of XML
+// output.
+static const char* const kReservedTestSuitesAttributes[] = {
+ "disabled",
+ "errors",
+ "failures",
+ "name",
+ "random_seed",
+ "tests",
+ "time",
+ "timestamp"
+};
+
+// The list of reserved attributes used in the <testsuite> element of XML
+// output.
+static const char* const kReservedTestSuiteAttributes[] = {
+ "disabled",
+ "errors",
+ "failures",
+ "name",
+ "tests",
+ "time"
+};
+
+// The list of reserved attributes used in the <testcase> element of XML output.
+static const char* const kReservedTestCaseAttributes[] = {
+ "classname",
+ "name",
+ "status",
+ "time",
+ "type_param",
+ "value_param"
+};
+
+template <int kSize>
+std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
+ return std::vector<std::string>(array, array + kSize);
+}
+
+static std::vector<std::string> GetReservedAttributesForElement(
+ const std::string& xml_element) {
+ if (xml_element == "testsuites") {
+ return ArrayAsVector(kReservedTestSuitesAttributes);
+ } else if (xml_element == "testsuite") {
+ return ArrayAsVector(kReservedTestSuiteAttributes);
+ } else if (xml_element == "testcase") {
+ return ArrayAsVector(kReservedTestCaseAttributes);
+ } else {
+ GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
+ }
+ // This code is unreachable but some compilers may not realizes that.
+ return std::vector<std::string>();
+}
+
+static std::string FormatWordList(const std::vector<std::string>& words) {
+ Message word_list;
+ for (size_t i = 0; i < words.size(); ++i) {
+ if (i > 0 && words.size() > 2) {
+ word_list << ", ";
+ }
+ if (i == words.size() - 1) {
+ word_list << "and ";
+ }
+ word_list << "'" << words[i] << "'";
+ }
+ return word_list.GetString();
+}
+
+bool ValidateTestPropertyName(const std::string& property_name,
+ const std::vector<std::string>& reserved_names) {
+ if (std::find(reserved_names.begin(), reserved_names.end(), property_name) !=
+ reserved_names.end()) {
+ ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name
+ << " (" << FormatWordList(reserved_names)
+ << " are reserved by " << GTEST_NAME_ << ")";
+ return false;
+ }
+ return true;
+}
+
+// Adds a failure if the key is a reserved attribute of the element named
+// xml_element. Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const std::string& xml_element,
+ const TestProperty& test_property) {
+ return ValidateTestPropertyName(test_property.key(),
+ GetReservedAttributesForElement(xml_element));
+}
+
+// Clears the object.
+void TestResult::Clear() {
+ test_part_results_.clear();
+ test_properties_.clear();
+ death_test_count_ = 0;
+ elapsed_time_ = 0;
+}
+
+// Returns true iff the test failed.
+bool TestResult::Failed() const {
+ for (int i = 0; i < total_part_count(); ++i) {
+ if (GetTestPartResult(i).failed())
+ return true;
+ }
+ return false;
+}
+
+// Returns true iff the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+ return result.fatally_failed();
+}
+
+// Returns true iff the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+ return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+ return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+ return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts. This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+ return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+ return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the values of all Google Test flags.
+Test::Test()
+ : gtest_flag_saver_(new internal::GTestFlagSaver) {
+}
+
+// The d'tor restores the values of all Google Test flags.
+Test::~Test() {
+ delete gtest_flag_saver_;
+}
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {
+}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, const std::string& value) {
+ UnitTest::GetInstance()->RecordProperty(key, value);
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, int value) {
+ Message value_message;
+ value_message << value;
+ RecordProperty(key, value_message.GetString().c_str());
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+ const std::string& message) {
+ // This function is a friend of UnitTest and as such has access to
+ // AddTestPartResult.
+ UnitTest::GetInstance()->AddTestPartResult(
+ result_type,
+ NULL, // No info about the source file where the exception occurred.
+ -1, // We have no info on which line caused the exception.
+ message,
+ ""); // No stack trace, either.
+}
+
+} // namespace internal
+
+// Google Test requires all tests in the same test case to use the same test
+// fixture class. This function checks if the current test has the
+// same fixture class as the first test in the current test case. If
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ const TestCase* const test_case = impl->current_test_case();
+
+ // Info about the first test in the current test case.
+ const TestInfo* const first_test_info = test_case->test_info_list()[0];
+ const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
+ const char* const first_test_name = first_test_info->name();
+
+ // Info about the current test.
+ const TestInfo* const this_test_info = impl->current_test_info();
+ const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
+ const char* const this_test_name = this_test_info->name();
+
+ if (this_fixture_id != first_fixture_id) {
+ // Is the first test defined using TEST?
+ const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+ // Is this test defined using TEST?
+ const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+ if (first_is_TEST || this_is_TEST) {
+ // The user mixed TEST and TEST_F in this test case - we'll tell
+ // him/her how to fix it.
+
+ // Gets the name of the TEST and the name of the TEST_F. Note
+ // that first_is_TEST and this_is_TEST cannot both be true, as
+ // the fixture IDs are different for the two tests.
+ const char* const TEST_name =
+ first_is_TEST ? first_test_name : this_test_name;
+ const char* const TEST_F_name =
+ first_is_TEST ? this_test_name : first_test_name;
+
+ ADD_FAILURE()
+ << "All tests in the same test case must use the same test fixture\n"
+ << "class, so mixing TEST_F and TEST in the same test case is\n"
+ << "illegal. In test case " << this_test_info->test_case_name()
+ << ",\n"
+ << "test " << TEST_F_name << " is defined using TEST_F but\n"
+ << "test " << TEST_name << " is defined using TEST. You probably\n"
+ << "want to change the TEST to TEST_F or move it to another test\n"
+ << "case.";
+ } else {
+ // The user defined two fixture classes with the same name in
+ // two namespaces - we'll tell him/her how to fix it.
+ ADD_FAILURE()
+ << "All tests in the same test case must use the same test fixture\n"
+ << "class. However, in test case "
+ << this_test_info->test_case_name() << ",\n"
+ << "you defined test " << first_test_name
+ << " and test " << this_test_name << "\n"
+ << "using two different test fixture classes. This can happen if\n"
+ << "the two classes are from different namespaces or translation\n"
+ << "units and have the same name. You should probably rename one\n"
+ << "of the classes to put the tests into different test cases.";
+ }
+ return false;
+ }
+
+ return true;
+}
+
+#if GTEST_HAS_SEH
+
+// Adds an "exception thrown" fatal failure to the current test. This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static std::string* FormatSehExceptionMessage(DWORD exception_code,
+ const char* location) {
+ Message message;
+ message << "SEH exception with code 0x" << std::setbase(16) <<
+ exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+ return new std::string(message.GetString());
+}
+
+#endif // GTEST_HAS_SEH
+
+namespace internal {
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static std::string FormatCxxExceptionMessage(const char* description,
+ const char* location) {
+ Message message;
+ if (description != NULL) {
+ message << "C++ exception with description \"" << description << "\"";
+ } else {
+ message << "Unknown C++ exception";
+ }
+ message << " thrown in " << location << ".";
+
+ return message.GetString();
+}
+
+static std::string PrintTestPartResultToString(
+ const TestPartResult& test_part_result);
+
+GoogleTestFailureException::GoogleTestFailureException(
+ const TestPartResult& failure)
+ : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+
+#endif // GTEST_HAS_EXCEPTIONS
+
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception. (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function. Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
+#if GTEST_HAS_SEH
+ __try {
+ return (object->*method)();
+ } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT
+ GetExceptionCode())) {
+ // We create the exception message on the heap because VC++ prohibits
+ // creation of objects with destructors on stack in functions using __try
+ // (see error C2712).
+ std::string* exception_message = FormatSehExceptionMessage(
+ GetExceptionCode(), location);
+ internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+ *exception_message);
+ delete exception_message;
+ return static_cast<Result>(0);
+ }
+#else
+ (void)location;
+ return (object->*method)();
+#endif // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
+ // NOTE: The user code can affect the way in which Google Test handles
+ // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+ // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+ // after the exception is caught and either report or re-throw the
+ // exception based on the flag's value:
+ //
+ // try {
+ // // Perform the test method.
+ // } catch (...) {
+ // if (GTEST_FLAG(catch_exceptions))
+ // // Report the exception as failure.
+ // else
+ // throw; // Re-throws the original exception.
+ // }
+ //
+ // However, the purpose of this flag is to allow the program to drop into
+ // the debugger when the exception is thrown. On most platforms, once the
+ // control enters the catch block, the exception origin information is
+ // lost and the debugger will stop the program at the point of the
+ // re-throw in this function -- instead of at the point of the original
+ // throw statement in the code under test. For this reason, we perform
+ // the check early, sacrificing the ability to affect Google Test's
+ // exception handling in the method where the exception is thrown.
+ if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+ try {
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+ } catch (const internal::GoogleTestFailureException&) { // NOLINT
+ // This exception type can only be thrown by a failed Google
+ // Test assertion with the intention of letting another testing
+ // framework catch it. Therefore we just re-throw it.
+ throw;
+ } catch (const std::exception& e) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(e.what(), location));
+ } catch (...) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(NULL, location));
+ }
+ return static_cast<Result>(0);
+#else
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif // GTEST_HAS_EXCEPTIONS
+ } else {
+ return (object->*method)();
+ }
+}
+
+} // namespace internal
+
+// Runs the test and updates the test result.
+void Test::Run() {
+ if (!HasSameFixtureClass()) return;
+
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
+ // We will run the test only if SetUp() was successful.
+ if (!HasFatalFailure()) {
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TestBody, "the test body");
+ }
+
+ // However, we want to clean up as much as possible. Hence we will
+ // always call TearDown(), even if SetUp() or the test body has
+ // failed.
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TearDown, "TearDown()");
+}
+
+// Returns true iff the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+ return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+ return internal::GetUnitTestImpl()->current_test_result()->
+ HasNonfatalFailure();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object.
+TestInfo::TestInfo(const std::string& a_test_case_name,
+ const std::string& a_name,
+ const char* a_type_param,
+ const char* a_value_param,
+ internal::TypeId fixture_class_id,
+ internal::TestFactoryBase* factory)
+ : test_case_name_(a_test_case_name),
+ name_(a_name),
+ type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+ value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+ fixture_class_id_(fixture_class_id),
+ should_run_(false),
+ is_disabled_(false),
+ matches_filter_(false),
+ factory_(factory),
+ result_() {}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() { delete factory_; }
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+// test_case_name: name of the test case
+// name: name of the test
+// type_param: the name of the test's type parameter, or NULL if
+// this is not a typed or a type-parameterized test.
+// value_param: text representation of the test's value parameter,
+// or NULL if this is not a value-parameterized test.
+// fixture_class_id: ID of the test fixture class
+// set_up_tc: pointer to the function that sets up the test case
+// tear_down_tc: pointer to the function that tears down the test case
+// factory: pointer to the factory that creates a test object.
+// The newly created TestInfo instance will assume
+// ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+ const char* test_case_name,
+ const char* name,
+ const char* type_param,
+ const char* value_param,
+ TypeId fixture_class_id,
+ SetUpTestCaseFunc set_up_tc,
+ TearDownTestCaseFunc tear_down_tc,
+ TestFactoryBase* factory) {
+ TestInfo* const test_info =
+ new TestInfo(test_case_name, name, type_param, value_param,
+ fixture_class_id, factory);
+ GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+ return test_info;
+}
+
+#if GTEST_HAS_PARAM_TEST
+void ReportInvalidTestCaseType(const char* test_case_name,
+ const char* file, int line) {
+ Message errors;
+ errors
+ << "Attempted redefinition of test case " << test_case_name << ".\n"
+ << "All tests in the same test case must use the same test fixture\n"
+ << "class. However, in test case " << test_case_name << ", you tried\n"
+ << "to define a test using a fixture class different from the one\n"
+ << "used earlier. This can happen if the two fixture classes are\n"
+ << "from different namespaces and have the same name. You should\n"
+ << "probably rename one of the classes to put the tests into different\n"
+ << "test cases.";
+
+ fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+ errors.GetString().c_str());
+}
+#endif // GTEST_HAS_PARAM_TEST
+
+} // namespace internal
+
+namespace {
+
+// A predicate that checks the test name of a TestInfo against a known
+// value.
+//
+// This is used for implementation of the TestCase class only. We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestNameIs is copyable.
+class TestNameIs {
+ public:
+ // Constructor.
+ //
+ // TestNameIs has NO default constructor.
+ explicit TestNameIs(const char* name)
+ : name_(name) {}
+
+ // Returns true iff the test name of test_info matches name_.
+ bool operator()(const TestInfo * test_info) const {
+ return test_info && test_info->name() == name_;
+ }
+
+ private:
+ std::string name_;
+};
+
+} // namespace
+
+namespace internal {
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_CASE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+#if GTEST_HAS_PARAM_TEST
+ if (!parameterized_tests_registered_) {
+ parameterized_test_registry_.RegisterTests();
+ parameterized_tests_registered_ = true;
+ }
+#endif
+}
+
+} // namespace internal
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfo::Run() {
+ if (!should_run_) return;
+
+ // Tells UnitTest where to store test result.
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->set_current_test_info(this);
+
+ TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+ // Notifies the unit test event listeners that a test is about to start.
+ repeater->OnTestStart(*this);
+
+ const TimeInMillis start = internal::GetTimeInMillis();
+
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+
+ // Creates the test object.
+ Test* const test = internal::HandleExceptionsInMethodIfSupported(
+ factory_, &internal::TestFactoryBase::CreateTest,
+ "the test fixture's constructor");
+
+ // Runs the test only if the test object was created and its
+ // constructor didn't generate a fatal failure.
+ if ((test != NULL) && !Test::HasFatalFailure()) {
+ // This doesn't throw as all user code that can throw are wrapped into
+ // exception handling code.
+ test->Run();
+ }
+
+ // Deletes the test object.
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ internal::HandleExceptionsInMethodIfSupported(
+ test, &Test::DeleteSelf_, "the test fixture's destructor");
+
+ result_.set_elapsed_time(internal::GetTimeInMillis() - start);
+
+ // Notifies the unit test event listener that a test has just finished.
+ repeater->OnTestEnd(*this);
+
+ // Tells UnitTest to stop associating assertion results to this
+ // test.
+ impl->set_current_test_info(NULL);
+}
+
+// class TestCase
+
+// Gets the number of successful tests in this test case.
+int TestCase::successful_test_count() const {
+ return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of failed tests in this test case.
+int TestCase::failed_test_count() const {
+ return CountIf(test_info_list_, TestFailed);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int TestCase::reportable_disabled_test_count() const {
+ return CountIf(test_info_list_, TestReportableDisabled);
+}
+
+// Gets the number of disabled tests in this test case.
+int TestCase::disabled_test_count() const {
+ return CountIf(test_info_list_, TestDisabled);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int TestCase::reportable_test_count() const {
+ return CountIf(test_info_list_, TestReportable);
+}
+
+// Get the number of tests in this test case that should run.
+int TestCase::test_to_run_count() const {
+ return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestCase::total_test_count() const {
+ return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestCase with the given name.
+//
+// Arguments:
+//
+// name: name of the test case
+// a_type_param: the name of the test case's type parameter, or NULL if
+// this is not a typed or a type-parameterized test case.
+// set_up_tc: pointer to the function that sets up the test case
+// tear_down_tc: pointer to the function that tears down the test case
+TestCase::TestCase(const char* a_name, const char* a_type_param,
+ Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc)
+ : name_(a_name),
+ type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+ set_up_tc_(set_up_tc),
+ tear_down_tc_(tear_down_tc),
+ should_run_(false),
+ elapsed_time_(0) {
+}
+
+// Destructor of TestCase.
+TestCase::~TestCase() {
+ // Deletes every Test in the collection.
+ ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestCase::GetTestInfo(int i) const {
+ const int index = GetElementOr(test_indices_, i, -1);
+ return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestCase::GetMutableTestInfo(int i) {
+ const int index = GetElementOr(test_indices_, i, -1);
+ return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Adds a test to this test case. Will delete the test upon
+// destruction of the TestCase object.
+void TestCase::AddTestInfo(TestInfo * test_info) {
+ test_info_list_.push_back(test_info);
+ test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestCase.
+void TestCase::Run() {
+ if (!should_run_) return;
+
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->set_current_test_case(this);
+
+ TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+ repeater->OnTestCaseStart(*this);
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
+
+ const internal::TimeInMillis start = internal::GetTimeInMillis();
+ for (int i = 0; i < total_test_count(); i++) {
+ GetMutableTestInfo(i)->Run();
+ }
+ elapsed_time_ = internal::GetTimeInMillis() - start;
+
+ impl->os_stack_trace_getter()->UponLeavingGTest();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
+ repeater->OnTestCaseEnd(*this);
+ impl->set_current_test_case(NULL);
+}
+
+// Clears the results of all tests in this test case.
+void TestCase::ClearResult() {
+ ad_hoc_test_result_.Clear();
+ ForEach(test_info_list_, TestInfo::ClearTestResult);
+}
+
+// Shuffles the tests in this test case.
+void TestCase::ShuffleTests(internal::Random* random) {
+ Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestCase::UnshuffleTests() {
+ for (size_t i = 0; i < test_indices_.size(); i++) {
+ test_indices_[i] = static_cast<int>(i);
+ }
+}
+
+// Formats a countable noun. Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static std::string FormatCountableNoun(int count,
+ const char * singular_form,
+ const char * plural_form) {
+ return internal::StreamableToString(count) + " " +
+ (count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static std::string FormatTestCount(int test_count) {
+ return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test cases.
+static std::string FormatTestCaseCount(int test_case_count) {
+ return FormatCountableNoun(test_case_count, "test case", "test cases");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation. Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char * TestPartResultTypeToString(TestPartResult::Type type) {
+ switch (type) {
+ case TestPartResult::kSuccess:
+ return "Success";
+
+ case TestPartResult::kNonFatalFailure:
+ case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+ return "error: ";
+#else
+ return "Failure\n";
+#endif
+ default:
+ return "Unknown result type";
+ }
+}
+
+namespace internal {
+
+// Prints a TestPartResult to an std::string.
+static std::string PrintTestPartResultToString(
+ const TestPartResult& test_part_result) {
+ return (Message()
+ << internal::FormatFileLocation(test_part_result.file_name(),
+ test_part_result.line_number())
+ << " " << TestPartResultTypeToString(test_part_result.type())
+ << test_part_result.message()).GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+ const std::string& result =
+ PrintTestPartResultToString(test_part_result);
+ printf("%s\n", result.c_str());
+ fflush(stdout);
+ // If the test program runs in Visual Studio or a debugger, the
+ // following statements add the test part result message to the Output
+ // window such that the user can double-click on it to jump to the
+ // corresponding source code location; otherwise they do nothing.
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+ // We don't call OutputDebugString*() on Windows Mobile, as printing
+ // to stdout is done by OutputDebugString() there already - we don't
+ // want the same message printed twice.
+ ::OutputDebugStringA(result.c_str());
+ ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+
+enum GTestColor {
+ COLOR_DEFAULT,
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_YELLOW
+};
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns the character attribute for the given color.
+WORD GetColorAttribute(GTestColor color) {
+ switch (color) {
+ case COLOR_RED: return FOREGROUND_RED;
+ case COLOR_GREEN: return FOREGROUND_GREEN;
+ case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
+ default: return 0;
+ }
+}
+
+#else
+
+// Returns the ANSI color code for the given color. COLOR_DEFAULT is
+// an invalid input.
+const char* GetAnsiColorCode(GTestColor color) {
+ switch (color) {
+ case COLOR_RED: return "1";
+ case COLOR_GREEN: return "2";
+ case COLOR_YELLOW: return "3";
+ default: return NULL;
+ };
+}
+
+#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true iff Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+ const char* const gtest_color = GTEST_FLAG(color).c_str();
+
+ if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if GTEST_OS_WINDOWS
+ // On Windows the TERM variable is usually not set, but the
+ // console there does support colors.
+ return stdout_is_tty;
+#else
+ // On non-Windows platforms, we rely on the TERM variable.
+ const char* const term = posix::GetEnv("TERM");
+ const bool term_supports_color =
+ String::CStringEquals(term, "xterm") ||
+ String::CStringEquals(term, "xterm-color") ||
+ String::CStringEquals(term, "xterm-256color") ||
+ String::CStringEquals(term, "screen") ||
+ String::CStringEquals(term, "screen-256color") ||
+ String::CStringEquals(term, "linux") ||
+ String::CStringEquals(term, "cygwin");
+ return stdout_is_tty && term_supports_color;
+#endif // GTEST_OS_WINDOWS
+ }
+
+ return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+ String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+ String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+ String::CStringEquals(gtest_color, "1");
+ // We take "yes", "true", "t", and "1" as meaning "yes". If the
+ // value is neither one of these nor "auto", we treat it as "no" to
+ // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+void ColoredPrintf(GTestColor color, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS
+ const bool use_color = false;
+#else
+ static const bool in_color_mode =
+ ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+ const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
+#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+ // The '!= 0' comparison is necessary to satisfy MSVC 7.1.
+
+ if (!use_color) {
+ vprintf(fmt, args);
+ va_end(args);
+ return;
+ }
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+ const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ // Gets the current text color.
+ CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+ GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+ const WORD old_color_attrs = buffer_info.wAttributes;
+
+ // We need to flush the stream buffers into the console before each
+ // SetConsoleTextAttribute call lest it affect the text that is already
+ // printed but has not yet reached the console.
+ fflush(stdout);
+ SetConsoleTextAttribute(stdout_handle,
+ GetColorAttribute(color) | FOREGROUND_INTENSITY);
+ vprintf(fmt, args);
+
+ fflush(stdout);
+ // Restores the text color.
+ SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+ printf("\033[0;3%sm", GetAnsiColorCode(color));
+ vprintf(fmt, args);
+ printf("\033[m"); // Resets the terminal to default.
+#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+ va_end(args);
+}
+
+// Text printed in Google Test's text output and --gunit_list_tests
+// output to label the type parameter and value parameter for a test.
+static const char kTypeParamLabel[] = "TypeParam";
+static const char kValueParamLabel[] = "GetParam()";
+
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+ const char* const type_param = test_info.type_param();
+ const char* const value_param = test_info.value_param();
+
+ if (type_param != NULL || value_param != NULL) {
+ printf(", where ");
+ if (type_param != NULL) {
+ printf("%s = %s", kTypeParamLabel, type_param);
+ if (value_param != NULL)
+ printf(" and ");
+ }
+ if (value_param != NULL) {
+ printf("%s = %s", kValueParamLabel, value_param);
+ }
+ }
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+ PrettyUnitTestResultPrinter() {}
+ static void PrintTestName(const char * test_case, const char * test) {
+ printf("%s.%s", test_case, test);
+ }
+
+ // The following methods override what's in the TestEventListener class.
+ virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+ virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+ virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestCaseStart(const TestCase& test_case);
+ virtual void OnTestStart(const TestInfo& test_info);
+ virtual void OnTestPartResult(const TestPartResult& result);
+ virtual void OnTestEnd(const TestInfo& test_info);
+ virtual void OnTestCaseEnd(const TestCase& test_case);
+ virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+ virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+ virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+ virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+
+ private:
+ static void PrintFailedTests(const UnitTest& unit_test);
+};
+
+ // Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+ const UnitTest& unit_test, int iteration) {
+ if (GTEST_FLAG(repeat) != 1)
+ printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+ const char* const filter = GTEST_FLAG(filter).c_str();
+
+ // Prints the filter if it's not *. This reminds the user that some
+ // tests may be skipped.
+ if (!String::CStringEquals(filter, kUniversalFilter)) {
+ ColoredPrintf(COLOR_YELLOW,
+ "Note: %s filter = %s\n", GTEST_NAME_, filter);
+ }
+
+ if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+ const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
+ ColoredPrintf(COLOR_YELLOW,
+ "Note: This is test shard %d of %s.\n",
+ static_cast<int>(shard_index) + 1,
+ internal::posix::GetEnv(kTestTotalShards));
+ }
+
+ if (GTEST_FLAG(shuffle)) {
+ ColoredPrintf(COLOR_YELLOW,
+ "Note: Randomizing tests' orders with a seed of %d .\n",
+ unit_test.random_seed());
+ }
+
+ ColoredPrintf(COLOR_GREEN, "[==========] ");
+ printf("Running %s from %s.\n",
+ FormatTestCount(unit_test.test_to_run_count()).c_str(),
+ FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+ const UnitTest& /*unit_test*/) {
+ ColoredPrintf(COLOR_GREEN, "[----------] ");
+ printf("Global test environment set-up.\n");
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+ const std::string counts =
+ FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+ ColoredPrintf(COLOR_GREEN, "[----------] ");
+ printf("%s from %s", counts.c_str(), test_case.name());
+ if (test_case.type_param() == NULL) {
+ printf("\n");
+ } else {
+ printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param());
+ }
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
+ ColoredPrintf(COLOR_GREEN, "[ RUN ] ");
+ PrintTestName(test_info.test_case_name(), test_info.name());
+ printf("\n");
+ fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+ const TestPartResult& result) {
+ // If the test part succeeded, we don't need to do anything.
+ if (result.type() == TestPartResult::kSuccess)
+ return;
+
+ // Print failure message from the assertion (e.g. expected this and got that).
+ PrintTestPartResult(result);
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+ if (test_info.result()->Passed()) {
+ ColoredPrintf(COLOR_GREEN, "[ OK ] ");
+ } else {
+ ColoredPrintf(COLOR_RED, "[ FAILED ] ");
+ }
+ PrintTestName(test_info.test_case_name(), test_info.name());
+ if (test_info.result()->Failed())
+ PrintFullTestCommentIfPresent(test_info);
+
+ if (GTEST_FLAG(print_time)) {
+ printf(" (%s ms)\n", internal::StreamableToString(
+ test_info.result()->elapsed_time()).c_str());
+ } else {
+ printf("\n");
+ }
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+ if (!GTEST_FLAG(print_time)) return;
+
+ const std::string counts =
+ FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+ ColoredPrintf(COLOR_GREEN, "[----------] ");
+ printf("%s from %s (%s ms total)\n\n",
+ counts.c_str(), test_case.name(),
+ internal::StreamableToString(test_case.elapsed_time()).c_str());
+ fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+ const UnitTest& /*unit_test*/) {
+ ColoredPrintf(COLOR_GREEN, "[----------] ");
+ printf("Global test environment tear-down\n");
+ fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+ const int failed_test_count = unit_test.failed_test_count();
+ if (failed_test_count == 0) {
+ return;
+ }
+
+ for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+ const TestCase& test_case = *unit_test.GetTestCase(i);
+ if (!test_case.should_run() || (test_case.failed_test_count() == 0)) {
+ continue;
+ }
+ for (int j = 0; j < test_case.total_test_count(); ++j) {
+ const TestInfo& test_info = *test_case.GetTestInfo(j);
+ if (!test_info.should_run() || test_info.result()->Passed()) {
+ continue;
+ }
+ ColoredPrintf(COLOR_RED, "[ FAILED ] ");
+ printf("%s.%s", test_case.name(), test_info.name());
+ PrintFullTestCommentIfPresent(test_info);
+ printf("\n");
+ }
+ }
+}
+
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+ int /*iteration*/) {
+ ColoredPrintf(COLOR_GREEN, "[==========] ");
+ printf("%s from %s ran.",
+ FormatTestCount(unit_test.test_to_run_count()).c_str(),
+ FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+ if (GTEST_FLAG(print_time)) {
+ printf(" (%s ms total)",
+ internal::StreamableToString(unit_test.elapsed_time()).c_str());
+ }
+ printf("\n");
+ ColoredPrintf(COLOR_GREEN, "[ PASSED ] ");
+ printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+ int num_failures = unit_test.failed_test_count();
+ if (!unit_test.Passed()) {
+ const int failed_test_count = unit_test.failed_test_count();
+ ColoredPrintf(COLOR_RED, "[ FAILED ] ");
+ printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+ PrintFailedTests(unit_test);
+ printf("\n%2d FAILED %s\n", num_failures,
+ num_failures == 1 ? "TEST" : "TESTS");
+ }
+
+ int num_disabled = unit_test.reportable_disabled_test_count();
+ if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+ if (!num_failures) {
+ printf("\n"); // Add a spacer if no FAILURE banner is displayed.
+ }
+ ColoredPrintf(COLOR_YELLOW,
+ " YOU HAVE %d DISABLED %s\n\n",
+ num_disabled,
+ num_disabled == 1 ? "TEST" : "TESTS");
+ }
+ // Ensure that Google Test output is printed before, e.g., heapchecker output.
+ fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+ TestEventRepeater() : forwarding_enabled_(true) {}
+ virtual ~TestEventRepeater();
+ void Append(TestEventListener *listener);
+ TestEventListener* Release(TestEventListener* listener);
+
+ // Controls whether events will be forwarded to listeners_. Set to false
+ // in death test child processes.
+ bool forwarding_enabled() const { return forwarding_enabled_; }
+ void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+ virtual void OnTestProgramStart(const UnitTest& unit_test);
+ virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+ virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+ virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
+ virtual void OnTestCaseStart(const TestCase& test_case);
+ virtual void OnTestStart(const TestInfo& test_info);
+ virtual void OnTestPartResult(const TestPartResult& result);
+ virtual void OnTestEnd(const TestInfo& test_info);
+ virtual void OnTestCaseEnd(const TestCase& test_case);
+ virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+ virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
+ virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+ virtual void OnTestProgramEnd(const UnitTest& unit_test);
+
+ private:
+ // Controls whether events will be forwarded to listeners_. Set to false
+ // in death test child processes.
+ bool forwarding_enabled_;
+ // The list of listeners that receive events.
+ std::vector<TestEventListener*> listeners_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
+};
+
+TestEventRepeater::~TestEventRepeater() {
+ ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener *listener) {
+ listeners_.push_back(listener);
+}
+
+// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
+TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
+ for (size_t i = 0; i < listeners_.size(); ++i) {
+ if (listeners_[i] == listener) {
+ listeners_.erase(listeners_.begin() + i);
+ return listener;
+ }
+ }
+
+ return NULL;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+ if (forwarding_enabled_) { \
+ for (size_t i = 0; i < listeners_.size(); i++) { \
+ listeners_[i]->Name(parameter); \
+ } \
+ } \
+}
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+ if (forwarding_enabled_) { \
+ for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
+ listeners_[i]->Name(parameter); \
+ } \
+ } \
+}
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+ int iteration) {
+ if (forwarding_enabled_) {
+ for (size_t i = 0; i < listeners_.size(); i++) {
+ listeners_[i]->OnTestIterationStart(unit_test, iteration);
+ }
+ }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+ int iteration) {
+ if (forwarding_enabled_) {
+ for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
+ listeners_[i]->OnTestIterationEnd(unit_test, iteration);
+ }
+ }
+}
+
+// End TestEventRepeater
+
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+ explicit XmlUnitTestResultPrinter(const char* output_file);
+
+ virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+
+ private:
+ // Is c a whitespace character that is normalized to a space character
+ // when it appears in an XML attribute value?
+ static bool IsNormalizableWhitespace(char c) {
+ return c == 0x9 || c == 0xA || c == 0xD;
+ }
+
+ // May c appear in a well-formed XML document?
+ static bool IsValidXmlCharacter(char c) {
+ return IsNormalizableWhitespace(c) || c >= 0x20;
+ }
+
+ // Returns an XML-escaped copy of the input string str. If
+ // is_attribute is true, the text is meant to appear as an attribute
+ // value, and normalizable whitespace is preserved by replacing it
+ // with character references.
+ static std::string EscapeXml(const std::string& str, bool is_attribute);
+
+ // Returns the given string with all characters invalid in XML removed.
+ static std::string RemoveInvalidXmlCharacters(const std::string& str);
+
+ // Convenience wrapper around EscapeXml when str is an attribute value.
+ static std::string EscapeXmlAttribute(const std::string& str) {
+ return EscapeXml(str, true);
+ }
+
+ // Convenience wrapper around EscapeXml when str is not an attribute value.
+ static std::string EscapeXmlText(const char* str) {
+ return EscapeXml(str, false);
+ }
+
+ // Verifies that the given attribute belongs to the given element and
+ // streams the attribute as XML.
+ static void OutputXmlAttribute(std::ostream* stream,
+ const std::string& element_name,
+ const std::string& name,
+ const std::string& value);
+
+ // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+ static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+ // Streams an XML representation of a TestInfo object.
+ static void OutputXmlTestInfo(::std::ostream* stream,
+ const char* test_case_name,
+ const TestInfo& test_info);
+
+ // Prints an XML representation of a TestCase object
+ static void PrintXmlTestCase(::std::ostream* stream,
+ const TestCase& test_case);
+
+ // Prints an XML summary of unit_test to output stream out.
+ static void PrintXmlUnitTest(::std::ostream* stream,
+ const UnitTest& unit_test);
+
+ // Produces a string representing the test properties in a result as space
+ // delimited XML attributes based on the property key="value" pairs.
+ // When the std::string is not empty, it includes a space at the beginning,
+ // to delimit this attribute from prior attributes.
+ static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
+
+ // The output file.
+ const std::string output_file_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+ : output_file_(output_file) {
+ if (output_file_.c_str() == NULL || output_file_.empty()) {
+ fprintf(stderr, "XML output file may not be null\n");
+ fflush(stderr);
+ exit(EXIT_FAILURE);
+ }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+ int /*iteration*/) {
+ FILE* xmlout = NULL;
+ FilePath output_file(output_file_);
+ FilePath output_dir(output_file.RemoveFileName());
+
+ if (output_dir.CreateDirectoriesRecursively()) {
+ xmlout = posix::FOpen(output_file_.c_str(), "w");
+ }
+ if (xmlout == NULL) {
+ // TODO(wan): report the reason of the failure.
+ //
+ // We don't do it for now as:
+ //
+ // 1. There is no urgent need for it.
+ // 2. It's a bit involved to make the errno variable thread-safe on
+ // all three operating systems (Linux, Windows, and Mac OS).
+ // 3. To interpret the meaning of errno in a thread-safe way,
+ // we need the strerror_r() function, which is not available on
+ // Windows.
+ fprintf(stderr,
+ "Unable to open file \"%s\"\n",
+ output_file_.c_str());
+ fflush(stderr);
+ exit(EXIT_FAILURE);
+ }
+ std::stringstream stream;
+ PrintXmlUnitTest(&stream, unit_test);
+ fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
+ fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str. If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+// TODO(wan): It might be nice to have a minimally invasive, human-readable
+// escaping scheme for invalid characters, rather than dropping them.
+std::string XmlUnitTestResultPrinter::EscapeXml(
+ const std::string& str, bool is_attribute) {
+ Message m;
+
+ for (size_t i = 0; i < str.size(); ++i) {
+ const char ch = str[i];
+ switch (ch) {
+ case '<':
+ m << "&lt;";
+ break;
+ case '>':
+ m << "&gt;";
+ break;
+ case '&':
+ m << "&amp;";
+ break;
+ case '\'':
+ if (is_attribute)
+ m << "&apos;";
+ else
+ m << '\'';
+ break;
+ case '"':
+ if (is_attribute)
+ m << "&quot;";
+ else
+ m << '"';
+ break;
+ default:
+ if (IsValidXmlCharacter(ch)) {
+ if (is_attribute && IsNormalizableWhitespace(ch))
+ m << "&#x" << String::FormatByte(static_cast<unsigned char>(ch))
+ << ";";
+ else
+ m << ch;
+ }
+ break;
+ }
+ }
+
+ return m.GetString();
+}
+
+// Returns the given string with all characters invalid in XML removed.
+// Currently invalid characters are dropped from the string. An
+// alternative is to replace them with certain characters such as . or ?.
+std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
+ const std::string& str) {
+ std::string output;
+ output.reserve(str.size());
+ for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
+ if (IsValidXmlCharacter(*it))
+ output.push_back(*it);
+
+ return output;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests"> <-- corresponds to a UnitTest object
+// <testsuite name="testcase-name"> <-- corresponds to a TestCase object
+// <testcase name="test-name"> <-- corresponds to a TestInfo object
+// <failure message="...">...</failure>
+// <failure message="...">...</failure>
+// <failure message="...">...</failure>
+// <-- individual assertion failures
+// </testcase>
+// </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+ ::std::stringstream ss;
+ ss << ms/1000.0;
+ return ss.str();
+}
+
+// Converts the given epoch time in milliseconds to a date string in the ISO
+// 8601 format, without the timezone information.
+std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
+ // Using non-reentrant version as localtime_r is not portable.
+ time_t seconds = static_cast<time_t>(ms / 1000);
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996
+ // (function or variable may be unsafe).
+ const struct tm* const time_struct = localtime(&seconds); // NOLINT
+# pragma warning(pop) // Restores the warning state again.
+#else
+ const struct tm* const time_struct = localtime(&seconds); // NOLINT
+#endif
+ if (time_struct == NULL)
+ return ""; // Invalid ms value
+
+ // YYYY-MM-DDThh:mm:ss
+ return StreamableToString(time_struct->tm_year + 1900) + "-" +
+ String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" +
+ String::FormatIntWidth2(time_struct->tm_mday) + "T" +
+ String::FormatIntWidth2(time_struct->tm_hour) + ":" +
+ String::FormatIntWidth2(time_struct->tm_min) + ":" +
+ String::FormatIntWidth2(time_struct->tm_sec);
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+ const char* data) {
+ const char* segment = data;
+ *stream << "<![CDATA[";
+ for (;;) {
+ const char* const next_segment = strstr(segment, "]]>");
+ if (next_segment != NULL) {
+ stream->write(
+ segment, static_cast<std::streamsize>(next_segment - segment));
+ *stream << "]]>]]&gt;<![CDATA[";
+ segment = next_segment + strlen("]]>");
+ } else {
+ *stream << segment;
+ break;
+ }
+ }
+ *stream << "]]>";
+}
+
+void XmlUnitTestResultPrinter::OutputXmlAttribute(
+ std::ostream* stream,
+ const std::string& element_name,
+ const std::string& name,
+ const std::string& value) {
+ const std::vector<std::string>& allowed_names =
+ GetReservedAttributesForElement(element_name);
+
+ GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+ allowed_names.end())
+ << "Attribute " << name << " is not allowed for element <" << element_name
+ << ">.";
+
+ *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\"";
+}
+
+// Prints an XML representation of a TestInfo object.
+// TODO(wan): There is also value in printing properties with the plain printer.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+ const char* test_case_name,
+ const TestInfo& test_info) {
+ const TestResult& result = *test_info.result();
+ const std::string kTestcase = "testcase";
+
+ *stream << " <testcase";
+ OutputXmlAttribute(stream, kTestcase, "name", test_info.name());
+
+ if (test_info.value_param() != NULL) {
+ OutputXmlAttribute(stream, kTestcase, "value_param",
+ test_info.value_param());
+ }
+ if (test_info.type_param() != NULL) {
+ OutputXmlAttribute(stream, kTestcase, "type_param", test_info.type_param());
+ }
+
+ OutputXmlAttribute(stream, kTestcase, "status",
+ test_info.should_run() ? "run" : "notrun");
+ OutputXmlAttribute(stream, kTestcase, "time",
+ FormatTimeInMillisAsSeconds(result.elapsed_time()));
+ OutputXmlAttribute(stream, kTestcase, "classname", test_case_name);
+ *stream << TestPropertiesAsXmlAttributes(result);
+
+ int failures = 0;
+ for (int i = 0; i < result.total_part_count(); ++i) {
+ const TestPartResult& part = result.GetTestPartResult(i);
+ if (part.failed()) {
+ if (++failures == 1) {
+ *stream << ">\n";
+ }
+ const string location = internal::FormatCompilerIndependentFileLocation(
+ part.file_name(), part.line_number());
+ const string summary = location + "\n" + part.summary();
+ *stream << " <failure message=\""
+ << EscapeXmlAttribute(summary.c_str())
+ << "\" type=\"\">";
+ const string detail = location + "\n" + part.message();
+ OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
+ *stream << "</failure>\n";
+ }
+ }
+
+ if (failures == 0)
+ *stream << " />\n";
+ else
+ *stream << " </testcase>\n";
+}
+
+// Prints an XML representation of a TestCase object
+void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream,
+ const TestCase& test_case) {
+ const std::string kTestsuite = "testsuite";
+ *stream << " <" << kTestsuite;
+ OutputXmlAttribute(stream, kTestsuite, "name", test_case.name());
+ OutputXmlAttribute(stream, kTestsuite, "tests",
+ StreamableToString(test_case.reportable_test_count()));
+ OutputXmlAttribute(stream, kTestsuite, "failures",
+ StreamableToString(test_case.failed_test_count()));
+ OutputXmlAttribute(
+ stream, kTestsuite, "disabled",
+ StreamableToString(test_case.reportable_disabled_test_count()));
+ OutputXmlAttribute(stream, kTestsuite, "errors", "0");
+ OutputXmlAttribute(stream, kTestsuite, "time",
+ FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
+ *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result())
+ << ">\n";
+
+ for (int i = 0; i < test_case.total_test_count(); ++i) {
+ if (test_case.GetTestInfo(i)->is_reportable())
+ OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i));
+ }
+ *stream << " </" << kTestsuite << ">\n";
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
+ const UnitTest& unit_test) {
+ const std::string kTestsuites = "testsuites";
+
+ *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ *stream << "<" << kTestsuites;
+
+ OutputXmlAttribute(stream, kTestsuites, "tests",
+ StreamableToString(unit_test.reportable_test_count()));
+ OutputXmlAttribute(stream, kTestsuites, "failures",
+ StreamableToString(unit_test.failed_test_count()));
+ OutputXmlAttribute(
+ stream, kTestsuites, "disabled",
+ StreamableToString(unit_test.reportable_disabled_test_count()));
+ OutputXmlAttribute(stream, kTestsuites, "errors", "0");
+ OutputXmlAttribute(
+ stream, kTestsuites, "timestamp",
+ FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()));
+ OutputXmlAttribute(stream, kTestsuites, "time",
+ FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
+
+ if (GTEST_FLAG(shuffle)) {
+ OutputXmlAttribute(stream, kTestsuites, "random_seed",
+ StreamableToString(unit_test.random_seed()));
+ }
+
+ *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
+
+ OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
+ *stream << ">\n";
+
+ for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+ if (unit_test.GetTestCase(i)->reportable_test_count() > 0)
+ PrintXmlTestCase(stream, *unit_test.GetTestCase(i));
+ }
+ *stream << "</" << kTestsuites << ">\n";
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+ const TestResult& result) {
+ Message attributes;
+ for (int i = 0; i < result.test_property_count(); ++i) {
+ const TestProperty& property = result.GetTestProperty(i);
+ attributes << " " << property.key() << "="
+ << "\"" << EscapeXmlAttribute(property.value()) << "\"";
+ }
+ return attributes.GetString();
+}
+
+// End XmlUnitTestResultPrinter
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D". This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+ string result;
+ result.reserve(strlen(str) + 1);
+ for (char ch = *str; ch != '\0'; ch = *++str) {
+ switch (ch) {
+ case '%':
+ case '=':
+ case '&':
+ case '\n':
+ result.append("%" + String::FormatByte(static_cast<unsigned char>(ch)));
+ break;
+ default:
+ result.push_back(ch);
+ break;
+ }
+ }
+ return result;
+}
+
+void StreamingListener::SocketWriter::MakeConnection() {
+ GTEST_CHECK_(sockfd_ == -1)
+ << "MakeConnection() can't be called when there is already a connection.";
+
+ addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses.
+ hints.ai_socktype = SOCK_STREAM;
+ addrinfo* servinfo = NULL;
+
+ // Use the getaddrinfo() to get a linked list of IP addresses for
+ // the given host name.
+ const int error_num = getaddrinfo(
+ host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+ if (error_num != 0) {
+ GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+ << gai_strerror(error_num);
+ }
+
+ // Loop through all the results and connect to the first we can.
+ for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+ cur_addr = cur_addr->ai_next) {
+ sockfd_ = socket(
+ cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+ if (sockfd_ != -1) {
+ // Connect the client socket to the server socket.
+ if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+ close(sockfd_);
+ sockfd_ = -1;
+ }
+ }
+ }
+
+ freeaddrinfo(servinfo); // all done with this structure
+
+ if (sockfd_ == -1) {
+ GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+ << host_name_ << ":" << port_num_;
+ }
+}
+
+// End of class Streaming Listener
+#endif // GTEST_CAN_STREAM_RESULTS__
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+ScopedTrace::ScopedTrace(const char* file, int line, const Message& message)
+ GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+ TraceInfo trace;
+ trace.file = file;
+ trace.line = line;
+ trace.message = message.GetString();
+
+ UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+ScopedTrace::~ScopedTrace()
+ GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+ UnitTest::GetInstance()->PopGTestTrace();
+}
+
+
+// class OsStackTraceGetter
+
+// Returns the current OS stack trace as an std::string. Parameters:
+//
+// max_depth - the maximum number of stack frames to be included
+// in the trace.
+// skip_count - the number of top frames to be skipped; doesn't count
+// against max_depth.
+//
+string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */,
+ int /* skip_count */)
+ GTEST_LOCK_EXCLUDED_(mutex_) {
+ return "";
+}
+
+void OsStackTraceGetter::UponLeavingGTest()
+ GTEST_LOCK_EXCLUDED_(mutex_) {
+}
+
+const char* const
+OsStackTraceGetter::kElidedFramesMarker =
+ "... " GTEST_NAME_ " internal frames ...";
+
+// A helper class that creates the premature-exit file in its
+// constructor and deletes the file in its destructor.
+class ScopedPrematureExitFile {
+ public:
+ explicit ScopedPrematureExitFile(const char* premature_exit_filepath)
+ : premature_exit_filepath_(premature_exit_filepath) {
+ // If a path to the premature-exit file is specified...
+ if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') {
+ // create the file with a single "0" character in it. I/O
+ // errors are ignored as there's nothing better we can do and we
+ // don't want to fail the test because of this.
+ FILE* pfile = posix::FOpen(premature_exit_filepath, "w");
+ fwrite("0", 1, 1, pfile);
+ fclose(pfile);
+ }
+ }
+
+ ~ScopedPrematureExitFile() {
+ if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') {
+ remove(premature_exit_filepath_);
+ }
+ }
+
+ private:
+ const char* const premature_exit_filepath_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile);
+};
+
+} // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+ : repeater_(new internal::TestEventRepeater()),
+ default_result_printer_(NULL),
+ default_xml_generator_(NULL) {
+}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output. Can be removed from the listeners list to shut down default
+// console output. Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+ repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it. It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+ if (listener == default_result_printer_)
+ default_result_printer_ = NULL;
+ else if (listener == default_xml_generator_)
+ default_xml_generator_ = NULL;
+ return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+ if (default_result_printer_ != listener) {
+ // It is an error to pass this method a listener that is already in the
+ // list.
+ delete Release(default_result_printer_);
+ default_result_printer_ = listener;
+ if (listener != NULL)
+ Append(listener);
+ }
+}
+
+// Sets the default_xml_generator attribute to the provided listener. The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+ if (default_xml_generator_ != listener) {
+ // It is an error to pass this method a listener that is already in the
+ // list.
+ delete Release(default_xml_generator_);
+ default_xml_generator_ = listener;
+ if (listener != NULL)
+ Append(listener);
+ }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+ return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding() {
+ repeater_->set_forwarding_enabled(false);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object. The first time this method is
+// called, a UnitTest object is constructed and returned. Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest* UnitTest::GetInstance() {
+ // When compiled with MSVC 7.1 in optimized mode, destroying the
+ // UnitTest object upon exiting the program messes up the exit code,
+ // causing successful tests to appear failed. We have to use a
+ // different implementation in this case to bypass the compiler bug.
+ // This implementation makes the compiler happy, at the cost of
+ // leaking the UnitTest object.
+
+ // CodeGear C++Builder insists on a public destructor for the
+ // default implementation. Use this implementation to keep good OO
+ // design with private destructor.
+
+#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+ static UnitTest* const instance = new UnitTest;
+ return instance;
+#else
+ static UnitTest instance;
+ return &instance;
+#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+}
+
+// Gets the number of successful test cases.
+int UnitTest::successful_test_case_count() const {
+ return impl()->successful_test_case_count();
+}
+
+// Gets the number of failed test cases.
+int UnitTest::failed_test_case_count() const {
+ return impl()->failed_test_case_count();
+}
+
+// Gets the number of all test cases.
+int UnitTest::total_test_case_count() const {
+ return impl()->total_test_case_count();
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTest::test_case_to_run_count() const {
+ return impl()->test_case_to_run_count();
+}
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+ return impl()->successful_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTest::reportable_disabled_test_count() const {
+ return impl()->reportable_disabled_test_count();
+}
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+ return impl()->disabled_test_count();
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTest::reportable_test_count() const {
+ return impl()->reportable_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the time of the test program start, in ms from the start of the
+// UNIX epoch.
+internal::TimeInMillis UnitTest::start_timestamp() const {
+ return impl()->start_timestamp();
+}
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+ return impl()->elapsed_time();
+}
+
+// Returns true iff the unit test passed (i.e. all test cases passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true iff the unit test failed (i.e. some test case failed
+// or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+const TestCase* UnitTest::GetTestCase(int i) const {
+ return impl()->GetTestCase(i);
+}
+
+// Returns the TestResult containing information on test failures and
+// properties logged outside of individual test cases.
+const TestResult& UnitTest::ad_hoc_test_result() const {
+ return *impl()->ad_hoc_test_result();
+}
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+TestCase* UnitTest::GetMutableTestCase(int i) {
+ return impl()->GetMutableTestCase(i);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() {
+ return *impl()->listeners();
+}
+
+// Registers and returns a global test environment. When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered. After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+ if (env == NULL) {
+ return NULL;
+ }
+
+ impl_->environments().push_back(env);
+ return env;
+}
+
+// Adds a TestPartResult to the current TestResult object. All Google Test
+// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
+// this to report their results. The user code should use the
+// assertion macros instead of calling this directly.
+void UnitTest::AddTestPartResult(
+ TestPartResult::Type result_type,
+ const char* file_name,
+ int line_number,
+ const std::string& message,
+ const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) {
+ Message msg;
+ msg << message;
+
+ internal::MutexLock lock(&mutex_);
+ if (impl_->gtest_trace_stack().size() > 0) {
+ msg << "\n" << GTEST_NAME_ << " trace:";
+
+ for (int i = static_cast<int>(impl_->gtest_trace_stack().size());
+ i > 0; --i) {
+ const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+ msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
+ << " " << trace.message;
+ }
+ }
+
+ if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) {
+ msg << internal::kStackTraceMarker << os_stack_trace;
+ }
+
+ const TestPartResult result =
+ TestPartResult(result_type, file_name, line_number,
+ msg.GetString().c_str());
+ impl_->GetTestPartResultReporterForCurrentThread()->
+ ReportTestPartResult(result);
+
+ if (result_type != TestPartResult::kSuccess) {
+ // gtest_break_on_failure takes precedence over
+ // gtest_throw_on_failure. This allows a user to set the latter
+ // in the code (perhaps in order to use Google Test assertions
+ // with another testing framework) and specify the former on the
+ // command line for debugging.
+ if (GTEST_FLAG(break_on_failure)) {
+#if GTEST_OS_WINDOWS
+ // Using DebugBreak on Windows allows gtest to still break into a debugger
+ // when a failure happens and both the --gtest_break_on_failure and
+ // the --gtest_catch_exceptions flags are specified.
+ DebugBreak();
+#else
+ // Dereference NULL through a volatile pointer to prevent the compiler
+ // from removing. We use this rather than abort() or __builtin_trap() for
+ // portability: Symbian doesn't implement abort() well, and some debuggers
+ // don't correctly trap abort().
+ *static_cast<volatile int*>(NULL) = 1;
+#endif // GTEST_OS_WINDOWS
+ } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+ throw internal::GoogleTestFailureException(result);
+#else
+ // We cannot call abort() as it generates a pop-up in debug mode
+ // that cannot be suppressed in VC 7.1 or below.
+ exit(1);
+#endif
+ }
+ }
+}
+
+// Adds a TestProperty to the current TestResult object when invoked from
+// inside a test, to current TestCase's ad_hoc_test_result_ when invoked
+// from SetUpTestCase or TearDownTestCase, or to the global property set
+// when invoked elsewhere. If the result already contains a property with
+// the same key, the value will be updated.
+void UnitTest::RecordProperty(const std::string& key,
+ const std::string& value) {
+ impl_->RecordProperty(TestProperty(key, value));
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+int UnitTest::Run() {
+ const bool in_death_test_child_process =
+ internal::GTEST_FLAG(internal_run_death_test).length() > 0;
+
+ // Google Test implements this protocol for catching that a test
+ // program exits before returning control to Google Test:
+ //
+ // 1. Upon start, Google Test creates a file whose absolute path
+ // is specified by the environment variable
+ // TEST_PREMATURE_EXIT_FILE.
+ // 2. When Google Test has finished its work, it deletes the file.
+ //
+ // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before
+ // running a Google-Test-based test program and check the existence
+ // of the file at the end of the test execution to see if it has
+ // exited prematurely.
+
+ // If we are in the child process of a death test, don't
+ // create/delete the premature exit file, as doing so is unnecessary
+ // and will confuse the parent process. Otherwise, create/delete
+ // the file upon entering/leaving this function. If the program
+ // somehow exits before this function has a chance to return, the
+ // premature-exit file will be left undeleted, causing a test runner
+ // that understands the premature-exit-file protocol to report the
+ // test as having failed.
+ const internal::ScopedPrematureExitFile premature_exit_file(
+ in_death_test_child_process ?
+ NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));
+
+ // Captures the value of GTEST_FLAG(catch_exceptions). This value will be
+ // used for the duration of the program.
+ impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+
+#if GTEST_HAS_SEH
+ // Either the user wants Google Test to catch exceptions thrown by the
+ // tests or this is executing in the context of death test child
+ // process. In either case the user does not want to see pop-up dialogs
+ // about crashes - they are expected.
+ if (impl()->catch_exceptions() || in_death_test_child_process) {
+# if !GTEST_OS_WINDOWS_MOBILE
+ // SetErrorMode doesn't exist on CE.
+ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+ SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+# endif // !GTEST_OS_WINDOWS_MOBILE
+
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+ // Death test children can be terminated with _abort(). On Windows,
+ // _abort() can show a dialog with a warning message. This forces the
+ // abort message to go to stderr instead.
+ _set_error_mode(_OUT_TO_STDERR);
+# endif
+
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+ // In the debug version, Visual Studio pops up a separate dialog
+ // offering a choice to debug the aborted program. We need to suppress
+ // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+ // executed. Google Test will notify the user of any unexpected
+ // failure via stderr.
+ //
+ // VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
+ // Users of prior VC versions shall suffer the agony and pain of
+ // clicking through the countless debug dialogs.
+ // TODO(vladl@google.com): find a way to suppress the abort dialog() in the
+ // debug mode when compiled with VC 7.1 or lower.
+ if (!GTEST_FLAG(break_on_failure))
+ _set_abort_behavior(
+ 0x0, // Clear the following flags:
+ _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
+# endif
+ }
+#endif // GTEST_HAS_SEH
+
+ return internal::HandleExceptionsInMethodIfSupported(
+ impl(),
+ &internal::UnitTestImpl::RunAllTests,
+ "auxiliary test code (environments or event listeners)") ? 0 : 1;
+}
+
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+ return impl_->original_working_dir_.c_str();
+}
+
+// Returns the TestCase object for the test that's currently running,
+// or NULL if no test is running.
+const TestCase* UnitTest::current_test_case() const
+ GTEST_LOCK_EXCLUDED_(mutex_) {
+ internal::MutexLock lock(&mutex_);
+ return impl_->current_test_case();
+}
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+const TestInfo* UnitTest::current_test_info() const
+ GTEST_LOCK_EXCLUDED_(mutex_) {
+ internal::MutexLock lock(&mutex_);
+ return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+#if GTEST_HAS_PARAM_TEST
+// Returns ParameterizedTestCaseRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+internal::ParameterizedTestCaseRegistry&
+ UnitTest::parameterized_test_registry()
+ GTEST_LOCK_EXCLUDED_(mutex_) {
+ return impl_->parameterized_test_registry();
+}
+#endif // GTEST_HAS_PARAM_TEST
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() {
+ impl_ = new internal::UnitTestImpl(this);
+}
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() {
+ delete impl_;
+}
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
+ GTEST_LOCK_EXCLUDED_(mutex_) {
+ internal::MutexLock lock(&mutex_);
+ impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+void UnitTest::PopGTestTrace()
+ GTEST_LOCK_EXCLUDED_(mutex_) {
+ internal::MutexLock lock(&mutex_);
+ impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+UnitTestImpl::UnitTestImpl(UnitTest* parent)
+ : parent_(parent),
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4355) // Temporarily disables warning 4355
+ // (using this in initializer).
+ default_global_test_part_result_reporter_(this),
+ default_per_thread_test_part_result_reporter_(this),
+# pragma warning(pop) // Restores the warning state again.
+#else
+ default_global_test_part_result_reporter_(this),
+ default_per_thread_test_part_result_reporter_(this),
+#endif // _MSC_VER
+ global_test_part_result_repoter_(
+ &default_global_test_part_result_reporter_),
+ per_thread_test_part_result_reporter_(
+ &default_per_thread_test_part_result_reporter_),
+#if GTEST_HAS_PARAM_TEST
+ parameterized_test_registry_(),
+ parameterized_tests_registered_(false),
+#endif // GTEST_HAS_PARAM_TEST
+ last_death_test_case_(-1),
+ current_test_case_(NULL),
+ current_test_info_(NULL),
+ ad_hoc_test_result_(),
+ os_stack_trace_getter_(NULL),
+ post_flag_parse_init_performed_(false),
+ random_seed_(0), // Will be overridden by the flag before first use.
+ random_(0), // Will be reseeded before first use.
+ start_timestamp_(0),
+ elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
+ death_test_factory_(new DefaultDeathTestFactory),
+#endif
+ // Will be overridden by the flag before first use.
+ catch_exceptions_(false) {
+ listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+ // Deletes every TestCase.
+ ForEach(test_cases_, internal::Delete<TestCase>);
+
+ // Deletes every Environment.
+ ForEach(environments_, internal::Delete<Environment>);
+
+ delete os_stack_trace_getter_;
+}
+
+// Adds a TestProperty to the current TestResult object when invoked in a
+// context of a test, to current test case's ad_hoc_test_result when invoke
+// from SetUpTestCase/TearDownTestCase, or to the global property set
+// otherwise. If the result already contains a property with the same key,
+// the value will be updated.
+void UnitTestImpl::RecordProperty(const TestProperty& test_property) {
+ std::string xml_element;
+ TestResult* test_result; // TestResult appropriate for property recording.
+
+ if (current_test_info_ != NULL) {
+ xml_element = "testcase";
+ test_result = &(current_test_info_->result_);
+ } else if (current_test_case_ != NULL) {
+ xml_element = "testsuite";
+ test_result = &(current_test_case_->ad_hoc_test_result_);
+ } else {
+ xml_element = "testsuites";
+ test_result = &ad_hoc_test_result_;
+ }
+ test_result->RecordProperty(xml_element, test_property);
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+ if (internal_run_death_test_flag_.get() != NULL)
+ listeners()->SuppressEventForwarding();
+}
+#endif // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+ const std::string& output_format = UnitTestOptions::GetOutputFormat();
+ if (output_format == "xml") {
+ listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+ UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+ } else if (output_format != "") {
+ printf("WARNING: unrecognized output format \"%s\" ignored.\n",
+ output_format.c_str());
+ fflush(stdout);
+ }
+}
+
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in string form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+ const std::string& target = GTEST_FLAG(stream_result_to);
+ if (!target.empty()) {
+ const size_t pos = target.find(':');
+ if (pos != std::string::npos) {
+ listeners()->Append(new StreamingListener(target.substr(0, pos),
+ target.substr(pos+1)));
+ } else {
+ printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+ target.c_str());
+ fflush(stdout);
+ }
+ }
+}
+#endif // GTEST_CAN_STREAM_RESULTS_
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests. Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+ // Ensures that this function does not execute more than once.
+ if (!post_flag_parse_init_performed_) {
+ post_flag_parse_init_performed_ = true;
+
+#if GTEST_HAS_DEATH_TEST
+ InitDeathTestSubprocessControlInfo();
+ SuppressTestEventsIfInSubprocess();
+#endif // GTEST_HAS_DEATH_TEST
+
+ // Registers parameterized tests. This makes parameterized tests
+ // available to the UnitTest reflection API without running
+ // RUN_ALL_TESTS.
+ RegisterParameterizedTests();
+
+ // Configures listeners for XML output. This makes it possible for users
+ // to shut down the default XML output before invoking RUN_ALL_TESTS.
+ ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+ // Configures listeners for streaming test results to the specified server.
+ ConfigureStreamingOutput();
+#endif // GTEST_CAN_STREAM_RESULTS_
+ }
+}
+
+// A predicate that checks the name of a TestCase against a known
+// value.
+//
+// This is used for implementation of the UnitTest class only. We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestCaseNameIs is copyable.
+class TestCaseNameIs {
+ public:
+ // Constructor.
+ explicit TestCaseNameIs(const std::string& name)
+ : name_(name) {}
+
+ // Returns true iff the name of test_case matches name_.
+ bool operator()(const TestCase* test_case) const {
+ return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0;
+ }
+
+ private:
+ std::string name_;
+};
+
+// Finds and returns a TestCase with the given name. If one doesn't
+// exist, creates one and returns it. It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+// test_case_name: name of the test case
+// type_param: the name of the test case's type parameter, or NULL if
+// this is not a typed or a type-parameterized test case.
+// set_up_tc: pointer to the function that sets up the test case
+// tear_down_tc: pointer to the function that tears down the test case
+TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
+ const char* type_param,
+ Test::SetUpTestCaseFunc set_up_tc,
+ Test::TearDownTestCaseFunc tear_down_tc) {
+ // Can we find a TestCase with the given name?
+ const std::vector<TestCase*>::const_iterator test_case =
+ std::find_if(test_cases_.begin(), test_cases_.end(),
+ TestCaseNameIs(test_case_name));
+
+ if (test_case != test_cases_.end())
+ return *test_case;
+
+ // No. Let's create one.
+ TestCase* const new_test_case =
+ new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
+
+ // Is this a death test case?
+ if (internal::UnitTestOptions::MatchesFilter(test_case_name,
+ kDeathTestCaseFilter)) {
+ // Yes. Inserts the test case after the last death test case
+ // defined so far. This only works when the test cases haven't
+ // been shuffled. Otherwise we may end up running a death test
+ // after a non-death test.
+ ++last_death_test_case_;
+ test_cases_.insert(test_cases_.begin() + last_death_test_case_,
+ new_test_case);
+ } else {
+ // No. Appends to the end of the list.
+ test_cases_.push_back(new_test_case);
+ }
+
+ test_case_indices_.push_back(static_cast<int>(test_case_indices_.size()));
+ return new_test_case;
+}
+
+// Helpers for setting up / tearing down the given environment. They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+
+// Runs all tests in this UnitTest object, prints the result, and
+// returns true if all tests are successful. If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
+// When parameterized tests are enabled, it expands and registers
+// parameterized tests first in RegisterParameterizedTests().
+// All other functions called from RunAllTests() may safely assume that
+// parameterized tests are ready to be counted and run.
+bool UnitTestImpl::RunAllTests() {
+ // Makes sure InitGoogleTest() was called.
+ if (!GTestIsInitialized()) {
+ printf("%s",
+ "\nThis test program did NOT call ::testing::InitGoogleTest "
+ "before calling RUN_ALL_TESTS(). Please fix it.\n");
+ return false;
+ }
+
+ // Do not run any test if the --help flag was specified.
+ if (g_help_flag)
+ return true;
+
+ // Repeats the call to the post-flag parsing initialization in case the
+ // user didn't call InitGoogleTest.
+ PostFlagParsingInit();
+
+ // Even if sharding is not on, test runners may want to use the
+ // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+ // protocol.
+ internal::WriteToShardStatusFileIfNeeded();
+
+ // True iff we are in a subprocess for running a thread-safe-style
+ // death test.
+ bool in_subprocess_for_death_test = false;
+
+#if GTEST_HAS_DEATH_TEST
+ in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
+#endif // GTEST_HAS_DEATH_TEST
+
+ const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+ in_subprocess_for_death_test);
+
+ // Compares the full test names with the filter to decide which
+ // tests to run.
+ const bool has_tests_to_run = FilterTests(should_shard
+ ? HONOR_SHARDING_PROTOCOL
+ : IGNORE_SHARDING_PROTOCOL) > 0;
+
+ // Lists the tests and exits if the --gtest_list_tests flag was specified.
+ if (GTEST_FLAG(list_tests)) {
+ // This must be called *after* FilterTests() has been called.
+ ListTestsMatchingFilter();
+ return true;
+ }
+
+ random_seed_ = GTEST_FLAG(shuffle) ?
+ GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
+
+ // True iff at least one test has failed.
+ bool failed = false;
+
+ TestEventListener* repeater = listeners()->repeater();
+
+ start_timestamp_ = GetTimeInMillis();
+ repeater->OnTestProgramStart(*parent_);
+
+ // How many times to repeat the tests? We don't want to repeat them
+ // when we are inside the subprocess of a death test.
+ const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
+ // Repeats forever if the repeat count is negative.
+ const bool forever = repeat < 0;
+ for (int i = 0; forever || i != repeat; i++) {
+ // We want to preserve failures generated by ad-hoc test
+ // assertions executed before RUN_ALL_TESTS().
+ ClearNonAdHocTestResult();
+
+ const TimeInMillis start = GetTimeInMillis();
+
+ // Shuffles test cases and tests if requested.
+ if (has_tests_to_run && GTEST_FLAG(shuffle)) {
+ random()->Reseed(random_seed_);
+ // This should be done before calling OnTestIterationStart(),
+ // such that a test event listener can see the actual test order
+ // in the event.
+ ShuffleTests();
+ }
+
+ // Tells the unit test event listeners that the tests are about to start.
+ repeater->OnTestIterationStart(*parent_, i);
+
+ // Runs each test case if there is at least one test to run.
+ if (has_tests_to_run) {
+ // Sets up all environments beforehand.
+ repeater->OnEnvironmentsSetUpStart(*parent_);
+ ForEach(environments_, SetUpEnvironment);
+ repeater->OnEnvironmentsSetUpEnd(*parent_);
+
+ // Runs the tests only if there was no fatal failure during global
+ // set-up.
+ if (!Test::HasFatalFailure()) {
+ for (int test_index = 0; test_index < total_test_case_count();
+ test_index++) {
+ GetMutableTestCase(test_index)->Run();
+ }
+ }
+
+ // Tears down all environments in reverse order afterwards.
+ repeater->OnEnvironmentsTearDownStart(*parent_);
+ std::for_each(environments_.rbegin(), environments_.rend(),
+ TearDownEnvironment);
+ repeater->OnEnvironmentsTearDownEnd(*parent_);
+ }
+
+ elapsed_time_ = GetTimeInMillis() - start;
+
+ // Tells the unit test event listener that the tests have just finished.
+ repeater->OnTestIterationEnd(*parent_, i);
+
+ // Gets the result and clears it.
+ if (!Passed()) {
+ failed = true;
+ }
+
+ // Restores the original test order after the iteration. This
+ // allows the user to quickly repro a failure that happens in the
+ // N-th iteration without repeating the first (N - 1) iterations.
+ // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+ // case the user somehow changes the value of the flag somewhere
+ // (it's always safe to unshuffle the tests).
+ UnshuffleTests();
+
+ if (GTEST_FLAG(shuffle)) {
+ // Picks a new random seed for each iteration.
+ random_seed_ = GetNextRandomSeed(random_seed_);
+ }
+ }
+
+ repeater->OnTestProgramEnd(*parent_);
+
+ return !failed;
+}
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+ const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+ if (test_shard_file != NULL) {
+ FILE* const file = posix::FOpen(test_shard_file, "w");
+ if (file == NULL) {
+ ColoredPrintf(COLOR_RED,
+ "Could not write to the test shard status file \"%s\" "
+ "specified by the %s environment variable.\n",
+ test_shard_file, kTestShardStatusFile);
+ fflush(stdout);
+ exit(EXIT_FAILURE);
+ }
+ fclose(file);
+ }
+}
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env,
+ const char* shard_index_env,
+ bool in_subprocess_for_death_test) {
+ if (in_subprocess_for_death_test) {
+ return false;
+ }
+
+ const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+ const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+ if (total_shards == -1 && shard_index == -1) {
+ return false;
+ } else if (total_shards == -1 && shard_index != -1) {
+ const Message msg = Message()
+ << "Invalid environment variables: you have "
+ << kTestShardIndex << " = " << shard_index
+ << ", but have left " << kTestTotalShards << " unset.\n";
+ ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+ fflush(stdout);
+ exit(EXIT_FAILURE);
+ } else if (total_shards != -1 && shard_index == -1) {
+ const Message msg = Message()
+ << "Invalid environment variables: you have "
+ << kTestTotalShards << " = " << total_shards
+ << ", but have left " << kTestShardIndex << " unset.\n";
+ ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+ fflush(stdout);
+ exit(EXIT_FAILURE);
+ } else if (shard_index < 0 || shard_index >= total_shards) {
+ const Message msg = Message()
+ << "Invalid environment variables: we require 0 <= "
+ << kTestShardIndex << " < " << kTestTotalShards
+ << ", but you have " << kTestShardIndex << "=" << shard_index
+ << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+ ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+ fflush(stdout);
+ exit(EXIT_FAILURE);
+ }
+
+ return total_shards > 1;
+}
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error
+// and aborts.
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
+ const char* str_val = posix::GetEnv(var);
+ if (str_val == NULL) {
+ return default_val;
+ }
+
+ Int32 result;
+ if (!ParseInt32(Message() << "The value of environment variable " << var,
+ str_val, &result)) {
+ exit(EXIT_FAILURE);
+ }
+ return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+ return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestCase and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide.
+// Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+ const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
+ Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
+ const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
+ Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
+
+ // num_runnable_tests are the number of tests that will
+ // run across all shards (i.e., match filter and are not disabled).
+ // num_selected_tests are the number of tests to be run on
+ // this shard.
+ int num_runnable_tests = 0;
+ int num_selected_tests = 0;
+ for (size_t i = 0; i < test_cases_.size(); i++) {
+ TestCase* const test_case = test_cases_[i];
+ const std::string &test_case_name = test_case->name();
+ test_case->set_should_run(false);
+
+ for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+ TestInfo* const test_info = test_case->test_info_list()[j];
+ const std::string test_name(test_info->name());
+ // A test is disabled if test case name or test name matches
+ // kDisableTestFilter.
+ const bool is_disabled =
+ internal::UnitTestOptions::MatchesFilter(test_case_name,
+ kDisableTestFilter) ||
+ internal::UnitTestOptions::MatchesFilter(test_name,
+ kDisableTestFilter);
+ test_info->is_disabled_ = is_disabled;
+
+ const bool matches_filter =
+ internal::UnitTestOptions::FilterMatchesTest(test_case_name,
+ test_name);
+ test_info->matches_filter_ = matches_filter;
+
+ const bool is_runnable =
+ (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
+ matches_filter;
+
+ const bool is_selected = is_runnable &&
+ (shard_tests == IGNORE_SHARDING_PROTOCOL ||
+ ShouldRunTestOnShard(total_shards, shard_index,
+ num_runnable_tests));
+
+ num_runnable_tests += is_runnable;
+ num_selected_tests += is_selected;
+
+ test_info->should_run_ = is_selected;
+ test_case->set_should_run(test_case->should_run() || is_selected);
+ }
+ }
+ return num_selected_tests;
+}
+
+// Prints the given C-string on a single line by replacing all '\n'
+// characters with string "\\n". If the output takes more than
+// max_length characters, only prints the first max_length characters
+// and "...".
+static void PrintOnOneLine(const char* str, int max_length) {
+ if (str != NULL) {
+ for (int i = 0; *str != '\0'; ++str) {
+ if (i >= max_length) {
+ printf("...");
+ break;
+ }
+ if (*str == '\n') {
+ printf("\\n");
+ i += 2;
+ } else {
+ printf("%c", *str);
+ ++i;
+ }
+ }
+ }
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+ // Print at most this many characters for each type/value parameter.
+ const int kMaxParamLength = 250;
+
+ for (size_t i = 0; i < test_cases_.size(); i++) {
+ const TestCase* const test_case = test_cases_[i];
+ bool printed_test_case_name = false;
+
+ for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+ const TestInfo* const test_info =
+ test_case->test_info_list()[j];
+ if (test_info->matches_filter_) {
+ if (!printed_test_case_name) {
+ printed_test_case_name = true;
+ printf("%s.", test_case->name());
+ if (test_case->type_param() != NULL) {
+ printf(" # %s = ", kTypeParamLabel);
+ // We print the type parameter on a single line to make
+ // the output easy to parse by a program.
+ PrintOnOneLine(test_case->type_param(), kMaxParamLength);
+ }
+ printf("\n");
+ }
+ printf(" %s", test_info->name());
+ if (test_info->value_param() != NULL) {
+ printf(" # %s = ", kValueParamLabel);
+ // We print the value parameter on a single line to make the
+ // output easy to parse by a program.
+ PrintOnOneLine(test_info->value_param(), kMaxParamLength);
+ }
+ printf("\n");
+ }
+ }
+ }
+ fflush(stdout);
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+ OsStackTraceGetterInterface* getter) {
+ if (os_stack_trace_getter_ != getter) {
+ delete os_stack_trace_getter_;
+ os_stack_trace_getter_ = getter;
+ }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+ if (os_stack_trace_getter_ == NULL) {
+ os_stack_trace_getter_ = new OsStackTraceGetter;
+ }
+
+ return os_stack_trace_getter_;
+}
+
+// Returns the TestResult for the test that's currently running, or
+// the TestResult for the ad hoc test if no test is running.
+TestResult* UnitTestImpl::current_test_result() {
+ return current_test_info_ ?
+ &(current_test_info_->result_) : &ad_hoc_test_result_;
+}
+
+// Shuffles all test cases, and the tests within each test case,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+ // Shuffles the death test cases.
+ ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_);
+
+ // Shuffles the non-death test cases.
+ ShuffleRange(random(), last_death_test_case_ + 1,
+ static_cast<int>(test_cases_.size()), &test_case_indices_);
+
+ // Shuffles the tests inside each test case.
+ for (size_t i = 0; i < test_cases_.size(); i++) {
+ test_cases_[i]->ShuffleTests(random());
+ }
+}
+
+// Restores the test cases and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+ for (size_t i = 0; i < test_cases_.size(); i++) {
+ // Unshuffles the tests in each test case.
+ test_cases_[i]->UnshuffleTests();
+ // Resets the index of each test case.
+ test_case_indices_[i] = static_cast<int>(i);
+ }
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag. The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
+ int skip_count) {
+ // We pass skip_count + 1 to skip this wrapper function in addition
+ // to what the user really wants to skip.
+ return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+ // This condition is always false so AlwaysTrue() never actually throws,
+ // but it makes the compiler think that it may throw.
+ if (IsTrue(false))
+ throw ClassUniqueToAlwaysTrue();
+#endif // GTEST_HAS_EXCEPTIONS
+ return true;
+}
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false. None of pstr, *pstr, and prefix can be NULL.
+bool SkipPrefix(const char* prefix, const char** pstr) {
+ const size_t prefix_len = strlen(prefix);
+ if (strncmp(*pstr, prefix, prefix_len) == 0) {
+ *pstr += prefix_len;
+ return true;
+ }
+ return false;
+}
+
+// Parses a string as a command line flag. The string should have
+// the format "--flag=value". When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+const char* ParseFlagValue(const char* str,
+ const char* flag,
+ bool def_optional) {
+ // str and flag must not be NULL.
+ if (str == NULL || flag == NULL) return NULL;
+
+ // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+ const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag;
+ const size_t flag_len = flag_str.length();
+ if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+ // Skips the flag name.
+ const char* flag_end = str + flag_len;
+
+ // When def_optional is true, it's OK to not have a "=value" part.
+ if (def_optional && (flag_end[0] == '\0')) {
+ return flag_end;
+ }
+
+ // If def_optional is true and there are more characters after the
+ // flag name, or if def_optional is false, there must be a '=' after
+ // the flag name.
+ if (flag_end[0] != '=') return NULL;
+
+ // Returns the string after "=".
+ return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true. On failure, returns false without changing *value.
+bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
+ // Gets the value of the flag as a string.
+ const char* const value_str = ParseFlagValue(str, flag, true);
+
+ // Aborts if the parsing failed.
+ if (value_str == NULL) return false;
+
+ // Converts the string value to a bool.
+ *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+ return true;
+}
+
+// Parses a string for an Int32 flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true. On failure, returns false without changing *value.
+bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
+ // Gets the value of the flag as a string.
+ const char* const value_str = ParseFlagValue(str, flag, false);
+
+ // Aborts if the parsing failed.
+ if (value_str == NULL) return false;
+
+ // Sets *value to the value of the flag.
+ return ParseInt32(Message() << "The value of flag --" << flag,
+ value_str, value);
+}
+
+// Parses a string for a string flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true. On failure, returns false without changing *value.
+bool ParseStringFlag(const char* str, const char* flag, std::string* value) {
+ // Gets the value of the flag as a string.
+ const char* const value_str = ParseFlagValue(str, flag, false);
+
+ // Aborts if the parsing failed.
+ if (value_str == NULL) return false;
+
+ // Sets *value to the value of the flag.
+ *value = value_str;
+ return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+ return (SkipPrefix("--", &str) ||
+ SkipPrefix("-", &str) ||
+ SkipPrefix("/", &str)) &&
+ !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+ (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+ SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text. The following escape
+// sequences can be used in the string to control the text color:
+//
+// @@ prints a single '@' character.
+// @R changes the color to red.
+// @G changes the color to green.
+// @Y changes the color to yellow.
+// @D changes to the default terminal text color.
+//
+// TODO(wan@google.com): Write tests for this once we add stdout
+// capturing to Google Test.
+static void PrintColorEncoded(const char* str) {
+ GTestColor color = COLOR_DEFAULT; // The current color.
+
+ // Conceptually, we split the string into segments divided by escape
+ // sequences. Then we print one segment at a time. At the end of
+ // each iteration, the str pointer advances to the beginning of the
+ // next segment.
+ for (;;) {
+ const char* p = strchr(str, '@');
+ if (p == NULL) {
+ ColoredPrintf(color, "%s", str);
+ return;
+ }
+
+ ColoredPrintf(color, "%s", std::string(str, p).c_str());
+
+ const char ch = p[1];
+ str = p + 2;
+ if (ch == '@') {
+ ColoredPrintf(color, "@");
+ } else if (ch == 'D') {
+ color = COLOR_DEFAULT;
+ } else if (ch == 'R') {
+ color = COLOR_RED;
+ } else if (ch == 'G') {
+ color = COLOR_GREEN;
+ } else if (ch == 'Y') {
+ color = COLOR_YELLOW;
+ } else {
+ --str;
+ }
+ }
+}
+
+static const char kColorEncodedHelpMessage[] =
+"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
+"following command line flags to control its behavior:\n"
+"\n"
+"Test Selection:\n"
+" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n"
+" List the names of all tests instead of running them. The name of\n"
+" TEST(Foo, Bar) is \"Foo.Bar\".\n"
+" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
+ "[@G-@YNEGATIVE_PATTERNS]@D\n"
+" Run only the tests whose name matches one of the positive patterns but\n"
+" none of the negative patterns. '?' matches any single character; '*'\n"
+" matches any substring; ':' separates two patterns.\n"
+" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n"
+" Run all disabled tests too.\n"
+"\n"
+"Test Execution:\n"
+" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
+" Run the tests repeatedly; use a negative count to repeat forever.\n"
+" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n"
+" Randomize tests' orders on every iteration.\n"
+" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
+" Random number seed to use for shuffling test orders (between 1 and\n"
+" 99999, or 0 to use a seed based on the current time).\n"
+"\n"
+"Test Output:\n"
+" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
+" Enable/disable colored output. The default is @Gauto@D.\n"
+" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
+" Don't print the elapsed time of each test.\n"
+" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G"
+ GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
+" Generate an XML report in the given directory or with the given file\n"
+" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
+" Stream test results to the given server.\n"
+#endif // GTEST_CAN_STREAM_RESULTS_
+"\n"
+"Assertion Behavior:\n"
+#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
+" Set the default death test style.\n"
+#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
+" Turn assertion failures into debugger break-points.\n"
+" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
+" Turn assertion failures into C++ exceptions.\n"
+" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
+" Do not report exceptions as test failures. Instead, allow them\n"
+" to crash the program or throw a pop-up (on Windows).\n"
+"\n"
+"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
+ "the corresponding\n"
+"environment variable of a flag (all letters in upper-case). For example, to\n"
+"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_
+ "color=no@D or set\n"
+"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n"
+"\n"
+"For more information, please read the " GTEST_NAME_ " documentation at\n"
+"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n"
+"(not one in your own code or tests), please report it to\n"
+"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test. The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+ for (int i = 1; i < *argc; i++) {
+ const std::string arg_string = StreamableToString(argv[i]);
+ const char* const arg = arg_string.c_str();
+
+ using internal::ParseBoolFlag;
+ using internal::ParseInt32Flag;
+ using internal::ParseStringFlag;
+
+ // Do we see a Google Test flag?
+ if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
+ &GTEST_FLAG(also_run_disabled_tests)) ||
+ ParseBoolFlag(arg, kBreakOnFailureFlag,
+ &GTEST_FLAG(break_on_failure)) ||
+ ParseBoolFlag(arg, kCatchExceptionsFlag,
+ &GTEST_FLAG(catch_exceptions)) ||
+ ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
+ ParseStringFlag(arg, kDeathTestStyleFlag,
+ &GTEST_FLAG(death_test_style)) ||
+ ParseBoolFlag(arg, kDeathTestUseFork,
+ &GTEST_FLAG(death_test_use_fork)) ||
+ ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
+ ParseStringFlag(arg, kInternalRunDeathTestFlag,
+ &GTEST_FLAG(internal_run_death_test)) ||
+ ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
+ ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
+ ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
+ ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
+ ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+ ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
+ ParseInt32Flag(arg, kStackTraceDepthFlag,
+ &GTEST_FLAG(stack_trace_depth)) ||
+ ParseStringFlag(arg, kStreamResultToFlag,
+ &GTEST_FLAG(stream_result_to)) ||
+ ParseBoolFlag(arg, kThrowOnFailureFlag,
+ &GTEST_FLAG(throw_on_failure))
+ ) {
+ // Yes. Shift the remainder of the argv list left by one. Note
+ // that argv has (*argc + 1) elements, the last one always being
+ // NULL. The following loop moves the trailing NULL element as
+ // well.
+ for (int j = i; j != *argc; j++) {
+ argv[j] = argv[j + 1];
+ }
+
+ // Decrements the argument count.
+ (*argc)--;
+
+ // We also need to decrement the iterator as we just removed
+ // an element.
+ i--;
+ } else if (arg_string == "--help" || arg_string == "-h" ||
+ arg_string == "-?" || arg_string == "/?" ||
+ HasGoogleTestFlagPrefix(arg)) {
+ // Both help flag and unrecognized Google Test flags (excluding
+ // internal ones) trigger help display.
+ g_help_flag = true;
+ }
+ }
+
+ if (g_help_flag) {
+ // We print the help here instead of in RUN_ALL_TESTS(), as the
+ // latter may not be called at all if the user is using Google
+ // Test with another testing framework.
+ PrintColorEncoded(kColorEncodedHelpMessage);
+ }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+ ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+ ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+ g_init_gtest_count++;
+
+ // We don't want to run the initialization code twice.
+ if (g_init_gtest_count != 1) return;
+
+ if (*argc <= 0) return;
+
+ internal::g_executable_path = internal::StreamableToString(argv[0]);
+
+#if GTEST_HAS_DEATH_TEST
+
+ g_argvs.clear();
+ for (int i = 0; i != *argc; i++) {
+ g_argvs.push_back(StreamableToString(argv[i]));
+ }
+
+#endif // GTEST_HAS_DEATH_TEST
+
+ ParseGoogleTestFlagsOnly(argc, argv);
+ GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+} // namespace internal
+
+// Initializes Google Test. This must be called before calling
+// RUN_ALL_TESTS(). In particular, it parses a command line for the
+// flags that Google Test recognizes. Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned. Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+ internal::InitGoogleTestImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+ internal::InitGoogleTestImpl(argc, argv);
+}
+
+} // namespace testing
diff --git a/thirdparty/gtest/src/gtest_main.cc b/thirdparty/gtest/src/gtest_main.cc
new file mode 100644
index 00000000..f3028225
--- /dev/null
+++ b/thirdparty/gtest/src/gtest_main.cc
@@ -0,0 +1,38 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+GTEST_API_ int main(int argc, char **argv) {
+ printf("Running main() from gtest_main.cc\n");
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/thirdparty/khronos/EGL/egl.h b/thirdparty/khronos/EGL/egl.h
index 0b1029ba..a52fb856 100644
--- a/thirdparty/khronos/EGL/egl.h
+++ b/thirdparty/khronos/EGL/egl.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -33,12 +33,12 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
-** Khronos $Revision: 26290 $ on $Date: 2014-04-16 05:35:38 -0700 (Wed, 16 Apr 2014) $
+** Khronos $Revision: 32351 $ on $Date: 2016-01-08 18:53:22 -0800 (Fri, 08 Jan 2016) $
*/
#include <EGL/eglplatform.h>
-/* Generated on date 20140416 */
+/* Generated on date 20160108 */
/* Generated C header for:
* API: egl
@@ -240,6 +240,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
typedef void *EGLSync;
typedef intptr_t EGLAttrib;
typedef khronos_utime_nanoseconds_t EGLTime;
+typedef void *EGLImage;
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
#define EGL_CONTEXT_MINOR_VERSION 0x30FB
#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
@@ -281,10 +282,14 @@ typedef khronos_utime_nanoseconds_t EGLTime;
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+#define EGL_IMAGE_PRESERVED 0x30D2
+#define EGL_NO_IMAGE ((EGLImage)0)
EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image);
EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
diff --git a/thirdparty/khronos/EGL/eglext.h b/thirdparty/khronos/EGL/eglext.h
index 60ced143..868c44a9 100644
--- a/thirdparty/khronos/EGL/eglext.h
+++ b/thirdparty/khronos/EGL/eglext.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -33,12 +33,12 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
-** Khronos $Revision: 26290 $ on $Date: 2014-04-16 05:35:38 -0700 (Wed, 16 Apr 2014) $
+** Khronos $Revision: 32351 $ on $Date: 2016-01-08 18:53:22 -0800 (Fri, 08 Jan 2016) $
*/
#include <EGL/eglplatform.h>
-#define EGL_EGLEXT_VERSION 20140416
+#define EGL_EGLEXT_VERSION 20160108
/* Generated C header for:
* API: egl
@@ -94,12 +94,55 @@ EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type,
#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
#endif /* EGL_KHR_create_context */
+#ifndef EGL_KHR_create_context_no_error
+#define EGL_KHR_create_context_no_error 1
+#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
+#endif /* EGL_KHR_create_context_no_error */
+
+#ifndef EGL_KHR_debug
+#define EGL_KHR_debug 1
+typedef void *EGLLabelKHR;
+typedef void *EGLObjectKHR;
+typedef void (EGLAPIENTRY *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message);
+#define EGL_OBJECT_THREAD_KHR 0x33B0
+#define EGL_OBJECT_DISPLAY_KHR 0x33B1
+#define EGL_OBJECT_CONTEXT_KHR 0x33B2
+#define EGL_OBJECT_SURFACE_KHR 0x33B3
+#define EGL_OBJECT_IMAGE_KHR 0x33B4
+#define EGL_OBJECT_SYNC_KHR 0x33B5
+#define EGL_OBJECT_STREAM_KHR 0x33B6
+#define EGL_DEBUG_MSG_CRITICAL_KHR 0x33B9
+#define EGL_DEBUG_MSG_ERROR_KHR 0x33BA
+#define EGL_DEBUG_MSG_WARN_KHR 0x33BB
+#define EGL_DEBUG_MSG_INFO_KHR 0x33BC
+#define EGL_DEBUG_CALLBACK_KHR 0x33B8
+typedef EGLint (EGLAPIENTRYP PFNEGLDEBUGMESSAGECONTROLKHRPROC) (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEBUGKHRPROC) (EGLint attribute, EGLAttrib *value);
+typedef EGLint (EGLAPIENTRYP PFNEGLLABELOBJECTKHRPROC) (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglDebugMessageControlKHR (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDebugKHR (EGLint attribute, EGLAttrib *value);
+EGLAPI EGLint EGLAPIENTRY eglLabelObjectKHR (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
+#endif
+#endif /* EGL_KHR_debug */
+
#ifndef EGL_KHR_fence_sync
#define EGL_KHR_fence_sync 1
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
#ifdef KHRONOS_SUPPORT_INT64
#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
#define EGL_SYNC_CONDITION_KHR 0x30F8
#define EGL_SYNC_FENCE_KHR 0x30F9
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif
#endif /* KHRONOS_SUPPORT_INT64 */
#endif /* EGL_KHR_fence_sync */
@@ -207,6 +250,15 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface s
#endif
#endif /* EGL_KHR_lock_surface3 */
+#ifndef EGL_KHR_partial_update
+#define EGL_KHR_partial_update 1
+#define EGL_BUFFER_AGE_KHR 0x313D
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_partial_update */
+
#ifndef EGL_KHR_platform_android
#define EGL_KHR_platform_android 1
#define EGL_PLATFORM_ANDROID_KHR 0x3141
@@ -230,7 +282,6 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface s
#ifndef EGL_KHR_reusable_sync
#define EGL_KHR_reusable_sync 1
-typedef khronos_utime_nanoseconds_t EGLTimeKHR;
#ifdef KHRONOS_SUPPORT_INT64
#define EGL_SYNC_STATUS_KHR 0x30F1
#define EGL_SIGNALED_KHR 0x30F2
@@ -242,17 +293,9 @@ typedef khronos_utime_nanoseconds_t EGLTimeKHR;
#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
-typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
-typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
-EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
#endif
#endif /* KHRONOS_SUPPORT_INT64 */
#endif /* EGL_KHR_reusable_sync */
@@ -354,6 +397,14 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy,
#define EGL_KHR_surfaceless_context 1
#endif /* EGL_KHR_surfaceless_context */
+#ifndef EGL_KHR_swap_buffers_with_damage
+#define EGL_KHR_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_swap_buffers_with_damage */
+
#ifndef EGL_KHR_vg_parent_image
#define EGL_KHR_vg_parent_image 1
#define EGL_VG_PARENT_IMAGE_KHR 0x30BA
@@ -410,6 +461,12 @@ EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR
#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
+#ifndef EGL_ANGLE_device_d3d
+#define EGL_ANGLE_device_d3d 1
+#define EGL_D3D9_DEVICE_ANGLE 0x33A0
+#define EGL_D3D11_DEVICE_ANGLE 0x33A1
+#endif /* EGL_ANGLE_device_d3d */
+
#ifndef EGL_ANGLE_query_surface_pointer
#define EGL_ANGLE_query_surface_pointer 1
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
@@ -422,6 +479,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+#ifndef EGL_ANGLE_window_fixed_size
+#define EGL_ANGLE_window_fixed_size 1
+#define EGL_FIXED_SIZE_ANGLE 0x3201
+#endif /* EGL_ANGLE_window_fixed_size */
+
#ifndef EGL_ARM_pixmap_multisample_discard
#define EGL_ARM_pixmap_multisample_discard 1
#define EGL_DISCARD_SAMPLES_ARM 0x3286
@@ -444,6 +506,42 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
#endif /* EGL_EXT_create_context_robustness */
+#ifndef EGL_EXT_device_base
+#define EGL_EXT_device_base 1
+typedef void *EGLDeviceEXT;
+#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0))
+#define EGL_BAD_DEVICE_EXT 0x322B
+#define EGL_DEVICE_EXT 0x322C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#endif
+#endif /* EGL_EXT_device_base */
+
+#ifndef EGL_EXT_device_drm
+#define EGL_EXT_device_drm 1
+#define EGL_DRM_DEVICE_FILE_EXT 0x3233
+#endif /* EGL_EXT_device_drm */
+
+#ifndef EGL_EXT_device_enumeration
+#define EGL_EXT_device_enumeration 1
+#endif /* EGL_EXT_device_enumeration */
+
+#ifndef EGL_EXT_device_openwf
+#define EGL_EXT_device_openwf 1
+#define EGL_OPENWF_DEVICE_ID_EXT 0x3237
+#endif /* EGL_EXT_device_openwf */
+
+#ifndef EGL_EXT_device_query
+#define EGL_EXT_device_query 1
+#endif /* EGL_EXT_device_query */
+
#ifndef EGL_EXT_image_dma_buf_import
#define EGL_EXT_image_dma_buf_import 1
#define EGL_LINUX_DMA_BUF_EXT 0x3270
@@ -475,6 +573,48 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
#endif /* EGL_EXT_multiview_window */
+#ifndef EGL_EXT_output_base
+#define EGL_EXT_output_base 1
+typedef void *EGLOutputLayerEXT;
+typedef void *EGLOutputPortEXT;
+#define EGL_NO_OUTPUT_LAYER_EXT ((EGLOutputLayerEXT)0)
+#define EGL_NO_OUTPUT_PORT_EXT ((EGLOutputPortEXT)0)
+#define EGL_BAD_OUTPUT_LAYER_EXT 0x322D
+#define EGL_BAD_OUTPUT_PORT_EXT 0x322E
+#define EGL_SWAP_INTERVAL_EXT 0x322F
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputLayersEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputPortsEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputLayerStringEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#endif
+#endif /* EGL_EXT_output_base */
+
+#ifndef EGL_EXT_output_drm
+#define EGL_EXT_output_drm 1
+#define EGL_DRM_CRTC_EXT 0x3234
+#define EGL_DRM_PLANE_EXT 0x3235
+#define EGL_DRM_CONNECTOR_EXT 0x3236
+#endif /* EGL_EXT_output_drm */
+
+#ifndef EGL_EXT_output_openwf
+#define EGL_EXT_output_openwf 1
+#define EGL_OPENWF_PIPELINE_ID_EXT 0x3238
+#define EGL_OPENWF_PORT_ID_EXT 0x3239
+#endif /* EGL_EXT_output_openwf */
+
#ifndef EGL_EXT_platform_base
#define EGL_EXT_platform_base 1
typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
@@ -487,6 +627,11 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy,
#endif
#endif /* EGL_EXT_platform_base */
+#ifndef EGL_EXT_platform_device
+#define EGL_EXT_platform_device 1
+#define EGL_PLATFORM_DEVICE_EXT 0x313F
+#endif /* EGL_EXT_platform_device */
+
#ifndef EGL_EXT_platform_wayland
#define EGL_EXT_platform_wayland 1
#define EGL_PLATFORM_WAYLAND_EXT 0x31D8
@@ -503,6 +648,14 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy,
#define EGL_PROTECTED_CONTENT_EXT 0x32C0
#endif /* EGL_EXT_protected_surface */
+#ifndef EGL_EXT_stream_consumer_egloutput
+#define EGL_EXT_stream_consumer_egloutput 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#endif
+#endif /* EGL_EXT_stream_consumer_egloutput */
+
#ifndef EGL_EXT_swap_buffers_with_damage
#define EGL_EXT_swap_buffers_with_damage 1
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
@@ -511,6 +664,35 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSu
#endif
#endif /* EGL_EXT_swap_buffers_with_damage */
+#ifndef EGL_EXT_yuv_surface
+#define EGL_EXT_yuv_surface 1
+#define EGL_YUV_ORDER_EXT 0x3301
+#define EGL_YUV_NUMBER_OF_PLANES_EXT 0x3311
+#define EGL_YUV_SUBSAMPLE_EXT 0x3312
+#define EGL_YUV_DEPTH_RANGE_EXT 0x3317
+#define EGL_YUV_CSC_STANDARD_EXT 0x330A
+#define EGL_YUV_PLANE_BPP_EXT 0x331A
+#define EGL_YUV_BUFFER_EXT 0x3300
+#define EGL_YUV_ORDER_YUV_EXT 0x3302
+#define EGL_YUV_ORDER_YVU_EXT 0x3303
+#define EGL_YUV_ORDER_YUYV_EXT 0x3304
+#define EGL_YUV_ORDER_UYVY_EXT 0x3305
+#define EGL_YUV_ORDER_YVYU_EXT 0x3306
+#define EGL_YUV_ORDER_VYUY_EXT 0x3307
+#define EGL_YUV_ORDER_AYUV_EXT 0x3308
+#define EGL_YUV_SUBSAMPLE_4_2_0_EXT 0x3313
+#define EGL_YUV_SUBSAMPLE_4_2_2_EXT 0x3314
+#define EGL_YUV_SUBSAMPLE_4_4_4_EXT 0x3315
+#define EGL_YUV_DEPTH_RANGE_LIMITED_EXT 0x3318
+#define EGL_YUV_DEPTH_RANGE_FULL_EXT 0x3319
+#define EGL_YUV_CSC_STANDARD_601_EXT 0x330B
+#define EGL_YUV_CSC_STANDARD_709_EXT 0x330C
+#define EGL_YUV_CSC_STANDARD_2020_EXT 0x330D
+#define EGL_YUV_PLANE_BPP_0_EXT 0x331B
+#define EGL_YUV_PLANE_BPP_8_EXT 0x331C
+#define EGL_YUV_PLANE_BPP_10_EXT 0x331D
+#endif /* EGL_EXT_yuv_surface */
+
#ifndef EGL_HI_clientpixmap
#define EGL_HI_clientpixmap 1
struct EGLClientPixmapHI {
@@ -542,6 +724,12 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfi
#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
#endif /* EGL_IMG_context_priority */
+#ifndef EGL_IMG_image_plane_attribs
+#define EGL_IMG_image_plane_attribs 1
+#define EGL_NATIVE_BUFFER_MULTIPLANE_SEPARATE_IMG 0x3105
+#define EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG 0x3106
+#endif /* EGL_IMG_image_plane_attribs */
+
#ifndef EGL_MESA_drm_image
#define EGL_MESA_drm_image 1
#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
@@ -559,6 +747,16 @@ EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR
#endif
#endif /* EGL_MESA_drm_image */
+#ifndef EGL_MESA_image_dma_buf_export
+#define EGL_MESA_image_dma_buf_export 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#endif
+#endif /* EGL_MESA_image_dma_buf_export */
+
#ifndef EGL_MESA_platform_gbm
#define EGL_MESA_platform_gbm 1
#define EGL_PLATFORM_GBM_MESA 0x31D7
@@ -603,6 +801,13 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurfa
#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
#endif /* EGL_NV_coverage_sample_resolve */
+#ifndef EGL_NV_cuda_event
+#define EGL_NV_cuda_event 1
+#define EGL_CUDA_EVENT_HANDLE_NV 0x323B
+#define EGL_SYNC_CUDA_EVENT_NV 0x323C
+#define EGL_SYNC_CUDA_EVENT_COMPLETE_NV 0x323D
+#endif /* EGL_NV_cuda_event */
+
#ifndef EGL_NV_depth_nonlinear
#define EGL_NV_depth_nonlinear 1
#define EGL_DEPTH_ENCODING_NV 0x30E2
@@ -610,6 +815,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurfa
#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
#endif /* EGL_NV_depth_nonlinear */
+#ifndef EGL_NV_device_cuda
+#define EGL_NV_device_cuda 1
+#define EGL_CUDA_DEVICE_NV 0x323A
+#endif /* EGL_NV_device_cuda */
+
#ifndef EGL_NV_native_query
#define EGL_NV_native_query 1
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
@@ -635,6 +845,43 @@ EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface sur
#endif
#endif /* EGL_NV_post_sub_buffer */
+#ifndef EGL_NV_stream_consumer_gltexture_yuv
+#define EGL_NV_stream_consumer_gltexture_yuv 1
+#define EGL_YUV_PLANE0_TEXTURE_UNIT_NV 0x332C
+#define EGL_YUV_PLANE1_TEXTURE_UNIT_NV 0x332D
+#define EGL_YUV_PLANE2_TEXTURE_UNIT_NV 0x332E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALATTRIBSNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalAttribsNV (EGLDisplay dpy, EGLStreamKHR stream, EGLAttrib *attrib_list);
+#endif
+#endif /* EGL_NV_stream_consumer_gltexture_yuv */
+
+#ifndef EGL_NV_stream_metadata
+#define EGL_NV_stream_metadata 1
+#define EGL_MAX_STREAM_METADATA_BLOCKS_NV 0x3250
+#define EGL_MAX_STREAM_METADATA_BLOCK_SIZE_NV 0x3251
+#define EGL_MAX_STREAM_METADATA_TOTAL_SIZE_NV 0x3252
+#define EGL_PRODUCER_METADATA_NV 0x3253
+#define EGL_CONSUMER_METADATA_NV 0x3254
+#define EGL_PENDING_METADATA_NV 0x3328
+#define EGL_METADATA0_SIZE_NV 0x3255
+#define EGL_METADATA1_SIZE_NV 0x3256
+#define EGL_METADATA2_SIZE_NV 0x3257
+#define EGL_METADATA3_SIZE_NV 0x3258
+#define EGL_METADATA0_TYPE_NV 0x3259
+#define EGL_METADATA1_TYPE_NV 0x325A
+#define EGL_METADATA2_TYPE_NV 0x325B
+#define EGL_METADATA3_TYPE_NV 0x325C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBNVPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribNV (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
+#endif
+#endif /* EGL_NV_stream_metadata */
+
#ifndef EGL_NV_stream_sync
#define EGL_NV_stream_sync 1
#define EGL_SYNC_NEW_FRAME_NV 0x321F
@@ -692,6 +939,16 @@ EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
#endif /* KHRONOS_SUPPORT_INT64 */
#endif /* EGL_NV_system_time */
+#ifndef EGL_TIZEN_image_native_buffer
+#define EGL_TIZEN_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_TIZEN 0x32A0
+#endif /* EGL_TIZEN_image_native_buffer */
+
+#ifndef EGL_TIZEN_image_native_surface
+#define EGL_TIZEN_image_native_surface 1
+#define EGL_NATIVE_SURFACE_TIZEN 0x32A1
+#endif /* EGL_TIZEN_image_native_surface */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/khronos/EGL/eglplatform.h b/thirdparty/khronos/EGL/eglplatform.h
index 0a51d9b3..203f08c5 100644
--- a/thirdparty/khronos/EGL/eglplatform.h
+++ b/thirdparty/khronos/EGL/eglplatform.h
@@ -25,7 +25,7 @@
*/
/* Platform-specific types and definitions for egl.h
- * $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $
+ * $Revision: 30994 $ on $Date: 2015-04-30 13:36:48 -0700 (Thu, 30 Apr 2015) $
*
* Adopters may modify khrplatform.h and this file to suit their platform.
* You are encouraged to submit all modifications to the Khronos group so that
@@ -77,7 +77,7 @@ typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
typedef HWND EGLNativeWindowType;
-#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
+#elif defined(__APPLE__) || defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
typedef int EGLNativeDisplayType;
typedef void *EGLNativeWindowType;
@@ -103,7 +103,7 @@ typedef struct ANativeWindow* EGLNativeWindowType;
typedef struct egl_native_pixmap_t* EGLNativePixmapType;
typedef void* EGLNativeDisplayType;
-#elif defined(__APPLE__)
+#elif defined(__APPLE__) || defined(__QNXNTO__)
typedef void *EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
diff --git a/thirdparty/khronos/EGL/eglplatform.patch b/thirdparty/khronos/EGL/eglplatform.patch
index d35bca3a..0882ecac 100644
--- a/thirdparty/khronos/EGL/eglplatform.patch
+++ b/thirdparty/khronos/EGL/eglplatform.patch
@@ -1,10 +1,8 @@
-diff --git a/thirdparty/khronos/EGL/eglplatform.h b/thirdparty/khronos/EGL/eglplatform.h
-index 6d34ab5..5f30ef1 100644
---- a/thirdparty/khronos/EGL/eglplatform.h
-+++ b/thirdparty/khronos/EGL/eglplatform.h
-@@ -83,6 +83,22 @@ typedef int EGLNativeDisplayType;
- typedef void *EGLNativeWindowType;
- typedef void *EGLNativePixmapType;
+--- eglplatform.h.orig 2015-04-30 22:05:42.000000000 +0100
++++ eglplatform.h 2015-06-25 16:35:12.366373499 +0100
+@@ -93,6 +93,22 @@
+ typedef struct egl_native_pixmap_t* EGLNativePixmapType;
+ typedef void* EGLNativeDisplayType;
+#elif defined(__ANDROID__) || defined(ANDROID)
+
@@ -16,7 +14,7 @@ index 6d34ab5..5f30ef1 100644
+typedef struct egl_native_pixmap_t* EGLNativePixmapType;
+typedef void* EGLNativeDisplayType;
+
-+#elif defined(__APPLE__)
++#elif defined(__APPLE__) || defined(__QNXNTO__)
+
+typedef void *EGLNativeDisplayType;
+typedef void *EGLNativePixmapType;
diff --git a/thirdparty/khronos/GL/glext.h b/thirdparty/khronos/GL/glext.h
index 17ae258f..313dcf46 100644
--- a/thirdparty/khronos/GL/glext.h
+++ b/thirdparty/khronos/GL/glext.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -33,7 +33,7 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
-** Khronos $Revision: 26745 $ on $Date: 2014-05-21 03:12:26 -0700 (Wed, 21 May 2014) $
+** Khronos $Revision: 32363 $ on $Date: 2016-01-14 19:17:52 -0500 (Thu, 14 Jan 2016) $
*/
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
@@ -53,7 +53,7 @@ extern "C" {
#define GLAPI extern
#endif
-#define GL_GLEXT_VERSION 20140521
+#define GL_GLEXT_VERSION 20160114
/* Generated C header for:
* API: gl
@@ -1041,6 +1041,22 @@ typedef unsigned short GLhalf;
#define GL_COLOR_ATTACHMENT13 0x8CED
#define GL_COLOR_ATTACHMENT14 0x8CEE
#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
#define GL_DEPTH_ATTACHMENT 0x8D00
#define GL_STENCIL_ATTACHMENT 0x8D20
#define GL_FRAMEBUFFER 0x8D40
@@ -1308,11 +1324,13 @@ GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array);
#define GL_UNIFORM_BUFFER_START 0x8A29
#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
@@ -1331,6 +1349,7 @@ GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array);
#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
#define GL_INVALID_INDEX 0xFFFFFFFFu
typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
@@ -2041,6 +2060,10 @@ GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data)
#ifndef GL_VERSION_4_2
#define GL_VERSION_4_2 1
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
@@ -2212,6 +2235,7 @@ typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum
#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER_BIT 0x00000020
#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
@@ -2571,10 +2595,297 @@ GLAPI void APIENTRY glBindVertexBuffers (GLuint first, GLsizei count, const GLui
#endif
#endif /* GL_VERSION_4_4 */
+#ifndef GL_VERSION_4_5
+#define GL_VERSION_4_5 1
+#define GL_CONTEXT_LOST 0x0507
+#define GL_NEGATIVE_ONE_TO_ONE 0x935E
+#define GL_ZERO_TO_ONE 0x935F
+#define GL_CLIP_ORIGIN 0x935C
+#define GL_CLIP_DEPTH_MODE 0x935D
+#define GL_QUERY_WAIT_INVERTED 0x8E17
+#define GL_QUERY_NO_WAIT_INVERTED 0x8E18
+#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19
+#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A
+#define GL_MAX_CULL_DISTANCES 0x82F9
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA
+#define GL_TEXTURE_TARGET 0x1006
+#define GL_QUERY_TARGET 0x82EA
+#define GL_GUILTY_CONTEXT_RESET 0x8253
+#define GL_INNOCENT_CONTEXT_RESET 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET 0x8252
+#define GL_NO_RESET_NOTIFICATION 0x8261
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
+#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
+typedef void (APIENTRYP PFNGLCLIPCONTROLPROC) (GLenum origin, GLenum depth);
+typedef void (APIENTRYP PFNGLCREATETRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC) (GLuint xfb, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKIVPROC) (GLuint xfb, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
+typedef void (APIENTRYP PFNGLCREATEBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
+typedef void (APIENTRYP PFNGLCOPYNAMEDBUFFERSUBDATAPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERPROC) (GLuint buffer, GLenum access);
+typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFERPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERI64VPROC) (GLuint buffer, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVPROC) (GLuint buffer, GLenum pname, void **params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data);
+typedef void (APIENTRYP PFNGLCREATEFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC) (GLuint framebuffer, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC) (GLuint framebuffer, GLenum buf);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC) (GLuint framebuffer, GLenum src);
+typedef void (APIENTRYP PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC) (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments);
+typedef void (APIENTRYP PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef void (APIENTRYP PFNGLBLITNAMEDFRAMEBUFFERPROC) (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) (GLuint framebuffer, GLenum target);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) (GLuint framebuffer, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCREATERENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC) (GLuint renderbuffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCREATETEXTURESPROC) (GLenum target, GLsizei n, GLuint *textures);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFERPROC) (GLuint texture, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEPROC) (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE1DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC) (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC) (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DPROC) (GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFPROC) (GLuint texture, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVPROC) (GLuint texture, GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIPROC) (GLuint texture, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVPROC) (GLuint texture, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVPROC) (GLuint texture, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVPROC) (GLuint texture, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLBINDTEXTUREUNITPROC) (GLuint unit, GLuint texture);
+typedef void (APIENTRYP PFNGLGETTEXTUREIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC) (GLuint texture, GLint level, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVPROC) (GLuint texture, GLint level, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVPROC) (GLuint texture, GLint level, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVPROC) (GLuint texture, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVPROC) (GLuint texture, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVPROC) (GLuint texture, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVPROC) (GLuint texture, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCREATEVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYATTRIBPROC) (GLuint vaobj, GLuint index);
+typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYATTRIBPROC) (GLuint vaobj, GLuint index);
+typedef void (APIENTRYP PFNGLVERTEXARRAYELEMENTBUFFERPROC) (GLuint vaobj, GLuint buffer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBUFFERPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBUFFERSPROC) (GLuint vaobj, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBBINDINGPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBIFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYATTRIBLFORMATPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYBINDINGDIVISORPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYIVPROC) (GLuint vaobj, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINDEXEDIVPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINDEXED64IVPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint64 *param);
+typedef void (APIENTRYP PFNGLCREATESAMPLERSPROC) (GLsizei n, GLuint *samplers);
+typedef void (APIENTRYP PFNGLCREATEPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef void (APIENTRYP PFNGLCREATEQUERIESPROC) (GLenum target, GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTI64VPROC) (GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTIVPROC) (GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTUI64VPROC) (GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTUIVPROC) (GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+typedef void (APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers);
+typedef void (APIENTRYP PFNGLGETTEXTURESUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void *pixels);
+typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC) (void);
+typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETNTEXIMAGEPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+typedef void (APIENTRYP PFNGLGETNUNIFORMDVPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMFVPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMUIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (APIENTRYP PFNGLREADNPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (APIENTRYP PFNGLGETNMAPDVPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+typedef void (APIENTRYP PFNGLGETNMAPFVPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+typedef void (APIENTRYP PFNGLGETNMAPIVPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPFVPROC) (GLenum map, GLsizei bufSize, GLfloat *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVPROC) (GLenum map, GLsizei bufSize, GLuint *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVPROC) (GLenum map, GLsizei bufSize, GLushort *values);
+typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEPROC) (GLsizei bufSize, GLubyte *pattern);
+typedef void (APIENTRYP PFNGLGETNCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+typedef void (APIENTRYP PFNGLGETNHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+typedef void (APIENTRYP PFNGLGETNMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+typedef void (APIENTRYP PFNGLTEXTUREBARRIERPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClipControl (GLenum origin, GLenum depth);
+GLAPI void APIENTRY glCreateTransformFeedbacks (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glTransformFeedbackBufferBase (GLuint xfb, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackBufferRange (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glGetTransformFeedbackiv (GLuint xfb, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetTransformFeedbacki_v (GLuint xfb, GLenum pname, GLuint index, GLint *param);
+GLAPI void APIENTRY glGetTransformFeedbacki64_v (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
+GLAPI void APIENTRY glCreateBuffers (GLsizei n, GLuint *buffers);
+GLAPI void APIENTRY glNamedBufferStorage (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags);
+GLAPI void APIENTRY glNamedBufferData (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage);
+GLAPI void APIENTRY glNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
+GLAPI void APIENTRY glCopyNamedBufferSubData (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GLAPI void APIENTRY glClearNamedBufferData (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearNamedBufferSubData (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+GLAPI void *APIENTRY glMapNamedBuffer (GLuint buffer, GLenum access);
+GLAPI void *APIENTRY glMapNamedBufferRange (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI GLboolean APIENTRY glUnmapNamedBuffer (GLuint buffer);
+GLAPI void APIENTRY glFlushMappedNamedBufferRange (GLuint buffer, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glGetNamedBufferParameteriv (GLuint buffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetNamedBufferParameteri64v (GLuint buffer, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetNamedBufferPointerv (GLuint buffer, GLenum pname, void **params);
+GLAPI void APIENTRY glGetNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data);
+GLAPI void APIENTRY glCreateFramebuffers (GLsizei n, GLuint *framebuffers);
+GLAPI void APIENTRY glNamedFramebufferRenderbuffer (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glNamedFramebufferParameteri (GLuint framebuffer, GLenum pname, GLint param);
+GLAPI void APIENTRY glNamedFramebufferTexture (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTextureLayer (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glNamedFramebufferDrawBuffer (GLuint framebuffer, GLenum buf);
+GLAPI void APIENTRY glNamedFramebufferDrawBuffers (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glNamedFramebufferReadBuffer (GLuint framebuffer, GLenum src);
+GLAPI void APIENTRY glInvalidateNamedFramebufferData (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments);
+GLAPI void APIENTRY glInvalidateNamedFramebufferSubData (GLuint framebuffer, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glClearNamedFramebufferiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value);
+GLAPI void APIENTRY glClearNamedFramebufferuiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value);
+GLAPI void APIENTRY glClearNamedFramebufferfv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GLAPI void APIENTRY glClearNamedFramebufferfi (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GLAPI void APIENTRY glBlitNamedFramebuffer (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLAPI GLenum APIENTRY glCheckNamedFramebufferStatus (GLuint framebuffer, GLenum target);
+GLAPI void APIENTRY glGetNamedFramebufferParameteriv (GLuint framebuffer, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetNamedFramebufferAttachmentParameteriv (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glCreateRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glNamedRenderbufferStorage (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisample (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetNamedRenderbufferParameteriv (GLuint renderbuffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glCreateTextures (GLenum target, GLsizei n, GLuint *textures);
+GLAPI void APIENTRY glTextureBuffer (GLuint texture, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glTextureBufferRange (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glTextureStorage1D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width);
+GLAPI void APIENTRY glTextureStorage2D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTextureStorage3D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glTextureStorage2DMultisample (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureStorage3DMultisample (GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureSubImage1D (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage2D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage3D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCompressedTextureSubImage1D (GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTextureSubImage2D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTextureSubImage3D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCopyTextureSubImage1D (GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTextureSubImage2D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glCopyTextureSubImage3D (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTextureParameterf (GLuint texture, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glTextureParameterfv (GLuint texture, GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glTextureParameteri (GLuint texture, GLenum pname, GLint param);
+GLAPI void APIENTRY glTextureParameterIiv (GLuint texture, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTextureParameterIuiv (GLuint texture, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glTextureParameteriv (GLuint texture, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glGenerateTextureMipmap (GLuint texture);
+GLAPI void APIENTRY glBindTextureUnit (GLuint unit, GLuint texture);
+GLAPI void APIENTRY glGetTextureImage (GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetCompressedTextureImage (GLuint texture, GLint level, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetTextureLevelParameterfv (GLuint texture, GLint level, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureLevelParameteriv (GLuint texture, GLint level, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureParameterfv (GLuint texture, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureParameterIiv (GLuint texture, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureParameterIuiv (GLuint texture, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glGetTextureParameteriv (GLuint texture, GLenum pname, GLint *params);
+GLAPI void APIENTRY glCreateVertexArrays (GLsizei n, GLuint *arrays);
+GLAPI void APIENTRY glDisableVertexArrayAttrib (GLuint vaobj, GLuint index);
+GLAPI void APIENTRY glEnableVertexArrayAttrib (GLuint vaobj, GLuint index);
+GLAPI void APIENTRY glVertexArrayElementBuffer (GLuint vaobj, GLuint buffer);
+GLAPI void APIENTRY glVertexArrayVertexBuffer (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexArrayVertexBuffers (GLuint vaobj, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+GLAPI void APIENTRY glVertexArrayAttribBinding (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexArrayAttribFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayAttribIFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayAttribLFormat (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayBindingDivisor (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+GLAPI void APIENTRY glGetVertexArrayiv (GLuint vaobj, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetVertexArrayIndexediv (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetVertexArrayIndexed64iv (GLuint vaobj, GLuint index, GLenum pname, GLint64 *param);
+GLAPI void APIENTRY glCreateSamplers (GLsizei n, GLuint *samplers);
+GLAPI void APIENTRY glCreateProgramPipelines (GLsizei n, GLuint *pipelines);
+GLAPI void APIENTRY glCreateQueries (GLenum target, GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glGetQueryBufferObjecti64v (GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+GLAPI void APIENTRY glGetQueryBufferObjectiv (GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+GLAPI void APIENTRY glGetQueryBufferObjectui64v (GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+GLAPI void APIENTRY glGetQueryBufferObjectuiv (GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+GLAPI void APIENTRY glMemoryBarrierByRegion (GLbitfield barriers);
+GLAPI void APIENTRY glGetTextureSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetCompressedTextureSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void *pixels);
+GLAPI GLenum APIENTRY glGetGraphicsResetStatus (void);
+GLAPI void APIENTRY glGetnCompressedTexImage (GLenum target, GLint lod, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetnTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
+GLAPI void APIENTRY glGetnUniformdv (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+GLAPI void APIENTRY glGetnUniformfv (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GLAPI void APIENTRY glGetnUniformiv (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetnUniformuiv (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GLAPI void APIENTRY glReadnPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GLAPI void APIENTRY glGetnMapdv (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+GLAPI void APIENTRY glGetnMapfv (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+GLAPI void APIENTRY glGetnMapiv (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+GLAPI void APIENTRY glGetnPixelMapfv (GLenum map, GLsizei bufSize, GLfloat *values);
+GLAPI void APIENTRY glGetnPixelMapuiv (GLenum map, GLsizei bufSize, GLuint *values);
+GLAPI void APIENTRY glGetnPixelMapusv (GLenum map, GLsizei bufSize, GLushort *values);
+GLAPI void APIENTRY glGetnPolygonStipple (GLsizei bufSize, GLubyte *pattern);
+GLAPI void APIENTRY glGetnColorTable (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+GLAPI void APIENTRY glGetnConvolutionFilter (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+GLAPI void APIENTRY glGetnSeparableFilter (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+GLAPI void APIENTRY glGetnHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+GLAPI void APIENTRY glGetnMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+GLAPI void APIENTRY glTextureBarrier (void);
+#endif
+#endif /* GL_VERSION_4_5 */
+
#ifndef GL_ARB_ES2_compatibility
#define GL_ARB_ES2_compatibility 1
#endif /* GL_ARB_ES2_compatibility */
+#ifndef GL_ARB_ES3_1_compatibility
+#define GL_ARB_ES3_1_compatibility 1
+#endif /* GL_ARB_ES3_1_compatibility */
+
+#ifndef GL_ARB_ES3_2_compatibility
+#define GL_ARB_ES3_2_compatibility 1
+#define GL_PRIMITIVE_BOUNDING_BOX_ARB 0x92BE
+#define GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB 0x9381
+#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB 0x9382
+typedef void (APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXARBPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPrimitiveBoundingBoxARB (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#endif
+#endif /* GL_ARB_ES3_2_compatibility */
+
#ifndef GL_ARB_ES3_compatibility
#define GL_ARB_ES3_compatibility 1
#endif /* GL_ARB_ES3_compatibility */
@@ -2655,6 +2966,10 @@ GLAPI GLsync APIENTRY glCreateSyncFromCLeventARB (struct _cl_context *context, s
#define GL_ARB_clear_texture 1
#endif /* GL_ARB_clear_texture */
+#ifndef GL_ARB_clip_control
+#define GL_ARB_clip_control 1
+#endif /* GL_ARB_clip_control */
+
#ifndef GL_ARB_color_buffer_float
#define GL_ARB_color_buffer_float 1
#define GL_RGBA_FLOAT_MODE_ARB 0x8820
@@ -2678,7 +2993,6 @@ GLAPI void APIENTRY glClampColorARB (GLenum target, GLenum clamp);
#ifndef GL_ARB_compute_shader
#define GL_ARB_compute_shader 1
-#define GL_COMPUTE_SHADER_BIT 0x00000020
#endif /* GL_ARB_compute_shader */
#ifndef GL_ARB_compute_variable_group_size
@@ -2693,20 +3007,26 @@ GLAPI void APIENTRY glDispatchComputeGroupSizeARB (GLuint num_groups_x, GLuint n
#endif
#endif /* GL_ARB_compute_variable_group_size */
+#ifndef GL_ARB_conditional_render_inverted
+#define GL_ARB_conditional_render_inverted 1
+#endif /* GL_ARB_conditional_render_inverted */
+
#ifndef GL_ARB_conservative_depth
#define GL_ARB_conservative_depth 1
#endif /* GL_ARB_conservative_depth */
#ifndef GL_ARB_copy_buffer
#define GL_ARB_copy_buffer 1
-#define GL_COPY_READ_BUFFER_BINDING 0x8F36
-#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
#endif /* GL_ARB_copy_buffer */
#ifndef GL_ARB_copy_image
#define GL_ARB_copy_image 1
#endif /* GL_ARB_copy_image */
+#ifndef GL_ARB_cull_distance
+#define GL_ARB_cull_distance 1
+#endif /* GL_ARB_cull_distance */
+
#ifndef GL_ARB_debug_output
#define GL_ARB_debug_output 1
typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
@@ -2761,6 +3081,14 @@ GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufSize, GL
#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
#endif /* GL_ARB_depth_texture */
+#ifndef GL_ARB_derivative_control
+#define GL_ARB_derivative_control 1
+#endif /* GL_ARB_derivative_control */
+
+#ifndef GL_ARB_direct_state_access
+#define GL_ARB_direct_state_access 1
+#endif /* GL_ARB_direct_state_access */
+
#ifndef GL_ARB_draw_buffers
#define GL_ARB_draw_buffers 1
#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
@@ -2971,6 +3299,10 @@ GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program);
#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
#endif /* GL_ARB_fragment_shader */
+#ifndef GL_ARB_fragment_shader_interlock
+#define GL_ARB_fragment_shader_interlock 1
+#endif /* GL_ARB_fragment_shader_interlock */
+
#ifndef GL_ARB_framebuffer_no_attachments
#define GL_ARB_framebuffer_no_attachments 1
#endif /* GL_ARB_framebuffer_no_attachments */
@@ -3019,6 +3351,10 @@ GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachmen
#define GL_ARB_get_program_binary 1
#endif /* GL_ARB_get_program_binary */
+#ifndef GL_ARB_get_texture_sub_image
+#define GL_ARB_get_texture_sub_image 1
+#endif /* GL_ARB_get_texture_sub_image */
+
#ifndef GL_ARB_gpu_shader5
#define GL_ARB_gpu_shader5 1
#endif /* GL_ARB_gpu_shader5 */
@@ -3027,6 +3363,91 @@ GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachmen
#define GL_ARB_gpu_shader_fp64 1
#endif /* GL_ARB_gpu_shader_fp64 */
+#ifndef GL_ARB_gpu_shader_int64
+#define GL_ARB_gpu_shader_int64 1
+#define GL_INT64_ARB 0x140E
+#define GL_INT64_VEC2_ARB 0x8FE9
+#define GL_INT64_VEC3_ARB 0x8FEA
+#define GL_INT64_VEC4_ARB 0x8FEB
+#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7
+typedef void (APIENTRYP PFNGLUNIFORM1I64ARBPROC) (GLint location, GLint64 x);
+typedef void (APIENTRYP PFNGLUNIFORM2I64ARBPROC) (GLint location, GLint64 x, GLint64 y);
+typedef void (APIENTRYP PFNGLUNIFORM3I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z);
+typedef void (APIENTRYP PFNGLUNIFORM4I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+typedef void (APIENTRYP PFNGLUNIFORM1I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM2I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM3I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM4I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64ARBPROC) (GLint location, GLuint64 x);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMI64VARBPROC) (GLuint program, GLint location, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLuint64 *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64ARBPROC) (GLuint program, GLint location, GLint64 x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64ARBPROC) (GLuint program, GLint location, GLuint64 x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniform1i64ARB (GLint location, GLint64 x);
+GLAPI void APIENTRY glUniform2i64ARB (GLint location, GLint64 x, GLint64 y);
+GLAPI void APIENTRY glUniform3i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z);
+GLAPI void APIENTRY glUniform4i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+GLAPI void APIENTRY glUniform1i64vARB (GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glUniform2i64vARB (GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glUniform3i64vARB (GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glUniform4i64vARB (GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glUniform1ui64ARB (GLint location, GLuint64 x);
+GLAPI void APIENTRY glUniform2ui64ARB (GLint location, GLuint64 x, GLuint64 y);
+GLAPI void APIENTRY glUniform3ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+GLAPI void APIENTRY glUniform4ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+GLAPI void APIENTRY glUniform1ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glUniform2ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glUniform3ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glUniform4ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glGetUniformi64vARB (GLuint program, GLint location, GLint64 *params);
+GLAPI void APIENTRY glGetUniformui64vARB (GLuint program, GLint location, GLuint64 *params);
+GLAPI void APIENTRY glGetnUniformi64vARB (GLuint program, GLint location, GLsizei bufSize, GLint64 *params);
+GLAPI void APIENTRY glGetnUniformui64vARB (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params);
+GLAPI void APIENTRY glProgramUniform1i64ARB (GLuint program, GLint location, GLint64 x);
+GLAPI void APIENTRY glProgramUniform2i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y);
+GLAPI void APIENTRY glProgramUniform3i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z);
+GLAPI void APIENTRY glProgramUniform4i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+GLAPI void APIENTRY glProgramUniform1i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glProgramUniform2i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glProgramUniform3i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glProgramUniform4i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glProgramUniform1ui64ARB (GLuint program, GLint location, GLuint64 x);
+GLAPI void APIENTRY glProgramUniform2ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y);
+GLAPI void APIENTRY glProgramUniform3ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+GLAPI void APIENTRY glProgramUniform4ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+GLAPI void APIENTRY glProgramUniform1ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniform2ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniform3ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniform4ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+#endif
+#endif /* GL_ARB_gpu_shader_int64 */
+
#ifndef GL_ARB_half_float_pixel
#define GL_ARB_half_float_pixel 1
typedef unsigned short GLhalfARB;
@@ -3406,6 +3827,30 @@ GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *par
#define GL_ARB_occlusion_query2 1
#endif /* GL_ARB_occlusion_query2 */
+#ifndef GL_ARB_parallel_shader_compile
+#define GL_ARB_parallel_shader_compile 1
+#define GL_MAX_SHADER_COMPILER_THREADS_ARB 0x91B0
+#define GL_COMPLETION_STATUS_ARB 0x91B1
+typedef void (APIENTRYP PFNGLMAXSHADERCOMPILERTHREADSARBPROC) (GLuint count);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMaxShaderCompilerThreadsARB (GLuint count);
+#endif
+#endif /* GL_ARB_parallel_shader_compile */
+
+#ifndef GL_ARB_pipeline_statistics_query
+#define GL_ARB_pipeline_statistics_query 1
+#define GL_VERTICES_SUBMITTED_ARB 0x82EE
+#define GL_PRIMITIVES_SUBMITTED_ARB 0x82EF
+#define GL_VERTEX_SHADER_INVOCATIONS_ARB 0x82F0
+#define GL_TESS_CONTROL_SHADER_PATCHES_ARB 0x82F1
+#define GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB 0x82F2
+#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB 0x82F3
+#define GL_FRAGMENT_SHADER_INVOCATIONS_ARB 0x82F4
+#define GL_COMPUTE_SHADER_INVOCATIONS_ARB 0x82F5
+#define GL_CLIPPING_INPUT_PRIMITIVES_ARB 0x82F6
+#define GL_CLIPPING_OUTPUT_PRIMITIVES_ARB 0x82F7
+#endif /* GL_ARB_pipeline_statistics_query */
+
#ifndef GL_ARB_pixel_buffer_object
#define GL_ARB_pixel_buffer_object 1
#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
@@ -3434,6 +3879,10 @@ GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params);
#define GL_COORD_REPLACE_ARB 0x8862
#endif /* GL_ARB_point_sprite */
+#ifndef GL_ARB_post_depth_coverage
+#define GL_ARB_post_depth_coverage 1
+#endif /* GL_ARB_post_depth_coverage */
+
#ifndef GL_ARB_program_interface_query
#define GL_ARB_program_interface_query 1
#endif /* GL_ARB_program_interface_query */
@@ -3507,6 +3956,26 @@ GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum form
#define GL_ARB_robustness_isolation 1
#endif /* GL_ARB_robustness_isolation */
+#ifndef GL_ARB_sample_locations
+#define GL_ARB_sample_locations 1
+#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB 0x933D
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB 0x933E
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB 0x933F
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB 0x9340
+#define GL_SAMPLE_LOCATION_ARB 0x8E50
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB 0x9341
+#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB 0x9342
+#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB 0x9343
+typedef void (APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLEVALUATEDEPTHVALUESARBPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferSampleLocationsfvARB (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glNamedFramebufferSampleLocationsfvARB (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glEvaluateDepthValuesARB (void);
+#endif
+#endif /* GL_ARB_sample_locations */
+
#ifndef GL_ARB_sample_shading
#define GL_ARB_sample_shading 1
#define GL_SAMPLE_SHADING_ARB 0x8C36
@@ -3533,14 +4002,26 @@ GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value);
#define GL_ARB_separate_shader_objects 1
#endif /* GL_ARB_separate_shader_objects */
+#ifndef GL_ARB_shader_atomic_counter_ops
+#define GL_ARB_shader_atomic_counter_ops 1
+#endif /* GL_ARB_shader_atomic_counter_ops */
+
#ifndef GL_ARB_shader_atomic_counters
#define GL_ARB_shader_atomic_counters 1
#endif /* GL_ARB_shader_atomic_counters */
+#ifndef GL_ARB_shader_ballot
+#define GL_ARB_shader_ballot 1
+#endif /* GL_ARB_shader_ballot */
+
#ifndef GL_ARB_shader_bit_encoding
#define GL_ARB_shader_bit_encoding 1
#endif /* GL_ARB_shader_bit_encoding */
+#ifndef GL_ARB_shader_clock
+#define GL_ARB_shader_clock 1
+#endif /* GL_ARB_shader_clock */
+
#ifndef GL_ARB_shader_draw_parameters
#define GL_ARB_shader_draw_parameters 1
#endif /* GL_ARB_shader_draw_parameters */
@@ -3697,10 +4178,18 @@ GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GL
#define GL_ARB_shader_subroutine 1
#endif /* GL_ARB_shader_subroutine */
+#ifndef GL_ARB_shader_texture_image_samples
+#define GL_ARB_shader_texture_image_samples 1
+#endif /* GL_ARB_shader_texture_image_samples */
+
#ifndef GL_ARB_shader_texture_lod
#define GL_ARB_shader_texture_lod 1
#endif /* GL_ARB_shader_texture_lod */
+#ifndef GL_ARB_shader_viewport_layer_array
+#define GL_ARB_shader_viewport_layer_array 1
+#endif /* GL_ARB_shader_viewport_layer_array */
+
#ifndef GL_ARB_shading_language_100
#define GL_ARB_shading_language_100 1
#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
@@ -3747,11 +4236,25 @@ GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GL
#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
#endif /* GL_ARB_shadow_ambient */
+#ifndef GL_ARB_sparse_buffer
+#define GL_ARB_sparse_buffer 1
+#define GL_SPARSE_STORAGE_BIT_ARB 0x0400
+#define GL_SPARSE_BUFFER_PAGE_SIZE_ARB 0x82F8
+typedef void (APIENTRYP PFNGLBUFFERPAGECOMMITMENTARBPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLboolean commit);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERPAGECOMMITMENTEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERPAGECOMMITMENTARBPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferPageCommitmentARB (GLenum target, GLintptr offset, GLsizeiptr size, GLboolean commit);
+GLAPI void APIENTRY glNamedBufferPageCommitmentEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit);
+GLAPI void APIENTRY glNamedBufferPageCommitmentARB (GLuint buffer, GLintptr offset, GLsizeiptr size, GLboolean commit);
+#endif
+#endif /* GL_ARB_sparse_buffer */
+
#ifndef GL_ARB_sparse_texture
#define GL_ARB_sparse_texture 1
#define GL_TEXTURE_SPARSE_ARB 0x91A6
#define GL_VIRTUAL_PAGE_SIZE_INDEX_ARB 0x91A7
-#define GL_MIN_SPARSE_LEVEL_ARB 0x919B
+#define GL_NUM_SPARSE_LEVELS_ARB 0x91AA
#define GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8
#define GL_VIRTUAL_PAGE_SIZE_X_ARB 0x9195
#define GL_VIRTUAL_PAGE_SIZE_Y_ARB 0x9196
@@ -3760,12 +4263,20 @@ GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GL
#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199
#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A
#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9
-typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
#ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
#endif
#endif /* GL_ARB_sparse_texture */
+#ifndef GL_ARB_sparse_texture2
+#define GL_ARB_sparse_texture2 1
+#endif /* GL_ARB_sparse_texture2 */
+
+#ifndef GL_ARB_sparse_texture_clamp
+#define GL_ARB_sparse_texture_clamp 1
+#endif /* GL_ARB_sparse_texture_clamp */
+
#ifndef GL_ARB_stencil_texturing
#define GL_ARB_stencil_texturing 1
#endif /* GL_ARB_stencil_texturing */
@@ -3778,6 +4289,10 @@ GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xo
#define GL_ARB_tessellation_shader 1
#endif /* GL_ARB_tessellation_shader */
+#ifndef GL_ARB_texture_barrier
+#define GL_ARB_texture_barrier 1
+#endif /* GL_ARB_texture_barrier */
+
#ifndef GL_ARB_texture_border_clamp
#define GL_ARB_texture_border_clamp 1
#define GL_CLAMP_TO_BORDER_ARB 0x812D
@@ -3914,6 +4429,12 @@ GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void
#define GL_DOT3_RGBA_ARB 0x86AF
#endif /* GL_ARB_texture_env_dot3 */
+#ifndef GL_ARB_texture_filter_minmax
+#define GL_ARB_texture_filter_minmax 1
+#define GL_TEXTURE_REDUCTION_MODE_ARB 0x9366
+#define GL_WEIGHTED_AVERAGE_ARB 0x9367
+#endif /* GL_ARB_texture_filter_minmax */
+
#ifndef GL_ARB_texture_float
#define GL_ARB_texture_float 1
#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
@@ -4012,8 +4533,6 @@ GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void
#ifndef GL_ARB_transform_feedback2
#define GL_ARB_transform_feedback2 1
-#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
-#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
#endif /* GL_ARB_transform_feedback2 */
#ifndef GL_ARB_transform_feedback3
@@ -4024,6 +4543,12 @@ GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void
#define GL_ARB_transform_feedback_instanced 1
#endif /* GL_ARB_transform_feedback_instanced */
+#ifndef GL_ARB_transform_feedback_overflow_query
+#define GL_ARB_transform_feedback_overflow_query 1
+#define GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB 0x82EC
+#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB 0x82ED
+#endif /* GL_ARB_transform_feedback_overflow_query */
+
#ifndef GL_ARB_transpose_matrix
#define GL_ARB_transpose_matrix 1
#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
@@ -4044,9 +4569,6 @@ GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *m);
#ifndef GL_ARB_uniform_buffer_object
#define GL_ARB_uniform_buffer_object 1
-#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
-#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
#endif /* GL_ARB_uniform_buffer_object */
#ifndef GL_ARB_vertex_array_bgra
@@ -4371,10 +4893,56 @@ GLAPI void APIENTRY glWindowPos3svARB (const GLshort *v);
#endif
#endif /* GL_ARB_window_pos */
+#ifndef GL_KHR_blend_equation_advanced
+#define GL_KHR_blend_equation_advanced 1
+#define GL_MULTIPLY_KHR 0x9294
+#define GL_SCREEN_KHR 0x9295
+#define GL_OVERLAY_KHR 0x9296
+#define GL_DARKEN_KHR 0x9297
+#define GL_LIGHTEN_KHR 0x9298
+#define GL_COLORDODGE_KHR 0x9299
+#define GL_COLORBURN_KHR 0x929A
+#define GL_HARDLIGHT_KHR 0x929B
+#define GL_SOFTLIGHT_KHR 0x929C
+#define GL_DIFFERENCE_KHR 0x929E
+#define GL_EXCLUSION_KHR 0x92A0
+#define GL_HSL_HUE_KHR 0x92AD
+#define GL_HSL_SATURATION_KHR 0x92AE
+#define GL_HSL_COLOR_KHR 0x92AF
+#define GL_HSL_LUMINOSITY_KHR 0x92B0
+typedef void (APIENTRYP PFNGLBLENDBARRIERKHRPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendBarrierKHR (void);
+#endif
+#endif /* GL_KHR_blend_equation_advanced */
+
+#ifndef GL_KHR_blend_equation_advanced_coherent
+#define GL_KHR_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
+#endif /* GL_KHR_blend_equation_advanced_coherent */
+
+#ifndef GL_KHR_context_flush_control
+#define GL_KHR_context_flush_control 1
+#endif /* GL_KHR_context_flush_control */
+
#ifndef GL_KHR_debug
#define GL_KHR_debug 1
#endif /* GL_KHR_debug */
+#ifndef GL_KHR_no_error
+#define GL_KHR_no_error 1
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
+#endif /* GL_KHR_no_error */
+
+#ifndef GL_KHR_robust_buffer_access_behavior
+#define GL_KHR_robust_buffer_access_behavior 1
+#endif /* GL_KHR_robust_buffer_access_behavior */
+
+#ifndef GL_KHR_robustness
+#define GL_KHR_robustness 1
+#define GL_CONTEXT_ROBUST_ACCESS 0x90F3
+#endif /* GL_KHR_robustness */
+
#ifndef GL_KHR_texture_compression_astc_hdr
#define GL_KHR_texture_compression_astc_hdr 1
#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
@@ -4411,6 +4979,10 @@ GLAPI void APIENTRY glWindowPos3svARB (const GLshort *v);
#define GL_KHR_texture_compression_astc_ldr 1
#endif /* GL_KHR_texture_compression_astc_ldr */
+#ifndef GL_KHR_texture_compression_astc_sliced_3d
+#define GL_KHR_texture_compression_astc_sliced_3d 1
+#endif /* GL_KHR_texture_compression_astc_sliced_3d */
+
#ifndef GL_OES_byte_coordinates
#define GL_OES_byte_coordinates 1
typedef void (APIENTRYP PFNGLMULTITEXCOORD1BOESPROC) (GLenum texture, GLbyte s);
@@ -4429,11 +5001,11 @@ typedef void (APIENTRYP PFNGLTEXCOORD3BOESPROC) (GLbyte s, GLbyte t, GLbyte r);
typedef void (APIENTRYP PFNGLTEXCOORD3BVOESPROC) (const GLbyte *coords);
typedef void (APIENTRYP PFNGLTEXCOORD4BOESPROC) (GLbyte s, GLbyte t, GLbyte r, GLbyte q);
typedef void (APIENTRYP PFNGLTEXCOORD4BVOESPROC) (const GLbyte *coords);
-typedef void (APIENTRYP PFNGLVERTEX2BOESPROC) (GLbyte x);
+typedef void (APIENTRYP PFNGLVERTEX2BOESPROC) (GLbyte x, GLbyte y);
typedef void (APIENTRYP PFNGLVERTEX2BVOESPROC) (const GLbyte *coords);
-typedef void (APIENTRYP PFNGLVERTEX3BOESPROC) (GLbyte x, GLbyte y);
+typedef void (APIENTRYP PFNGLVERTEX3BOESPROC) (GLbyte x, GLbyte y, GLbyte z);
typedef void (APIENTRYP PFNGLVERTEX3BVOESPROC) (const GLbyte *coords);
-typedef void (APIENTRYP PFNGLVERTEX4BOESPROC) (GLbyte x, GLbyte y, GLbyte z);
+typedef void (APIENTRYP PFNGLVERTEX4BOESPROC) (GLbyte x, GLbyte y, GLbyte z, GLbyte w);
typedef void (APIENTRYP PFNGLVERTEX4BVOESPROC) (const GLbyte *coords);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glMultiTexCoord1bOES (GLenum texture, GLbyte s);
@@ -4452,11 +5024,11 @@ GLAPI void APIENTRY glTexCoord3bOES (GLbyte s, GLbyte t, GLbyte r);
GLAPI void APIENTRY glTexCoord3bvOES (const GLbyte *coords);
GLAPI void APIENTRY glTexCoord4bOES (GLbyte s, GLbyte t, GLbyte r, GLbyte q);
GLAPI void APIENTRY glTexCoord4bvOES (const GLbyte *coords);
-GLAPI void APIENTRY glVertex2bOES (GLbyte x);
+GLAPI void APIENTRY glVertex2bOES (GLbyte x, GLbyte y);
GLAPI void APIENTRY glVertex2bvOES (const GLbyte *coords);
-GLAPI void APIENTRY glVertex3bOES (GLbyte x, GLbyte y);
+GLAPI void APIENTRY glVertex3bOES (GLbyte x, GLbyte y, GLbyte z);
GLAPI void APIENTRY glVertex3bvOES (const GLbyte *coords);
-GLAPI void APIENTRY glVertex4bOES (GLbyte x, GLbyte y, GLbyte z);
+GLAPI void APIENTRY glVertex4bOES (GLbyte x, GLbyte y, GLbyte z, GLbyte w);
GLAPI void APIENTRY glVertex4bvOES (const GLbyte *coords);
#endif
#endif /* GL_OES_byte_coordinates */
@@ -4508,7 +5080,6 @@ typedef void (APIENTRYP PFNGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfix
typedef void (APIENTRYP PFNGLPOINTSIZEXOESPROC) (GLfixed size);
typedef void (APIENTRYP PFNGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units);
typedef void (APIENTRYP PFNGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
-typedef void (APIENTRYP PFNGLSAMPLECOVERAGEOESPROC) (GLfixed value, GLboolean invert);
typedef void (APIENTRYP PFNGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
typedef void (APIENTRYP PFNGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param);
typedef void (APIENTRYP PFNGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
@@ -4613,7 +5184,6 @@ GLAPI void APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params);
GLAPI void APIENTRY glPointSizexOES (GLfixed size);
GLAPI void APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units);
GLAPI void APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
-GLAPI void APIENTRY glSampleCoverageOES (GLfixed value, GLboolean invert);
GLAPI void APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z);
GLAPI void APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param);
GLAPI void APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params);
@@ -6327,7 +6897,7 @@ typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaob
typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
-typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) (GLuint vaobj, GLuint index, GLuint divisor);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m);
@@ -6583,7 +7153,7 @@ GLAPI void APIENTRY glVertexArrayVertexAttribLFormatEXT (GLuint vaobj, GLuint at
GLAPI void APIENTRY glVertexArrayVertexAttribBindingEXT (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
GLAPI void APIENTRY glVertexArrayVertexBindingDivisorEXT (GLuint vaobj, GLuint bindingindex, GLuint divisor);
GLAPI void APIENTRY glVertexArrayVertexAttribLOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
-GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
GLAPI void APIENTRY glVertexArrayVertexAttribDivisorEXT (GLuint vaobj, GLuint index, GLuint divisor);
#endif
#endif /* GL_EXT_direct_state_access */
@@ -7109,6 +7679,19 @@ GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat factor, GLfloat bias);
#endif
#endif /* GL_EXT_polygon_offset */
+#ifndef GL_EXT_polygon_offset_clamp
+#define GL_EXT_polygon_offset_clamp 1
+#define GL_POLYGON_OFFSET_CLAMP_EXT 0x8E1B
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETCLAMPEXTPROC) (GLfloat factor, GLfloat units, GLfloat clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPolygonOffsetClampEXT (GLfloat factor, GLfloat units, GLfloat clamp);
+#endif
+#endif /* GL_EXT_polygon_offset_clamp */
+
+#ifndef GL_EXT_post_depth_coverage
+#define GL_EXT_post_depth_coverage 1
+#endif /* GL_EXT_post_depth_coverage */
+
#ifndef GL_EXT_provoking_vertex
#define GL_EXT_provoking_vertex 1
#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
@@ -7121,6 +7704,20 @@ GLAPI void APIENTRY glProvokingVertexEXT (GLenum mode);
#endif
#endif /* GL_EXT_provoking_vertex */
+#ifndef GL_EXT_raster_multisample
+#define GL_EXT_raster_multisample 1
+#define GL_RASTER_MULTISAMPLE_EXT 0x9327
+#define GL_RASTER_SAMPLES_EXT 0x9328
+#define GL_MAX_RASTER_SAMPLES_EXT 0x9329
+#define GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A
+#define GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B
+#define GL_EFFECTIVE_RASTER_SAMPLES_EXT 0x932C
+typedef void (APIENTRYP PFNGLRASTERSAMPLESEXTPROC) (GLuint samples, GLboolean fixedsamplelocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRasterSamplesEXT (GLuint samples, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_EXT_raster_multisample */
+
#ifndef GL_EXT_rescale_normal
#define GL_EXT_rescale_normal 1
#define GL_RESCALE_NORMAL_EXT 0x803A
@@ -7275,6 +7872,10 @@ GLAPI void APIENTRY glMemoryBarrierEXT (GLbitfield barriers);
#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
#endif /* GL_EXT_shared_texture_palette */
+#ifndef GL_EXT_sparse_texture2
+#define GL_EXT_sparse_texture2 1
+#endif /* GL_EXT_sparse_texture2 */
+
#ifndef GL_EXT_stencil_clear_tag
#define GL_EXT_stencil_clear_tag 1
#define GL_STENCIL_TAG_BITS_EXT 0x88F2
@@ -7387,6 +7988,10 @@ GLAPI void APIENTRY glTexSubImage3DEXT (GLenum target, GLint level, GLint xoffse
#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
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+#endif
#endif /* GL_EXT_texture_array */
#ifndef GL_EXT_texture_buffer_object
@@ -7483,6 +8088,10 @@ GLAPI void APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#endif /* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_minmax
+#define GL_EXT_texture_filter_minmax 1
+#endif /* GL_EXT_texture_filter_minmax */
+
#ifndef GL_EXT_texture_integer
#define GL_EXT_texture_integer 1
#define GL_RGBA32UI_EXT 0x8D70
@@ -8208,6 +8817,14 @@ GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRG
#define GL_INTEL_fragment_shader_ordering 1
#endif /* GL_INTEL_fragment_shader_ordering */
+#ifndef GL_INTEL_framebuffer_CMAA
+#define GL_INTEL_framebuffer_CMAA 1
+typedef void (APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void);
+#endif
+#endif /* GL_INTEL_framebuffer_CMAA */
+
#ifndef GL_INTEL_map_texture
#define GL_INTEL_map_texture 1
#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF
@@ -8402,6 +9019,16 @@ GLAPI void APIENTRY glMultiDrawElementsIndirectBindlessNV (GLenum mode, GLenum t
#endif
#endif /* GL_NV_bindless_multi_draw_indirect */
+#ifndef GL_NV_bindless_multi_draw_indirect_count
+#define GL_NV_bindless_multi_draw_indirect_count 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSCOUNTNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSCOUNTNVPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectBindlessCountNV (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount);
+GLAPI void APIENTRY glMultiDrawElementsIndirectBindlessCountNV (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei maxDrawCount, GLsizei stride, GLint vertexBufferCount);
+#endif
+#endif /* GL_NV_bindless_multi_draw_indirect_count */
+
#ifndef GL_NV_bindless_texture
#define GL_NV_bindless_texture 1
typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
@@ -8502,6 +9129,65 @@ GLAPI void APIENTRY glBlendBarrierNV (void);
#define GL_NV_blend_square 1
#endif /* GL_NV_blend_square */
+#ifndef GL_NV_command_list
+#define GL_NV_command_list 1
+#define GL_TERMINATE_SEQUENCE_COMMAND_NV 0x0000
+#define GL_NOP_COMMAND_NV 0x0001
+#define GL_DRAW_ELEMENTS_COMMAND_NV 0x0002
+#define GL_DRAW_ARRAYS_COMMAND_NV 0x0003
+#define GL_DRAW_ELEMENTS_STRIP_COMMAND_NV 0x0004
+#define GL_DRAW_ARRAYS_STRIP_COMMAND_NV 0x0005
+#define GL_DRAW_ELEMENTS_INSTANCED_COMMAND_NV 0x0006
+#define GL_DRAW_ARRAYS_INSTANCED_COMMAND_NV 0x0007
+#define GL_ELEMENT_ADDRESS_COMMAND_NV 0x0008
+#define GL_ATTRIBUTE_ADDRESS_COMMAND_NV 0x0009
+#define GL_UNIFORM_ADDRESS_COMMAND_NV 0x000A
+#define GL_BLEND_COLOR_COMMAND_NV 0x000B
+#define GL_STENCIL_REF_COMMAND_NV 0x000C
+#define GL_LINE_WIDTH_COMMAND_NV 0x000D
+#define GL_POLYGON_OFFSET_COMMAND_NV 0x000E
+#define GL_ALPHA_REF_COMMAND_NV 0x000F
+#define GL_VIEWPORT_COMMAND_NV 0x0010
+#define GL_SCISSOR_COMMAND_NV 0x0011
+#define GL_FRONT_FACE_COMMAND_NV 0x0012
+typedef void (APIENTRYP PFNGLCREATESTATESNVPROC) (GLsizei n, GLuint *states);
+typedef void (APIENTRYP PFNGLDELETESTATESNVPROC) (GLsizei n, const GLuint *states);
+typedef GLboolean (APIENTRYP PFNGLISSTATENVPROC) (GLuint state);
+typedef void (APIENTRYP PFNGLSTATECAPTURENVPROC) (GLuint state, GLenum mode);
+typedef GLuint (APIENTRYP PFNGLGETCOMMANDHEADERNVPROC) (GLenum tokenID, GLuint size);
+typedef GLushort (APIENTRYP PFNGLGETSTAGEINDEXNVPROC) (GLenum shadertype);
+typedef void (APIENTRYP PFNGLDRAWCOMMANDSNVPROC) (GLenum primitiveMode, GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, GLuint count);
+typedef void (APIENTRYP PFNGLDRAWCOMMANDSADDRESSNVPROC) (GLenum primitiveMode, const GLuint64 *indirects, const GLsizei *sizes, GLuint count);
+typedef void (APIENTRYP PFNGLDRAWCOMMANDSSTATESNVPROC) (GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+typedef void (APIENTRYP PFNGLDRAWCOMMANDSSTATESADDRESSNVPROC) (const GLuint64 *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+typedef void (APIENTRYP PFNGLCREATECOMMANDLISTSNVPROC) (GLsizei n, GLuint *lists);
+typedef void (APIENTRYP PFNGLDELETECOMMANDLISTSNVPROC) (GLsizei n, const GLuint *lists);
+typedef GLboolean (APIENTRYP PFNGLISCOMMANDLISTNVPROC) (GLuint list);
+typedef void (APIENTRYP PFNGLLISTDRAWCOMMANDSSTATESCLIENTNVPROC) (GLuint list, GLuint segment, const void **indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+typedef void (APIENTRYP PFNGLCOMMANDLISTSEGMENTSNVPROC) (GLuint list, GLuint segments);
+typedef void (APIENTRYP PFNGLCOMPILECOMMANDLISTNVPROC) (GLuint list);
+typedef void (APIENTRYP PFNGLCALLCOMMANDLISTNVPROC) (GLuint list);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCreateStatesNV (GLsizei n, GLuint *states);
+GLAPI void APIENTRY glDeleteStatesNV (GLsizei n, const GLuint *states);
+GLAPI GLboolean APIENTRY glIsStateNV (GLuint state);
+GLAPI void APIENTRY glStateCaptureNV (GLuint state, GLenum mode);
+GLAPI GLuint APIENTRY glGetCommandHeaderNV (GLenum tokenID, GLuint size);
+GLAPI GLushort APIENTRY glGetStageIndexNV (GLenum shadertype);
+GLAPI void APIENTRY glDrawCommandsNV (GLenum primitiveMode, GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, GLuint count);
+GLAPI void APIENTRY glDrawCommandsAddressNV (GLenum primitiveMode, const GLuint64 *indirects, const GLsizei *sizes, GLuint count);
+GLAPI void APIENTRY glDrawCommandsStatesNV (GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+GLAPI void APIENTRY glDrawCommandsStatesAddressNV (const GLuint64 *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+GLAPI void APIENTRY glCreateCommandListsNV (GLsizei n, GLuint *lists);
+GLAPI void APIENTRY glDeleteCommandListsNV (GLsizei n, const GLuint *lists);
+GLAPI GLboolean APIENTRY glIsCommandListNV (GLuint list);
+GLAPI void APIENTRY glListDrawCommandsStatesClientNV (GLuint list, GLuint segment, const void **indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+GLAPI void APIENTRY glCommandListSegmentsNV (GLuint list, GLuint segments);
+GLAPI void APIENTRY glCompileCommandListNV (GLuint list);
+GLAPI void APIENTRY glCallCommandListNV (GLuint list);
+#endif
+#endif /* GL_NV_command_list */
+
#ifndef GL_NV_compute_program5
#define GL_NV_compute_program5 1
#define GL_COMPUTE_PROGRAM_NV 0x90FB
@@ -8522,6 +9208,29 @@ GLAPI void APIENTRY glEndConditionalRenderNV (void);
#endif
#endif /* GL_NV_conditional_render */
+#ifndef GL_NV_conservative_raster
+#define GL_NV_conservative_raster 1
+#define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346
+#define GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV 0x9347
+#define GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV 0x9348
+#define GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV 0x9349
+typedef void (APIENTRYP PFNGLSUBPIXELPRECISIONBIASNVPROC) (GLuint xbits, GLuint ybits);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits);
+#endif
+#endif /* GL_NV_conservative_raster */
+
+#ifndef GL_NV_conservative_raster_dilate
+#define GL_NV_conservative_raster_dilate 1
+#define GL_CONSERVATIVE_RASTER_DILATE_NV 0x9379
+#define GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV 0x937A
+#define GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV 0x937B
+typedef void (APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERFNVPROC) (GLenum pname, GLfloat value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glConservativeRasterParameterfNV (GLenum pname, GLfloat value);
+#endif
+#endif /* GL_NV_conservative_raster_dilate */
+
#ifndef GL_NV_copy_depth_to_color
#define GL_NV_copy_depth_to_color 1
#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
@@ -8664,6 +9373,11 @@ GLAPI void APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
#endif
#endif /* GL_NV_fence */
+#ifndef GL_NV_fill_rectangle
+#define GL_NV_fill_rectangle 1
+#define GL_FILL_RECTANGLE_NV 0x933C
+#endif /* GL_NV_fill_rectangle */
+
#ifndef GL_NV_float_buffer
#define GL_NV_float_buffer 1
#define GL_FLOAT_R_NV 0x8880
@@ -8690,6 +9404,16 @@ GLAPI void APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
#endif /* GL_NV_fog_distance */
+#ifndef GL_NV_fragment_coverage_to_color
+#define GL_NV_fragment_coverage_to_color 1
+#define GL_FRAGMENT_COVERAGE_TO_COLOR_NV 0x92DD
+#define GL_FRAGMENT_COVERAGE_COLOR_NV 0x92DE
+typedef void (APIENTRYP PFNGLFRAGMENTCOVERAGECOLORNVPROC) (GLuint color);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFragmentCoverageColorNV (GLuint color);
+#endif
+#endif /* GL_NV_fragment_coverage_to_color */
+
#ifndef GL_NV_fragment_program
#define GL_NV_fragment_program 1
#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
@@ -8731,6 +9455,30 @@ GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, cons
#define GL_NV_fragment_program_option 1
#endif /* GL_NV_fragment_program_option */
+#ifndef GL_NV_fragment_shader_interlock
+#define GL_NV_fragment_shader_interlock 1
+#endif /* GL_NV_fragment_shader_interlock */
+
+#ifndef GL_NV_framebuffer_mixed_samples
+#define GL_NV_framebuffer_mixed_samples 1
+#define GL_COVERAGE_MODULATION_TABLE_NV 0x9331
+#define GL_COLOR_SAMPLES_NV 0x8E20
+#define GL_DEPTH_SAMPLES_NV 0x932D
+#define GL_STENCIL_SAMPLES_NV 0x932E
+#define GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV 0x932F
+#define GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV 0x9330
+#define GL_COVERAGE_MODULATION_NV 0x9332
+#define GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333
+typedef void (APIENTRYP PFNGLCOVERAGEMODULATIONTABLENVPROC) (GLsizei n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufsize, GLfloat *v);
+typedef void (APIENTRYP PFNGLCOVERAGEMODULATIONNVPROC) (GLenum components);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCoverageModulationTableNV (GLsizei n, const GLfloat *v);
+GLAPI void APIENTRY glGetCoverageModulationTableNV (GLsizei bufsize, GLfloat *v);
+GLAPI void APIENTRY glCoverageModulationNV (GLenum components);
+#endif
+#endif /* GL_NV_framebuffer_mixed_samples */
+
#ifndef GL_NV_framebuffer_multisample_coverage
#define GL_NV_framebuffer_multisample_coverage 1
#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
@@ -8750,12 +9498,10 @@ GLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum target, G
#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28
typedef void (APIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit);
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
-typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glProgramVertexLimitNV (GLenum target, GLint limit);
GLAPI void APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level);
-GLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
#endif
#endif /* GL_NV_geometry_program4 */
@@ -8764,6 +9510,10 @@ GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachmen
#define GL_NV_geometry_shader4 1
#endif /* GL_NV_geometry_shader4 */
+#ifndef GL_NV_geometry_shader_passthrough
+#define GL_NV_geometry_shader_passthrough 1
+#endif /* GL_NV_geometry_shader_passthrough */
+
#ifndef GL_NV_gpu_program4
#define GL_NV_gpu_program4 1
#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904
@@ -8936,6 +9686,18 @@ GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfN
#endif
#endif /* GL_NV_half_float */
+#ifndef GL_NV_internalformat_sample_query
+#define GL_NV_internalformat_sample_query 1
+#define GL_MULTISAMPLES_NV 0x9371
+#define GL_SUPERSAMPLE_SCALE_X_NV 0x9372
+#define GL_SUPERSAMPLE_SCALE_Y_NV 0x9373
+#define GL_CONFORMANT_NV 0x9374
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_NV_internalformat_sample_query */
+
#ifndef GL_NV_light_max_exponent
#define GL_NV_light_max_exponent 1
#define GL_MAX_SHININESS_NV 0x8504
@@ -8944,7 +9706,6 @@ GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfN
#ifndef GL_NV_multisample_coverage
#define GL_NV_multisample_coverage 1
-#define GL_COLOR_SAMPLES_NV 0x8E20
#endif /* GL_NV_multisample_coverage */
#ifndef GL_NV_multisample_filter_hint
@@ -9057,13 +9818,11 @@ GLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum target, GLuint bindi
#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
#define GL_USE_MISSING_GLYPH_NV 0x90AA
#define GL_PATH_ERROR_POSITION_NV 0x90AB
-#define GL_PATH_FOG_GEN_MODE_NV 0x90AC
#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
#define GL_ADJACENT_PAIRS_NV 0x90AE
#define GL_FIRST_TO_REST_NV 0x90AF
#define GL_PATH_GEN_MODE_NV 0x90B0
#define GL_PATH_GEN_COEFF_NV 0x90B1
-#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
#define GL_PATH_STENCIL_FUNC_NV 0x90B7
#define GL_PATH_STENCIL_REF_NV 0x90B8
@@ -9132,8 +9891,44 @@ GLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum target, GLuint bindi
#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+#define GL_ROUNDED_RECT_NV 0xE8
+#define GL_RELATIVE_ROUNDED_RECT_NV 0xE9
+#define GL_ROUNDED_RECT2_NV 0xEA
+#define GL_RELATIVE_ROUNDED_RECT2_NV 0xEB
+#define GL_ROUNDED_RECT4_NV 0xEC
+#define GL_RELATIVE_ROUNDED_RECT4_NV 0xED
+#define GL_ROUNDED_RECT8_NV 0xEE
+#define GL_RELATIVE_ROUNDED_RECT8_NV 0xEF
+#define GL_RELATIVE_RECT_NV 0xF7
+#define GL_FONT_GLYPHS_AVAILABLE_NV 0x9368
+#define GL_FONT_TARGET_UNAVAILABLE_NV 0x9369
+#define GL_FONT_UNAVAILABLE_NV 0x936A
+#define GL_FONT_UNINTELLIGIBLE_NV 0x936B
+#define GL_CONIC_CURVE_TO_NV 0x1A
+#define GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B
+#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000
+#define GL_STANDARD_FONT_FORMAT_NV 0x936C
+#define GL_2_BYTES_NV 0x1407
+#define GL_3_BYTES_NV 0x1408
+#define GL_4_BYTES_NV 0x1409
+#define GL_EYE_LINEAR_NV 0x2400
+#define GL_OBJECT_LINEAR_NV 0x2401
+#define GL_CONSTANT_NV 0x8576
+#define GL_PATH_FOG_GEN_MODE_NV 0x90AC
#define GL_PRIMARY_COLOR_NV 0x852C
#define GL_SECONDARY_COLOR_NV 0x852D
+#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
+#define GL_PATH_PROJECTION_NV 0x1701
+#define GL_PATH_MODELVIEW_NV 0x1700
+#define GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3
+#define GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6
+#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36
+#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3
+#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4
+#define GL_PATH_PROJECTION_MATRIX_NV 0x0BA7
+#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38
+#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4
+#define GL_FRAGMENT_INPUT_NV 0x936D
typedef GLuint (APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range);
typedef void (APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
typedef GLboolean (APIENTRYP PFNGLISPATHNVPROC) (GLuint path);
@@ -9160,9 +9955,6 @@ typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint refere
typedef void (APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
typedef void (APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func);
-typedef void (APIENTRYP PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
-typedef void (APIENTRYP PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
-typedef void (APIENTRYP PFNGLPATHFOGGENNVPROC) (GLenum genMode);
typedef void (APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
typedef void (APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode);
typedef void (APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
@@ -9175,14 +9967,32 @@ typedef void (APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dash
typedef void (APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
typedef void (APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
typedef void (APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
-typedef void (APIENTRYP PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint *value);
-typedef void (APIENTRYP PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat *value);
-typedef void (APIENTRYP PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint *value);
-typedef void (APIENTRYP PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat *value);
typedef GLboolean (APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
typedef GLboolean (APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
typedef GLfloat (APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
typedef GLboolean (APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+typedef void (APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef GLenum (APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (APIENTRYP PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLPATHFOGGENNVPROC) (GLenum genMode);
+typedef void (APIENTRYP PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat *value);
+typedef void (APIENTRYP PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat *value);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI GLuint APIENTRY glGenPathsNV (GLsizei range);
GLAPI void APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
@@ -9210,9 +10020,6 @@ GLAPI void APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint
GLAPI void APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
GLAPI void APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
GLAPI void APIENTRY glPathCoverDepthFuncNV (GLenum func);
-GLAPI void APIENTRY glPathColorGenNV (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
-GLAPI void APIENTRY glPathTexGenNV (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
-GLAPI void APIENTRY glPathFogGenNV (GLenum genMode);
GLAPI void APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode);
GLAPI void APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode);
GLAPI void APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
@@ -9225,17 +10032,40 @@ GLAPI void APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray);
GLAPI void APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
GLAPI void APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
GLAPI void APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
-GLAPI void APIENTRY glGetPathColorGenivNV (GLenum color, GLenum pname, GLint *value);
-GLAPI void APIENTRY glGetPathColorGenfvNV (GLenum color, GLenum pname, GLfloat *value);
-GLAPI void APIENTRY glGetPathTexGenivNV (GLenum texCoordSet, GLenum pname, GLint *value);
-GLAPI void APIENTRY glGetPathTexGenfvNV (GLenum texCoordSet, GLenum pname, GLfloat *value);
GLAPI GLboolean APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y);
GLAPI GLboolean APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y);
GLAPI GLfloat APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments);
GLAPI GLboolean APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+GLAPI void APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GLAPI void APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+GLAPI void APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+GLAPI void APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI GLenum APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+GLAPI GLenum APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI GLenum APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI void APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+GLAPI void APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GLAPI void APIENTRY glPathColorGenNV (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
+GLAPI void APIENTRY glPathTexGenNV (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
+GLAPI void APIENTRY glPathFogGenNV (GLenum genMode);
+GLAPI void APIENTRY glGetPathColorGenivNV (GLenum color, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathColorGenfvNV (GLenum color, GLenum pname, GLfloat *value);
+GLAPI void APIENTRY glGetPathTexGenivNV (GLenum texCoordSet, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathTexGenfvNV (GLenum texCoordSet, GLenum pname, GLfloat *value);
#endif
#endif /* GL_NV_path_rendering */
+#ifndef GL_NV_path_rendering_shared_edge
+#define GL_NV_path_rendering_shared_edge 1
+#define GL_SHARED_EDGE_NV 0xC0
+#endif /* GL_NV_path_rendering_shared_edge */
+
#ifndef GL_NV_pixel_data_range
#define GL_NV_pixel_data_range 1
#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
@@ -9393,6 +10223,30 @@ GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname,
#endif
#endif /* GL_NV_register_combiners2 */
+#ifndef GL_NV_sample_locations
+#define GL_NV_sample_locations 1
+#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV 0x933E
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV 0x933F
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV 0x9340
+#define GL_SAMPLE_LOCATION_NV 0x8E50
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9341
+#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV 0x9342
+#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV 0x9343
+typedef void (APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLRESOLVEDEPTHVALUESNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferSampleLocationsfvNV (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glNamedFramebufferSampleLocationsfvNV (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glResolveDepthValuesNV (void);
+#endif
+#endif /* GL_NV_sample_locations */
+
+#ifndef GL_NV_sample_mask_override_coverage
+#define GL_NV_sample_mask_override_coverage 1
+#endif /* GL_NV_sample_mask_override_coverage */
+
#ifndef GL_NV_shader_atomic_counters
#define GL_NV_shader_atomic_counters 1
#endif /* GL_NV_shader_atomic_counters */
@@ -9401,6 +10255,14 @@ GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname,
#define GL_NV_shader_atomic_float 1
#endif /* GL_NV_shader_atomic_float */
+#ifndef GL_NV_shader_atomic_fp16_vector
+#define GL_NV_shader_atomic_fp16_vector 1
+#endif /* GL_NV_shader_atomic_fp16_vector */
+
+#ifndef GL_NV_shader_atomic_int64
+#define GL_NV_shader_atomic_int64 1
+#endif /* GL_NV_shader_atomic_int64 */
+
#ifndef GL_NV_shader_buffer_load
#define GL_NV_shader_buffer_load 1
#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D
@@ -9670,7 +10532,7 @@ GLAPI void APIENTRY glTextureImage3DMultisampleCoverageNV (GLuint texture, GLenu
#define GL_SKIP_COMPONENTS1_NV -6
typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode);
typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void);
-typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLsizei count, const GLint *attribs, GLenum bufferMode);
typedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
typedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer);
@@ -9683,7 +10545,7 @@ typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC) (GLsizei coun
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glBeginTransformFeedbackNV (GLenum primitiveMode);
GLAPI void APIENTRY glEndTransformFeedbackNV (void);
-GLAPI void APIENTRY glTransformFeedbackAttribsNV (GLuint count, const GLint *attribs, GLenum bufferMode);
+GLAPI void APIENTRY glTransformFeedbackAttribsNV (GLsizei count, const GLint *attribs, GLenum bufferMode);
GLAPI void APIENTRY glBindBufferRangeNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
GLAPI void APIENTRY glBindBufferOffsetNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
GLAPI void APIENTRY glBindBufferBaseNV (GLenum target, GLuint index, GLuint buffer);
@@ -9720,6 +10582,13 @@ GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id);
#endif
#endif /* GL_NV_transform_feedback2 */
+#ifndef GL_NV_uniform_buffer_unified_memory
+#define GL_NV_uniform_buffer_unified_memory 1
+#define GL_UNIFORM_BUFFER_UNIFIED_NV 0x936E
+#define GL_UNIFORM_BUFFER_ADDRESS_NV 0x936F
+#define GL_UNIFORM_BUFFER_LENGTH_NV 0x9370
+#endif /* GL_NV_uniform_buffer_unified_memory */
+
#ifndef GL_NV_vdpau_interop
#define GL_NV_vdpau_interop 1
typedef GLintptr GLvdpauSurfaceNV;
@@ -10215,6 +11084,10 @@ GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot
#endif
#endif /* GL_NV_video_capture */
+#ifndef GL_NV_viewport_array2
+#define GL_NV_viewport_array2 1
+#endif /* GL_NV_viewport_array2 */
+
#ifndef GL_OML_interlace
#define GL_OML_interlace 1
#define GL_INTERLACE_OML 0x8980
@@ -10237,6 +11110,21 @@ GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot
#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
#endif /* GL_OML_subsample */
+#ifndef GL_OVR_multiview
+#define GL_OVR_multiview 1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
+#define GL_MAX_VIEWS_OVR 0x9631
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview */
+
+#ifndef GL_OVR_multiview2
+#define GL_OVR_multiview2 1
+#endif /* GL_OVR_multiview2 */
+
#ifndef GL_PGI_misc_hints
#define GL_PGI_misc_hints 1
#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8
@@ -10793,10 +11681,10 @@ GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *equation);
#ifndef GL_SGIX_resample
#define GL_SGIX_resample 1
-#define GL_PACK_RESAMPLE_SGIX 0x842C
-#define GL_UNPACK_RESAMPLE_SGIX 0x842D
-#define GL_RESAMPLE_REPLICATE_SGIX 0x842E
-#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F
+#define GL_PACK_RESAMPLE_SGIX 0x842E
+#define GL_UNPACK_RESAMPLE_SGIX 0x842F
+#define GL_RESAMPLE_REPLICATE_SGIX 0x8433
+#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434
#define GL_RESAMPLE_DECIMATE_SGIX 0x8430
#endif /* GL_SGIX_resample */
diff --git a/thirdparty/khronos/GL/glxext.h b/thirdparty/khronos/GL/glxext.h
index 7437d148..227045ad 100644
--- a/thirdparty/khronos/GL/glxext.h
+++ b/thirdparty/khronos/GL/glxext.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -33,10 +33,10 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
-** Khronos $Revision: 26290 $ on $Date: 2014-04-16 05:35:38 -0700 (Wed, 16 Apr 2014) $
+** Khronos $Revision: 31597 $ on $Date: 2015-06-25 16:32:35 -0400 (Thu, 25 Jun 2015) $
*/
-#define GLX_GLXEXT_VERSION 20140416
+#define GLX_GLXEXT_VERSION 20150623
/* Generated C header for:
* API: glx
@@ -158,6 +158,13 @@ __GLXextFuncPtr glXGetProcAddress (const GLubyte *procName);
#endif
#endif /* GLX_VERSION_1_4 */
+#ifndef GLX_ARB_context_flush_control
+#define GLX_ARB_context_flush_control 1
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#endif /* GLX_ARB_context_flush_control */
+
#ifndef GLX_ARB_create_context
#define GLX_ARB_create_context 1
#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
@@ -243,6 +250,26 @@ __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *procName);
#define GLX_GPU_NUM_SIMD_AMD 0x21A6
#define GLX_GPU_NUM_RB_AMD 0x21A7
#define GLX_GPU_NUM_SPI_AMD 0x21A8
+typedef unsigned int ( *PFNGLXGETGPUIDSAMDPROC) (unsigned int maxCount, unsigned int *ids);
+typedef int ( *PFNGLXGETGPUINFOAMDPROC) (unsigned int id, int property, GLenum dataType, unsigned int size, void *data);
+typedef unsigned int ( *PFNGLXGETCONTEXTGPUIDAMDPROC) (GLXContext ctx);
+typedef GLXContext ( *PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC) (unsigned int id, GLXContext share_list);
+typedef GLXContext ( *PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (unsigned int id, GLXContext share_context, const int *attribList);
+typedef Bool ( *PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC) (GLXContext ctx);
+typedef Bool ( *PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (GLXContext ctx);
+typedef GLXContext ( *PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void);
+typedef void ( *PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC) (GLXContext dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#ifdef GLX_GLXEXT_PROTOTYPES
+unsigned int glXGetGPUIDsAMD (unsigned int maxCount, unsigned int *ids);
+int glXGetGPUInfoAMD (unsigned int id, int property, GLenum dataType, unsigned int size, void *data);
+unsigned int glXGetContextGPUIDAMD (GLXContext ctx);
+GLXContext glXCreateAssociatedContextAMD (unsigned int id, GLXContext share_list);
+GLXContext glXCreateAssociatedContextAttribsAMD (unsigned int id, GLXContext share_context, const int *attribList);
+Bool glXDeleteAssociatedContextAMD (GLXContext ctx);
+Bool glXMakeAssociatedContextCurrentAMD (GLXContext ctx);
+GLXContext glXGetCurrentAssociatedContextAMD (void);
+void glXBlitContextFramebufferAMD (GLXContext dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
#endif /* GLX_AMD_gpu_association */
#ifndef GLX_EXT_buffer_age
@@ -468,6 +495,16 @@ Bool glXSet3DfxModeMESA (int mode);
#endif
#endif /* GLX_MESA_set_3dfx_mode */
+#ifndef GLX_NV_copy_buffer
+#define GLX_NV_copy_buffer 1
+typedef void ( *PFNGLXCOPYBUFFERSUBDATANVPROC) (Display *dpy, GLXContext readCtx, GLXContext writeCtx, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void ( *PFNGLXNAMEDCOPYBUFFERSUBDATANVPROC) (Display *dpy, GLXContext readCtx, GLXContext writeCtx, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#ifdef GLX_GLXEXT_PROTOTYPES
+void glXCopyBufferSubDataNV (Display *dpy, GLXContext readCtx, GLXContext writeCtx, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+void glXNamedCopyBufferSubDataNV (Display *dpy, GLXContext readCtx, GLXContext writeCtx, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+#endif
+#endif /* GLX_NV_copy_buffer */
+
#ifndef GLX_NV_copy_image
#define GLX_NV_copy_image 1
typedef void ( *PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
@@ -544,8 +581,8 @@ void glXReleaseVideoCaptureDeviceNV (Display *dpy, GLXVideoCaptureDeviceNV devic
#endif
#endif /* GLX_NV_video_capture */
-#ifndef GLX_NV_video_output
-#define GLX_NV_video_output 1
+#ifndef GLX_NV_video_out
+#define GLX_NV_video_out 1
typedef unsigned int GLXVideoDeviceNV;
#define GLX_VIDEO_OUT_COLOR_NV 0x20C3
#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4
@@ -571,7 +608,7 @@ int glXReleaseVideoImageNV (Display *dpy, GLXPbuffer pbuf);
int glXSendPbufferToVideoNV (Display *dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock);
int glXGetVideoInfoNV (Display *dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
#endif
-#endif /* GLX_NV_video_output */
+#endif /* GLX_NV_video_out */
#ifndef GLX_OML_swap_method
#define GLX_OML_swap_method 1
diff --git a/thirdparty/khronos/GL/wglext.h b/thirdparty/khronos/GL/wglext.h
index e9648c37..912e31c6 100644
--- a/thirdparty/khronos/GL/wglext.h
+++ b/thirdparty/khronos/GL/wglext.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -33,7 +33,7 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
-** Khronos $Revision: 26290 $ on $Date: 2014-04-16 05:35:38 -0700 (Wed, 16 Apr 2014) $
+** Khronos $Revision: 31597 $ on $Date: 2015-06-25 16:32:35 -0400 (Thu, 25 Jun 2015) $
*/
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
@@ -41,7 +41,7 @@ extern "C" {
#include <windows.h>
#endif
-#define WGL_WGLEXT_VERSION 20140416
+#define WGL_WGLEXT_VERSION 20150623
/* Generated C header for:
* API: wgl
@@ -70,6 +70,13 @@ BOOL WINAPI wglRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width,
#endif
#endif /* WGL_ARB_buffer_region */
+#ifndef WGL_ARB_context_flush_control
+#define WGL_ARB_context_flush_control 1
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#endif /* WGL_ARB_context_flush_control */
+
#ifndef WGL_ARB_create_context
#define WGL_ARB_create_context 1
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
diff --git a/thirdparty/khronos/GLES2/gl2.h b/thirdparty/khronos/GLES2/gl2.h
index dff0dd1d..07bffb3a 100644
--- a/thirdparty/khronos/GLES2/gl2.h
+++ b/thirdparty/khronos/GLES2/gl2.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -33,12 +33,16 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
-** Khronos $Revision: 26744 $ on $Date: 2014-05-21 03:11:42 -0700 (Wed, 21 May 2014) $
+** Khronos $Revision: 32347 $ on $Date: 2016-01-08 03:01:49 -0800 (Fri, 08 Jan 2016) $
*/
#include <GLES2/gl2platform.h>
-/* Generated on date 20140521 */
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/* Generated on date 20160108 */
/* Generated C header for:
* API: gles2
@@ -374,6 +378,149 @@ typedef khronos_uint8_t GLubyte;
#define GL_RENDERBUFFER_BINDING 0x8CA7
#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
@@ -516,6 +663,7 @@ GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y
GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
#endif /* GL_ES_VERSION_2_0 */
#ifdef __cplusplus
diff --git a/thirdparty/khronos/GLES2/gl2ext.h b/thirdparty/khronos/GLES2/gl2ext.h
index b29b358a..40f09163 100644
--- a/thirdparty/khronos/GLES2/gl2ext.h
+++ b/thirdparty/khronos/GLES2/gl2ext.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -33,14 +33,14 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
-** Khronos $Revision: 26744 $ on $Date: 2014-05-21 03:11:42 -0700 (Wed, 21 May 2014) $
+** Khronos $Revision: 32347 $ on $Date: 2016-01-08 03:01:49 -0800 (Fri, 08 Jan 2016) $
*/
#ifndef GL_APIENTRYP
#define GL_APIENTRYP GL_APIENTRY*
#endif
-/* Generated on date 20140521 */
+/* Generated on date 20160108 */
/* Generated C header for:
* API: gles2
@@ -54,7 +54,6 @@ extern "C" {
#ifndef GL_KHR_blend_equation_advanced
#define GL_KHR_blend_equation_advanced 1
-#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
#define GL_MULTIPLY_KHR 0x9294
#define GL_SCREEN_KHR 0x9295
#define GL_OVERLAY_KHR 0x9296
@@ -76,6 +75,17 @@ GL_APICALL void GL_APIENTRY glBlendBarrierKHR (void);
#endif
#endif /* GL_KHR_blend_equation_advanced */
+#ifndef GL_KHR_blend_equation_advanced_coherent
+#define GL_KHR_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
+#endif /* GL_KHR_blend_equation_advanced_coherent */
+
+#ifndef GL_KHR_context_flush_control
+#define GL_KHR_context_flush_control 1
+#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC
+#endif /* GL_KHR_context_flush_control */
+
#ifndef GL_KHR_debug
#define GL_KHR_debug 1
typedef void (GL_APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
@@ -107,6 +117,7 @@ typedef void (GL_APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,
#define GL_PROGRAM_KHR 0x82E2
#define GL_VERTEX_ARRAY_KHR 0x8074
#define GL_QUERY_KHR 0x82E3
+#define GL_PROGRAM_PIPELINE_KHR 0x82E4
#define GL_SAMPLER_KHR 0x82E6
#define GL_MAX_LABEL_LENGTH_KHR 0x82E8
#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143
@@ -145,6 +156,39 @@ GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, void **params);
#endif
#endif /* GL_KHR_debug */
+#ifndef GL_KHR_no_error
+#define GL_KHR_no_error 1
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
+#endif /* GL_KHR_no_error */
+
+#ifndef GL_KHR_robust_buffer_access_behavior
+#define GL_KHR_robust_buffer_access_behavior 1
+#endif /* GL_KHR_robust_buffer_access_behavior */
+
+#ifndef GL_KHR_robustness
+#define GL_KHR_robustness 1
+#define GL_CONTEXT_ROBUST_ACCESS_KHR 0x90F3
+#define GL_LOSE_CONTEXT_ON_RESET_KHR 0x8252
+#define GL_GUILTY_CONTEXT_RESET_KHR 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_KHR 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_KHR 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256
+#define GL_NO_RESET_NOTIFICATION_KHR 0x8261
+#define GL_CONTEXT_LOST_KHR 0x0507
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsKHR (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvKHR (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivKHR (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GL_APICALL void GL_APIENTRY glGetnUniformuivKHR (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+#endif
+#endif /* GL_KHR_robustness */
+
#ifndef GL_KHR_texture_compression_astc_hdr
#define GL_KHR_texture_compression_astc_hdr 1
#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
@@ -181,6 +225,10 @@ GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, void **params);
#define GL_KHR_texture_compression_astc_ldr 1
#endif /* GL_KHR_texture_compression_astc_ldr */
+#ifndef GL_KHR_texture_compression_astc_sliced_3d
+#define GL_KHR_texture_compression_astc_sliced_3d 1
+#endif /* GL_KHR_texture_compression_astc_sliced_3d */
+
#ifndef GL_OES_EGL_image
#define GL_OES_EGL_image 1
typedef void *GLeglImageOES;
@@ -200,6 +248,14 @@ GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum targe
#define GL_SAMPLER_EXTERNAL_OES 0x8D66
#endif /* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external_essl3
+#define GL_OES_EGL_image_external_essl3 1
+#endif /* GL_OES_EGL_image_external_essl3 */
+
+#ifndef GL_OES_compressed_ETC1_RGB8_sub_texture
+#define GL_OES_compressed_ETC1_RGB8_sub_texture 1
+#endif /* GL_OES_compressed_ETC1_RGB8_sub_texture */
+
#ifndef GL_OES_compressed_ETC1_RGB8_texture
#define GL_OES_compressed_ETC1_RGB8_texture 1
#define GL_ETC1_RGB8_OES 0x8D64
@@ -219,6 +275,14 @@ GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum targe
#define GL_PALETTE8_RGB5_A1_OES 0x8B99
#endif /* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_copy_image
+#define GL_OES_copy_image 1
+typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAOESPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyImageSubDataOES (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#endif
+#endif /* GL_OES_copy_image */
+
#ifndef GL_OES_depth24
#define GL_OES_depth24 1
#define GL_DEPTH_COMPONENT24_OES 0x81A6
@@ -233,6 +297,44 @@ GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum targe
#define GL_OES_depth_texture 1
#endif /* GL_OES_depth_texture */
+#ifndef GL_OES_draw_buffers_indexed
+#define GL_OES_draw_buffers_indexed 1
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+typedef void (GL_APIENTRYP PFNGLENABLEIOESPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEIOESPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIOESPROC) (GLuint buf, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIOESPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCIOESPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIOESPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKIOESPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIOESPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEnableiOES (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiOES (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glBlendEquationiOES (GLuint buf, GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparateiOES (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunciOES (GLuint buf, GLenum src, GLenum dst);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparateiOES (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glColorMaskiOES (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediOES (GLenum target, GLuint index);
+#endif
+#endif /* GL_OES_draw_buffers_indexed */
+
+#ifndef GL_OES_draw_elements_base_vertex
+#define GL_OES_draw_elements_base_vertex 1
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexOES (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexOES (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#endif
+#endif /* GL_OES_draw_elements_base_vertex */
+
#ifndef GL_OES_element_index_uint
#define GL_OES_element_index_uint 1
#endif /* GL_OES_element_index_uint */
@@ -245,6 +347,51 @@ GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum targe
#define GL_OES_fragment_precision_high 1
#endif /* GL_OES_fragment_precision_high */
+#ifndef GL_OES_geometry_point_size
+#define GL_OES_geometry_point_size 1
+#endif /* GL_OES_geometry_point_size */
+
+#ifndef GL_OES_geometry_shader
+#define GL_OES_geometry_shader 1
+#define GL_GEOMETRY_SHADER_OES 0x8DD9
+#define GL_GEOMETRY_SHADER_BIT_OES 0x00000004
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_OES 0x8916
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_OES 0x8917
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES 0x8918
+#define GL_GEOMETRY_SHADER_INVOCATIONS_OES 0x887F
+#define GL_LAYER_PROVOKING_VERTEX_OES 0x825E
+#define GL_LINES_ADJACENCY_OES 0x000A
+#define GL_LINE_STRIP_ADJACENCY_OES 0x000B
+#define GL_TRIANGLES_ADJACENCY_OES 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_OES 0x000D
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES 0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8A32
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES 0x8DE1
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES 0x8E5A
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES 0x8C29
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES 0x92D5
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES 0x90CD
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES 0x90D7
+#define GL_FIRST_VERTEX_CONVENTION_OES 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_OES 0x8E4E
+#define GL_UNDEFINED_VERTEX_OES 0x8260
+#define GL_PRIMITIVES_GENERATED_OES 0x8C87
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_OES 0x9312
+#define GL_MAX_FRAMEBUFFER_LAYERS_OES 0x9317
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES 0x8DA8
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES 0x8DA7
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_OES 0x9309
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREOESPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureOES (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif
+#endif /* GL_OES_geometry_shader */
+
#ifndef GL_OES_get_program_binary
#define GL_OES_get_program_binary 1
#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
@@ -258,6 +405,10 @@ GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFor
#endif
#endif /* GL_OES_get_program_binary */
+#ifndef GL_OES_gpu_shader5
+#define GL_OES_gpu_shader5 1
+#endif /* GL_OES_gpu_shader5 */
+
#ifndef GL_OES_mapbuffer
#define GL_OES_mapbuffer 1
#define GL_WRITE_ONLY_OES 0x88B9
@@ -281,6 +432,15 @@ GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname,
#define GL_DEPTH24_STENCIL8_OES 0x88F0
#endif /* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_primitive_bounding_box
+#define GL_OES_primitive_bounding_box 1
+#define GL_PRIMITIVE_BOUNDING_BOX_OES 0x92BE
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXOESPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxOES (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#endif
+#endif /* GL_OES_primitive_bounding_box */
+
#ifndef GL_OES_required_internalformat
#define GL_OES_required_internalformat 1
#define GL_ALPHA8_OES 0x803C
@@ -319,6 +479,10 @@ GL_APICALL void GL_APIENTRY glMinSampleShadingOES (GLfloat value);
#define GL_OES_shader_image_atomic 1
#endif /* GL_OES_shader_image_atomic */
+#ifndef GL_OES_shader_io_blocks
+#define GL_OES_shader_io_blocks 1
+#endif /* GL_OES_shader_io_blocks */
+
#ifndef GL_OES_shader_multisample_interpolation
#define GL_OES_shader_multisample_interpolation 1
#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B
@@ -346,6 +510,61 @@ GL_APICALL void GL_APIENTRY glMinSampleShadingOES (GLfloat value);
#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
#endif /* GL_OES_surfaceless_context */
+#ifndef GL_OES_tessellation_point_size
+#define GL_OES_tessellation_point_size 1
+#endif /* GL_OES_tessellation_point_size */
+
+#ifndef GL_OES_tessellation_shader
+#define GL_OES_tessellation_shader 1
+#define GL_PATCHES_OES 0x000E
+#define GL_PATCH_VERTICES_OES 0x8E72
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_OES 0x8E75
+#define GL_TESS_GEN_MODE_OES 0x8E76
+#define GL_TESS_GEN_SPACING_OES 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER_OES 0x8E78
+#define GL_TESS_GEN_POINT_MODE_OES 0x8E79
+#define GL_ISOLINES_OES 0x8E7A
+#define GL_QUADS_OES 0x0007
+#define GL_FRACTIONAL_ODD_OES 0x8E7B
+#define GL_FRACTIONAL_EVEN_OES 0x8E7C
+#define GL_MAX_PATCH_VERTICES_OES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL_OES 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS_OES 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E1F
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES 0x92CE
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES 0x92D4
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES 0x90CC
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES 0x90D9
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES 0x8221
+#define GL_IS_PER_PATCH_OES 0x92E7
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES 0x9308
+#define GL_TESS_CONTROL_SHADER_OES 0x8E88
+#define GL_TESS_EVALUATION_SHADER_OES 0x8E87
+#define GL_TESS_CONTROL_SHADER_BIT_OES 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT_OES 0x00000010
+typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIOESPROC) (GLenum pname, GLint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPatchParameteriOES (GLenum pname, GLint value);
+#endif
+#endif /* GL_OES_tessellation_shader */
+
#ifndef GL_OES_texture_3D
#define GL_OES_texture_3D 1
#define GL_TEXTURE_WRAP_R_OES 0x8072
@@ -370,6 +589,54 @@ GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum att
#endif
#endif /* GL_OES_texture_3D */
+#ifndef GL_OES_texture_border_clamp
+#define GL_OES_texture_border_clamp 1
+#define GL_TEXTURE_BORDER_COLOR_OES 0x1004
+#define GL_CLAMP_TO_BORDER_OES 0x812D
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexParameterIivOES (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuivOES (GLenum target, GLenum pname, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIivOES (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuivOES (GLenum target, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIivOES (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuivOES (GLuint sampler, GLenum pname, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIivOES (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivOES (GLuint sampler, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_OES_texture_border_clamp */
+
+#ifndef GL_OES_texture_buffer
+#define GL_OES_texture_buffer 1
+#define GL_TEXTURE_BUFFER_OES 0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING_OES 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_OES 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_OES 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES 0x919F
+#define GL_SAMPLER_BUFFER_OES 0x8DC2
+#define GL_INT_SAMPLER_BUFFER_OES 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_OES 0x8DD8
+#define GL_IMAGE_BUFFER_OES 0x9051
+#define GL_INT_IMAGE_BUFFER_OES 0x905C
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_OES 0x9067
+#define GL_TEXTURE_BUFFER_OFFSET_OES 0x919D
+#define GL_TEXTURE_BUFFER_SIZE_OES 0x919E
+typedef void (GL_APIENTRYP PFNGLTEXBUFFEROESPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEOESPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexBufferOES (GLenum target, GLenum internalformat, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTexBufferRangeOES (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif
+#endif /* GL_OES_texture_buffer */
+
#ifndef GL_OES_texture_compression_astc
#define GL_OES_texture_compression_astc 1
#define GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0
@@ -394,6 +661,19 @@ GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum att
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9
#endif /* GL_OES_texture_compression_astc */
+#ifndef GL_OES_texture_cube_map_array
+#define GL_OES_texture_cube_map_array 1
+#define GL_TEXTURE_CUBE_MAP_ARRAY_OES 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES 0x900A
+#define GL_SAMPLER_CUBE_MAP_ARRAY_OES 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900F
+#define GL_IMAGE_CUBE_MAP_ARRAY_OES 0x9054
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x905F
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x906A
+#endif /* GL_OES_texture_cube_map_array */
+
#ifndef GL_OES_texture_float
#define GL_OES_texture_float 1
#endif /* GL_OES_texture_float */
@@ -434,6 +714,19 @@ GL_APICALL void GL_APIENTRY glTexStorage3DMultisampleOES (GLenum target, GLsizei
#endif
#endif /* GL_OES_texture_storage_multisample_2d_array */
+#ifndef GL_OES_texture_view
+#define GL_OES_texture_view 1
+#define GL_TEXTURE_VIEW_MIN_LEVEL_OES 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS_OES 0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER_OES 0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS_OES 0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWOESPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTextureViewOES (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif
+#endif /* GL_OES_texture_view */
+
#ifndef GL_OES_vertex_array_object
#define GL_OES_vertex_array_object 1
#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
@@ -512,6 +805,10 @@ GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLen
#define GL_Z400_BINARY_AMD 0x8740
#endif /* GL_AMD_program_binary_Z400 */
+#ifndef GL_ANDROID_extension_pack_es31a
+#define GL_ANDROID_extension_pack_es31a 1
+#endif /* GL_ANDROID_extension_pack_es31a */
+
#ifndef GL_ANGLE_depth_texture
#define GL_ANGLE_depth_texture 1
#endif /* GL_ANGLE_depth_texture */
@@ -587,6 +884,23 @@ GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLs
#endif
#endif /* GL_ANGLE_translated_shader_source */
+#ifndef GL_APPLE_clip_distance
+#define GL_APPLE_clip_distance 1
+#define GL_MAX_CLIP_DISTANCES_APPLE 0x0D32
+#define GL_CLIP_DISTANCE0_APPLE 0x3000
+#define GL_CLIP_DISTANCE1_APPLE 0x3001
+#define GL_CLIP_DISTANCE2_APPLE 0x3002
+#define GL_CLIP_DISTANCE3_APPLE 0x3003
+#define GL_CLIP_DISTANCE4_APPLE 0x3004
+#define GL_CLIP_DISTANCE5_APPLE 0x3005
+#define GL_CLIP_DISTANCE6_APPLE 0x3006
+#define GL_CLIP_DISTANCE7_APPLE 0x3007
+#endif /* GL_APPLE_clip_distance */
+
+#ifndef GL_APPLE_color_buffer_packed_float
+#define GL_APPLE_color_buffer_packed_float 1
+#endif /* GL_APPLE_color_buffer_packed_float */
+
#ifndef GL_APPLE_copy_texture_levels
#define GL_APPLE_copy_texture_levels 1
typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
@@ -667,6 +981,14 @@ GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei
#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D
#endif /* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_packed_float
+#define GL_APPLE_texture_packed_float 1
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE 0x8C3B
+#define GL_UNSIGNED_INT_5_9_9_9_REV_APPLE 0x8C3E
+#define GL_R11F_G11F_B10F_APPLE 0x8C3A
+#define GL_RGB9_E5_APPLE 0x8C3D
+#endif /* GL_APPLE_texture_packed_float */
+
#ifndef GL_ARM_mali_program_binary
#define GL_ARM_mali_program_binary 1
#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61
@@ -691,17 +1013,83 @@ GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei
#define GL_ARM_shader_framebuffer_fetch_depth_stencil 1
#endif /* GL_ARM_shader_framebuffer_fetch_depth_stencil */
+#ifndef GL_DMP_program_binary
+#define GL_DMP_program_binary 1
+#define GL_SMAPHS30_PROGRAM_BINARY_DMP 0x9251
+#define GL_SMAPHS_PROGRAM_BINARY_DMP 0x9252
+#define GL_DMP_PROGRAM_BINARY_DMP 0x9253
+#endif /* GL_DMP_program_binary */
+
#ifndef GL_DMP_shader_binary
#define GL_DMP_shader_binary 1
#define GL_SHADER_BINARY_DMP 0x9250
#endif /* GL_DMP_shader_binary */
+#ifndef GL_EXT_YUV_target
+#define GL_EXT_YUV_target 1
+#define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT 0x8BE7
+#endif /* GL_EXT_YUV_target */
+
+#ifndef GL_EXT_base_instance
+#define GL_EXT_base_instance 1
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedBaseInstanceEXT (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#endif
+#endif /* GL_EXT_base_instance */
+
+#ifndef GL_EXT_blend_func_extended
+#define GL_EXT_blend_func_extended 1
+#define GL_SRC1_COLOR_EXT 0x88F9
+#define GL_SRC1_ALPHA_EXT 0x8589
+#define GL_ONE_MINUS_SRC1_COLOR_EXT 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA_EXT 0x88FB
+#define GL_SRC_ALPHA_SATURATE_EXT 0x0308
+#define GL_LOCATION_INDEX_EXT 0x930F
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT 0x88FC
+typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATAINDEXEXTPROC) (GLuint program, const GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindFragDataLocationIndexedEXT (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocationIndexEXT (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL GLint GL_APIENTRY glGetFragDataIndexEXT (GLuint program, const GLchar *name);
+#endif
+#endif /* GL_EXT_blend_func_extended */
+
#ifndef GL_EXT_blend_minmax
#define GL_EXT_blend_minmax 1
#define GL_MIN_EXT 0x8007
#define GL_MAX_EXT 0x8008
#endif /* GL_EXT_blend_minmax */
+#ifndef GL_EXT_buffer_storage
+#define GL_EXT_buffer_storage 1
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_PERSISTENT_BIT_EXT 0x0040
+#define GL_MAP_COHERENT_BIT_EXT 0x0080
+#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100
+#define GL_CLIENT_STORAGE_BIT_EXT 0x0200
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
+#define GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F
+#define GL_BUFFER_STORAGE_FLAGS_EXT 0x8220
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBufferStorageEXT (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+#endif
+#endif /* GL_EXT_buffer_storage */
+
+#ifndef GL_EXT_color_buffer_float
+#define GL_EXT_color_buffer_float 1
+#endif /* GL_EXT_color_buffer_float */
+
#ifndef GL_EXT_color_buffer_half_float
#define GL_EXT_color_buffer_half_float 1
#define GL_RGBA16F_EXT 0x881A
@@ -839,8 +1227,6 @@ GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs);
#ifndef GL_EXT_draw_buffers_indexed
#define GL_EXT_draw_buffers_indexed 1
-#define GL_MIN 0x8007
-#define GL_MAX 0x8008
typedef void (GL_APIENTRYP PFNGLENABLEIEXTPROC) (GLenum target, GLuint index);
typedef void (GL_APIENTRYP PFNGLDISABLEIEXTPROC) (GLenum target, GLuint index);
typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIEXTPROC) (GLuint buf, GLenum mode);
@@ -861,6 +1247,20 @@ GL_APICALL GLboolean GL_APIENTRY glIsEnablediEXT (GLenum target, GLuint index);
#endif
#endif /* GL_EXT_draw_buffers_indexed */
+#ifndef GL_EXT_draw_elements_base_vertex
+#define GL_EXT_draw_elements_base_vertex 1
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#endif
+#endif /* GL_EXT_draw_elements_base_vertex */
+
#ifndef GL_EXT_draw_instanced
#define GL_EXT_draw_instanced 1
typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
@@ -871,6 +1271,10 @@ GL_APICALL void GL_APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei cou
#endif
#endif /* GL_EXT_draw_instanced */
+#ifndef GL_EXT_float_blend
+#define GL_EXT_float_blend 1
+#endif /* GL_EXT_float_blend */
+
#ifndef GL_EXT_geometry_point_size
#define GL_EXT_geometry_point_size 1
#endif /* GL_EXT_geometry_point_size */
@@ -955,6 +1359,22 @@ GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *
#endif
#endif /* GL_EXT_multi_draw_arrays */
+#ifndef GL_EXT_multi_draw_indirect
+#define GL_EXT_multi_draw_indirect 1
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysIndirectEXT (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsIndirectEXT (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#endif
+#endif /* GL_EXT_multi_draw_indirect */
+
+#ifndef GL_EXT_multisampled_compatibility
+#define GL_EXT_multisampled_compatibility 1
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#endif /* GL_EXT_multisampled_compatibility */
+
#ifndef GL_EXT_multisampled_render_to_texture
#define GL_EXT_multisampled_render_to_texture 1
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
@@ -992,6 +1412,28 @@ GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLi
#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
#endif /* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_polygon_offset_clamp
+#define GL_EXT_polygon_offset_clamp 1
+#define GL_POLYGON_OFFSET_CLAMP_EXT 0x8E1B
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETCLAMPEXTPROC) (GLfloat factor, GLfloat units, GLfloat clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPolygonOffsetClampEXT (GLfloat factor, GLfloat units, GLfloat clamp);
+#endif
+#endif /* GL_EXT_polygon_offset_clamp */
+
+#ifndef GL_EXT_post_depth_coverage
+#define GL_EXT_post_depth_coverage 1
+#endif /* GL_EXT_post_depth_coverage */
+
+#ifndef GL_EXT_primitive_bounding_box
+#define GL_EXT_primitive_bounding_box 1
+#define GL_PRIMITIVE_BOUNDING_BOX_EXT 0x92BE
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXEXTPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxEXT (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#endif
+#endif /* GL_EXT_primitive_bounding_box */
+
#ifndef GL_EXT_pvrtc_sRGB
#define GL_EXT_pvrtc_sRGB 1
#define GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
@@ -1002,12 +1444,36 @@ GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLi
#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG 0x93F1
#endif /* GL_EXT_pvrtc_sRGB */
+#ifndef GL_EXT_raster_multisample
+#define GL_EXT_raster_multisample 1
+#define GL_RASTER_MULTISAMPLE_EXT 0x9327
+#define GL_RASTER_SAMPLES_EXT 0x9328
+#define GL_MAX_RASTER_SAMPLES_EXT 0x9329
+#define GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A
+#define GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B
+#define GL_EFFECTIVE_RASTER_SAMPLES_EXT 0x932C
+typedef void (GL_APIENTRYP PFNGLRASTERSAMPLESEXTPROC) (GLuint samples, GLboolean fixedsamplelocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRasterSamplesEXT (GLuint samples, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_EXT_raster_multisample */
+
#ifndef GL_EXT_read_format_bgra
#define GL_EXT_read_format_bgra 1
#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
#endif /* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_render_snorm
+#define GL_EXT_render_snorm 1
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM_EXT 0x8F98
+#define GL_RG16_SNORM_EXT 0x8F99
+#define GL_RGBA16_SNORM_EXT 0x8F9B
+#endif /* GL_EXT_render_snorm */
+
#ifndef GL_EXT_robustness
#define GL_EXT_robustness 1
#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
@@ -1147,6 +1613,10 @@ GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLin
#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
#endif /* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_group_vote
+#define GL_EXT_shader_group_vote 1
+#endif /* GL_EXT_shader_group_vote */
+
#ifndef GL_EXT_shader_implicit_conversions
#define GL_EXT_shader_implicit_conversions 1
#endif /* GL_EXT_shader_implicit_conversions */
@@ -1166,6 +1636,21 @@ GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLin
#define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64
#endif /* GL_EXT_shader_pixel_local_storage */
+#ifndef GL_EXT_shader_pixel_local_storage2
+#define GL_EXT_shader_pixel_local_storage2 1
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT 0x9650
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT 0x9651
+#define GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT 0x9652
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target, GLsizei size);
+typedef GLsizei (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target);
+typedef void (GL_APIENTRYP PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC) (GLsizei offset, GLsizei n, const GLuint *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferPixelLocalStorageSizeEXT (GLuint target, GLsizei size);
+GL_APICALL GLsizei GL_APIENTRY glGetFramebufferPixelLocalStorageSizeEXT (GLuint target);
+GL_APICALL void GL_APIENTRY glClearPixelLocalStorageuiEXT (GLsizei offset, GLsizei n, const GLuint *values);
+#endif
+#endif /* GL_EXT_shader_pixel_local_storage2 */
+
#ifndef GL_EXT_shader_texture_lod
#define GL_EXT_shader_texture_lod 1
#endif /* GL_EXT_shader_texture_lod */
@@ -1178,6 +1663,27 @@ GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLin
#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62
#endif /* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_sparse_texture
+#define GL_EXT_sparse_texture 1
+#define GL_TEXTURE_SPARSE_EXT 0x91A6
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_EXT 0x91A7
+#define GL_NUM_SPARSE_LEVELS_EXT 0x91AA
+#define GL_NUM_VIRTUAL_PAGE_SIZES_EXT 0x91A8
+#define GL_VIRTUAL_PAGE_SIZE_X_EXT 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_EXT 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_EXT 0x9197
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_3D 0x806F
+#define GL_MAX_SPARSE_TEXTURE_SIZE_EXT 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT 0x919A
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT 0x91A9
+typedef void (GL_APIENTRYP PFNGLTEXPAGECOMMITMENTEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexPageCommitmentEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+#endif
+#endif /* GL_EXT_sparse_texture */
+
#ifndef GL_EXT_tessellation_point_size
#define GL_EXT_tessellation_point_size 1
#endif /* GL_EXT_tessellation_point_size */
@@ -1312,10 +1818,23 @@ GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalf
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#endif /* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_minmax
+#define GL_EXT_texture_filter_minmax 1
+#endif /* GL_EXT_texture_filter_minmax */
+
#ifndef GL_EXT_texture_format_BGRA8888
#define GL_EXT_texture_format_BGRA8888 1
#endif /* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_norm16
+#define GL_EXT_texture_norm16 1
+#define GL_R16_EXT 0x822A
+#define GL_RG16_EXT 0x822C
+#define GL_RGBA16_EXT 0x805B
+#define GL_RGB16_EXT 0x8054
+#define GL_RGB16_SNORM_EXT 0x8F9A
+#endif /* GL_EXT_texture_norm16 */
+
#ifndef GL_EXT_texture_rg
#define GL_EXT_texture_rg 1
#define GL_RED_EXT 0x1903
@@ -1324,6 +1843,16 @@ GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalf
#define GL_RG8_EXT 0x822B
#endif /* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_sRGB_R8
+#define GL_EXT_texture_sRGB_R8 1
+#define GL_SR8_EXT 0x8FBD
+#endif /* GL_EXT_texture_sRGB_R8 */
+
+#ifndef GL_EXT_texture_sRGB_RG8
+#define GL_EXT_texture_sRGB_RG8 1
+#define GL_SRG8_EXT 0x8FBE
+#endif /* GL_EXT_texture_sRGB_RG8 */
+
#ifndef GL_EXT_texture_sRGB_decode
#define GL_EXT_texture_sRGB_decode 1
#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
@@ -1374,7 +1903,6 @@ GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target
#define GL_TEXTURE_VIEW_NUM_LEVELS_EXT 0x82DC
#define GL_TEXTURE_VIEW_MIN_LAYER_EXT 0x82DD
#define GL_TEXTURE_VIEW_NUM_LAYERS_EXT 0x82DE
-#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWEXTPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glTextureViewEXT (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
@@ -1393,6 +1921,20 @@ GL_APICALL void GL_APIENTRY glTextureViewEXT (GLuint texture, GLenum target, GLu
#define GL_GCCSO_SHADER_BINARY_FJ 0x9260
#endif /* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_IMG_framebuffer_downsample
+#define GL_IMG_framebuffer_downsample 1
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG 0x913C
+#define GL_NUM_DOWNSAMPLE_SCALES_IMG 0x913D
+#define GL_DOWNSAMPLE_SCALES_IMG 0x913E
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG 0x913F
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DDownsampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayerDownsampleIMG (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale);
+#endif
+#endif /* GL_IMG_framebuffer_downsample */
+
#ifndef GL_IMG_multisampled_render_to_texture
#define GL_IMG_multisampled_render_to_texture 1
#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
@@ -1437,6 +1979,21 @@ GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target,
#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
#endif /* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_filter_cubic
+#define GL_IMG_texture_filter_cubic 1
+#define GL_CUBIC_IMG 0x9139
+#define GL_CUBIC_MIPMAP_NEAREST_IMG 0x913A
+#define GL_CUBIC_MIPMAP_LINEAR_IMG 0x913B
+#endif /* GL_IMG_texture_filter_cubic */
+
+#ifndef GL_INTEL_framebuffer_CMAA
+#define GL_INTEL_framebuffer_CMAA 1
+typedef void (GL_APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void);
+#endif
+#endif /* GL_INTEL_framebuffer_CMAA */
+
#ifndef GL_INTEL_performance_query
#define GL_INTEL_performance_query 1
#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000
@@ -1483,6 +2040,38 @@ GL_APICALL void GL_APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint quer
#endif
#endif /* GL_INTEL_performance_query */
+#ifndef GL_NV_bindless_texture
+#define GL_NV_bindless_texture 1
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (GL_APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureHandleNV (GLuint texture);
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler);
+GL_APICALL void GL_APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle);
+GL_APICALL void GL_APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle);
+GL_APICALL GLuint64 GL_APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GL_APICALL void GL_APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access);
+GL_APICALL void GL_APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle);
+GL_APICALL void GL_APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GL_APICALL GLboolean GL_APIENTRY glIsTextureHandleResidentNV (GLuint64 handle);
+GL_APICALL GLboolean GL_APIENTRY glIsImageHandleResidentNV (GLuint64 handle);
+#endif
+#endif /* GL_NV_bindless_texture */
+
#ifndef GL_NV_blend_equation_advanced
#define GL_NV_blend_equation_advanced 1
#define GL_BLEND_OVERLAP_NV 0x9281
@@ -1547,6 +2136,32 @@ GL_APICALL void GL_APIENTRY glBlendBarrierNV (void);
#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285
#endif /* GL_NV_blend_equation_advanced_coherent */
+#ifndef GL_NV_conditional_render
+#define GL_NV_conditional_render 1
+#define GL_QUERY_WAIT_NV 0x8E13
+#define GL_QUERY_NO_WAIT_NV 0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16
+typedef void (GL_APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode);
+GL_APICALL void GL_APIENTRY glEndConditionalRenderNV (void);
+#endif
+#endif /* GL_NV_conditional_render */
+
+#ifndef GL_NV_conservative_raster
+#define GL_NV_conservative_raster 1
+#define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346
+#define GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV 0x9347
+#define GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV 0x9348
+#define GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV 0x9349
+typedef void (GL_APIENTRYP PFNGLSUBPIXELPRECISIONBIASNVPROC) (GLuint xbits, GLuint ybits);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits);
+#endif
+#endif /* GL_NV_conservative_raster */
+
#ifndef GL_NV_copy_buffer
#define GL_NV_copy_buffer 1
#define GL_COPY_READ_BUFFER_NV 0x8F36
@@ -1664,6 +2279,25 @@ GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
#endif
#endif /* GL_NV_fence */
+#ifndef GL_NV_fill_rectangle
+#define GL_NV_fill_rectangle 1
+#define GL_FILL_RECTANGLE_NV 0x933C
+#endif /* GL_NV_fill_rectangle */
+
+#ifndef GL_NV_fragment_coverage_to_color
+#define GL_NV_fragment_coverage_to_color 1
+#define GL_FRAGMENT_COVERAGE_TO_COLOR_NV 0x92DD
+#define GL_FRAGMENT_COVERAGE_COLOR_NV 0x92DE
+typedef void (GL_APIENTRYP PFNGLFRAGMENTCOVERAGECOLORNVPROC) (GLuint color);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFragmentCoverageColorNV (GLuint color);
+#endif
+#endif /* GL_NV_fragment_coverage_to_color */
+
+#ifndef GL_NV_fragment_shader_interlock
+#define GL_NV_fragment_shader_interlock 1
+#endif /* GL_NV_fragment_shader_interlock */
+
#ifndef GL_NV_framebuffer_blit
#define GL_NV_framebuffer_blit 1
#define GL_READ_FRAMEBUFFER_NV 0x8CA8
@@ -1676,6 +2310,26 @@ GL_APICALL void GL_APIENTRY glBlitFramebufferNV (GLint srcX0, GLint srcY0, GLint
#endif
#endif /* GL_NV_framebuffer_blit */
+#ifndef GL_NV_framebuffer_mixed_samples
+#define GL_NV_framebuffer_mixed_samples 1
+#define GL_COVERAGE_MODULATION_TABLE_NV 0x9331
+#define GL_COLOR_SAMPLES_NV 0x8E20
+#define GL_DEPTH_SAMPLES_NV 0x932D
+#define GL_STENCIL_SAMPLES_NV 0x932E
+#define GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV 0x932F
+#define GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV 0x9330
+#define GL_COVERAGE_MODULATION_NV 0x9332
+#define GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONTABLENVPROC) (GLsizei n, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufsize, GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONNVPROC) (GLenum components);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageModulationTableNV (GLsizei n, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glGetCoverageModulationTableNV (GLsizei bufsize, GLfloat *v);
+GL_APICALL void GL_APIENTRY glCoverageModulationNV (GLenum components);
+#endif
+#endif /* GL_NV_framebuffer_mixed_samples */
+
#ifndef GL_NV_framebuffer_multisample
#define GL_NV_framebuffer_multisample 1
#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB
@@ -1691,6 +2345,14 @@ GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV (GLenum target, G
#define GL_NV_generate_mipmap_sRGB 1
#endif /* GL_NV_generate_mipmap_sRGB */
+#ifndef GL_NV_geometry_shader_passthrough
+#define GL_NV_geometry_shader_passthrough 1
+#endif /* GL_NV_geometry_shader_passthrough */
+
+#ifndef GL_NV_image_formats
+#define GL_NV_image_formats 1
+#endif /* GL_NV_image_formats */
+
#ifndef GL_NV_instanced_arrays
#define GL_NV_instanced_arrays 1
#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE
@@ -1700,6 +2362,20 @@ GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint diviso
#endif
#endif /* GL_NV_instanced_arrays */
+#ifndef GL_NV_internalformat_sample_query
+#define GL_NV_internalformat_sample_query 1
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_MULTISAMPLES_NV 0x9371
+#define GL_SUPERSAMPLE_SCALE_X_NV 0x9372
+#define GL_SUPERSAMPLE_SCALE_Y_NV 0x9373
+#define GL_CONFORMANT_NV 0x9374
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_NV_internalformat_sample_query */
+
#ifndef GL_NV_non_square_matrices
#define GL_NV_non_square_matrices 1
#define GL_FLOAT_MAT2x3_NV 0x8B65
@@ -1724,6 +2400,298 @@ GL_APICALL void GL_APIENTRY glUniformMatrix4x3fvNV (GLint location, GLsizei coun
#endif
#endif /* GL_NV_non_square_matrices */
+#ifndef GL_NV_path_rendering
+#define GL_NV_path_rendering 1
+#define GL_PATH_FORMAT_SVG_NV 0x9070
+#define GL_PATH_FORMAT_PS_NV 0x9071
+#define GL_STANDARD_FONT_NAME_NV 0x9072
+#define GL_SYSTEM_FONT_NAME_NV 0x9073
+#define GL_FILE_NAME_NV 0x9074
+#define GL_PATH_STROKE_WIDTH_NV 0x9075
+#define GL_PATH_END_CAPS_NV 0x9076
+#define GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define GL_PATH_JOIN_STYLE_NV 0x9079
+#define GL_PATH_MITER_LIMIT_NV 0x907A
+#define GL_PATH_DASH_CAPS_NV 0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define GL_PATH_DASH_OFFSET_NV 0x907E
+#define GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define GL_PATH_FILL_MODE_NV 0x9080
+#define GL_PATH_FILL_MASK_NV 0x9081
+#define GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define GL_PATH_STROKE_MASK_NV 0x9084
+#define GL_COUNT_UP_NV 0x9088
+#define GL_COUNT_DOWN_NV 0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define GL_CONVEX_HULL_NV 0x908B
+#define GL_BOUNDING_BOX_NV 0x908D
+#define GL_TRANSLATE_X_NV 0x908E
+#define GL_TRANSLATE_Y_NV 0x908F
+#define GL_TRANSLATE_2D_NV 0x9090
+#define GL_TRANSLATE_3D_NV 0x9091
+#define GL_AFFINE_2D_NV 0x9092
+#define GL_AFFINE_3D_NV 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define GL_UTF8_NV 0x909A
+#define GL_UTF16_NV 0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV 0x909D
+#define GL_PATH_COORD_COUNT_NV 0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define GL_SQUARE_NV 0x90A3
+#define GL_ROUND_NV 0x90A4
+#define GL_TRIANGULAR_NV 0x90A5
+#define GL_BEVEL_NV 0x90A6
+#define GL_MITER_REVERT_NV 0x90A7
+#define GL_MITER_TRUNCATE_NV 0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define GL_USE_MISSING_GLYPH_NV 0x90AA
+#define GL_PATH_ERROR_POSITION_NV 0x90AB
+#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define GL_ADJACENT_PAIRS_NV 0x90AE
+#define GL_FIRST_TO_REST_NV 0x90AF
+#define GL_PATH_GEN_MODE_NV 0x90B0
+#define GL_PATH_GEN_COEFF_NV 0x90B1
+#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define GL_PATH_STENCIL_REF_NV 0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define GL_MOVE_TO_RESETS_NV 0x90B5
+#define GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define GL_CLOSE_PATH_NV 0x00
+#define GL_MOVE_TO_NV 0x02
+#define GL_RELATIVE_MOVE_TO_NV 0x03
+#define GL_LINE_TO_NV 0x04
+#define GL_RELATIVE_LINE_TO_NV 0x05
+#define GL_HORIZONTAL_LINE_TO_NV 0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_VERTICAL_LINE_TO_NV 0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV 0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV 0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define GL_SMALL_CW_ARC_TO_NV 0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define GL_LARGE_CCW_ARC_TO_NV 0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define GL_LARGE_CW_ARC_TO_NV 0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define GL_RESTART_PATH_NV 0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define GL_RECT_NV 0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define GL_ARC_TO_NV 0xFE
+#define GL_RELATIVE_ARC_TO_NV 0xFF
+#define GL_BOLD_BIT_NV 0x01
+#define GL_ITALIC_BIT_NV 0x02
+#define GL_GLYPH_WIDTH_BIT_NV 0x01
+#define GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+#define GL_ROUNDED_RECT_NV 0xE8
+#define GL_RELATIVE_ROUNDED_RECT_NV 0xE9
+#define GL_ROUNDED_RECT2_NV 0xEA
+#define GL_RELATIVE_ROUNDED_RECT2_NV 0xEB
+#define GL_ROUNDED_RECT4_NV 0xEC
+#define GL_RELATIVE_ROUNDED_RECT4_NV 0xED
+#define GL_ROUNDED_RECT8_NV 0xEE
+#define GL_RELATIVE_ROUNDED_RECT8_NV 0xEF
+#define GL_RELATIVE_RECT_NV 0xF7
+#define GL_FONT_GLYPHS_AVAILABLE_NV 0x9368
+#define GL_FONT_TARGET_UNAVAILABLE_NV 0x9369
+#define GL_FONT_UNAVAILABLE_NV 0x936A
+#define GL_FONT_UNINTELLIGIBLE_NV 0x936B
+#define GL_CONIC_CURVE_TO_NV 0x1A
+#define GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B
+#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000
+#define GL_STANDARD_FONT_FORMAT_NV 0x936C
+#define GL_PATH_PROJECTION_NV 0x1701
+#define GL_PATH_MODELVIEW_NV 0x1700
+#define GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3
+#define GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6
+#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36
+#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3
+#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4
+#define GL_PATH_PROJECTION_MATRIX_NV 0x0BA7
+#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38
+#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4
+#define GL_FRAGMENT_INPUT_NV 0x936D
+typedef GLuint (GL_APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (GL_APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLboolean (GL_APIENTRYP PFNGLISPATHNVPROC) (GLuint path);
+typedef void (GL_APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString);
+typedef void (GL_APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+typedef void (GL_APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (GL_APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (GL_APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+typedef void (GL_APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value);
+typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands);
+typedef void (GL_APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords);
+typedef void (GL_APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray);
+typedef void (GL_APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (GL_APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+typedef void (GL_APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef GLfloat (GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef GLboolean (GL_APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef GLenum (GL_APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint GL_APIENTRY glGenPathsNV (GLsizei range);
+GL_APICALL void GL_APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
+GL_APICALL GLboolean GL_APIENTRY glIsPathNV (GLuint path);
+GL_APICALL void GL_APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString);
+GL_APICALL void GL_APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+GL_APICALL void GL_APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath);
+GL_APICALL void GL_APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+GL_APICALL void GL_APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value);
+GL_APICALL void GL_APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value);
+GL_APICALL void GL_APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathCoverDepthFuncNV (GLenum func);
+GL_APICALL void GL_APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value);
+GL_APICALL void GL_APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value);
+GL_APICALL void GL_APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands);
+GL_APICALL void GL_APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords);
+GL_APICALL void GL_APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y);
+GL_APICALL GLfloat GL_APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments);
+GL_APICALL GLboolean GL_APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL GLenum GL_APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+GL_APICALL void GL_APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#endif
+#endif /* GL_NV_path_rendering */
+
+#ifndef GL_NV_path_rendering_shared_edge
+#define GL_NV_path_rendering_shared_edge 1
+#define GL_SHARED_EDGE_NV 0xC0
+#endif /* GL_NV_path_rendering_shared_edge */
+
+#ifndef GL_NV_polygon_mode
+#define GL_NV_polygon_mode 1
+#define GL_POLYGON_MODE_NV 0x0B40
+#define GL_POLYGON_OFFSET_POINT_NV 0x2A01
+#define GL_POLYGON_OFFSET_LINE_NV 0x2A02
+#define GL_POINT_NV 0x1B00
+#define GL_LINE_NV 0x1B01
+#define GL_FILL_NV 0x1B02
+typedef void (GL_APIENTRYP PFNGLPOLYGONMODENVPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPolygonModeNV (GLenum face, GLenum mode);
+#endif
+#endif /* GL_NV_polygon_mode */
+
#ifndef GL_NV_read_buffer
#define GL_NV_read_buffer 1
#define GL_READ_BUFFER_NV 0x0C02
@@ -1763,6 +2731,34 @@ GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
#define GL_ETC1_SRGB8_NV 0x88EE
#endif /* GL_NV_sRGB_formats */
+#ifndef GL_NV_sample_locations
+#define GL_NV_sample_locations 1
+#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV 0x933E
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV 0x933F
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV 0x9340
+#define GL_SAMPLE_LOCATION_NV 0x8E50
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9341
+#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV 0x9342
+#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV 0x9343
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLRESOLVEDEPTHVALUESNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferSampleLocationsfvNV (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glNamedFramebufferSampleLocationsfvNV (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glResolveDepthValuesNV (void);
+#endif
+#endif /* GL_NV_sample_locations */
+
+#ifndef GL_NV_sample_mask_override_coverage
+#define GL_NV_sample_mask_override_coverage 1
+#endif /* GL_NV_sample_mask_override_coverage */
+
+#ifndef GL_NV_shader_noperspective_interpolation
+#define GL_NV_shader_noperspective_interpolation 1
+#endif /* GL_NV_shader_noperspective_interpolation */
+
#ifndef GL_NV_shadow_samplers_array
#define GL_NV_shadow_samplers_array 1
#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4
@@ -1787,6 +2783,67 @@ GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
#define GL_NV_texture_npot_2D_mipmap 1
#endif /* GL_NV_texture_npot_2D_mipmap */
+#ifndef GL_NV_viewport_array
+#define GL_NV_viewport_array 1
+#define GL_MAX_VIEWPORTS_NV 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS_NV 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE_NV 0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV 0x825F
+typedef void (GL_APIENTRYP PFNGLVIEWPORTARRAYVNVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDNVPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDVNVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEARRAYFVNVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEINDEXEDFNVPROC) (GLuint index, GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLGETFLOATI_VNVPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLENABLEINVPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEINVPROC) (GLenum target, GLuint index);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDINVPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportArrayvNV (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glViewportIndexedfNV (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GL_APICALL void GL_APIENTRY glViewportIndexedfvNV (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glScissorArrayvNV (GLuint first, GLsizei count, const GLint *v);
+GL_APICALL void GL_APIENTRY glScissorIndexedNV (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glScissorIndexedvNV (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glDepthRangeArrayfvNV (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glDepthRangeIndexedfNV (GLuint index, GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glGetFloati_vNV (GLenum target, GLuint index, GLfloat *data);
+GL_APICALL void GL_APIENTRY glEnableiNV (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiNV (GLenum target, GLuint index);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediNV (GLenum target, GLuint index);
+#endif
+#endif /* GL_NV_viewport_array */
+
+#ifndef GL_NV_viewport_array2
+#define GL_NV_viewport_array2 1
+#endif /* GL_NV_viewport_array2 */
+
+#ifndef GL_OVR_multiview
+#define GL_OVR_multiview 1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
+#define GL_MAX_VIEWS_OVR 0x9631
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview */
+
+#ifndef GL_OVR_multiview2
+#define GL_OVR_multiview2 1
+#endif /* GL_OVR_multiview2 */
+
+#ifndef GL_OVR_multiview_multisampled_render_to_texture
+#define GL_OVR_multiview_multisampled_render_to_texture 1
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultisampleMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview_multisampled_render_to_texture */
+
#ifndef GL_QCOM_alpha_test
#define GL_QCOM_alpha_test 1
#define GL_ALPHA_TEST_QCOM 0x0BC0
diff --git a/thirdparty/khronos/Makefile b/thirdparty/khronos/Makefile
index 3ce2162b..2c04a6f3 100644
--- a/thirdparty/khronos/Makefile
+++ b/thirdparty/khronos/Makefile
@@ -14,29 +14,29 @@ update: \
GLES2/gl2platform.h
GL/wglext.h GL/glxext.h: FORCE
- wget -O $@ "http://www.opengl.org/registry/api/$@"
+ wget -nv -O $@ "https://www.opengl.org/registry/api/$@"
GL/glext.h: GL/glext.patch FORCE
- wget -O $@ "http://www.opengl.org/registry/api/$@"
+ wget -nv -O $@ "https://www.opengl.org/registry/api/$@"
patch $@ $<
EGL/egl.h EGL/eglext.h KHR/khrplatform.h: FORCE
- wget -O $@ "http://www.khronos.org/registry/egl/api/$@"
+ wget -nv -O $@ "https://www.khronos.org/registry/egl/api/$@"
EGL/eglplatform.h: EGL/eglplatform.patch FORCE
- wget -O $@ "http://www.khronos.org/registry/egl/api/$@"
+ wget -nv -O $@ "https://www.khronos.org/registry/egl/api/$@"
patch $@ $<
GLES/gl.h GLES/glplatform.h: FORCE
- wget -O $@ "http://www.khronos.org/registry/gles/api/$@"
+ wget -nv -O $@ "https://www.khronos.org/registry/gles/api/$@"
GLES/glext.h: GLES/glext.patch FORCE
- wget -O $@ "http://www.khronos.org/registry/gles/api/$@"
+ wget -nv -O $@ "https://www.khronos.org/registry/gles/api/$@"
patch $@ $<
GLES2/gl2.h GLES2/gl2ext.h GLES2/gl2platform.h: FORCE
- wget -O $@ "http://www.khronos.org/registry/gles/api/$@"
-
-.PHONY: update
+ wget -nv -O $@ "https://www.khronos.org/registry/gles/api/$@"
FORCE:
+
+.PHONY: update FORCE
diff --git a/thirdparty/libbacktrace/CMakeLists.txt b/thirdparty/libbacktrace/CMakeLists.txt
index 26604200..ac0089f0 100644
--- a/thirdparty/libbacktrace/CMakeLists.txt
+++ b/thirdparty/libbacktrace/CMakeLists.txt
@@ -54,7 +54,7 @@ if (FLAG_UNWIND_TABLES)
endif ()
# Adjust warnings
-if (CMAKE_COMPILER_IS_GNUCC)
+if (NOT MSVC)
add_definitions ("-Wno-switch -Wno-enum-compare")
endif ()
@@ -66,6 +66,13 @@ check_c_source_compiles (
__sync_lock_release (&i);}"
HAVE_SYNC_FUNCTIONS)
+check_c_source_compiles (
+ "int i;
+ int main() {
+ __atomic_load_n (&i, __ATOMIC_ACQUIRE);
+ __atomic_store_n (&i, i, __ATOMIC_RELEASE);}"
+ HAVE_ATOMIC_FUNCTIONS)
+
if (HAVE_SYNC_FUNCTIONS)
set (BACKTRACE_SUPPORTS_THREADS 1)
else ()
@@ -75,10 +82,12 @@ endif ()
if (CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
set (FORMAT_FILE elf.c dwarf.c)
math (EXPR BACKTRACE_ELF_SIZE 8*${CMAKE_C_SIZEOF_DATA_PTR})
+ set (BACKTRACE_SUPPORTS_DATA 1)
else ()
set (FORMAT_FILE unknown.c)
set (BACKTRACE_SUPPORTED 0)
message (STATUS "Executable format is not ELF. Disabling Backtrace support.")
+ set (BACKTRACE_SUPPORTS_DATA 0)
endif ()
check_symbol_exists (mmap sys/mman.h HAVE_MMAP)
@@ -88,9 +97,9 @@ if (HAVE_MMAP)
check_symbol_exists (MAP_ANONYMOUS sys/mman.h HAVE_MMAP_ANONYMOUS)
check_symbol_exists (MAP_ANON sys/mman.h HAVE_MMAP_ANON)
if (HAVE_MMAP_ANONYMOUS AND HAVE_MMAP_ANON)
- set (ALLOC_FILE mmap.c)
+ set (ALLOC_FILE mmap.c)
else ()
- set (ALLOC_FILE alloc.c)
+ set (ALLOC_FILE alloc.c)
endif ()
else ()
set (VIEW_FILE read.c)
@@ -127,31 +136,32 @@ configure_file (backtrace-supported.h.in backtrace-supported.h)
configure_file (config.h.in.cmake config.h)
-include_directories (BEFORE
- ${CMAKE_CURRENT_BINARY_DIR}
-)
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
+
include_directories (
auxincl
)
-add_library (backtrace STATIC EXCLUDE_FROM_ALL
+add_convenience_library (backtrace EXCLUDE_FROM_ALL
${BACKTRACE_FILE}
${FORMAT_FILE}
${VIEW_FILE}
${ALLOC_FILE}
+ atomic.c
fileline.c
posix.c
print.c
state.c
-)
-set_target_properties (backtrace PROPERTIES
- COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}"
+ sort.c
)
-set (ENABLE_LIBBACKTRACE_TEST false CACHE BOOL "Enable libbacktrace testing")
-if (ENABLE_LIBBACKTRACE_TEST)
- enable_testing ()
- add_executable (btest btest.c)
- set_property (SOURCE btest.c PROPERTY COMPILE_FLAGS "-g")
- target_link_libraries (btest backtrace)
- add_test (test-libbacktrace btest)
-endif ()
+add_executable (btest btest.c)
+set_target_properties (btest PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS_DEBUG}")
+target_link_libraries (btest backtrace)
+add_dependencies (check btest)
+add_test (NAME libbacktrace_btest COMMAND $<TARGET_FILE:btest>)
+
+add_executable (stest stest.c)
+set_target_properties (stest PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS_DEBUG}")
+target_link_libraries (stest backtrace)
+add_dependencies (check stest)
+add_test (NAME libbacktrace_stest COMMAND $<TARGET_FILE:stest>)
diff --git a/thirdparty/libbacktrace/ChangeLog b/thirdparty/libbacktrace/ChangeLog
index d6f7205f..2afa4705 100644
--- a/thirdparty/libbacktrace/ChangeLog
+++ b/thirdparty/libbacktrace/ChangeLog
@@ -1,3 +1,275 @@
+2016-01-04 Jakub Jelinek <jakub@redhat.com>
+
+ Update copyright years.
+
+2015-12-18 Andris Pavenis <andris.pavenis@iki.fi>
+
+ * configure.ac: Specify that DJGPP do not have mmap even when sys/mman.h exists
+ * configure: Regenerate
+
+2015-12-09 John David Anglin <danglin@gcc.gnu.org>
+
+ PR 68115/libfortran
+ * configure.ac: Set libbacktrace_cv_sys_sync to no on hppa*-*-hpux*.
+ * configure: Regenerate.
+ * elf.c (backtrace_initialize): Cast __sync_bool_compare_and_swap call
+ to void.
+
+2015-09-17 Ian Lance Taylor <iant@google.com>
+
+ * posix.c (backtrace_open): Cast second argument of open() to int.
+
+2015-09-11 Ian Lance Taylor <iant@google.com>
+
+ * Makefile.am (backtrace.lo): Depend on internal.h.
+ (sort.lo, stest.lo): Add explicit dependencies.
+ * Makefile.in: Rebuild.
+
+2015-09-09 Hans-Peter Nilsson <hp@axis.com>
+
+ * backtrace.c: #include <sys/types.h>.
+
+2015-09-08 Ian Lance Taylor <iant@google.com>
+
+ PR other/67457
+ * backtrace.c: #include "internal.h".
+ (struct backtrace_data): Add can_alloc field.
+ (unwind): If can_alloc is false, don't try to get file/line
+ information.
+ (backtrace_full): Set can_alloc field in bdata.
+ * alloc.c (backtrace_alloc): Don't call error_callback if it is
+ NULL.
+ * mmap.c (backtrace_alloc): Likewise.
+ * internal.h: Update comments for backtrace_alloc and
+ backtrace_free.
+
+2015-09-08 Ian Lance Taylor <iant@google.com>
+
+ PR other/67457
+ * mmap.c (backtrace_alloc): Correct test for mmap failure.
+
+2015-08-31 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * configure.ac: For spu-*-* targets, set have_fcntl to no.
+ * configure: Regenerate.
+
+2015-08-27 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * configure.ac: Remove [disable-shared] argument to LT_INIT.
+ Remove setting PIC_FLAG when building as target library.
+ * configure: Regenerate.
+
+2015-08-26 Hans-Peter Nilsson <hp@axis.com>
+
+ * configure.ac: Only compile with -fPIC if the target
+ supports it.
+ * configure: Regenerate.
+
+2015-08-24 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * configure.ac: Set have_mmap to no on spu-*-* targets.
+ * configure: Regenerate.
+
+2015-08-13 Ian Lance Taylor <iant@google.com>
+
+ * dwarf.c (read_function_entry): Add vec_inlined parameter.
+ Change all callers.
+
+2015-06-11 Martin Sebor <msebor@redhat.com>
+
+ PR sanitizer/65479
+ * dwarf.c (struct line): Add new field idx.
+ (line_compare): Use it.
+ (add_line): Set it.
+ (read_line_info): Reset it.
+
+2015-05-29 Tristan Gingold <gingold@adacore.com>
+
+ * pecoff.c: New file.
+ * Makefile.am (FORMAT_FILES): Add pecoff.c and dependencies.
+ * Makefile.in: Regenerate.
+ * filetype.awk: Detect pecoff.
+ * configure.ac: Define BACKTRACE_SUPPORTS_DATA on elf platforms.
+ Add pecoff.
+ * btest.c (test5): Test enabled only if BACKTRACE_SUPPORTS_DATA is
+ true.
+ * backtrace-supported.h.in (BACKTRACE_SUPPORTS_DATA): Define.
+ * configure: Regenerate.
+ * pecoff.c: New file.
+
+2015-05-13 Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
+
+ * Makefile.in: Regenerated with automake-1.11.6.
+ * aclocal.m4: Likewise.
+ * configure: Likewise.
+
+2015-01-24 Matthias Klose <doko@ubuntu.com>
+
+ * configure.ac: Move AM_ENABLE_MULTILIB before AC_PROG_CC.
+ * configure: Regenerate.
+
+2015-01-05 Jakub Jelinek <jakub@redhat.com>
+
+ Update copyright years.
+
+2014-11-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR bootstrap/63784
+ * configure: Regenerated.
+
+2014-11-11 David Malcolm <dmalcolm@redhat.com>
+
+ * ChangeLog.jit: New.
+
+2014-11-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR target/63610
+ * configure: Regenerate.
+
+2014-10-23 Ian Lance Taylor <iant@google.com>
+
+ * internal.h (backtrace_atomic_load_pointer) [no atomic or sync]:
+ Fix to return void *.
+
+2014-05-08 Ian Lance Taylor <iant@google.com>
+
+ * mmap.c (backtrace_free): If freeing a large aligned block of
+ memory, call munmap rather than holding onto it.
+ (backtrace_vector_grow): When growing a vector, double the number
+ of pages requested. When releasing the old version of a grown
+ vector, pass the correct size to backtrace_free.
+
+2014-03-07 Ian Lance Taylor <iant@google.com>
+
+ * sort.c (backtrace_qsort): Use middle element as pivot.
+
+2014-03-06 Ian Lance Taylor <iant@google.com>
+
+ * sort.c: New file.
+ * stest.c: New file.
+ * internal.h (backtrace_qsort): Declare.
+ * dwarf.c (read_abbrevs): Call backtrace_qsort instead of qsort.
+ (read_line_info, read_function_entry): Likewise.
+ (read_function_info, build_dwarf_data): Likewise.
+ * elf.c (elf_initialize_syminfo): Likewise.
+ * Makefile.am (libbacktrace_la_SOURCES): Add sort.c.
+ (stest_SOURCES, stest_LDADD): Define.
+ (check_PROGRAMS): Add stest.
+
+2014-02-07 Misty De Meo <misty@brew.sh>
+
+ PR target/58710
+ * configure.ac: Use AC_LINK_IFELSE in check for
+ _Unwind_GetIPInfo.
+ * configure: Regenerate.
+
+2014-01-02 Richard Sandiford <rdsandiford@googlemail.com>
+
+ Update copyright years
+
+2013-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ * elf.c (ET_DYN): Undefine and define again.
+ (elf_add): Add exe argument, if true and ehdr.e_type is ET_DYN,
+ return early -1 without closing the descriptor.
+ (struct phdr_data): Add exe_descriptor.
+ (phdr_callback): If pd->exe_descriptor is not -1, for very first
+ call if dlpi_name is NULL just call elf_add with the exe_descriptor,
+ otherwise backtrace_close the exe_descriptor if not -1. Adjust
+ call to elf_add.
+ (backtrace_initialize): Adjust call to elf_add. If it returns
+ -1, set pd.exe_descriptor to descriptor, otherwise set it to -1.
+
+2013-12-05 Ian Lance Taylor <iant@google.com>
+
+ * alloc.c (backtrace_vector_finish): Add error_callback and data
+ parameters. Call backtrace_vector_release. Return address base.
+ * mmap.c (backtrace_vector_finish): Add error_callback and data
+ parameters. Return address base.
+ * dwarf.c (read_function_info): Get new address base from
+ backtrace_vector_finish.
+ * internal.h (backtrace_vector_finish): Update declaration.
+
+2013-11-27 Ian Lance Taylor <iant@google.com>
+
+ * dwarf.c (find_address_ranges): New static function, broken out
+ of build_address_map.
+ (build_address_map): Call it.
+ * btest.c (check): Check for missing filename or function, rather
+ than crashing.
+ (f3): Check that enough frames were returned.
+
+2013-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ * backtrace.h (backtrace_syminfo_callback): Add symsize argument.
+ * elf.c (elf_syminfo): Pass 0 or sym->size to the callback as
+ last argument.
+ * btest.c (struct symdata): Add size field.
+ (callback_three): Add symsize argument. Copy it to the data->size
+ field.
+ (f23): Set symdata.size to 0.
+ (test5): Likewise. If sizeof (int) > 1, lookup address of
+ ((uintptr_t) &global) + 1. Verify symdata.val and symdata.size
+ values.
+
+ * atomic.c: Include sys/types.h.
+
+2013-11-18 Ian Lance Taylor <iant@google.com>
+
+ * configure.ac: Check for support of __atomic extensions.
+ * internal.h: Declare or #define atomic functions for use in
+ backtrace code.
+ * atomic.c: New file.
+ * dwarf.c (dwarf_lookup_pc): Use atomic functions.
+ (dwarf_fileline, backtrace_dwarf_add): Likewise.
+ * elf.c (elf_add_syminfo_data, elf_syminfo): Likewise.
+ (backtrace_initialize): Likewise.
+ * fileline.c (fileline_initialize): Likewise.
+ * Makefile.am (libbacktrace_la_SOURCES): Add atomic.c.
+ * configure, config.h.in, Makefile.in: Rebuild.
+
+2013-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * elf.c (SHN_UNDEF): Define.
+ (elf_initialize_syminfo): Add base_address argument. Ignore symbols
+ with st_shndx == SHN_UNDEF. Add base_address to address fields.
+ (elf_add): Adjust caller.
+
+ * elf.c (phdr_callback): Process info->dlpi_addr == 0 normally.
+
+2013-11-16 Ian Lance Taylor <iant@google.com>
+
+ * backtrace.h (backtrace_create_state): Correct comment about
+ threading.
+
+2013-11-15 Ian Lance Taylor <iant@google.com>
+
+ * backtrace.h (backtrace_syminfo): Update comment and parameter
+ name to take any address, not just a PC value.
+ * elf.c (STT_OBJECT): Define.
+ (elf_nosyms): Rename parameter pc to addr.
+ (elf_symbol_search): Rename local variable pc to addr.
+ (elf_initialize_syminfo): Add STT_OBJECT symbols to elf_symbols.
+ (elf_syminfo): Rename parameter pc to addr.
+ * btest.c (global): New global variable.
+ (test5): New test.
+ (main): Call test5.
+
+2013-10-17 Ian Lance Taylor <iant@google.com>
+
+ * elf.c (elf_add): Don't get the wrong offsets if a debug section
+ is missing.
+
+2013-10-15 David Malcolm <dmalcolm@redhat.com>
+
+ * configure.ac: Add --enable-host-shared, setting up
+ pre-existing PIC_FLAG variable within Makefile.am et al.
+ * configure: Regenerate.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-07-23 Alexander Monakov <amonakov@ispras.ru>
* elf.c (elf_syminfo): Loop over the elf_syminfo_data chain.
@@ -292,3 +564,9 @@
2012-09-17 Ian Lance Taylor <iant@google.com>
* Initial implementation.
+
+Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/thirdparty/libbacktrace/alloc.c b/thirdparty/libbacktrace/alloc.c
index d0796737..a9f07a01 100644
--- a/thirdparty/libbacktrace/alloc.c
+++ b/thirdparty/libbacktrace/alloc.c
@@ -1,5 +1,5 @@
/* alloc.c -- Memory allocation without mmap.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,8 @@ POSSIBILITY OF SUCH DAMAGE. */
backtrace functions may not be safely invoked from a signal
handler. */
-/* Allocate memory like malloc. */
+/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
+ report an error. */
void *
backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
@@ -55,7 +56,10 @@ backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
ret = malloc (size);
if (ret == NULL)
- error_callback (data, "malloc", errno);
+ {
+ if (error_callback)
+ error_callback (data, "malloc", errno);
+ }
return ret;
}
@@ -113,12 +117,24 @@ backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
/* Finish the current allocation on VEC. */
-void
-backtrace_vector_finish (struct backtrace_state *state ATTRIBUTE_UNUSED,
- struct backtrace_vector *vec)
+void *
+backtrace_vector_finish (struct backtrace_state *state,
+ struct backtrace_vector *vec,
+ backtrace_error_callback error_callback,
+ void *data)
{
- vec->base = (char *) vec->base + vec->size;
+ void *ret;
+
+ /* With this allocator we call realloc in backtrace_vector_grow,
+ which means we can't easily reuse the memory here. So just
+ release it. */
+ if (!backtrace_vector_release (state, vec, error_callback, data))
+ return NULL;
+ ret = vec->base;
+ vec->base = NULL;
vec->size = 0;
+ vec->alc = 0;
+ return ret;
}
/* Release any extra space allocated for VEC. */
diff --git a/thirdparty/libbacktrace/atomic.c b/thirdparty/libbacktrace/atomic.c
new file mode 100644
index 00000000..cb0ad029
--- /dev/null
+++ b/thirdparty/libbacktrace/atomic.c
@@ -0,0 +1,113 @@
+/* atomic.c -- Support for atomic functions if not present.
+ Copyright (C) 2013-2016 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ (1) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ (2) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ (3) The name of the author may not be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+#include "config.h"
+
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+#include "internal.h"
+
+/* This file holds implementations of the atomic functions that are
+ used if the host compiler has the sync functions but not the atomic
+ functions, as is true of versions of GCC before 4.7. */
+
+#if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS)
+
+/* Do an atomic load of a pointer. */
+
+void *
+backtrace_atomic_load_pointer (void *arg)
+{
+ void **pp;
+ void *p;
+
+ pp = (void **) arg;
+ p = *pp;
+ while (!__sync_bool_compare_and_swap (pp, p, p))
+ p = *pp;
+ return p;
+}
+
+/* Do an atomic load of an int. */
+
+int
+backtrace_atomic_load_int (int *p)
+{
+ int i;
+
+ i = *p;
+ while (!__sync_bool_compare_and_swap (p, i, i))
+ i = *p;
+ return i;
+}
+
+/* Do an atomic store of a pointer. */
+
+void
+backtrace_atomic_store_pointer (void *arg, void *p)
+{
+ void **pp;
+ void *old;
+
+ pp = (void **) arg;
+ old = *pp;
+ while (!__sync_bool_compare_and_swap (pp, old, p))
+ old = *pp;
+}
+
+/* Do an atomic store of a size_t value. */
+
+void
+backtrace_atomic_store_size_t (size_t *p, size_t v)
+{
+ size_t old;
+
+ old = *p;
+ while (!__sync_bool_compare_and_swap (p, old, v))
+ old = *p;
+}
+
+/* Do an atomic store of a int value. */
+
+void
+backtrace_atomic_store_int (int *p, int v)
+{
+ size_t old;
+
+ old = *p;
+ while (!__sync_bool_compare_and_swap (p, old, v))
+ old = *p;
+}
+
+#endif
diff --git a/thirdparty/libbacktrace/backtrace-supported.h.in b/thirdparty/libbacktrace/backtrace-supported.h.in
index c615f640..ab34199f 100644
--- a/thirdparty/libbacktrace/backtrace-supported.h.in
+++ b/thirdparty/libbacktrace/backtrace-supported.h.in
@@ -1,5 +1,5 @@
/* backtrace-supported.h.in -- Whether stack backtrace is supported.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -59,3 +59,8 @@ POSSIBILITY OF SUCH DAMAGE. */
as 0. */
#define BACKTRACE_SUPPORTS_THREADS @BACKTRACE_SUPPORTS_THREADS@
+
+/* BACKTRACE_SUPPORTS_DATA will be #defined'd as 1 if the backtrace_syminfo
+ will work for variables. It will always work for functions. */
+
+#define BACKTRACE_SUPPORTS_DATA @BACKTRACE_SUPPORTS_DATA@
diff --git a/thirdparty/libbacktrace/backtrace.c b/thirdparty/libbacktrace/backtrace.c
index 428f53a2..b89bf554 100644
--- a/thirdparty/libbacktrace/backtrace.c
+++ b/thirdparty/libbacktrace/backtrace.c
@@ -1,5 +1,5 @@
/* backtrace.c -- Entry point for stack backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -32,8 +32,11 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
+#include <sys/types.h>
+
#include "unwind.h"
#include "backtrace.h"
+#include "internal.h"
/* The main backtrace_full routine. */
@@ -53,6 +56,8 @@ struct backtrace_data
void *data;
/* Value to return from backtrace_full. */
int ret;
+ /* Whether there is any memory available. */
+ int can_alloc;
};
/* Unwind library callback routine. This is passed to
@@ -80,8 +85,11 @@ unwind (struct _Unwind_Context *context, void *vdata)
if (!ip_before_insn)
--pc;
- bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
- bdata->error_callback, bdata->data);
+ if (!bdata->can_alloc)
+ bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL);
+ else
+ bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
+ bdata->error_callback, bdata->data);
if (bdata->ret != 0)
return _URC_END_OF_STACK;
@@ -96,6 +104,7 @@ backtrace_full (struct backtrace_state *state, int skip,
backtrace_error_callback error_callback, void *data)
{
struct backtrace_data bdata;
+ void *p;
bdata.skip = skip + 1;
bdata.state = state;
@@ -103,6 +112,18 @@ backtrace_full (struct backtrace_state *state, int skip,
bdata.error_callback = error_callback;
bdata.data = data;
bdata.ret = 0;
+
+ /* If we can't allocate any memory at all, don't try to produce
+ file/line information. */
+ p = backtrace_alloc (state, 4096, NULL, NULL);
+ if (p == NULL)
+ bdata.can_alloc = 0;
+ else
+ {
+ backtrace_free (state, p, 4096, NULL, NULL);
+ bdata.can_alloc = 1;
+ }
+
_Unwind_Backtrace (unwind, &bdata);
return bdata.ret;
}
diff --git a/thirdparty/libbacktrace/backtrace.h b/thirdparty/libbacktrace/backtrace.h
index da16e3d7..d209219d 100644
--- a/thirdparty/libbacktrace/backtrace.h
+++ b/thirdparty/libbacktrace/backtrace.h
@@ -1,5 +1,5 @@
/* backtrace.h -- Public header file for stack backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -89,8 +89,7 @@ typedef void (*backtrace_error_callback) (void *data, const char *msg,
system-specific path names. If not NULL, FILENAME must point to a
permanent buffer. If THREADED is non-zero the state may be
accessed by multiple threads simultaneously, and the library will
- use appropriate locks (this requires that the library be configured
- with --enable-backtrace-threads). If THREADED is zero the state
+ use appropriate atomic operations. If THREADED is zero the state
may only be accessed by one thread at a time. This returns a state
pointer on success, NULL on error. If an error occurs, this will
call the ERROR_CALLBACK routine. */
@@ -170,24 +169,25 @@ extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
/* The type of the callback argument to backtrace_syminfo. DATA and
PC are the arguments passed to backtrace_syminfo. SYMNAME is the
name of the symbol for the corresponding code. SYMVAL is the
- value. SYMNAME will be NULL if no error occurred but the symbol
- could not be found. */
+ value and SYMSIZE is the size of the symbol. SYMNAME will be NULL
+ if no error occurred but the symbol could not be found. */
typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,
const char *symname,
- uintptr_t symval);
-
-/* Given PC, a program counter in the current program, call the
- callback information with the symbol name and value describing the
- function in which PC may be found. This will call either CALLBACK
- or ERROR_CALLBACK exactly once. This returns 1 on success, 0 on
- failure. This function requires the symbol table but does not
- require the debug info. Note that if the symbol table is present
- but PC could not be found in the table, CALLBACK will be called
- with a NULL SYMNAME argument. Returns 1 on success, 0 on
- error. */
-
-extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
+ uintptr_t symval,
+ uintptr_t symsize);
+
+/* Given ADDR, an address or program counter in the current program,
+ call the callback information with the symbol name and value
+ describing the function or variable in which ADDR may be found.
+ This will call either CALLBACK or ERROR_CALLBACK exactly once.
+ This returns 1 on success, 0 on failure. This function requires
+ the symbol table but does not require the debug info. Note that if
+ the symbol table is present but ADDR could not be found in the
+ table, CALLBACK will be called with a NULL SYMNAME argument.
+ Returns 1 on success, 0 on error. */
+
+extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr,
backtrace_syminfo_callback callback,
backtrace_error_callback error_callback,
void *data);
diff --git a/thirdparty/libbacktrace/btest.c b/thirdparty/libbacktrace/btest.c
index cc647b8d..0506d2b1 100644
--- a/thirdparty/libbacktrace/btest.c
+++ b/thirdparty/libbacktrace/btest.c
@@ -1,5 +1,5 @@
/* btest.c -- Test for libbacktrace library
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -92,7 +92,7 @@ struct sdata
struct symdata
{
const char *name;
- uintptr_t val;
+ uintptr_t val, size;
int failed;
};
@@ -129,6 +129,13 @@ check (const char *name, int index, const struct info *all, int want_lineno,
{
if (*failed)
return;
+ if (all[index].filename == NULL || all[index].function == NULL)
+ {
+ fprintf (stderr, "%s: [%d]: missing file name or function name\n",
+ name, index);
+ *failed = 1;
+ return;
+ }
if (strcmp (base (all[index].filename), "btest.c") != 0)
{
fprintf (stderr, "%s: [%d]: got %s expected test.c\n", name, index,
@@ -238,7 +245,8 @@ error_callback_two (void *vdata, const char *msg, int errnum)
static void
callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
- const char *symname, uintptr_t symval)
+ const char *symname, uintptr_t symval,
+ uintptr_t symsize)
{
struct symdata *data = (struct symdata *) vdata;
@@ -250,6 +258,7 @@ callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
assert (data->name != NULL);
}
data->val = symval;
+ data->size = symsize;
}
/* The backtrace_syminfo error callback function. */
@@ -308,6 +317,14 @@ f3 (int f1line, int f2line)
data.failed = 1;
}
+ if (data.index < 3)
+ {
+ fprintf (stderr,
+ "test1: not enough frames; got %zu, expected at least 3\n",
+ data.index);
+ data.failed = 1;
+ }
+
check ("test1", 0, all, f3line, "f3", &data.failed);
check ("test1", 1, all, f2line, "f2", &data.failed);
check ("test1", 2, all, f1line, "test1", &data.failed);
@@ -458,6 +475,7 @@ f23 (int f1line, int f2line)
symdata.name = NULL;
symdata.val = 0;
+ symdata.size = 0;
symdata.failed = 0;
i = backtrace_syminfo (state, addrs[j], callback_three,
@@ -598,6 +616,78 @@ f33 (int f1line, int f2line)
return failures;
}
+#if BACKTRACE_SUPPORTS_DATA
+
+int global = 1;
+
+static int
+test5 (void)
+{
+ struct symdata symdata;
+ int i;
+ uintptr_t addr = (uintptr_t) &global;
+
+ if (sizeof (global) > 1)
+ addr += 1;
+
+ symdata.name = NULL;
+ symdata.val = 0;
+ symdata.size = 0;
+ symdata.failed = 0;
+
+ i = backtrace_syminfo (state, addr, callback_three,
+ error_callback_three, &symdata);
+ if (i == 0)
+ {
+ fprintf (stderr,
+ "test5: unexpected return value from backtrace_syminfo %d\n",
+ i);
+ symdata.failed = 1;
+ }
+
+ if (!symdata.failed)
+ {
+ if (symdata.name == NULL)
+ {
+ fprintf (stderr, "test5: NULL syminfo name\n");
+ symdata.failed = 1;
+ }
+ else if (strcmp (symdata.name, "global") != 0)
+ {
+ fprintf (stderr,
+ "test5: unexpected syminfo name got %s expected %s\n",
+ symdata.name, "global");
+ symdata.failed = 1;
+ }
+ else if (symdata.val != (uintptr_t) &global)
+ {
+ fprintf (stderr,
+ "test5: unexpected syminfo value got %lx expected %lx\n",
+ (unsigned long) symdata.val,
+ (unsigned long) (uintptr_t) &global);
+ symdata.failed = 1;
+ }
+ else if (symdata.size != sizeof (global))
+ {
+ fprintf (stderr,
+ "test5: unexpected syminfo size got %lx expected %lx\n",
+ (unsigned long) symdata.size,
+ (unsigned long) sizeof (global));
+ symdata.failed = 1;
+ }
+ }
+
+ printf ("%s: backtrace_syminfo variable\n",
+ symdata.failed ? "FAIL" : "PASS");
+
+ if (symdata.failed)
+ ++failures;
+
+ return failures;
+}
+
+#endif /* BACKTRACE_SUPPORTS_DATA */
+
static void
error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
int errnum)
@@ -622,6 +712,9 @@ main (int argc ATTRIBUTE_UNUSED, char **argv)
test2 ();
test3 ();
test4 ();
+#if BACKTRACE_SUPPORTS_DATA
+ test5 ();
+#endif
#endif
exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
diff --git a/thirdparty/libbacktrace/config.h.in.cmake b/thirdparty/libbacktrace/config.h.in.cmake
index 4ac13266..876ea359 100644
--- a/thirdparty/libbacktrace/config.h.in.cmake
+++ b/thirdparty/libbacktrace/config.h.in.cmake
@@ -1,6 +1,9 @@
/* ELF size: 32 or 64 */
#define BACKTRACE_ELF_SIZE @BACKTRACE_ELF_SIZE@
+/* Define to 1 if you have the __atomic functions */
+#cmakedefine HAVE_ATOMIC_FUNCTIONS 1
+
/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_STRNLEN 1
diff --git a/thirdparty/libbacktrace/dwarf.c b/thirdparty/libbacktrace/dwarf.c
index 501afe55..55b8d7dc 100644
--- a/thirdparty/libbacktrace/dwarf.c
+++ b/thirdparty/libbacktrace/dwarf.c
@@ -1,5 +1,5 @@
/* dwarf.c -- Get file/line information from DWARF for backtraces.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -211,6 +211,10 @@ struct line
const char *filename;
/* Line number. */
int lineno;
+ /* Index of the object in the original array read from the DWARF
+ section, before it has been sorted. The index makes it possible
+ to use Quicksort and maintain stability. */
+ int idx;
};
/* A growable vector of line number information. This is used while
@@ -940,9 +944,10 @@ unit_addrs_search (const void *vkey, const void *ventry)
return 0;
}
-/* Sort the line vector by PC. We want a stable sort here. We know
- that the pointers are into the same array, so it is safe to compare
- them directly. */
+/* Sort the line vector by PC. We want a stable sort here to maintain
+ the order of lines for the same PC values. Since the sequence is
+ being sorted in place, their addresses cannot be relied on to
+ maintain stability. That is the purpose of the index member. */
static int
line_compare (const void *v1, const void *v2)
@@ -954,9 +959,9 @@ line_compare (const void *v1, const void *v2)
return -1;
else if (ln1->pc > ln2->pc)
return 1;
- else if (ln1 < ln2)
+ else if (ln1->idx < ln2->idx)
return -1;
- else if (ln1 > ln2)
+ else if (ln1->idx > ln2->idx)
return 1;
else
return 0;
@@ -1134,8 +1139,8 @@ read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,
++num_abbrevs;
}
- qsort (abbrevs->abbrevs, abbrevs->num_abbrevs, sizeof (struct abbrev),
- abbrev_compare);
+ backtrace_qsort (abbrevs->abbrevs, abbrevs->num_abbrevs,
+ sizeof (struct abbrev), abbrev_compare);
return 1;
@@ -1235,54 +1240,24 @@ add_unit_ranges (struct backtrace_state *state, uintptr_t base_address,
return 1;
}
-/* Build a mapping from address ranges to the compilation units where
- the line number information for that range can be found. Returns 1
- on success, 0 on failure. */
+/* Find the address range covered by a compilation unit, reading from
+ UNIT_BUF and adding values to U. Returns 1 if all data could be
+ read, 0 if there is some error. */
static int
-build_address_map (struct backtrace_state *state, uintptr_t base_address,
- const unsigned char *dwarf_info, size_t dwarf_info_size,
- const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
- const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
- const unsigned char *dwarf_str, size_t dwarf_str_size,
- int is_bigendian, backtrace_error_callback error_callback,
- void *data, struct unit_addrs_vector *addrs)
+find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
+ struct dwarf_buf *unit_buf,
+ const unsigned char *dwarf_str, size_t dwarf_str_size,
+ const unsigned char *dwarf_ranges,
+ size_t dwarf_ranges_size,
+ int is_bigendian, backtrace_error_callback error_callback,
+ void *data, struct unit *u,
+ struct unit_addrs_vector *addrs)
{
- struct dwarf_buf info;
- struct abbrevs abbrevs;
-
- memset (&addrs->vec, 0, sizeof addrs->vec);
- addrs->count = 0;
-
- /* Read through the .debug_info section. FIXME: Should we use the
- .debug_aranges section? gdb and addr2line don't use it, but I'm
- not sure why. */
-
- info.name = ".debug_info";
- info.start = dwarf_info;
- info.buf = dwarf_info;
- info.left = dwarf_info_size;
- info.is_bigendian = is_bigendian;
- info.error_callback = error_callback;
- info.data = data;
- info.reported_underflow = 0;
-
- memset (&abbrevs, 0, sizeof abbrevs);
- while (info.left > 0)
+ while (unit_buf->left > 0)
{
- const unsigned char *unit_data_start;
- uint64_t len;
- int is_dwarf64;
- struct dwarf_buf unit_buf;
- int version;
- uint64_t abbrev_offset;
- const struct abbrev *abbrev;
- int addrsize;
- const unsigned char *unit_data;
- size_t unit_data_len;
- size_t unit_data_offset;
uint64_t code;
- size_t i;
+ const struct abbrev *abbrev;
uint64_t lowpc;
int have_lowpc;
uint64_t highpc;
@@ -1290,57 +1265,15 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
int highpc_is_relative;
uint64_t ranges;
int have_ranges;
- uint64_t lineoff;
- int have_lineoff;
- const char *filename;
- const char *comp_dir;
-
- if (info.reported_underflow)
- goto fail;
-
- unit_data_start = info.buf;
-
- is_dwarf64 = 0;
- len = read_uint32 (&info);
- if (len == 0xffffffff)
- {
- len = read_uint64 (&info);
- is_dwarf64 = 1;
- }
-
- unit_buf = info;
- unit_buf.left = len;
-
- if (!advance (&info, len))
- goto fail;
-
- version = read_uint16 (&unit_buf);
- if (version < 2 || version > 4)
- {
- dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
- goto fail;
- }
-
- abbrev_offset = read_offset (&unit_buf, is_dwarf64);
- if (!read_abbrevs (state, abbrev_offset, dwarf_abbrev, dwarf_abbrev_size,
- is_bigendian, error_callback, data, &abbrevs))
- goto fail;
-
- addrsize = read_byte (&unit_buf);
-
- unit_data = unit_buf.buf;
- unit_data_len = unit_buf.left;
- unit_data_offset = unit_buf.buf - unit_data_start;
+ size_t i;
- /* We only look at the first attribute in the compilation unit.
- In practice this will be a DW_TAG_compile_unit which will
- tell us the PC range and where to find the line number
- information. */
+ code = read_uleb128 (unit_buf);
+ if (code == 0)
+ return 1;
- code = read_uleb128 (&unit_buf);
- abbrev = lookup_abbrev (&abbrevs, code, error_callback, data);
+ abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
if (abbrev == NULL)
- goto fail;
+ return 0;
lowpc = 0;
have_lowpc = 0;
@@ -1349,18 +1282,14 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
highpc_is_relative = 0;
ranges = 0;
have_ranges = 0;
- lineoff = 0;
- have_lineoff = 0;
- filename = NULL;
- comp_dir = NULL;
for (i = 0; i < abbrev->num_attrs; ++i)
{
struct attr_val val;
- if (!read_attribute (abbrev->attrs[i].form, &unit_buf, is_dwarf64,
- version, addrsize, dwarf_str, dwarf_str_size,
- &val))
- goto fail;
+ if (!read_attribute (abbrev->attrs[i].form, unit_buf,
+ u->is_dwarf64, u->version, u->addrsize,
+ dwarf_str, dwarf_str_size, &val))
+ return 0;
switch (abbrev->attrs[i].name)
{
@@ -1371,6 +1300,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
have_lowpc = 1;
}
break;
+
case DW_AT_high_pc:
if (val.encoding == ATTR_VAL_ADDRESS)
{
@@ -1384,6 +1314,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
highpc_is_relative = 1;
}
break;
+
case DW_AT_ranges:
if (val.encoding == ATTR_VAL_UINT
|| val.encoding == ATTR_VAL_REF_SECTION)
@@ -1392,73 +1323,46 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
have_ranges = 1;
}
break;
+
case DW_AT_stmt_list:
- if (val.encoding == ATTR_VAL_UINT
- || val.encoding == ATTR_VAL_REF_SECTION)
- {
- lineoff = val.u.uint;
- have_lineoff = 1;
- }
+ if (abbrev->tag == DW_TAG_compile_unit
+ && (val.encoding == ATTR_VAL_UINT
+ || val.encoding == ATTR_VAL_REF_SECTION))
+ u->lineoff = val.u.uint;
break;
+
case DW_AT_name:
- if (val.encoding == ATTR_VAL_STRING)
- filename = val.u.string;
+ if (abbrev->tag == DW_TAG_compile_unit
+ && val.encoding == ATTR_VAL_STRING)
+ u->filename = val.u.string;
break;
+
case DW_AT_comp_dir:
- if (val.encoding == ATTR_VAL_STRING)
- comp_dir = val.u.string;
+ if (abbrev->tag == DW_TAG_compile_unit
+ && val.encoding == ATTR_VAL_STRING)
+ u->comp_dir = val.u.string;
break;
+
default:
break;
}
}
- if (unit_buf.reported_underflow)
- goto fail;
-
- if (((have_lowpc && have_highpc) || have_ranges) && have_lineoff)
+ if (abbrev->tag == DW_TAG_compile_unit
+ || abbrev->tag == DW_TAG_subprogram)
{
- struct unit *u;
- struct unit_addrs a;
-
- u = ((struct unit *)
- backtrace_alloc (state, sizeof *u, error_callback, data));
- if (u == NULL)
- goto fail;
- u->unit_data = unit_data;
- u->unit_data_len = unit_data_len;
- u->unit_data_offset = unit_data_offset;
- u->version = version;
- u->is_dwarf64 = is_dwarf64;
- u->addrsize = addrsize;
- u->filename = filename;
- u->comp_dir = comp_dir;
- u->abs_filename = NULL;
- u->lineoff = lineoff;
- u->abbrevs = abbrevs;
- memset (&abbrevs, 0, sizeof abbrevs);
-
- /* The actual line number mappings will be read as
- needed. */
- u->lines = NULL;
- u->lines_count = 0;
- u->function_addrs = NULL;
- u->function_addrs_count = 0;
-
if (have_ranges)
{
if (!add_unit_ranges (state, base_address, u, ranges, lowpc,
is_bigendian, dwarf_ranges,
- dwarf_ranges_size, error_callback, data,
- addrs))
- {
- free_abbrevs (state, &u->abbrevs, error_callback, data);
- backtrace_free (state, u, sizeof *u, error_callback, data);
- goto fail;
- }
+ dwarf_ranges_size, error_callback,
+ data, addrs))
+ return 0;
}
- else
+ else if (have_lowpc && have_highpc)
{
+ struct unit_addrs a;
+
if (highpc_is_relative)
highpc += lowpc;
a.low = lowpc;
@@ -1467,17 +1371,146 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
if (!add_unit_addr (state, base_address, a, error_callback, data,
addrs))
- {
- free_abbrevs (state, &u->abbrevs, error_callback, data);
- backtrace_free (state, u, sizeof *u, error_callback, data);
- goto fail;
- }
+ return 0;
}
+
+ /* If we found the PC range in the DW_TAG_compile_unit, we
+ can stop now. */
+ if (abbrev->tag == DW_TAG_compile_unit
+ && (have_ranges || (have_lowpc && have_highpc)))
+ return 1;
}
- else
+
+ if (abbrev->has_children)
+ {
+ if (!find_address_ranges (state, base_address, unit_buf,
+ dwarf_str, dwarf_str_size,
+ dwarf_ranges, dwarf_ranges_size,
+ is_bigendian, error_callback, data,
+ u, addrs))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* Build a mapping from address ranges to the compilation units where
+ the line number information for that range can be found. Returns 1
+ on success, 0 on failure. */
+
+static int
+build_address_map (struct backtrace_state *state, uintptr_t base_address,
+ const unsigned char *dwarf_info, size_t dwarf_info_size,
+ const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
+ const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
+ const unsigned char *dwarf_str, size_t dwarf_str_size,
+ int is_bigendian, backtrace_error_callback error_callback,
+ void *data, struct unit_addrs_vector *addrs)
+{
+ struct dwarf_buf info;
+ struct abbrevs abbrevs;
+
+ memset (&addrs->vec, 0, sizeof addrs->vec);
+ addrs->count = 0;
+
+ /* Read through the .debug_info section. FIXME: Should we use the
+ .debug_aranges section? gdb and addr2line don't use it, but I'm
+ not sure why. */
+
+ info.name = ".debug_info";
+ info.start = dwarf_info;
+ info.buf = dwarf_info;
+ info.left = dwarf_info_size;
+ info.is_bigendian = is_bigendian;
+ info.error_callback = error_callback;
+ info.data = data;
+ info.reported_underflow = 0;
+
+ memset (&abbrevs, 0, sizeof abbrevs);
+ while (info.left > 0)
+ {
+ const unsigned char *unit_data_start;
+ uint64_t len;
+ int is_dwarf64;
+ struct dwarf_buf unit_buf;
+ int version;
+ uint64_t abbrev_offset;
+ int addrsize;
+ struct unit *u;
+
+ if (info.reported_underflow)
+ goto fail;
+
+ unit_data_start = info.buf;
+
+ is_dwarf64 = 0;
+ len = read_uint32 (&info);
+ if (len == 0xffffffff)
+ {
+ len = read_uint64 (&info);
+ is_dwarf64 = 1;
+ }
+
+ unit_buf = info;
+ unit_buf.left = len;
+
+ if (!advance (&info, len))
+ goto fail;
+
+ version = read_uint16 (&unit_buf);
+ if (version < 2 || version > 4)
{
- free_abbrevs (state, &abbrevs, error_callback, data);
- memset (&abbrevs, 0, sizeof abbrevs);
+ dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
+ goto fail;
+ }
+
+ abbrev_offset = read_offset (&unit_buf, is_dwarf64);
+ if (!read_abbrevs (state, abbrev_offset, dwarf_abbrev, dwarf_abbrev_size,
+ is_bigendian, error_callback, data, &abbrevs))
+ goto fail;
+
+ addrsize = read_byte (&unit_buf);
+
+ u = ((struct unit *)
+ backtrace_alloc (state, sizeof *u, error_callback, data));
+ if (u == NULL)
+ goto fail;
+ u->unit_data = unit_buf.buf;
+ u->unit_data_len = unit_buf.left;
+ u->unit_data_offset = unit_buf.buf - unit_data_start;
+ u->version = version;
+ u->is_dwarf64 = is_dwarf64;
+ u->addrsize = addrsize;
+ u->filename = NULL;
+ u->comp_dir = NULL;
+ u->abs_filename = NULL;
+ u->lineoff = 0;
+ u->abbrevs = abbrevs;
+ memset (&abbrevs, 0, sizeof abbrevs);
+
+ /* The actual line number mappings will be read as needed. */
+ u->lines = NULL;
+ u->lines_count = 0;
+ u->function_addrs = NULL;
+ u->function_addrs_count = 0;
+
+ if (!find_address_ranges (state, base_address, &unit_buf,
+ dwarf_str, dwarf_str_size,
+ dwarf_ranges, dwarf_ranges_size,
+ is_bigendian, error_callback, data,
+ u, addrs))
+ {
+ free_abbrevs (state, &u->abbrevs, error_callback, data);
+ backtrace_free (state, u, sizeof *u, error_callback, data);
+ goto fail;
+ }
+
+ if (unit_buf.reported_underflow)
+ {
+ free_abbrevs (state, &u->abbrevs, error_callback, data);
+ backtrace_free (state, u, sizeof *u, error_callback, data);
+ goto fail;
}
}
if (info.reported_underflow)
@@ -1523,6 +1556,7 @@ add_line (struct backtrace_state *state, struct dwarf_data *ddata,
ln->filename = filename;
ln->lineno = lineno;
+ ln->idx = vec->count;
++vec->count;
@@ -1983,12 +2017,13 @@ read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
ln->pc = (uintptr_t) -1;
ln->filename = NULL;
ln->lineno = 0;
+ ln->idx = 0;
if (!backtrace_vector_release (state, &vec.vec, error_callback, data))
goto fail;
ln = (struct line *) vec.vec.base;
- qsort (ln, vec.count, sizeof (struct line), line_compare);
+ backtrace_qsort (ln, vec.count, sizeof (struct line), line_compare);
*lines = ln;
*lines_count = vec.count;
@@ -2215,7 +2250,8 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
struct unit *u, uint64_t base, struct dwarf_buf *unit_buf,
const struct line_header *lhdr,
backtrace_error_callback error_callback, void *data,
- struct function_vector *vec)
+ struct function_vector *vec_function,
+ struct function_vector *vec_inlined)
{
while (unit_buf->left > 0)
{
@@ -2223,6 +2259,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
const struct abbrev *abbrev;
int is_function;
struct function *function;
+ struct function_vector *vec;
size_t i;
uint64_t lowpc;
int have_lowpc;
@@ -2244,6 +2281,11 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
|| abbrev->tag == DW_TAG_entry_point
|| abbrev->tag == DW_TAG_inlined_subroutine);
+ if (abbrev->tag == DW_TAG_inlined_subroutine)
+ vec = vec_inlined;
+ else
+ vec = vec_function;
+
function = NULL;
if (is_function)
{
@@ -2423,7 +2465,8 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
if (!is_function)
{
if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
- error_callback, data, vec))
+ error_callback, data, vec_function,
+ vec_inlined))
return 0;
}
else
@@ -2436,7 +2479,8 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
memset (&fvec, 0, sizeof fvec);
if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
- error_callback, data, &fvec))
+ error_callback, data, vec_function,
+ &fvec))
return 0;
if (fvec.count > 0)
@@ -2448,9 +2492,9 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
return 0;
faddrs = (struct function_addrs *) fvec.vec.base;
- qsort (faddrs, fvec.count,
- sizeof (struct function_addrs),
- function_addrs_compare);
+ backtrace_qsort (faddrs, fvec.count,
+ sizeof (struct function_addrs),
+ function_addrs_compare);
function->function_addrs = faddrs;
function->function_addrs_count = fvec.count;
@@ -2500,31 +2544,35 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
while (unit_buf.left > 0)
{
if (!read_function_entry (state, ddata, u, 0, &unit_buf, lhdr,
- error_callback, data, pfvec))
+ error_callback, data, pfvec, pfvec))
return;
}
if (pfvec->count == 0)
return;
- addrs = (struct function_addrs *) pfvec->vec.base;
addrs_count = pfvec->count;
if (fvec == NULL)
{
if (!backtrace_vector_release (state, &lvec.vec, error_callback, data))
return;
+ addrs = (struct function_addrs *) pfvec->vec.base;
}
else
{
/* Finish this list of addresses, but leave the remaining space in
the vector available for the next function unit. */
- backtrace_vector_finish (state, &fvec->vec);
+ addrs = ((struct function_addrs *)
+ backtrace_vector_finish (state, &fvec->vec,
+ error_callback, data));
+ if (addrs == NULL)
+ return;
fvec->count = 0;
}
- qsort (addrs, addrs_count, sizeof (struct function_addrs),
- function_addrs_compare);
+ backtrace_qsort (addrs, addrs_count, sizeof (struct function_addrs),
+ function_addrs_compare);
*ret_addrs = addrs;
*ret_addrs_count = addrs_count;
@@ -2643,12 +2691,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
&& pc < (entry - 1)->high)
{
if (state->threaded)
- {
- /* Use __sync_bool_compare_and_swap to do a
- load-acquire. */
- while (!__sync_bool_compare_and_swap (&u->lines, lines, lines))
- lines = u->lines;
- }
+ lines = (struct line *) backtrace_atomic_load_pointer (&u->lines);
if (lines != (struct line *) (uintptr_t) -1)
break;
@@ -2659,13 +2702,8 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
lines = u->lines;
}
- /* Do a load-acquire of u->lines. */
if (state->threaded)
- {
- /* Use __sync_bool_compare_and_swap to do an atomic load. */
- while (!__sync_bool_compare_and_swap (&u->lines, lines, lines))
- lines = u->lines;
- }
+ lines = backtrace_atomic_load_pointer (&u->lines);
new_data = 0;
if (lines == NULL)
@@ -2713,12 +2751,11 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
}
else
{
- __sync_bool_compare_and_swap (&u->lines_count, 0, count);
- __sync_bool_compare_and_swap (&u->function_addrs, NULL,
- function_addrs);
- __sync_bool_compare_and_swap (&u->function_addrs_count, 0,
- function_addrs_count);
- __sync_bool_compare_and_swap (&u->lines, NULL, lines);
+ backtrace_atomic_store_size_t (&u->lines_count, count);
+ backtrace_atomic_store_pointer (&u->function_addrs, function_addrs);
+ backtrace_atomic_store_size_t (&u->function_addrs_count,
+ function_addrs_count);
+ backtrace_atomic_store_pointer (&u->lines, lines);
}
}
@@ -2849,11 +2886,7 @@ dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
pp = (struct dwarf_data **) (void *) &state->fileline_data;
while (1)
{
- ddata = *pp;
- /* Atomic load. */
- while (!__sync_bool_compare_and_swap (pp, ddata, ddata))
- ddata = *pp;
-
+ ddata = backtrace_atomic_load_pointer (pp);
if (ddata == NULL)
break;
@@ -2906,7 +2939,8 @@ build_dwarf_data (struct backtrace_state *state,
return NULL;
addrs = (struct unit_addrs *) addrs_vec.vec.base;
addrs_count = addrs_vec.count;
- qsort (addrs, addrs_count, sizeof (struct unit_addrs), unit_addrs_compare);
+ backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
+ unit_addrs_compare);
fdata = ((struct dwarf_data *)
backtrace_alloc (state, sizeof (struct dwarf_data),
@@ -2985,10 +3019,7 @@ backtrace_dwarf_add (struct backtrace_state *state,
{
struct dwarf_data *p;
- /* Atomic load. */
- p = *pp;
- while (!__sync_bool_compare_and_swap (pp, p, p))
- p = *pp;
+ p = backtrace_atomic_load_pointer (pp);
if (p == NULL)
break;
diff --git a/thirdparty/libbacktrace/elf.c b/thirdparty/libbacktrace/elf.c
index c1dbc549..05cc5c04 100644
--- a/thirdparty/libbacktrace/elf.c
+++ b/thirdparty/libbacktrace/elf.c
@@ -1,5 +1,5 @@
/* elf.c -- Get debug data from an ELF file for backtraces.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -96,11 +96,14 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
#undef ELFDATA2LSB
#undef ELFDATA2MSB
#undef EV_CURRENT
+#undef ET_DYN
#undef SHN_LORESERVE
#undef SHN_XINDEX
+#undef SHN_UNDEF
#undef SHT_SYMTAB
#undef SHT_STRTAB
#undef SHT_DYNSYM
+#undef STT_OBJECT
#undef STT_FUNC
/* Basic types. */
@@ -169,6 +172,8 @@ typedef struct {
#define EV_CURRENT 1
+#define ET_DYN 3
+
typedef struct {
b_elf_word sh_name; /* Section name, index in string tbl */
b_elf_word sh_type; /* Type of section */
@@ -182,6 +187,7 @@ typedef struct {
b_elf_wxword sh_entsize; /* Entry size if section holds table */
} b_elf_shdr; /* Elf_Shdr. */
+#define SHN_UNDEF 0x0000 /* Undefined section */
#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
@@ -215,6 +221,7 @@ typedef struct
#endif /* BACKTRACE_ELF_SIZE != 32 */
+#define STT_OBJECT 1
#define STT_FUNC 2
/* An index of ELF sections we care about. */
@@ -293,7 +300,7 @@ elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
static void
elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
- uintptr_t pc ATTRIBUTE_UNUSED,
+ uintptr_t addr ATTRIBUTE_UNUSED,
backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
backtrace_error_callback error_callback, void *data)
{
@@ -316,7 +323,7 @@ elf_symbol_compare (const void *v1, const void *v2)
return 0;
}
-/* Compare a PC against an elf_symbol for bsearch. We allocate one
+/* Compare an ADDR against an elf_symbol for bsearch. We allocate one
extra entry in the array so that this can look safely at the next
entry. */
@@ -325,12 +332,12 @@ elf_symbol_search (const void *vkey, const void *ventry)
{
const uintptr_t *key = (const uintptr_t *) vkey;
const struct elf_symbol *entry = (const struct elf_symbol *) ventry;
- uintptr_t pc;
+ uintptr_t addr;
- pc = *key;
- if (pc < entry->address)
+ addr = *key;
+ if (addr < entry->address)
return -1;
- else if (pc >= entry->address + entry->size)
+ else if (addr >= entry->address + entry->size)
return 1;
else
return 0;
@@ -340,6 +347,7 @@ elf_symbol_search (const void *vkey, const void *ventry)
static int
elf_initialize_syminfo (struct backtrace_state *state,
+ uintptr_t base_address,
const unsigned char *symtab_data, size_t symtab_size,
const unsigned char *strtab, size_t strtab_size,
backtrace_error_callback error_callback,
@@ -360,7 +368,11 @@ elf_initialize_syminfo (struct backtrace_state *state,
elf_symbol_count = 0;
for (i = 0; i < sym_count; ++i, ++sym)
{
- if ((sym->st_info & 0xf) == STT_FUNC)
+ int info;
+
+ info = sym->st_info & 0xf;
+ if ((info == STT_FUNC || info == STT_OBJECT)
+ && sym->st_shndx != SHN_UNDEF)
++elf_symbol_count;
}
@@ -375,7 +387,12 @@ elf_initialize_syminfo (struct backtrace_state *state,
j = 0;
for (i = 0; i < sym_count; ++i, ++sym)
{
- if ((sym->st_info & 0xf) != STT_FUNC)
+ int info;
+
+ info = sym->st_info & 0xf;
+ if (info != STT_FUNC && info != STT_OBJECT)
+ continue;
+ if (sym->st_shndx == SHN_UNDEF)
continue;
if (sym->st_name >= strtab_size)
{
@@ -385,13 +402,13 @@ elf_initialize_syminfo (struct backtrace_state *state,
return 0;
}
elf_symbols[j].name = (const char *) strtab + sym->st_name;
- elf_symbols[j].address = sym->st_value;
+ elf_symbols[j].address = sym->st_value + base_address;
elf_symbols[j].size = sym->st_size;
++j;
}
- qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol),
- elf_symbol_compare);
+ backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol),
+ elf_symbol_compare);
sdata->next = NULL;
sdata->symbols = elf_symbols;
@@ -428,10 +445,7 @@ elf_add_syminfo_data (struct backtrace_state *state,
{
struct elf_syminfo_data *p;
- /* Atomic load. */
- p = *pp;
- while (!__sync_bool_compare_and_swap (pp, p, p))
- p = *pp;
+ p = backtrace_atomic_load_pointer (pp);
if (p == NULL)
break;
@@ -445,10 +459,10 @@ elf_add_syminfo_data (struct backtrace_state *state,
}
}
-/* Return the symbol name and value for a PC. */
+/* Return the symbol name and value for an ADDR. */
static void
-elf_syminfo (struct backtrace_state *state, uintptr_t pc,
+elf_syminfo (struct backtrace_state *state, uintptr_t addr,
backtrace_syminfo_callback callback,
backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
void *data)
@@ -463,7 +477,7 @@ elf_syminfo (struct backtrace_state *state, uintptr_t pc,
edata = edata->next)
{
sym = ((struct elf_symbol *)
- bsearch (&pc, edata->symbols, edata->count,
+ bsearch (&addr, edata->symbols, edata->count,
sizeof (struct elf_symbol), elf_symbol_search));
if (sym != NULL)
break;
@@ -476,16 +490,12 @@ elf_syminfo (struct backtrace_state *state, uintptr_t pc,
pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
while (1)
{
- edata = *pp;
- /* Atomic load. */
- while (!__sync_bool_compare_and_swap (pp, edata, edata))
- edata = *pp;
-
+ edata = backtrace_atomic_load_pointer (pp);
if (edata == NULL)
break;
sym = ((struct elf_symbol *)
- bsearch (&pc, edata->symbols, edata->count,
+ bsearch (&addr, edata->symbols, edata->count,
sizeof (struct elf_symbol), elf_symbol_search));
if (sym != NULL)
break;
@@ -495,17 +505,21 @@ elf_syminfo (struct backtrace_state *state, uintptr_t pc,
}
if (sym == NULL)
- callback (data, pc, NULL, 0);
+ callback (data, addr, NULL, 0, 0);
else
- callback (data, pc, sym->name, sym->address);
+ callback (data, addr, sym->name, sym->address, sym->size);
}
-/* Add the backtrace data for one ELF file. */
+/* Add the backtrace data for one ELF file. Returns 1 on success,
+ 0 on failure (in both cases descriptor is closed) or -1 if exe
+ is non-zero and the ELF file is ET_DYN, which tells the caller that
+ elf_add will need to be called on the descriptor again after
+ base_address is determined. */
static int
elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
backtrace_error_callback error_callback, void *data,
- fileline *fileline_fn, int *found_sym, int *found_dwarf)
+ fileline *fileline_fn, int *found_sym, int *found_dwarf, int exe)
{
struct backtrace_view ehdr_view;
b_elf_ehdr ehdr;
@@ -584,6 +598,12 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
goto fail;
}
+ /* If the executable is ET_DYN, it is either a PIE, or we are running
+ directly a shared library with .interp. We need to wait for
+ dl_iterate_phdr in that case to determine the actual base_address. */
+ if (exe && ehdr.e_type == ET_DYN)
+ return -1;
+
shoff = ehdr.e_shoff;
shnum = ehdr.e_shnum;
shstrndx = ehdr.e_shstrndx;
@@ -725,7 +745,7 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
if (sdata == NULL)
goto fail;
- if (!elf_initialize_syminfo (state,
+ if (!elf_initialize_syminfo (state, base_address,
symtab_view.data, symtab_shdr->sh_size,
strtab_view.data, strtab_shdr->sh_size,
error_callback, data, sdata))
@@ -759,6 +779,8 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
{
off_t end;
+ if (sections[i].size == 0)
+ continue;
if (min_offset == 0 || sections[i].offset < min_offset)
min_offset = sections[i].offset;
end = sections[i].offset + sections[i].size;
@@ -785,8 +807,13 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
descriptor = -1;
for (i = 0; i < (int) DEBUG_MAX; ++i)
- sections[i].data = ((const unsigned char *) debug_view.data
- + (sections[i].offset - min_offset));
+ {
+ if (sections[i].size == 0)
+ sections[i].data = NULL;
+ else
+ sections[i].data = ((const unsigned char *) debug_view.data
+ + (sections[i].offset - min_offset));
+ }
if (!backtrace_dwarf_add (state, base_address,
sections[DEBUG_INFO].data,
@@ -833,6 +860,7 @@ struct phdr_data
fileline *fileline_fn;
int *found_sym;
int *found_dwarf;
+ int exe_descriptor;
};
/* Callback passed to dl_iterate_phdr. Load debug info from shared
@@ -848,21 +876,32 @@ phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
fileline elf_fileline_fn;
int found_dwarf;
- /* There is not much we can do if we don't have the module name. If
- the base address is 0, this is probably the executable, which we
- already loaded. */
- if (info->dlpi_name == NULL
- || info->dlpi_name[0] == '\0'
- || info->dlpi_addr == 0)
- return 0;
+ /* There is not much we can do if we don't have the module name,
+ unless executable is ET_DYN, where we expect the very first
+ phdr_callback to be for the PIE. */
+ if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0')
+ {
+ if (pd->exe_descriptor == -1)
+ return 0;
+ descriptor = pd->exe_descriptor;
+ pd->exe_descriptor = -1;
+ }
+ else
+ {
+ if (pd->exe_descriptor != -1)
+ {
+ backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data);
+ pd->exe_descriptor = -1;
+ }
- descriptor = backtrace_open (info->dlpi_name, pd->error_callback, pd->data,
- &does_not_exist);
- if (descriptor < 0)
- return 0;
+ descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
+ pd->data, &does_not_exist);
+ if (descriptor < 0)
+ return 0;
+ }
if (elf_add (pd->state, descriptor, info->dlpi_addr, pd->error_callback,
- pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf))
+ pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf, 0))
{
if (found_dwarf)
{
@@ -883,14 +922,15 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
backtrace_error_callback error_callback,
void *data, fileline *fileline_fn)
{
+ int ret;
int found_sym;
int found_dwarf;
- syminfo elf_syminfo_fn;
fileline elf_fileline_fn;
struct phdr_data pd;
- if (!elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn,
- &found_sym, &found_dwarf))
+ ret = elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn,
+ &found_sym, &found_dwarf, 1);
+ if (!ret)
return 0;
pd.state = state;
@@ -899,21 +939,24 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
pd.fileline_fn = &elf_fileline_fn;
pd.found_sym = &found_sym;
pd.found_dwarf = &found_dwarf;
+ pd.exe_descriptor = ret < 0 ? descriptor : -1;
dl_iterate_phdr (phdr_callback, (void *) &pd);
- elf_syminfo_fn = found_sym ? elf_syminfo : elf_nosyms;
if (!state->threaded)
{
- if (state->syminfo_fn == NULL || found_sym)
- state->syminfo_fn = elf_syminfo_fn;
+ if (found_sym)
+ state->syminfo_fn = elf_syminfo;
+ else if (state->syminfo_fn == NULL)
+ state->syminfo_fn = elf_nosyms;
}
else
{
- __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, elf_syminfo_fn);
if (found_sym)
- __sync_bool_compare_and_swap (&state->syminfo_fn, elf_nosyms,
- elf_syminfo_fn);
+ backtrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo);
+ else
+ (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
+ elf_nosyms);
}
if (!state->threaded)
@@ -925,11 +968,7 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
{
fileline current_fn;
- /* Atomic load. */
- current_fn = state->fileline_fn;
- while (!__sync_bool_compare_and_swap (&state->fileline_fn, current_fn,
- current_fn))
- current_fn = state->fileline_fn;
+ current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
if (current_fn == NULL || current_fn == elf_nodebug)
*fileline_fn = elf_fileline_fn;
}
diff --git a/thirdparty/libbacktrace/fileline.c b/thirdparty/libbacktrace/fileline.c
index e5c39be8..27ebbedc 100644
--- a/thirdparty/libbacktrace/fileline.c
+++ b/thirdparty/libbacktrace/fileline.c
@@ -1,5 +1,5 @@
/* fileline.c -- Get file and line number information in a backtrace.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -58,15 +58,10 @@ fileline_initialize (struct backtrace_state *state,
int called_error_callback;
int descriptor;
- failed = state->fileline_initialization_failed;
-
- if (state->threaded)
- {
- /* Use __sync_bool_compare_and_swap to do an atomic load. */
- while (!__sync_bool_compare_and_swap
- (&state->fileline_initialization_failed, failed, failed))
- failed = state->fileline_initialization_failed;
- }
+ if (!state->threaded)
+ failed = state->fileline_initialization_failed;
+ else
+ failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
if (failed)
{
@@ -74,13 +69,10 @@ fileline_initialize (struct backtrace_state *state,
return 0;
}
- fileline_fn = state->fileline_fn;
- if (state->threaded)
- {
- while (!__sync_bool_compare_and_swap (&state->fileline_fn, fileline_fn,
- fileline_fn))
- fileline_fn = state->fileline_fn;
- }
+ if (!state->threaded)
+ fileline_fn = state->fileline_fn;
+ else
+ fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
if (fileline_fn != NULL)
return 1;
@@ -151,8 +143,7 @@ fileline_initialize (struct backtrace_state *state,
if (!state->threaded)
state->fileline_initialization_failed = 1;
else
- __sync_bool_compare_and_swap (&state->fileline_initialization_failed,
- 0, failed);
+ backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
return 0;
}
@@ -160,15 +151,10 @@ fileline_initialize (struct backtrace_state *state,
state->fileline_fn = fileline_fn;
else
{
- __sync_bool_compare_and_swap (&state->fileline_fn, NULL, fileline_fn);
-
- /* At this point we know that state->fileline_fn is not NULL.
- Either we stored our value, or some other thread stored its
- value. If some other thread stored its value, we leak the
- one we just initialized. Either way, state->fileline_fn is
- initialized. The compare_and_swap is a full memory barrier,
- so we should have full access to that value even if it was
- created by another thread. */
+ backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
+
+ /* Note that if two threads initialize at once, one of the data
+ sets may be leaked. */
}
return 1;
diff --git a/thirdparty/libbacktrace/internal.h b/thirdparty/libbacktrace/internal.h
index 1ea664a0..73728da3 100644
--- a/thirdparty/libbacktrace/internal.h
+++ b/thirdparty/libbacktrace/internal.h
@@ -1,5 +1,5 @@
/* internal.h -- Internal header file for stack backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -65,7 +65,48 @@ POSSIBILITY OF SUCH DAMAGE. */
#define __sync_lock_test_and_set(A, B) (abort(), 0)
#define __sync_lock_release(A) abort()
-#endif /* !defined(HAVE_SYNC_FUNCTIONS) */
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+#ifdef HAVE_ATOMIC_FUNCTIONS
+
+/* We have the atomic builtin functions. */
+
+#define backtrace_atomic_load_pointer(p) \
+ __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_load_int(p) \
+ __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_store_pointer(p, v) \
+ __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_size_t(p, v) \
+ __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_int(p, v) \
+ __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+
+#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */
+#ifdef HAVE_SYNC_FUNCTIONS
+
+/* We have the sync functions but not the atomic functions. Define
+ the atomic ones in terms of the sync ones. */
+
+extern void *backtrace_atomic_load_pointer (void *);
+extern int backtrace_atomic_load_int (int *);
+extern void backtrace_atomic_store_pointer (void *, void *);
+extern void backtrace_atomic_store_size_t (size_t *, size_t);
+extern void backtrace_atomic_store_int (int *, int);
+
+#else /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+/* We have neither the sync nor the atomic functions. These will
+ never be called. */
+
+#define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL)
+#define backtrace_atomic_load_int(p) (abort(), 0)
+#define backtrace_atomic_store_pointer(p, v) abort()
+#define backtrace_atomic_store_size_t(p, v) abort()
+#define backtrace_atomic_store_int(p, v) abort()
+
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */
/* The type of the function that collects file/line information. This
is like backtrace_pcinfo. */
@@ -155,13 +196,20 @@ extern int backtrace_close (int descriptor,
backtrace_error_callback error_callback,
void *data);
-/* Allocate memory. This is like malloc. */
+/* Sort without using memory. */
+
+extern void backtrace_qsort (void *base, size_t count, size_t size,
+ int (*compar) (const void *, const void *));
+
+/* Allocate memory. This is like malloc. If ERROR_CALLBACK is NULL,
+ this does not report an error, it just returns NULL. */
extern void *backtrace_alloc (struct backtrace_state *state, size_t size,
backtrace_error_callback error_callback,
void *data) ATTRIBUTE_MALLOC;
-/* Free memory allocated by backtrace_alloc. */
+/* Free memory allocated by backtrace_alloc. If ERROR_CALLBACK is
+ NULL, this does not report an error. */
extern void backtrace_free (struct backtrace_state *state, void *mem,
size_t size,
@@ -192,13 +240,17 @@ extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size,
struct backtrace_vector *vec);
/* Finish the current allocation on VEC. Prepare to start a new
- allocation. The finished allocation will never be freed. */
+ allocation. The finished allocation will never be freed. Returns
+ a pointer to the base of the finished entries, or NULL on
+ failure. */
-extern void backtrace_vector_finish (struct backtrace_state *state,
- struct backtrace_vector *vec);
+extern void* backtrace_vector_finish (struct backtrace_state *state,
+ struct backtrace_vector *vec,
+ backtrace_error_callback error_callback,
+ void *data);
-/* Release any extra space allocated for VEC. Returns 1 on success, 0
- on failure. */
+/* Release any extra space allocated for VEC. This may change
+ VEC->base. Returns 1 on success, 0 on failure. */
extern int backtrace_vector_release (struct backtrace_state *state,
struct backtrace_vector *vec,
diff --git a/thirdparty/libbacktrace/mmap.c b/thirdparty/libbacktrace/mmap.c
index 04aae85e..0ed4802d 100644
--- a/thirdparty/libbacktrace/mmap.c
+++ b/thirdparty/libbacktrace/mmap.c
@@ -1,5 +1,5 @@
/* mmap.c -- Memory allocation with mmap.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -77,7 +77,8 @@ backtrace_free_locked (struct backtrace_state *state, void *addr, size_t size)
}
}
-/* Allocate memory like malloc. */
+/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
+ report an error. */
void *
backtrace_alloc (struct backtrace_state *state,
@@ -139,8 +140,11 @@ backtrace_alloc (struct backtrace_state *state,
asksize = (size + pagesize - 1) & ~ (pagesize - 1);
page = mmap (NULL, asksize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (page == NULL)
- error_callback (data, "mmap", errno);
+ if (page == MAP_FAILED)
+ {
+ if (error_callback)
+ error_callback (data, "mmap", errno);
+ }
else
{
size = (size + 7) & ~ (size_t) 7;
@@ -164,6 +168,26 @@ backtrace_free (struct backtrace_state *state, void *addr, size_t size,
{
int locked;
+ /* If we are freeing a large aligned block, just release it back to
+ the system. This case arises when growing a vector for a large
+ binary with lots of debug info. Calling munmap here may cause us
+ to call mmap again if there is also a large shared library; we
+ just live with that. */
+ if (size >= 16 * 4096)
+ {
+ size_t pagesize;
+
+ pagesize = getpagesize ();
+ if (((uintptr_t) addr & (pagesize - 1)) == 0
+ && (size & (pagesize - 1)) == 0)
+ {
+ /* If munmap fails for some reason, just add the block to
+ the freelist. */
+ if (munmap (addr, size) == 0)
+ return;
+ }
+ }
+
/* If we can acquire the lock, add the new space to the free list.
If we can't acquire the lock, just leak the memory.
__sync_lock_test_and_set returns the old state of the lock, so we
@@ -209,14 +233,18 @@ backtrace_vector_grow (struct backtrace_state *state,size_t size,
alc = pagesize;
}
else
- alc = (alc + pagesize - 1) & ~ (pagesize - 1);
+ {
+ alc *= 2;
+ alc = (alc + pagesize - 1) & ~ (pagesize - 1);
+ }
base = backtrace_alloc (state, alc, error_callback, data);
if (base == NULL)
return NULL;
if (vec->base != NULL)
{
memcpy (base, vec->base, vec->size);
- backtrace_free (state, vec->base, vec->alc, error_callback, data);
+ backtrace_free (state, vec->base, vec->size + vec->alc,
+ error_callback, data);
}
vec->base = base;
vec->alc = alc - vec->size;
@@ -230,12 +258,19 @@ backtrace_vector_grow (struct backtrace_state *state,size_t size,
/* Finish the current allocation on VEC. */
-void
-backtrace_vector_finish (struct backtrace_state *state ATTRIBUTE_UNUSED,
- struct backtrace_vector *vec)
+void *
+backtrace_vector_finish (
+ struct backtrace_state *state ATTRIBUTE_UNUSED,
+ struct backtrace_vector *vec,
+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
{
+ void *ret;
+
+ ret = vec->base;
vec->base = (char *) vec->base + vec->size;
vec->size = 0;
+ return ret;
}
/* Release any extra space allocated for VEC. */
diff --git a/thirdparty/libbacktrace/mmapio.c b/thirdparty/libbacktrace/mmapio.c
index 60c68c66..dfdaf6fa 100644
--- a/thirdparty/libbacktrace/mmapio.c
+++ b/thirdparty/libbacktrace/mmapio.c
@@ -1,5 +1,5 @@
/* mmapio.c -- File views using mmap.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/nounwind.c b/thirdparty/libbacktrace/nounwind.c
index 5c8e23c9..448a2049 100644
--- a/thirdparty/libbacktrace/nounwind.c
+++ b/thirdparty/libbacktrace/nounwind.c
@@ -1,5 +1,5 @@
/* backtrace.c -- Entry point for stack backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/pecoff.c b/thirdparty/libbacktrace/pecoff.c
new file mode 100644
index 00000000..c7d32aa6
--- /dev/null
+++ b/thirdparty/libbacktrace/pecoff.c
@@ -0,0 +1,937 @@
+/* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
+ Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Adapted from elf.c by Tristan Gingold, AdaCore.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ (1) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ (2) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ (3) The name of the author may not be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Coff file header. */
+
+typedef struct {
+ uint16_t machine;
+ uint16_t number_of_sections;
+ uint32_t time_date_stamp;
+ uint32_t pointer_to_symbol_table;
+ uint32_t number_of_symbols;
+ uint16_t size_of_optional_header;
+ uint16_t characteristics;
+} b_coff_file_header;
+
+/* Coff optional header. */
+
+typedef struct {
+ uint16_t magic;
+ uint8_t major_linker_version;
+ uint8_t minor_linker_version;
+ uint32_t size_of_code;
+ uint32_t size_of_initialized_data;
+ uint32_t size_of_uninitialized_data;
+ uint32_t address_of_entry_point;
+ uint32_t base_of_code;
+ union {
+ struct {
+ uint32_t base_of_data;
+ uint32_t image_base;
+ } pe;
+ struct {
+ uint64_t image_base;
+ } pep;
+ } u;
+} b_coff_optional_header;
+
+/* Values of magic in optional header. */
+
+#define PE_MAGIC 0x10b /* PE32 executable. */
+#define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
+
+/* Coff section header. */
+
+typedef struct {
+ char name[8];
+ uint32_t virtual_size;
+ uint32_t virtual_address;
+ uint32_t size_of_raw_data;
+ uint32_t pointer_to_raw_data;
+ uint32_t pointer_to_relocations;
+ uint32_t pointer_to_line_numbers;
+ uint16_t number_of_relocations;
+ uint16_t number_of_line_numbers;
+ uint32_t characteristics;
+} b_coff_section_header;
+
+/* Coff symbol name. */
+
+typedef union {
+ char short_name[8];
+ struct {
+ unsigned char zeroes[4];
+ unsigned char off[4];
+ } long_name;
+} b_coff_name;
+
+/* Coff symbol (external representation which is unaligned). */
+
+typedef struct {
+ b_coff_name name;
+ unsigned char value[4];
+ unsigned char section_number[2];
+ unsigned char type[2];
+ unsigned char storage_class;
+ unsigned char number_of_aux_symbols;
+} b_coff_external_symbol;
+
+/* Symbol types. */
+
+#define N_TBSHFT 4 /* Shift for the derived type. */
+#define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
+
+/* Size of a coff symbol. */
+
+#define SYM_SZ 18
+
+/* Coff symbol, internal representation (aligned). */
+
+typedef struct {
+ const char *name;
+ uint32_t value;
+ int16_t sec;
+ uint16_t type;
+ uint16_t sc;
+} b_coff_internal_symbol;
+
+/* An index of sections we care about. */
+
+enum debug_section
+{
+ DEBUG_INFO,
+ DEBUG_LINE,
+ DEBUG_ABBREV,
+ DEBUG_RANGES,
+ DEBUG_STR,
+ DEBUG_MAX
+};
+
+/* Names of sections, indexed by enum debug_section. */
+
+static const char * const debug_section_names[DEBUG_MAX] =
+{
+ ".debug_info",
+ ".debug_line",
+ ".debug_abbrev",
+ ".debug_ranges",
+ ".debug_str"
+};
+
+/* Information we gather for the sections we care about. */
+
+struct debug_section_info
+{
+ /* Section file offset. */
+ off_t offset;
+ /* Section size. */
+ size_t size;
+ /* Section contents, after read from file. */
+ const unsigned char *data;
+};
+
+/* Information we keep for an coff symbol. */
+
+struct coff_symbol
+{
+ /* The name of the symbol. */
+ const char *name;
+ /* The address of the symbol. */
+ uintptr_t address;
+};
+
+/* Information to pass to coff_syminfo. */
+
+struct coff_syminfo_data
+{
+ /* Symbols for the next module. */
+ struct coff_syminfo_data *next;
+ /* The COFF symbols, sorted by address. */
+ struct coff_symbol *symbols;
+ /* The number of symbols. */
+ size_t count;
+};
+
+/* A dummy callback function used when we can't find any debug info. */
+
+static int
+coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
+ uintptr_t pc ATTRIBUTE_UNUSED,
+ backtrace_full_callback callback ATTRIBUTE_UNUSED,
+ backtrace_error_callback error_callback, void *data)
+{
+ error_callback (data, "no debug info in PE/COFF executable", -1);
+ return 0;
+}
+
+/* A dummy callback function used when we can't find a symbol
+ table. */
+
+static void
+coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
+ uintptr_t addr ATTRIBUTE_UNUSED,
+ backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
+ backtrace_error_callback error_callback, void *data)
+{
+ error_callback (data, "no symbol table in PE/COFF executable", -1);
+}
+
+/* Read a potentially unaligned 4 byte word at P, using native endianness. */
+
+static uint32_t
+coff_read4 (const unsigned char *p)
+{
+ uint32_t res;
+
+ memcpy (&res, p, 4);
+ return res;
+}
+
+/* Read a potentially unaligned 2 byte word at P, using native endianness.
+ All 2 byte word in symbols are always aligned, but for coherency all
+ fields are declared as char arrays. */
+
+static uint16_t
+coff_read2 (const unsigned char *p)
+{
+ uint16_t res;
+
+ memcpy (&res, p, sizeof (res));
+ return res;
+}
+
+/* Return the length (without the trailing 0) of a COFF short name. */
+
+static size_t
+coff_short_name_len (const char *name)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ if (name[i] == 0)
+ return i;
+ return 8;
+}
+
+/* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
+ string). */
+
+static int
+coff_short_name_eq (const char *name, const char *cname)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ if (name[i] != cname[i])
+ return 0;
+ if (name[i] == 0)
+ return 1;
+ }
+ return name[8] == 0;
+}
+
+/* Return true iff NAME is the same as string at offset OFF. */
+
+static int
+coff_long_name_eq (const char *name, unsigned int off,
+ struct backtrace_view *str_view)
+{
+ if (off >= str_view->len)
+ return 0;
+ return strcmp (name, (const char *)str_view->data + off) == 0;
+}
+
+/* Compare struct coff_symbol for qsort. */
+
+static int
+coff_symbol_compare (const void *v1, const void *v2)
+{
+ const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
+ const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
+
+ if (e1->address < e2->address)
+ return -1;
+ else if (e1->address > e2->address)
+ return 1;
+ else
+ return 0;
+}
+
+/* Convert SYM to internal (and aligned) format ISYM, using string table
+ from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
+ Return -1 in case of error (invalid section number or string index). */
+
+static int
+coff_expand_symbol (b_coff_internal_symbol *isym,
+ const b_coff_external_symbol *sym,
+ uint16_t sects_num,
+ const unsigned char *strtab, size_t strtab_size)
+{
+ isym->type = coff_read2 (sym->type);
+ isym->sec = coff_read2 (sym->section_number);
+ isym->sc = sym->storage_class;
+
+ if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
+ return -1;
+ if (sym->name.short_name[0] != 0)
+ isym->name = sym->name.short_name;
+ else
+ {
+ uint32_t off = coff_read4 (sym->name.long_name.off);
+
+ if (off >= strtab_size)
+ return -1;
+ isym->name = (const char *) strtab + off;
+ }
+ return 0;
+}
+
+/* Return true iff SYM is a defined symbol for a function. Data symbols
+ aren't considered because they aren't easily identified (same type as
+ section names, presence of symbols defined by the linker script). */
+
+static int
+coff_is_function_symbol (const b_coff_internal_symbol *isym)
+{
+ return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
+ && isym->sec > 0;
+}
+
+/* Initialize the symbol table info for coff_syminfo. */
+
+static int
+coff_initialize_syminfo (struct backtrace_state *state,
+ uintptr_t base_address,
+ const b_coff_section_header *sects, size_t sects_num,
+ const b_coff_external_symbol *syms, size_t syms_size,
+ const unsigned char *strtab, size_t strtab_size,
+ backtrace_error_callback error_callback,
+ void *data, struct coff_syminfo_data *sdata)
+{
+ size_t syms_count;
+ char *coff_symstr;
+ size_t coff_symstr_len;
+ size_t coff_symbol_count;
+ size_t coff_symbol_size;
+ struct coff_symbol *coff_symbols;
+ struct coff_symbol *coff_sym;
+ char *coff_str;
+ size_t i;
+
+ syms_count = syms_size / SYM_SZ;
+
+ /* We only care about function symbols. Count them. Also count size of
+ strings for in-symbol names. */
+ coff_symbol_count = 0;
+ coff_symstr_len = 0;
+ for (i = 0; i < syms_count; ++i)
+ {
+ const b_coff_external_symbol *asym = &syms[i];
+ b_coff_internal_symbol isym;
+
+ if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
+ {
+ error_callback (data, "invalid section or offset in coff symbol", 0);
+ return 0;
+ }
+ if (coff_is_function_symbol (&isym))
+ {
+ ++coff_symbol_count;
+ if (asym->name.short_name[0] != 0)
+ coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
+ }
+
+ i += asym->number_of_aux_symbols;
+ }
+
+ coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
+ coff_symbols = ((struct coff_symbol *)
+ backtrace_alloc (state, coff_symbol_size, error_callback,
+ data));
+ if (coff_symbols == NULL)
+ return 0;
+
+ /* Allocate memory for symbols strings. */
+ if (coff_symstr_len > 0)
+ {
+ coff_symstr = ((char *)
+ backtrace_alloc (state, coff_symstr_len, error_callback,
+ data));
+ if (coff_symstr == NULL)
+ {
+ backtrace_free (state, coff_symbols, coff_symbol_size,
+ error_callback, data);
+ return 0;
+ }
+ }
+ else
+ coff_symstr = NULL;
+
+ /* Copy symbols. */
+ coff_sym = coff_symbols;
+ coff_str = coff_symstr;
+ for (i = 0; i < syms_count; ++i)
+ {
+ const b_coff_external_symbol *asym = &syms[i];
+ b_coff_internal_symbol isym;
+
+ if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
+ {
+ /* Should not fail, as it was already tested in the previous
+ loop. */
+ abort ();
+ }
+ if (coff_is_function_symbol (&isym))
+ {
+ const char *name;
+ int16_t secnum;
+
+ if (asym->name.short_name[0] != 0)
+ {
+ size_t len = coff_short_name_len (isym.name);
+ name = coff_str;
+ memcpy (coff_str, isym.name, len);
+ coff_str[len] = 0;
+ coff_str += len + 1;
+ }
+ else
+ name = isym.name;
+
+ /* Strip leading '_'. */
+ if (name[0] == '_')
+ name++;
+
+ /* Symbol value is section relative, so we need to read the address
+ of its section. */
+ secnum = coff_read2 (asym->section_number);
+
+ coff_sym->name = name;
+ coff_sym->address = (coff_read4 (asym->value)
+ + sects[secnum - 1].virtual_address
+ + base_address);
+ coff_sym++;
+ }
+
+ i += asym->number_of_aux_symbols;
+ }
+
+ /* End of symbols marker. */
+ coff_sym->name = NULL;
+ coff_sym->address = -1;
+
+ backtrace_qsort (coff_symbols, coff_symbol_count,
+ sizeof (struct coff_symbol), coff_symbol_compare);
+
+ sdata->next = NULL;
+ sdata->symbols = coff_symbols;
+ sdata->count = coff_symbol_count;
+
+ return 1;
+}
+
+/* Add EDATA to the list in STATE. */
+
+static void
+coff_add_syminfo_data (struct backtrace_state *state,
+ struct coff_syminfo_data *sdata)
+{
+ if (!state->threaded)
+ {
+ struct coff_syminfo_data **pp;
+
+ for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
+ *pp != NULL;
+ pp = &(*pp)->next)
+ ;
+ *pp = sdata;
+ }
+ else
+ {
+ while (1)
+ {
+ struct coff_syminfo_data **pp;
+
+ pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
+
+ while (1)
+ {
+ struct coff_syminfo_data *p;
+
+ p = backtrace_atomic_load_pointer (pp);
+
+ if (p == NULL)
+ break;
+
+ pp = &p->next;
+ }
+
+ if (__sync_bool_compare_and_swap (pp, NULL, sdata))
+ break;
+ }
+ }
+}
+
+/* Compare an ADDR against an elf_symbol for bsearch. We allocate one
+ extra entry in the array so that this can look safely at the next
+ entry. */
+
+static int
+coff_symbol_search (const void *vkey, const void *ventry)
+{
+ const uintptr_t *key = (const uintptr_t *) vkey;
+ const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
+ uintptr_t addr;
+
+ addr = *key;
+ if (addr < entry->address)
+ return -1;
+ else if (addr >= entry[1].address)
+ return 1;
+ else
+ return 0;
+}
+
+/* Return the symbol name and value for an ADDR. */
+
+static void
+coff_syminfo (struct backtrace_state *state, uintptr_t addr,
+ backtrace_syminfo_callback callback,
+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+ void *data)
+{
+ struct coff_syminfo_data *sdata;
+ struct coff_symbol *sym = NULL;
+
+ if (!state->threaded)
+ {
+ for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
+ sdata != NULL;
+ sdata = sdata->next)
+ {
+ sym = ((struct coff_symbol *)
+ bsearch (&addr, sdata->symbols, sdata->count,
+ sizeof (struct coff_symbol), coff_symbol_search));
+ if (sym != NULL)
+ break;
+ }
+ }
+ else
+ {
+ struct coff_syminfo_data **pp;
+
+ pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
+ while (1)
+ {
+ sdata = backtrace_atomic_load_pointer (pp);
+ if (sdata == NULL)
+ break;
+
+ sym = ((struct coff_symbol *)
+ bsearch (&addr, sdata->symbols, sdata->count,
+ sizeof (struct coff_symbol), coff_symbol_search));
+ if (sym != NULL)
+ break;
+
+ pp = &sdata->next;
+ }
+ }
+
+ if (sym == NULL)
+ callback (data, addr, NULL, 0, 0);
+ else
+ callback (data, addr, sym->name, sym->address, 0);
+}
+
+/* Add the backtrace data for one PE/COFF file. Returns 1 on success,
+ 0 on failure (in both cases descriptor is closed). */
+
+static int
+coff_add (struct backtrace_state *state, int descriptor,
+ backtrace_error_callback error_callback, void *data,
+ fileline *fileline_fn, int *found_sym, int *found_dwarf)
+{
+ struct backtrace_view fhdr_view;
+ off_t fhdr_off;
+ int magic_ok;
+ b_coff_file_header fhdr;
+ off_t opt_sects_off;
+ size_t opt_sects_size;
+ unsigned int sects_num;
+ struct backtrace_view sects_view;
+ int sects_view_valid;
+ const b_coff_optional_header *opt_hdr;
+ const b_coff_section_header *sects;
+ struct backtrace_view str_view;
+ int str_view_valid;
+ size_t str_size;
+ off_t str_off;
+ struct backtrace_view syms_view;
+ off_t syms_off;
+ size_t syms_size;
+ int syms_view_valid;
+ unsigned int syms_num;
+ unsigned int i;
+ struct debug_section_info sections[DEBUG_MAX];
+ off_t min_offset;
+ off_t max_offset;
+ struct backtrace_view debug_view;
+ int debug_view_valid;
+ uintptr_t image_base;
+
+ *found_sym = 0;
+ *found_dwarf = 0;
+
+ sects_view_valid = 0;
+ syms_view_valid = 0;
+ str_view_valid = 0;
+ debug_view_valid = 0;
+
+ /* Map the MS-DOS stub (if any) and extract file header offset. */
+ if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
+ data, &fhdr_view))
+ goto fail;
+
+ {
+ const char *vptr = (const char *)fhdr_view.data;
+
+ if (vptr[0] == 'M' && vptr[1] == 'Z')
+ memcpy (&fhdr_off, vptr + 0x3c, 4);
+ else
+ fhdr_off = 0;
+ }
+
+ backtrace_release_view (state, &fhdr_view, error_callback, data);
+
+ /* Map the coff file header. */
+ if (!backtrace_get_view (state, descriptor, fhdr_off,
+ sizeof (b_coff_file_header) + 4,
+ error_callback, data, &fhdr_view))
+ goto fail;
+
+ if (fhdr_off != 0)
+ {
+ const char *magic = (const char *) fhdr_view.data;
+ magic_ok = memcmp (magic, "PE\0", 4) == 0;
+ fhdr_off += 4;
+
+ memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
+ }
+ else
+ {
+ memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
+ /* TODO: test fhdr.machine for coff but non-PE platforms. */
+ magic_ok = 0;
+ }
+ backtrace_release_view (state, &fhdr_view, error_callback, data);
+
+ if (!magic_ok)
+ {
+ error_callback (data, "executable file is not COFF", 0);
+ goto fail;
+ }
+
+ sects_num = fhdr.number_of_sections;
+ syms_num = fhdr.number_of_symbols;
+
+ opt_sects_off = fhdr_off + sizeof (fhdr);
+ opt_sects_size = (fhdr.size_of_optional_header
+ + sects_num * sizeof (b_coff_section_header));
+
+ /* To translate PC to file/line when using DWARF, we need to find
+ the .debug_info and .debug_line sections. */
+
+ /* Read the optional header and the section headers. */
+
+ if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
+ error_callback, data, &sects_view))
+ goto fail;
+ sects_view_valid = 1;
+ opt_hdr = (const b_coff_optional_header *) sects_view.data;
+ sects = (const b_coff_section_header *)
+ (sects_view.data + fhdr.size_of_optional_header);
+
+ if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
+ {
+ if (opt_hdr->magic == PE_MAGIC)
+ image_base = opt_hdr->u.pe.image_base;
+ else if (opt_hdr->magic == PEP_MAGIC)
+ image_base = opt_hdr->u.pep.image_base;
+ else
+ {
+ error_callback (data, "bad magic in PE optional header", 0);
+ goto fail;
+ }
+ }
+ else
+ image_base = 0;
+
+ /* Read the symbol table and the string table. */
+
+ if (fhdr.pointer_to_symbol_table == 0)
+ {
+ /* No symbol table, no string table. */
+ str_off = 0;
+ str_size = 0;
+ syms_num = 0;
+ syms_size = 0;
+ }
+ else
+ {
+ /* Symbol table is followed by the string table. The string table
+ starts with its length (on 4 bytes).
+ Map the symbol table and the length of the string table. */
+ syms_off = fhdr.pointer_to_symbol_table;
+ syms_size = syms_num * SYM_SZ;
+
+ if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
+ error_callback, data, &syms_view))
+ goto fail;
+ syms_view_valid = 1;
+
+ memcpy (&str_size, syms_view.data + syms_size, 4);
+
+ str_off = syms_off + syms_size;
+
+ if (str_size > 4)
+ {
+ /* Map string table (including the length word). */
+
+ if (!backtrace_get_view (state, descriptor, str_off, str_size,
+ error_callback, data, &str_view))
+ goto fail;
+ str_view_valid = 1;
+ }
+ }
+
+ memset (sections, 0, sizeof sections);
+
+ /* Look for the symbol table. */
+ for (i = 0; i < sects_num; ++i)
+ {
+ const b_coff_section_header *s = sects + i;
+ unsigned int str_off;
+ int j;
+
+ if (s->name[0] == '/')
+ {
+ /* Extended section name. */
+ str_off = atoi (s->name + 1);
+ }
+ else
+ str_off = 0;
+
+ for (j = 0; j < (int) DEBUG_MAX; ++j)
+ {
+ const char *dbg_name = debug_section_names[j];
+ int match;
+
+ if (str_off != 0)
+ match = coff_long_name_eq (dbg_name, str_off, &str_view);
+ else
+ match = coff_short_name_eq (dbg_name, s->name);
+ if (match)
+ {
+ sections[j].offset = s->pointer_to_raw_data;
+ sections[j].size = s->virtual_size <= s->size_of_raw_data ?
+ s->virtual_size : s->size_of_raw_data;
+ break;
+ }
+ }
+ }
+
+ if (syms_num != 0)
+ {
+ struct coff_syminfo_data *sdata;
+
+ sdata = ((struct coff_syminfo_data *)
+ backtrace_alloc (state, sizeof *sdata, error_callback, data));
+ if (sdata == NULL)
+ goto fail;
+
+ if (!coff_initialize_syminfo (state, image_base,
+ sects, sects_num,
+ syms_view.data, syms_size,
+ str_view.data, str_size,
+ error_callback, data, sdata))
+ {
+ backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
+ goto fail;
+ }
+
+ *found_sym = 1;
+
+ coff_add_syminfo_data (state, sdata);
+ }
+
+ backtrace_release_view (state, &sects_view, error_callback, data);
+ sects_view_valid = 0;
+ backtrace_release_view (state, &syms_view, error_callback, data);
+ syms_view_valid = 0;
+
+ /* Read all the debug sections in a single view, since they are
+ probably adjacent in the file. We never release this view. */
+
+ min_offset = 0;
+ max_offset = 0;
+ for (i = 0; i < (int) DEBUG_MAX; ++i)
+ {
+ off_t end;
+
+ if (sections[i].size == 0)
+ continue;
+ if (min_offset == 0 || sections[i].offset < min_offset)
+ min_offset = sections[i].offset;
+ end = sections[i].offset + sections[i].size;
+ if (end > max_offset)
+ max_offset = end;
+ }
+ if (min_offset == 0 || max_offset == 0)
+ {
+ if (!backtrace_close (descriptor, error_callback, data))
+ goto fail;
+ *fileline_fn = coff_nodebug;
+ return 1;
+ }
+
+ if (!backtrace_get_view (state, descriptor, min_offset,
+ max_offset - min_offset,
+ error_callback, data, &debug_view))
+ goto fail;
+ debug_view_valid = 1;
+
+ /* We've read all we need from the executable. */
+ if (!backtrace_close (descriptor, error_callback, data))
+ goto fail;
+ descriptor = -1;
+
+ for (i = 0; i < (int) DEBUG_MAX; ++i)
+ {
+ if (sections[i].size == 0)
+ sections[i].data = NULL;
+ else
+ sections[i].data = ((const unsigned char *) debug_view.data
+ + (sections[i].offset - min_offset));
+ }
+
+ if (!backtrace_dwarf_add (state, /* base_address */ 0,
+ sections[DEBUG_INFO].data,
+ sections[DEBUG_INFO].size,
+ sections[DEBUG_LINE].data,
+ sections[DEBUG_LINE].size,
+ sections[DEBUG_ABBREV].data,
+ sections[DEBUG_ABBREV].size,
+ sections[DEBUG_RANGES].data,
+ sections[DEBUG_RANGES].size,
+ sections[DEBUG_STR].data,
+ sections[DEBUG_STR].size,
+ 0, /* FIXME */
+ error_callback, data, fileline_fn))
+ goto fail;
+
+ *found_dwarf = 1;
+
+ return 1;
+
+ fail:
+ if (sects_view_valid)
+ backtrace_release_view (state, &sects_view, error_callback, data);
+ if (str_view_valid)
+ backtrace_release_view (state, &str_view, error_callback, data);
+ if (syms_view_valid)
+ backtrace_release_view (state, &syms_view, error_callback, data);
+ if (debug_view_valid)
+ backtrace_release_view (state, &debug_view, error_callback, data);
+ if (descriptor != -1)
+ backtrace_close (descriptor, error_callback, data);
+ return 0;
+}
+
+/* Initialize the backtrace data we need from an ELF executable. At
+ the ELF level, all we need to do is find the debug info
+ sections. */
+
+int
+backtrace_initialize (struct backtrace_state *state, int descriptor,
+ backtrace_error_callback error_callback,
+ void *data, fileline *fileline_fn)
+{
+ int ret;
+ int found_sym;
+ int found_dwarf;
+ fileline coff_fileline_fn;
+
+ ret = coff_add (state, descriptor, error_callback, data,
+ &coff_fileline_fn, &found_sym, &found_dwarf);
+ if (!ret)
+ return 0;
+
+ if (!state->threaded)
+ {
+ if (found_sym)
+ state->syminfo_fn = coff_syminfo;
+ else if (state->syminfo_fn == NULL)
+ state->syminfo_fn = coff_nosyms;
+ }
+ else
+ {
+ if (found_sym)
+ backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
+ else
+ __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, coff_nosyms);
+ }
+
+ if (!state->threaded)
+ {
+ if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
+ *fileline_fn = coff_fileline_fn;
+ }
+ else
+ {
+ fileline current_fn;
+
+ current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+ if (current_fn == NULL || current_fn == coff_nodebug)
+ *fileline_fn = coff_fileline_fn;
+ }
+
+ return 1;
+}
diff --git a/thirdparty/libbacktrace/posix.c b/thirdparty/libbacktrace/posix.c
index be0a1a55..09f5e95a 100644
--- a/thirdparty/libbacktrace/posix.c
+++ b/thirdparty/libbacktrace/posix.c
@@ -1,5 +1,5 @@
/* posix.c -- POSIX file I/O routines for the backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -64,7 +64,7 @@ backtrace_open (const char *filename, backtrace_error_callback error_callback,
if (does_not_exist != NULL)
*does_not_exist = 0;
- descriptor = open (filename, O_RDONLY | O_BINARY | O_CLOEXEC);
+ descriptor = open (filename, (int) (O_RDONLY | O_BINARY | O_CLOEXEC));
if (descriptor < 0)
{
if (does_not_exist != NULL && errno == ENOENT)
diff --git a/thirdparty/libbacktrace/print.c b/thirdparty/libbacktrace/print.c
index c8cc2989..74c8fcbe 100644
--- a/thirdparty/libbacktrace/print.c
+++ b/thirdparty/libbacktrace/print.c
@@ -1,5 +1,5 @@
/* print.c -- Print the current backtrace.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/read.c b/thirdparty/libbacktrace/read.c
index d6e648e5..7f0317c3 100644
--- a/thirdparty/libbacktrace/read.c
+++ b/thirdparty/libbacktrace/read.c
@@ -1,5 +1,5 @@
/* read.c -- File views without mmap.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/simple.c b/thirdparty/libbacktrace/simple.c
index b03f039f..018773a7 100644
--- a/thirdparty/libbacktrace/simple.c
+++ b/thirdparty/libbacktrace/simple.c
@@ -1,5 +1,5 @@
/* simple.c -- The backtrace_simple function.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/sort.c b/thirdparty/libbacktrace/sort.c
new file mode 100644
index 00000000..68a7df65
--- /dev/null
+++ b/thirdparty/libbacktrace/sort.c
@@ -0,0 +1,108 @@
+/* sort.c -- Sort without allocating memory
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ (1) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ (2) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ (3) The name of the author may not be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+#include "config.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* The GNU glibc version of qsort allocates memory, which we must not
+ do if we are invoked by a signal handler. So provide our own
+ sort. */
+
+static void
+swap (char *a, char *b, size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; i++, a++, b++)
+ {
+ char t;
+
+ t = *a;
+ *a = *b;
+ *b = t;
+ }
+}
+
+void
+backtrace_qsort (void *basearg, size_t count, size_t size,
+ int (*compar) (const void *, const void *))
+{
+ char *base = (char *) basearg;
+ size_t i;
+ size_t mid;
+
+ tail_recurse:
+ if (count < 2)
+ return;
+
+ /* The symbol table and DWARF tables, which is all we use this
+ routine for, tend to be roughly sorted. Pick the middle element
+ in the array as our pivot point, so that we are more likely to
+ cut the array in half for each recursion step. */
+ swap (base, base + (count / 2) * size, size);
+
+ mid = 0;
+ for (i = 1; i < count; i++)
+ {
+ if ((*compar) (base, base + i * size) > 0)
+ {
+ ++mid;
+ if (i != mid)
+ swap (base + mid * size, base + i * size, size);
+ }
+ }
+
+ if (mid > 0)
+ swap (base, base + mid * size, size);
+
+ /* Recurse with the smaller array, loop with the larger one. That
+ ensures that our maximum stack depth is log count. */
+ if (2 * mid < count)
+ {
+ backtrace_qsort (base, mid, size, compar);
+ base += (mid + 1) * size;
+ count -= mid + 1;
+ goto tail_recurse;
+ }
+ else
+ {
+ backtrace_qsort (base + (mid + 1) * size, count - (mid + 1),
+ size, compar);
+ count = mid;
+ goto tail_recurse;
+ }
+}
diff --git a/thirdparty/libbacktrace/state.c b/thirdparty/libbacktrace/state.c
index 03bba481..93420d9c 100644
--- a/thirdparty/libbacktrace/state.c
+++ b/thirdparty/libbacktrace/state.c
@@ -1,5 +1,5 @@
/* state.c -- Create the backtrace state.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/stest.c b/thirdparty/libbacktrace/stest.c
new file mode 100644
index 00000000..55ec31d1
--- /dev/null
+++ b/thirdparty/libbacktrace/stest.c
@@ -0,0 +1,137 @@
+/* stest.c -- Test for libbacktrace internal sort function
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ (1) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ (2) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ (3) The name of the author may not be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Test the local qsort implementation. */
+
+#define MAX 10
+
+struct test
+{
+ size_t count;
+ int input[MAX];
+ int output[MAX];
+};
+
+static struct test tests[] =
+ {
+ {
+ 10,
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
+ },
+ {
+ 9,
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
+ },
+ {
+ 10,
+ { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+ },
+ {
+ 9,
+ { 9, 8, 7, 6, 5, 4, 3, 2, 1 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+ },
+ {
+ 10,
+ { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+ },
+ {
+ 5,
+ { 4, 5, 3, 1, 2 },
+ { 1, 2, 3, 4, 5 },
+ },
+ {
+ 5,
+ { 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 },
+ },
+ {
+ 5,
+ { 1, 1, 2, 1, 1 },
+ { 1, 1, 1, 1, 2 },
+ },
+ {
+ 5,
+ { 2, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 2 },
+ },
+ };
+
+static int
+compare (const void *a, const void *b)
+{
+ const int *ai = (const int *) a;
+ const int *bi = (const int *) b;
+
+ return *ai - *bi;
+}
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+ int failures;
+ size_t i;
+ int a[MAX];
+
+ failures = 0;
+ for (i = 0; i < sizeof tests / sizeof tests[0]; i++)
+ {
+ memcpy (a, tests[i].input, tests[i].count * sizeof (int));
+ backtrace_qsort (a, tests[i].count, sizeof (int), compare);
+ if (memcmp (a, tests[i].output, tests[i].count * sizeof (int)) != 0)
+ {
+ size_t j;
+
+ fprintf (stderr, "test %d failed:", (int) i);
+ for (j = 0; j < tests[i].count; j++)
+ fprintf (stderr, " %d", a[j]);
+ fprintf (stderr, "\n");
+ ++failures;
+ }
+ }
+
+ exit (failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/thirdparty/libbacktrace/unknown.c b/thirdparty/libbacktrace/unknown.c
index d9a3ac75..8d06c315 100644
--- a/thirdparty/libbacktrace/unknown.c
+++ b/thirdparty/libbacktrace/unknown.c
@@ -1,5 +1,5 @@
/* unknown.c -- used when backtrace configury does not know file format.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libpng/ANNOUNCE b/thirdparty/libpng/ANNOUNCE
index 3bf7c73e..5de4eed0 100644
--- a/thirdparty/libpng/ANNOUNCE
+++ b/thirdparty/libpng/ANNOUNCE
@@ -1,5 +1,4 @@
-
-Libpng 1.5.9 - February 18, 2012
+Libpng 1.6.21 - January 15, 2016
This is a public release of libpng, intended for use in production codes.
@@ -8,30 +7,49 @@ Files available for download:
Source files with LF line endings (for Unix/Linux) and with a
"configure" script
- libpng-1.5.9.tar.xz (LZMA-compressed, recommended)
- libpng-1.5.9.tar.gz
- libpng-1.5.9.tar.bz2
+ libpng-1.6.21.tar.xz (LZMA-compressed, recommended)
+ libpng-1.6.21.tar.gz
Source files with CRLF line endings (for Windows), without the
"configure" script
- lpng159.7z (LZMA-compressed, recommended)
- lpng159.zip
+ /scratch/glennrp/Libpng16/lpng1621.7z (LZMA-compressed, recommended)
+ /scratch/glennrp/Libpng16/lpng1621.zip
Other information:
- libpng-1.5.9-README.txt
- libpng-1.5.9-LICENSE.txt
-
-Changes since the last public release (1.5.8):
-
- Rebuilt configure scripts in the tar distributions.
- Removed two unused definitions from scripts/pnglibconf.h.prebuilt
- Removed some unused arrays (with #ifdef) from png_read_push_finish_row().
- Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h
- Fixed CVE-2011-3026 buffer overrun bug. Deal more correctly with the test
- on iCCP chunk length. Also removed spurious casts that may hide problems
- on 16-bit systems.
+ libpng-1.6.21-README.txt
+ libpng-1.6.21-LICENSE.txt
+ libpng-1.6.21-*.asc (armored detached GPG signatures)
+
+Changes since the last public release (1.6.20):
+
+ Fixed syntax "$(command)" in tests/pngstest that some shells other than
+ bash could not parse (Bug report by Nelson Beebe). Use `command` instead.
+ Moved png_check_keyword() from pngwutil.c to pngset.c
+ Removed LE/BE dependencies in pngvalid, to 'fix' the current problem
+ in the BigEndian tests by not testing it, making the BE code the same
+ as the LE version.
+ Fixes to pngvalid for various reduced build configurations (eliminate unused
+ statics) and a fix for the case in rgb_to_gray when the digitize option
+ reduces graylo to 0, producing a large error.
+ Widened the 'limit' check on the internally calculated error limits in
+ the 'DIGITIZE' case (the code used prior to 1.7 for rgb_to_gray error
+ checks) and changed the check to only operate in non-release builds
+ (base build type not RC or RELEASE.)
+ Fixed undefined behavior in pngvalid.c, undefined because
+ (png_byte) << shift is undefined if it changes the signed bit
+ (because png_byte is promoted to int). The libpng exported functions
+ png_get_uint_32 and png_get_uint_16 handle this. (Bug reported by
+ David Drysdale as a result of reports from UBSAN in clang 3.8).
+ This changes pngvalid to use BE random numbers; this used to produce
+ errors but these should not be fixed as a result of the previous changes.
+ In projects/vstudio, combined readme.txt and WARNING into README.txt
+ Relocated assert() in contrib/tools/pngfix.c, bug found by American
+ Fuzzy Lop, reported by Brian Carpenter.
+ Marked 'limit' UNUSED in transform_range_check(). This only affects
+ release builds.
+ Worked around a false-positive Coverity issue in pngvalid.c.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit
diff --git a/thirdparty/libpng/CHANGES b/thirdparty/libpng/CHANGES
index 301b80c7..8e589f64 100644
--- a/thirdparty/libpng/CHANGES
+++ b/thirdparty/libpng/CHANGES
@@ -1,11 +1,14 @@
#if 0
CHANGES - changes for libpng
-Version 0.2
+version 0.1 [March 29, 1995]
+ initial work-in-progress release
+
+version 0.2 [April 1, 1995]
added reader into png.h
fixed small problems in stub file
-Version 0.3
+version 0.3 [April 8, 1995]
added pull reader
split up pngwrite.c to several files
added pnglib.txt
@@ -14,9 +17,9 @@ Version 0.3
fixed some bugs in writer
interfaced with zlib 0.5
added K&R support
- added check for 64 KB blocks for 16-bit machines
+ added check for 64 KB blocks for 16 bit machines
-Version 0.4
+version 0.4 [April 26, 1995]
cleaned up code and commented code
simplified time handling into png_time
created png_color_16 and png_color_8 to handle color needs
@@ -27,28 +30,29 @@ Version 0.4
cleaned up zTXt reader and writer (using zlib's Reset functions)
split transformations into pngrtran.c and pngwtran.c
-Version 0.5
+version 0.5 [April 30, 1995]
interfaced with zlib 0.8
fixed many reading and writing bugs
saved using 3 spaces instead of tabs
-Version 0.6
+version 0.6 [May 1, 1995]
+ first beta release
added png_large_malloc() and png_large_free()
added png_size_t
cleaned up some compiler warnings
added png_start_read_image()
-Version 0.7
+version 0.7 [June 24, 1995]
cleaned up lots of bugs
finished dithering and other stuff
added test program
changed name from pnglib to libpng
-Version 0.71 [June, 1995]
+version 0.71 [June 26, 1995]
changed pngtest.png for zlib 0.93
fixed error in libpng.txt and example.c
-Version 0.8
+version 0.8 [August 20, 1995]
cleaned up some bugs
added png_set_filler()
split up pngstub.c into pngmem.c, pngio.c, and pngerror.c
@@ -91,7 +95,7 @@ Version 0.88 [January, 1996]
cleaned up documentation
added callbacks for read/write and warning/error functions
-Version 0.89 [July, 1996]
+Version 0.89 [June 5, 1996]
Added new initialization API to make libpng work better with shared libs
we now have png_create_read_struct(), png_create_write_struct(),
png_create_info_struct(), png_destroy_read_struct(), and
@@ -118,6 +122,9 @@ Version 0.89 [July, 1996]
New pngtest image also has interlacing and zTXt
Updated documentation to reflect new API
+Version 0.89c [June 17, 1996]
+ Bug fixes.
+
Version 0.90 [January, 1997]
Made CRC errors/warnings on critical and ancillary chunks configurable
libpng will use the zlib CRC routines by (compile-time) default
@@ -158,7 +165,7 @@ Version 0.95 [March, 1997]
Added new pCAL chunk read/write support
Added experimental filter selection weighting (Greg Roelofs)
Removed old png_set_rgbx() and png_set_xrgb() functions that have been
- obsolete for about 2 years now (use png_set_filler() instead)
+ obsolete for about 2 years now (use png_set_filler() instead)
Added macros to read 16- and 32-bit ints directly from buffer, to be
used only on those systems that support it (namely PowerPC and 680x0)
With some testing, this may become the default for MACOS/PPC systems.
@@ -440,7 +447,7 @@ Version 1.0.3 [January 14, 1999]
Version 1.0.3a [August 12, 1999]
Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning
- if an attempt is made to read an interlaced image when it's not supported.
+ if an attempt is made to read an interlaced image when it's not supported.
Added check if png_ptr->trans is defined before freeing it in pngread.c
Modified the Y2K statement to include versions back to version 0.71
Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c
@@ -448,7 +455,7 @@ Version 1.0.3a [August 12, 1999]
Replaced leading blanks with tab characters in makefile.hux
Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents.
Changed (float)red and (float)green to (double)red, (double)green
- in png_set_rgb_to_gray() to avoid "promotion" problems in AIX.
+ in png_set_rgb_to_gray() to avoid "promotion" problems in AIX.
Fixed a bug in pngconf.h that omitted <stdio.h> when PNG_DEBUG==0 (K Bracey).
Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt).
Updated documentation to refer to the PNG-1.2 specification.
@@ -491,7 +498,7 @@ Version 1.0.3d [September 4, 1999]
Added new png_expand functions to scripts/pngdef.pas and pngos2.def
Added a demo read_user_transform_fn that examines the row filters in pngtest.c
-Version 1.0.4 [September 24, 1999]
+Version 1.0.4 [September 24, 1999, not distributed publicly]
Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined
Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h
Made several minor corrections to pngtest.c
@@ -518,6 +525,7 @@ Version 1.0.4c [October 1, 1999]
Added a "png_check_version" function in png.c and pngtest.c that will generate
a helpful compiler error if an old png.h is found in the search path.
Changed type of png_user_transform_depth|channels from int to png_byte.
+ Added "Libpng is OSI Certified Open Source Software" statement to png.h
Version 1.0.4d [October 6, 1999]
Changed 0.45 to 0.45455 in png_set_sRGB()
@@ -904,7 +912,7 @@ Version 1.0.7 [July 1, 2000]
Version 1.0.8beta1 [July 8, 2000]
Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks.
Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and
- pngwutil.c.
+ pngwutil.c.
Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h.
Removed unused "#include <assert.h>" from png.c
Added WindowsCE support.
@@ -912,12 +920,12 @@ Version 1.0.8beta1 [July 8, 2000]
Version 1.0.8beta2 [July 10, 2000]
Added project files to the wince directory and made further revisions
- of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE.
+ of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE.
Version 1.0.8beta3 [July 11, 2000]
Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS()
- for indexed-color input files to avoid potential double-freeing trans array
- under some unusual conditions; problem was introduced in version 1.0.6f.
+ for indexed-color input files to avoid potential double-freeing trans array
+ under some unusual conditions; problem was introduced in version 1.0.6f.
Further revisions to pngtest.c and files in the wince subdirectory.
Version 1.0.8beta4 [July 14, 2000]
@@ -1089,16 +1097,16 @@ Version 1.2.0beta3 [May 17, 2001]
Version 1.2.0beta4 [June 23, 2001]
Check for missing profile length field in iCCP chunk and free chunk_data
- in case of truncated iCCP chunk.
+ in case of truncated iCCP chunk.
Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc
Bumped dll-number from 2 to 3 in makefile.cygwin
Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly
- if user attempts to run it on an 8-bit display.
+ if user attempts to run it on an 8-bit display.
Updated contrib/gregbook
Use png_malloc instead of png_zalloc to allocate palette in pngset.c
Updated makefile.ibmc
Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes
- of png_write_oFFS width and height from png_uint_32 to png_int_32.
+ of png_write_oFFS width and height from png_uint_32 to png_int_32.
Updated example.c
Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c
@@ -1106,9 +1114,9 @@ Version 1.2.0beta5 [August 8, 2001]
Revised contrib/gregbook
Revised makefile.gcmmx
Revised pnggccrd.c to conditionally compile some thread-unsafe code only
- when PNG_THREAD_UNSAFE_OK is defined.
+ when PNG_THREAD_UNSAFE_OK is defined.
Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with
- value exceeding 2^bit_depth-1
+ value exceeding 2^bit_depth-1
Revised makefile.sgi and makefile.sggcc
Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c
Removed restriction that do_invert_mono only operate on 1-bit opaque files
@@ -1449,8 +1457,9 @@ Version 1.2.6beta4 [July 28, 2004]
Use png_malloc instead of png_zalloc to allocate the pallete.
Version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004]
- Fixed buffer overflow vulnerability in png_handle_tRNS()
- Fixed integer arithmetic overflow vulnerability in png_read_png().
+ Fixed buffer overflow vulnerability (CVE-2004-0597) in png_handle_tRNS().
+ Fixed NULL dereference vulnerability (CVE-2004-0598) in png_handle_iCCP().
+ Fixed integer overflow vulnerability (CVE-2004-0599) in png_read_png().
Fixed some harmless bugs in png_handle_sBIT, etc, that would cause
duplicate chunk types to go undetected.
Fixed some timestamps in the -config version
@@ -1493,7 +1502,7 @@ Version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004]
Version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004]
Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED
- section of png.h where they were inadvertently placed in version rc3.
+ section of png.h where they were inadvertently placed in version rc3.
Version 1.2.6 and 1.0.16 [August 15, 2004]
Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1.
@@ -2102,7 +2111,7 @@ Version 1.4.0beta24 [July 25, 2008]
png_decompress_chunk(), and remove "chunkdata" from parameter list.
Put a call to png_check_chunk_name() in png_read_chunk_header().
Revised png_check_chunk_name() to reject a name with a lowercase 3rd byte.
- Removed two calls to png_check_chunk_name() occuring later in the process.
+ Removed two calls to png_check_chunk_name() occurring later in the process.
Define PNG_NO_ERROR_NUMBERS by default in pngconf.h
Version 1.4.0beta25 [July 30, 2008]
@@ -2325,7 +2334,7 @@ Version 1.4.0beta63 [June 15, 2009]
Version 1.4.0beta64 [June 24, 2009]
Eliminated PNG_LEGACY_SUPPORTED code.
Moved the various unknown chunk macro definitions outside of the
- PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks.
+ PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks.
Version 1.4.0beta65 [June 26, 2009]
Added a reference to the libpng license in each file.
@@ -3672,7 +3681,8 @@ Version 1.5.6 [November 3, 2011]
No changes.
Version 1.5.7beta01 [November 4, 2011]
- Added support for ARM processor (Mans Rullgard)
+ Added support for ARM processor, when decoding all PNG up-filtered rows
+ and any other-filtered rows with 3 or 4 bytes per pixel (Mans Rullgard).
Fixed bug in pngvalid on early allocation failure; fixed type cast in
pngmem.c; pngvalid would attempt to call png_error() if the allocation
of a png_struct or png_info failed. This would probably have led to a
@@ -3746,8 +3756,9 @@ Version 1.5.7beta04 [November 17, 2011]
Version 1.5.7beta05 [November 25, 2011]
Removed "zTXt" from warning in generic chunk decompression function.
- Validate time settings passed to pngset() and png_convert_to_rfc1123()
- (Frank Busse).
+ Validate time settings passed to png_set_tIME() and png_convert_to_rfc1123()
+ (Frank Busse). Note: This prevented CVE-2015-7981 from affecting
+ libpng-1.5.7 and later.
Added MINGW support to CMakeLists.txt
Reject invalid compression flag or method when reading the iTXt chunk.
Backed out 'simplified' API changes. The API seems too complex and there
@@ -3775,41 +3786,1704 @@ Version 1.5.7rc03 [December 7, 2011]
Version 1.5.7 [December 15, 2011]
Minor fixes to pngvalid.c for gcc 4.6.2 compatibility to remove warnings
reported by earlier versions.
-
-Version 1.5.8beta01 [January 15, 2011]
- Removed '#include config.h"' from contrib/libtests/pngvalid.c. It's not
- needed and causes trouble for VPATH building.
+ Fixed minor memset/sizeof errors in pngvalid.c.
+
+Version 1.6.0beta01 [December 15, 2011]
+ Removed machine-generated configure files from the GIT repository (they will
+ continue to appear in the tarball distributions and in the libpng15 and
+ earlier GIT branches).
+ Restored the new 'simplified' API, which was started in libpng-1.5.7beta02
+ but later deleted from libpng-1.5.7beta05.
+ Added example programs for the new 'simplified' API.
+ Added ANSI-C (C90) headers and require them, and take advantage of the
+ change. Also fixed some of the projects/* and contrib/* files that needed
+ updates for libpng16 and the move of pngvalid.c.
+ With this change the required ANSI-C header files are assumed to exist: the
+ implementation must provide float.h, limits.h, stdarg.h and stddef.h and
+ libpng relies on limits.h and stddef.h existing and behaving as defined
+ (the other two required headers aren't used). Non-ANSI systems that don't
+ have stddef.h or limits.h will have to provide an appropriate fake
+ containing the relevant types and #defines.
+ Dropped support for 16-bit platforms. The use of FAR/far has been eliminated
+ and the definition of png_alloc_size_t is now controlled by a flag so
+ that 'small size_t' systems can select it if necessary. Libpng 1.6 may
+ not currently work on such systems -- it seems likely that it will
+ ask 'malloc' for more than 65535 bytes with any image that has a
+ sufficiently large row size (rather than simply failing to read such
+ images).
+ New tools directory containing tools used to generate libpng code.
+ Fixed race conditions in parallel make builds. With higher degrees of
+ parallelism during 'make' the use of the same temporary file names such
+ as 'dfn*' can result in a race where a temporary file from one arm of the
+ build is deleted or overwritten in another arm. This changes the
+ temporary files for suffix rules to always use $* and ensures that the
+ non-suffix rules use unique file names.
+
+Version 1.6.0beta02 [December 21, 2011]
+ Correct configure builds where build and source directories are separate.
+ The include path of 'config.h' was erroneously made relative in pngvalid.c
+ in libpng 1.5.7.
+
+Version 1.6.0beta03 [December 22, 2011]
+ Start-up code size improvements, error handler flexibility. These changes
+ alter how the tricky allocation of the initial png_struct and png_info
+ structures are handled. png_info is now handled in pretty much the same
+ way as everything else, except that the allocations handle NULL return
+ silently. png_struct is changed in a similar way on allocation and on
+ deallocation a 'safety' error handler is put in place (which should never
+ be required). The error handler itself is changed to permit mismatches
+ in the application and libpng error buffer size; however, this means a
+ silent change to the API to return the jmp_buf if the size doesn't match
+ the size from the libpng compilation; libpng now allocates the memory and
+ this may fail. Overall these changes result in slight code size
+ reductions; however, this is a reduction in code that is always executed
+ so is particularly valuable. Overall on a 64-bit system the libpng DLL
+ decreases in code size by 1733 bytes. pngerror.o increases in size by
+ about 465 bytes because of the new functionality.
+ Added png_convert_to_rfc1123_buffer() and deprecated png_convert_to_rfc1123()
+ to avoid including a spurious buffer in the png_struct.
+
+Version 1.6.0beta04 [December 30, 2011]
+ Regenerated configure scripts with automake-1.11.2
+ Eliminated png_info_destroy(). It is now used only in png.c and only calls
+ one other internal function and memset().
+ Enabled png_get_sCAL_fixed() if floating point APIs are enabled. Previously
+ it was disabled whenever internal fixed point arithmetic was selected,
+ which meant it didn't exist even on systems where FP was available but not
+ preferred.
+ Added pngvalid.c compile time checks for const APIs.
+ Implemented 'restrict' for png_info and png_struct. Because of the way
+ libpng works both png_info and png_struct are always accessed via a
+ single pointer. This means adding C99 'restrict' to the pointer gives
+ the compiler some opportunity to optimize the code. This change allows
+ that.
Moved AC_MSG_CHECKING([if libraries can be versioned]) later to the proper
location in configure.ac (Gilles Espinasse).
+ Changed png_memcpy to C assignment where appropriate. Changed all those
+ uses of png_memcpy that were doing a simple assignment to assignments
+ (all those cases where the thing being copied is a non-array C L-value).
+ Added some error checking to png_set_*() routines.
+ Removed the reference to the non-exported function png_memcpy() from
+ example.c.
+ Fixed the Visual C 64-bit build - it requires jmp_buf to be aligned, but
+ it had become misaligned.
+ Revised contrib/pngminus/pnm2png.c to avoid warnings when png_uint_32
+ and unsigned long are of different sizes.
+
+Version 1.6.0beta05 [January 15, 2012]
+ Updated manual with description of the simplified API (copied from png.h)
Fix bug in pngerror.c: some long warnings were being improperly truncated
(CVE-2011-3464, bug introduced in libpng-1.5.3beta05).
-Version 1.5.8rc01 [January 21, 2012]
+Version 1.6.0beta06 [January 24, 2012]
+ Added palette support to the simplified APIs. This commit
+ changes some of the macro definitions in png.h, app code
+ may need corresponding changes.
+ Increased the formatted warning buffer to 192 bytes.
+ Added color-map support to simplified API. This is an initial version for
+ review; the documentation has not yet been updated.
+ Fixed Min/GW uninstall to remove libpng.dll.a
+
+Version 1.6.0beta07 [January 28, 2012]
+ Eliminated Intel icc/icl compiler warnings. The Intel (GCC derived)
+ compiler issues slightly different warnings from those issued by the
+ current vesions of GCC. This eliminates those warnings by
+ adding/removing casts and small code rewrites.
+ Updated configure.ac from autoupdate: added --enable-werror option.
+ Also some layout regularization and removal of introduced tab characters
+ (replaced with 3-character indentation). Obsolete macros identified by
+ autoupdate have been removed; the replacements are all in 2.59 so
+ the pre-req hasn't been changed. --enable-werror checks for support
+ for -Werror (or the given argument) in the compiler. This mimics the
+ gcc configure option by allowing -Werror to be turned on safely; without
+ the option the tests written in configure itself fail compilation because
+ they cause compiler warnings.
+ Rewrote autogen.sh to run autoreconf instead of running tools one-by-one.
+ Conditionalize the install rules for MINGW and CYGWIN in CMakeLists.txt and
+ set CMAKE_LIBRARY_OUTPUT_DIRECTORY to "lib" on all platforms (C. Yapp).
+ Freeze libtool files in the 'scripts' directory. This version of autogen.sh
+ attempts to dissuade people from running it when it is not, or should not,
+ be necessary. In fact, autogen.sh does not work when run in a libpng
+ directory extracted from a tar distribution anymore. You must run it in
+ a GIT clone instead.
+ Added two images to contrib/pngsuite (1-bit and 2-bit transparent grayscale),
+ and renamed three whose names were inconsistent with those in
+ pngsuite/README.txt.
+
+Version 1.6.0beta08 [February 1, 2012]
+ Fixed Image::colormap misalignment in pngstest.c
+ Check libtool/libtoolize version number (2.4.2) in configure.ac
+ Divide test-pngstest.sh into separate pngstest runs for basic and
+ transparent images.
+ Moved automake options to AM_INIT_AUTOMAKE in configure.ac
+ Added color-tests, silent-rules (Not yet implemented in Makefile.am) and
+ version checking to configure.ac
+ Improved pngstest speed by not doing redundant tests and add const to
+ the background parameter of png_image_finish_read. The --background
+ option is now done automagically only when required, so that commandline
+ option no longer exists.
+ Cleaned up pngpriv.h to consistently declare all functions and data.
+ Also eliminated PNG_CONST_DATA, which is apparently not needed but we
+ can't be sure until it is gone.
+ Added symbol prefixing that allows all the libpng external symbols
+ to be prefixed (suggested by Reuben Hawkins).
+ Updated "ftbb*.png" list in the owatcom and vstudio projects.
+ Fixed 'prefix' builds on clean systems. The generation of pngprefix.h
+ should not require itself.
+ Updated INSTALL to explain that autogen.sh must be run in a GIT clone,
+ not in a libpng directory extracted from a tar distribution.
+
+Version 1.6.0beta09 [February 1, 2012]
+ Reverted the prebuilt configure files to libpng-1.6.0beta05 condition.
+
+Version 1.6.0beta10 [February 3, 2012]
+ Added Z_SOLO for zlib-1.2.6+ and correct pngstest tests
+ Updated list of test images in CMakeLists.txt
+ Updated the prebuilt configure files to current condition.
+ Revised INSTALL information about autogen.sh; it works in tar distributions.
+
+Version 1.6.0beta11 [February 16, 2012]
+ Fix character count in pngstest command in projects/owatcom/pngstest.tgt
+ Revised test-pngstest.sh to report PASS/FAIL for each image.
+ Updated documentation about the simplified API.
+ Corrected estimate of error in libpng png_set_rgb_to_gray API. The API is
+ extremely inaccurate for sRGB conversions because it uses an 8-bit
+ intermediate linear value and it does not use the sRGB transform, so it
+ suffers from the known instability in gamma transforms for values close
+ to 0 (see Poynton). The net result is that the calculation has a maximum
+ error of 14.99/255; 0.5/255^(1/2.2). pngstest now uses 15 for the
+ permitted 8-bit error. This may still not be enough because of arithmetic
+ error.
+ Removed some unused arrays (with #ifdef) from png_read_push_finish_row().
+ Fixed a memory overwrite bug in simplified read of RGB PNG with
+ non-linear gamma Also bugs in the error checking in pngread.c and changed
+ quite a lot of the checks in pngstest.c to be correct; either correctly
+ written or not over-optimistic. The pngstest changes are insufficient to
+ allow all possible RGB transforms to be passed; pngstest cmppixel needs
+ to be rewritten to make it clearer which errors it allows and then changed
+ to permit known inaccuracies.
+ Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h
+ Fixed fixed/float API export conditionals. 1) If FIXED_POINT or
+ FLOATING_POINT options were switched off, png.h ended up with lone ';'
+ characters. This is not valid ANSI-C outside a function. The ';'
+ characters have been moved inside the definition of PNG_FP_EXPORT and
+ PNG_FIXED_EXPORT. 2) If either option was switched off, the declaration
+ of the corresponding functions were completely omitted, even though some
+ of them are still used internally. The result is still valid, but
+ produces warnings from gcc with some warning options (including -Wall). The
+ fix is to cause png.h to declare the functions with PNG_INTERNAL_FUNCTION
+ when png.h is included from pngpriv.h.
+ Check for invalid palette index while reading paletted PNG. When one is
+ found, issue a warning and increase png_ptr->num_palette accordingly.
+ Apps are responsible for checking to see if that happened.
+
+Version 1.6.0beta12 [February 18, 2012]
+ Do not increase num_palette on invalid_index.
+ Relocated check for invalid palette index to pngrtran.c, after unpacking
+ the sub-8-bit pixels.
+ Fixed CVE-2011-3026 buffer overrun bug. This bug was introduced when
+ iCCP chunk support was added at libpng-1.0.6. Deal more correctly with the
+ test on iCCP chunk length. Also removed spurious casts that may hide
+ problems on 16-bit systems.
+
+Version 1.6.0beta13 [February 24, 2012]
+ Eliminated redundant png_push_read_tEXt|zTXt|iTXt|unknown code from
+ pngpread.c and use the sequential png_handle_tEXt, etc., in pngrutil.c;
+ now that png_ptr->buffer is inaccessible to applications, the special
+ handling is no longer useful.
+ Added PNG_SAFE_LIMITS feature to pnglibconf.dfa, pngpriv.h, and new
+ pngusr.dfa to reset the user limits to safe ones if PNG_SAFE_LIMITS is
+ defined. To enable, use "CPPFLAGS=-DPNG_SAFE_LIMITS_SUPPORTED=1" on the
+ configure command or put #define PNG_SAFE_LIMITS_SUPPORTED in
+ pnglibconf.h.prebuilt and pnglibconf.h.
+
+Version 1.6.0beta14 [February 27, 2012]
+ Added information about the new limits in the manual.
+ Updated Makefile.in
+
+Version 1.6.0beta15 [March 2, 2012]
+ Removed unused "current_text" members of png_struct and the png_free()
+ of png_ptr->current_text from pngread.c
+ Rewrote pngstest.c for substantial speed improvement.
+ Fixed transparent pixel and 16-bit rgb tests in pngstest and removed a
+ spurious check in pngwrite.c
+ Added PNG_IMAGE_FLAG_FAST for the benefit of applications that store
+ intermediate files, or intermediate in-memory data, while processing
+ image data with the simplified API. The option makes the files larger
+ but faster to write and read. pngstest now uses this by default; this
+ can be disabled with the --slow option.
+ Improved pngstest fine tuning of error numbers, new test file generator.
+ The generator generates images that test the full range of sample values,
+ allow the error numbers in pngstest to be tuned and checked. makepng
+ also allows generation of images with extra chunks, although this is
+ still work-in-progress.
+ Added check for invalid palette index while reading.
+ Fixed some bugs in ICC profile writing. The code should now accept
+ all potentially valid ICC profiles and reject obviously invalid ones.
+ It now uses png_error() to do so rather than casually writing a PNG
+ without the necessary color data.
+ Removed whitespace from the end of lines in all source files and scripts.
+
+Version 1.6.0beta16 [March 6, 2012]
+ Relocated palette-index checking function from pngrutil.c to pngtrans.c
+ Added palette-index checking while writing.
+ Changed png_inflate() and calling routines to avoid overflow problems.
+ This is an intermediate check-in that solves the immediate problems and
+ introduces one performance improvement (avoiding a copy via png_ptr->zbuf.)
+ Further changes will be made to make ICC profile handling more secure.
+ Fixed build warnings (MSVC, GCC, GCC v3). Cygwin GCC with default options
+ declares 'index' as a global, causing a warning if it is used as a local
+ variable. GCC 64-bit warns about assigning a (size_t) (unsigned 64-bit)
+ to an (int) (signed 32-bit). MSVC, however, warns about using the
+ unary '-' operator on an unsigned value (even though it is well defined
+ by ANSI-C to be ~x+1). The padding calculation was changed to use a
+ different method. Removed the tests on png_ptr->pass.
+ Added contrib/libtests/tarith.c to test internal arithmetic functions from
+ png.c. This is a libpng maintainer program used to validate changes to the
+ internal arithmetic functions.
+ Made read 'inflate' handling like write 'deflate' handling. The read
+ code now claims and releases png_ptr->zstream, like the write code.
+ The bug whereby the progressive reader failed to release the zstream
+ is now fixed, all initialization is delayed, and the code checks for
+ changed parameters on deflate rather than always calling
+ deflatedEnd/deflateInit.
+ Validate the zTXt strings in pngvalid.
+ Added code to validate the windowBits value passed to deflateInit2().
+ If the call to deflateInit2() is wrong a png_warning will be issued
+ (in fact this is harmless, but the PNG data produced may be sub-optimal).
+
+Version 1.6.0beta17 [March 10, 2012]
+ Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition.
+ Reject all iCCP chunks after the first, even if the first one is invalid.
+ Deflate/inflate was reworked to move common zlib calls into single
+ functions [rw]util.c. A new shared keyword check routine was also added
+ and the 'zbuf' is no longer allocated on progressive read. It is now
+ possible to call png_inflate() incrementally. A warning is no longer
+ issued if the language tag or translated keyword in the iTXt chunk
+ has zero length.
+ If benign errors are disabled use maximum window on ancilliary inflate.
+ This works round a bug introduced in 1.5.4 where compressed ancillary
+ chunks could end up with a too-small windowBits value in the deflate
+ header.
+
+Version 1.6.0beta18 [March 16, 2012]
+ Issue a png_benign_error() instead of png_warning() about bad palette index.
+ In pngtest, treat benign errors as errors if "-strict" is present.
+ Fixed an off-by-one error in the palette index checking function.
+ Fixed a compiler warning under Cygwin (Windows-7, 32-bit system)
+ Revised example.c to put text strings in a temporary character array
+ instead of directly assigning string constants to png_textp members.
+ This avoids compiler warnings when -Wwrite-strings is enabled.
+ Added output flushing to aid debugging under Visual Studio. Unfortunately
+ this is necessary because the VS2010 output window otherwise simply loses
+ the error messages on error (they weren't flushed to the window before
+ the process exited, apparently!)
+ Added configuration support for benign errors and changed the read
+ default. Also changed some warnings in the iCCP and sRGB handling
+ from to benign errors. Configuration now makes read benign
+ errors warnings and write benign errors to errors by default (thus
+ changing the behavior on read). The simplified API always forces
+ read benign errors to warnings (regardless of the system default, unless
+ this is disabled in which case the simplified API can't be built.)
+
+Version 1.6.0beta19 [March 18, 2012]
+ Work around for duplicate row start calls; added warning messages.
+ This turns on PNG_FLAG_DETECT_UNINITIALIZED to detect app code that
+ fails to call one of the 'start' routines (not enabled in libpng-1.5
+ because it is technically an API change, since it did normally work
+ before.) It also makes duplicate calls to png_read_start_row (an
+ internal function called at the start of the image read) benign, as
+ they were before changes to use png_inflate_claim. Somehow webkit is
+ causing this to happen; this is probably a mis-feature in the zlib
+ changes so this commit is only a work-round.
+ Removed erroneous setting of DETECT_UNINITIALIZED and added more
+ checks. The code now does a png_error if an attempt is made to do the
+ row initialization twice; this is an application error and it has
+ serious consequences because the transform data in png_struct is
+ changed by each call.
+ Added application error reporting and added chunk names to read
+ benign errors; also added --strict to pngstest - not enabled
+ yet because a warning is produced.
+ Avoid the double gamma correction warning in the simplified API.
+ This allows the --strict option to pass in the pngstest checks
+
+Version 1.6.0beta20 [March 29, 2012]
+ Changed chunk handler warnings into benign errors, incrementally load iCCP
+ Added checksum-icc.c to contrib/tools
+ Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice.
+ Recognize known sRGB ICC profiles while reading; prefer writing the
+ iCCP profile over writing the sRGB chunk, controlled by the
+ PNG_sRGB_PROFILE_CHECKS option.
+ Revised png_set_text_2() to avoid potential memory corruption (fixes
+ CVE-2011-3048, also known as CVE-2012-3425).
+
+Version 1.6.0beta21 [April 27, 2012]
+ Revised scripts/makefile.darwin: use system zlib; remove quotes around
+ architecture list; add missing ppc architecture; add architecture options
+ to shared library link; don't try to create a shared lib based on missing
+ RELEASE variable.
+ Enable png_set_check_for_invalid_index() for both read and write.
+ Removed #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED in pngpriv.h around
+ declaration of png_handle_unknown().
+ Added -lssp_nonshared in a comment in scripts/makefile.freebsd
+ and changed deprecated NOOBJ and NOPROFILE to NO_OBJ and NO_PROFILE.
+
+Version 1.6.0beta22 [May 23, 2012]
+ Removed need for -Wno-cast-align with clang. clang correctly warns on
+ alignment increasing pointer casts when -Wcast-align is passed. This
+ fixes the cases that clang warns about either by eliminating the
+ casts from png_bytep to png_uint_16p (pngread.c), or, for pngrutil.c
+ where the cast is previously verified or pngstest.c where it is OK, by
+ introducing new png_aligncast macros to do the cast in a way that clang
+ accepts.
+
+Version 1.6.0beta23 [June 6, 2012]
+ Revised CMakeLists.txt to not attempt to make a symlink under mingw.
+ Made fixes for new optimization warnings from gcc 4.7.0. The compiler
+ performs an optimization which is safe; however it then warns about it.
+ Changing the type of 'palette_number' in pngvalid.c removes the warning.
+ Do not depend upon a GCC feature macro being available for use in generating
+ the linker mapfile symbol prefix.
+ Improved performance of new do_check_palette_indexes() function (only
+ update the value when it actually increases, move test for whether
+ the check is wanted out of the function.
+
+Version 1.6.0beta24 [June 7, 2012]
+ Don't check palette indexes if num_palette is 0 (as it can be in MNG files).
+
+Version 1.6.0beta25 [June 16, 2012]
+ Revised png_set_keep_unknown_chunks() so num_chunks < 0 means ignore all
+ unknown chunks and all known chunks except for IHDR, PLTE, tRNS, IDAT,
+ and IEND. Previously it only meant ignore all unknown chunks, the
+ same as num_chunks == 0. Revised png_image_skip_unused_chunks() to
+ provide a list of chunks to be processed instead of a list of chunks to
+ ignore. Revised contrib/gregbook/readpng2.c accordingly.
+
+Version 1.6.0beta26 [July 10, 2012]
+ Removed scripts/makefile.cegcc from the *.zip and *.7z distributions; it
+ depends on configure, which is not included in those archives.
+ Moved scripts/chkfmt to contrib/tools.
+ Changed "a+w" to "u+w" in Makefile.in to fix CVE-2012-3386.
+
+Version 1.6.0beta27 [August 11, 2012]
+ Do not compile PNG_DEPRECATED, PNG_ALLOC and PNG_PRIVATE when __GNUC__ < 3.
+ Do not use __restrict when GNUC is <= 3.1
+ Removed references to png_zalloc() and png_zfree() from the manual.
+ Fixed configurations where floating point is completely disabled. Because
+ of the changes to support symbol prefixing PNG_INTERNAL_FUNCTION declares
+ floating point APIs during libpng builds even if they are completely
+ disabled. This requires the png floating point types (png_double*) to be
+ declared even though the functions are never actually defined. This
+ change provides a dummy definition so that the declarations work, yet any
+ implementation will fail to compile because of an incomplete type.
+ Re-eliminated the use of strcpy() in pngtest.c. An unncessary use of
+ strcpy() was accidentally re-introduced in libpng16; this change replaces
+ it with strncpy().
+ Eliminated use of png_sizeof(); use sizeof() instead.
+ Use a consistent style for (sizeof type) and (sizeof (array))
+ Cleanup of png_set_filler(). This function does very different things on
+ read and write. In libpng 1.6 the two cases can be distinguished and
+ considerable code cleanup, and extra error checking, is possible. This
+ makes calls on the write side that have no effect be ignored with a
+ png_app_error(), which can be disabled in the app using
+ png_set_benign_errors(), and removes the spurious use of usr_channels
+ on the read side.
+ Insist on autotools 1.12.1 for git builds because there are security issues
+ with 1.12 and insisting on anything less would allow 1.12 to be used.
+ Removed info_ptr->signature[8] from WRITE-only builds.
+ Add some conditions for compiling png_fixed(). This is a small function
+ but it requires "-lm" on some platforms.
+ Cause pngtest --strict to fail on any warning from libpng (not just errors)
+ and cause it not to fail at the comparison step if libpng lacks support
+ for writing chunks that it reads from the input (currently only implemented
+ for compressed text chunks).
+ Make all three "make check" test programs work without READ or WRITE support.
+ Now "make check" will succeed even if libpng is compiled with -DPNG_NO_READ
+ or -DPNG_NO_WRITE. The tests performed are reduced, but the basic reading
+ and writing of a PNG file is always tested by one or more of the tests.
+ Consistently use strlen(), memset(), memcpy(), and memcmp() instead of the
+ png_strlen(), png_memset(), png_memcpy(), and png_memcmp() macros.
+ Removed the png_sizeof(), png_strlen(), png_memset(), png_memcpy(), and
+ png_memcmp() macros.
+ Work around gcc 3.x and Microsoft Visual Studio 2010 complaints. Both object
+ to the split initialization of num_chunks.
+
+Version 1.6.0beta28 [August 29, 2012]
+ Unknown handling fixes and clean up. This adds more correct option
+ control of the unknown handling, corrects the pre-existing bug where
+ the per-chunk 'keep' setting is ignored and makes it possible to skip
+ IDAT chunks in the sequential reader (broken in earlier 1.6 versions).
+ There is a new test program, test-unknown.c, which is a work in progress
+ (not currently part of the test suite). Comments in the header files now
+ explain how the unknown handling works.
+ Allow fine grain control of unknown chunk APIs. This change allows
+ png_set_keep_unknown_chunks() to be turned off if not required and causes
+ both read and write to behave appropriately (on read this is only possible
+ if the user callback is used to handle unknown chunks). The change
+ also removes the support for storing unknown chunks in the info_struct
+ if the only unknown handling enabled is via the callback, allowing libpng
+ to be configured with callback reading and none of the unnecessary code.
+ Corrected fix for unknown handling in pngtest. This reinstates the
+ libpng handling of unknown chunks other than vpAg and sTER (including
+ unsafe-to-copy chunks which were dropped before) and eliminates the
+ repositioning of vpAg and sTER in pngtest.png by changing pngtest.png
+ (so the chunks are where libpng would put them).
+ Added "tunknown" test and corrected a logic error in png_handle_unknown()
+ when SAVE support is absent. Moved the shell test scripts for
+ contrib/libtests from the libpng top directory to contrib/libtests.
+ png_handle_unknown() must always read or skip the chunk, if
+ SAVE_UNKNOWN_CHUNKS is turned off *and* the application does not set
+ a user callback an unknown chunk will not be read, leading to a read
+ error, which was revealed by the "tunknown" test.
+ Cleaned up and corrected ICC profile handling.
+ contrib/libtests/makepng: corrected 'rgb' and 'gray' cases. profile_error
+ messages could be truncated; made a correct buffer size calculation and
+ adjusted pngerror.c appropriately. png_icc_check_* checking improved;
+ changed the functions to receive the correct color type of the PNG on read
+ or write and check that it matches the color space of the profile (despite
+ what the comments said before, there is danger in assuming the app will
+ cope correctly with an RGB profile on a grayscale image and, since it
+ violates the PNG spec, allowing it is certain to produce inconsistent
+ app behavior and might even cause app crashes.) Check that profiles
+ contain the tags needed to process the PNG (tags all required by the ICC
+ spec). Removed unused PNG_STATIC from pngpriv.h.
+
+Version 1.6.0beta29 [September 4, 2012]
+ Fixed the simplified API example programs to add the *colormap parameter
+ to several of he API and improved the error message if the version field
+ is not set.
+ Added contrib/examples/* to the *.zip and *.7z distributions.
+ Updated simplified API synopses and description of the png_image structure
+ in the manual.
+ Made makepng and pngtest produce identical PNGs, add "--relaxed" option
+ to pngtest. The "--relaxed" option turns off the benign errors that are
+ enabled by default in pre-RC builds. makepng can now write ICC profiles
+ where the length has not been extended to a multiple of 4, and pngtest
+ now intercepts all libpng errors, allowing the previously-introduced
+ "--strict test" on no warnings to actually work.
+ Improved ICC profile handling including cHRM chunk generation and fixed
+ Cygwin+MSVC build errors. The ICC profile handling now includes more
+ checking. Several errors that caused rejection of the profile are now
+ handled with a warning in such a way that the invalid profiles will be
+ read by default in release (but not pre-RC) builds but will not be
+ written by default. The easy part of handling the cHRM chunk is written,
+ where the ICC profile contains the required data. The more difficult
+ part plus guessing a gAMA value requires code to pass selected RGB values
+ through the profile.
+
+Version 1.6.0beta30 [October 24, 2012]
+ Changed ICC profile matrix/vector types to not depend on array type rules.
+ By the ANSI-C standard the new types should be identical to the previous
+ versions, and all known versions of gcc tested with the previous versions
+ except for GCC-4.2.1 work with this version. The change makes the ANSI-C
+ rule that const applied to an array of elements applies instead to the
+ elements in the array moot by explicitly applying const to the base
+ elements of the png_icc_matrix and png_icc_vector types. The accidental
+ (harmless) 'const' previously applied to the parameters of two of the
+ functions have also been removed.
+ Added a work around for GCC 4.2 optimization bug.
+ Marked the broken (bad white point) original HP sRGB profiles correctly and
+ correct comments.
+ Added -DZ_SOLO to contrib/pngminim/*/makefile to work with zlib-1.2.7
+ Use /MDd for vstudio debug builds. Also added pngunkown to the vstudio
+ builds, fixed build errors and corrected a minor exit code error in
+ pngvalid if the 'touch' file name is invalid.
+ Add updated WARNING file to projects/vstudio from libpng 1.5/vstudio
+ Fixed build when using #define PNG_NO_READ_GAMMA in png_do_compose() in
+ pngrtran.c (Domani Hannes).
+
+Version 1.6.0beta31 [November 1, 2012]
+ Undid the erroneous change to vstudio/pngvalid build in libpng-1.6.0beta30.
+ Made pngvalid so that it will build outside the libpng source tree.
+ Made builds -DPNG_NO_READ_GAMMA compile (the unit tests still fail).
+ Made PNG_NO_READ_GAMMA switch off interfaces that depend on READ_GAMMA.
+ Prior to 1.6.0 switching off READ_GAMMA did unpredictable things to the
+ interfaces that use it (specifically, png_do_background in 1.4 would
+ simply display composite for grayscale images but do composition
+ with the incorrect arithmetic for color ones). In 1.6 the semantic
+ of -DPNG_NO_READ_GAMMA is changed to simply disable any interface that
+ depends on it; this obliges people who set it to consider whether they
+ really want it off if they happen to use any of the interfaces in
+ question (typically most users who disable it won't).
+ Fixed GUIDs in projects/vstudio. Some were duplicated or missing,
+ resulting in VS2010 having to update the files.
+ Removed non-working ICC profile support code that was mostly added to
+ libpng-1.6.0beta29 and beta30. There was too much code for too little
+ gain; implementing full ICC color correction may be desireable but is left
+ up to applications.
+
+Version 1.6.0beta32 [November 25, 2012]
+ Fixed an intermittent SEGV in pngstest due to an uninitialized array element.
+ Added the ability for contrib/libtests/makepng.c to make a PNG with just one
+ color. This is useful for debugging pngstest color inaccuracy reports.
+ Fixed error checking in the simplified write API (Olaf van der Spek)
+ Made png_user_version_check() ok to use with libpng version 1.10.x and later.
+
+Version 1.6.0beta33 [December 15, 2012]
+ Fixed typo in png.c (PNG_SET_CHUNK_MALLOC_MAX should be PNG_CHUNK_MALLOC_MAX)
+ that causes the MALLOC_MAX limit not to work (John Bowler)
+ Change png_warning() to png_app_error() in pngwrite.c and comment the
+ fall-through condition.
+ Change png_warning() to png_app_warning() in png_write_tRNS().
+ Rearranged the ARM-NEON optimizations: Isolated the machine specific code
+ to the hardware subdirectory and added comments to pngrutil.c so that
+ implementors of other optimizations know what to do.
+ Fixed cases of unquoted DESTDIR in Makefile.am
+ Rebuilt Makefile.in, etc., with autoconf-2.69 and automake-1.12.5.
+
+Version 1.6.0beta34 [December 19, 2012]
+ Cleaned up whitespace in the synopsis portion of the manpage "libpng.3"
+ Disassembled the version number in scripts/options.awk (necessary for
+ building on SunOs).
+
+Version 1.6.0beta35 [December 23, 2012]
+ Made default Zlib compression settings be configurable. This adds #defines to
+ pnglibconf.h to control the defaults.
+ Fixed Windows build issues, enabled ARM compilation. Various warnings issued
+ by earlier versions of GCC fixed for Cygwin and Min/GW (which both use old
+ GCCs.) ARM support is enabled by default in zlib.props (unsupported by
+ Microsoft) and ARM compilation is made possible by deleting the check for
+ x86. The test programs cannot be run because they are not signed.
+
+Version 1.6.0beta36 [January 2, 2013]
+ Discontinued distributing libpng-1.x.x.tar.bz2.
+ Discontinued distributing libpng-1.7.0-1.6.0-diff.txt and similar.
+ Rebuilt configure with autoconf-2.69 (inadvertently not done in beta33)
+ Fixed 'make distcheck' on SUN OS - libpng.so was not being removed
+
+Version 1.6.0beta37 [January 10, 2013]
+ Fixed conceivable but difficult to repro overflow. Also added two test
+ programs to generate and test a PNG which should have the problem.
+
+Version 1.6.0beta39 [January 19, 2013]
+ Again corrected attempt at overflow detection in png_set_unknown_chunks()
+ (CVE-2013-7353). Added overflow detection in png_set_sPLT() and
+ png_set_text_2() (CVE-2013-7354).
+
+Version 1.6.0beta40 [January 20, 2013]
+ Use consistent handling of overflows in text, sPLT and unknown png_set_* APIs
+
+Version 1.6.0rc01 [January 26, 2013]
No changes.
-Version 1.5.8rc02 [January 25, 2012]
- Fixed Min/GW uninstall to remove libpng.dll.a
- Conditionalize the install rules for MINGW and CYGWIN in CMakeLists.txt
+Version 1.6.0rc02 [February 4, 2013]
+ Added png_get_palette_max() function.
+
+Version 1.6.0rc03 [February 5, 2013]
+ Fixed the png_get_palette_max API.
-Version 1.5.8 [February 1, 2012]
+Version 1.6.0rc04 [February 7, 2013]
+ Turn serial tests back on (recently turned off by autotools upgrade).
+
+Version 1.6.0rc05 [February 8, 2013]
+ Update manual about png_get_palette_max().
+
+Version 1.6.0rc06 [February 9, 2013]
+ Fixed missing dependency in --prefix builds The intermediate
+ internal 'prefix.h' file can only be generated correctly after
+ pnglibconf.h, however the dependency was not in Makefile.am. The
+ symptoms are unpredictable depending on the order make chooses to
+ build pngprefix.h and pnglibconf.h, often the error goes unnoticed
+ because there is a system pnglibconf.h to use instead.
+
+Version 1.6.0rc07 [February 10, 2013]
+ Enclosed the new png_get_palette_max in #ifdef PNG_GET_PALETTE_MAX_SUPPORTED
+ block, and revised pnglibconf.h and pnglibconf.h.prebuilt accordingly.
+
+Version 1.6.0rc08 [February 10, 2013]
+ Fix typo in png.h #ifdef
+
+Version 1.6.0 [February 14, 2013]
No changes.
-Version 1.5.9beta01 [February 3, 2012]
- Rebuilt configure scripts in the tar distributions.
+Version 1.6.1beta01 [February 16, 2013]
+ Made symbol prefixing work with the ARM neon optimizations. Also allow
+ pngpriv.h to be included for preprocessor definitions only, so it can
+ be used in non-C/C++ files. Back ported from libpng 1.7.
+ Made sRGB check numbers consistent.
+ Ported libpng 1.5 options.awk/dfn file handling to 1.6, fixed one bug.
+ Removed cc -E workround, corrected png_get_palette_max API Tested on
+ SUN OS cc 5.9, which demonstrates the tokenization problem previously
+ avoided by using /lib/cpp. Since all .dfn output is now protected in
+ double quotes unless it is to be macro substituted the fix should
+ work everywhere.
+ Enabled parallel tests - back ported from libpng-1.7.
+ scripts/pnglibconf.dfa formatting improvements back ported from libpng17.
+ Fixed a race condition in the creation of the build 'scripts' directory
+ while building with a parallel make.
+ Use approved/supported Android method to check for NEON, use Linux/POSIX
+ 1003.1 API to check /proc/self/auxv avoiding buffer allocation and other
+ library calls (ported from libpng15).
+
+Version 1.6.1beta02 [February 19, 2013]
+ Use parentheses more consistently in "#if defined(MACRO)" tests.
+ Folded long lines.
+ Reenabled code to allow zero length PLTE chunks for MNG.
+
+Version 1.6.1beta03 [February 22, 2013]
+ Fixed ALIGNED_MEMORY support.
+ Added a new configure option:
+ --enable-arm-neon=always will stop the run-time checks. New checks
+ within arm/arm_init.c will cause the code not to be compiled unless
+ __ARM_NEON__ is set. This should make it fail safe (if someone asks
+ for it on then the build will fail if it can't be done.)
+ Updated the INSTALL document.
+
+Version 1.6.1beta04 [February 27, 2013]
+ Revised INSTALL to recommend using CPPFLAGS instead of INCLUDES.
+ Revised scripts/makefile.freebsd to respect ZLIBLIB and ZLIBINC.
+ Revised scripts/dfn.awk to work with the buggy MSYS awk that has trouble
+ with CRLF line endings.
+
+Version 1.6.1beta05 [March 1, 2013]
+ Avoid a possible memory leak in contrib/gregbook/readpng.c
+
+Version 1.6.1beta06 [March 4, 2013]
+ Better documentation of unknown handling API interactions.
+ Corrected Android builds and corrected libpng.vers with symbol
+ prefixing. It also makes those tests compile and link on Android.
+ Added an API png_set_option() to set optimization options externally,
+ providing an alternative and general solution for the non-portable
+ run-time tests used by the ARM Neon code, using the PNG_ARM_NEON option.
+ The order of settings vs options in pnglibconf.h is reversed to allow
+ settings to depend on options and options can now set (or override) the
+ defaults for settings.
+
+Version 1.6.1beta07 [March 7, 2013]
+ Corrected simplified API default gamma for color-mapped output, added
+ a flag to change default. In 1.6.0 when the simplified API was used
+ to produce color-mapped output from an input image with no gamma
+ information the gamma assumed for the input could be different from
+ that assumed for non-color-mapped output. In particular 16-bit depth
+ input files were assumed to be sRGB encoded, whereas in the 'direct'
+ case they were assumed to have linear data. This was an error. The
+ fix makes the simplified API treat all input files the same way and
+ adds a new flag to the png_image::flags member to allow the
+ application/user to specify that 16-bit files contain sRGB data
+ rather than the default linear.
+ Fixed bugs in the pngpixel and makepng test programs.
+
+Version 1.6.1beta08 [March 7, 2013]
+ Fixed CMakelists.txt to allow building a single variant of the library
+ (Claudio Bley):
+ Introduced a PNG_LIB_TARGETS variable that lists all activated library
+ targets. It is an error if this variable ends up empty, ie. you have
+ to build at least one library variant.
+ Made the *_COPY targets only depend on library targets actually being build.
+ Use PNG_LIB_TARGETS to unify a code path.
+ Changed the CREATE_SYMLINK macro to expect the full path to a file as the
+ first argument. When symlinking the filename component of that path is
+ determined and used as the link target.
+ Use copy_if_different in the CREATE_SYMLINK macro.
+
+Version 1.6.1beta09 [March 13, 2013]
+ Eliminated two warnings from the Intel C compiler. The warnings are
+ technically valid, although a reasonable treatment of division would
+ show it to be incorrect.
+
+Version 1.6.1rc01 [March 21, 2013]
+ No changes.
-Version 1.5.9beta02 [February 16, 2012]
- Removed two unused definitions from scripts/pnglibconf.h.prebuilt
- Removed some unused arrays (with #ifdef) from png_read_push_finish_row().
- Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h
+Version 1.6.1 [March 28, 2013]
+ No changes.
+
+Version 1.6.2beta01 [April 14, 2013]
+ Updated documentation of 1.5.x to 1.6.x changes in iCCP chunk handling.
+ Fixed incorrect warning of excess deflate data. End condition - the
+ warning would be produced if the end of the deflate stream wasn't read
+ in the last row. The warning is harmless.
+ Corrected the test on user transform changes on read. It was in the
+ png_set of the transform function, but that doesn't matter unless the
+ transform function changes the rowbuf size, and that is only valid if
+ transform_info is called.
+ Corrected a misplaced closing bracket in contrib/libtests/pngvalid.c
+ (Flavio Medeiros).
+ Corrected length written to uncompressed iTXt chunks (Samuli Suominen).
+ Bug was introduced in libpng-1.6.0.
+
+Version 1.6.2rc01 [April 18, 2013]
+ Added contrib/tools/fixitxt.c, to repair the erroneous iTXt chunk length
+ written by libpng-1.6.0 and 1.6.1.
+ Disallow storing sRGB information when the sRGB is not supported.
+
+Version 1.6.2rc02 [April 18, 2013]
+ Merge pngtest.c with libpng-1.7.0
+
+Version 1.6.2rc03 [April 22, 2013]
+ Trivial spelling cleanup.
+
+Version 1.6.2rc04 and 1.6.2rc05 [omitted]
+
+Version 1.6.2rc06 [April 24, 2013]
+ Reverted to version 1.6.2rc03. Recent changes to arm/neon support
+ have been ported to libpng-1.7.0beta09 and will reappear in version
+ 1.6.3beta01.
+
+Version 1.6.2 [April 25, 2013]
+ No changes.
+
+Version 1.6.3beta01 [April 25, 2013]
+ Revised stack marking in arm/filter_neon.S and configure.ac.
+ Ensure that NEON filter stuff is completely disabled when switched 'off'.
+ Previously the ARM NEON specific files were still built if the option
+ was switched 'off' as opposed to being explicitly disabled.
+
+Version 1.6.3beta02 [April 26, 2013]
+ Test for 'arm*' not just 'arm' in the host_cpu configure variable.
+ Rebuilt the configure scripts.
+
+Version 1.6.3beta03 [April 30, 2013]
+ Expanded manual paragraph about writing private chunks, particularly
+ the need to call png_set_keep_unknown_chunks() when writing them.
+ Avoid dereferencing NULL pointer possibly returned from
+ png_create_write_struct() (Andrew Church).
+
+Version 1.6.3beta05 [May 9, 2013]
+ Calculate our own zlib windowBits when decoding rather than trusting the
+ CMF bytes in the PNG datastream.
+ Added an option to force maximum window size for inflating, which was
+ the behavior of libpng15 and earlier, via a new PNG_MAXIMUM_INFLATE_WINDOW
+ option for png_set_options().
+ Added png-fix-itxt and png-fix-too-far-back to the built programs and
+ removed warnings from the source code and timepng that are revealed as
+ a result.
+ Detect wrong libpng versions linked to png-fix-too-far-back, which currently
+ only works with libpng versions that can be made to reliably fail when
+ the deflate data contains an out-of-window reference. This means only
+ 1.6 and later.
+ Fixed gnu issues: g++ needs a static_cast, gcc 4.4.7 has a broken warning
+ message which it is easier to work round than ignore.
+ Updated contrib/pngminus/pnm2png.c (Paul Stewart):
+ Check for EOF
+ Ignore "#" delimited comments in input file to pnm2png.c.
+ Fixed whitespace handling
+ Added a call to png_set_packing()
+ Initialize dimension values so if sscanf fails at least we have known
+ invalid values.
+ Attempt to detect configuration issues with png-fix-too-far-back, which
+ requires both the correct libpng and the correct zlib to function
+ correctly.
+ Check ZLIB_VERNUM for mismatches, enclose #error in quotes
+ Added information in the documentation about problems with and fixes for
+ the bad CRC and bad iTXt chunk situations.
+
+Version 1.6.3beta06 [May 12, 2013]
+ Allow contrib/pngminus/pnm2png.c to compile without WRITE_INVERT and
+ WRITE_PACK supported (writes error message that it can't read P1 or
+ P4 PBM files).
+ Improved png-fix-too-far-back usage message, added --suffix option.
+ Revised contrib/pngminim/*/makefile to generate pnglibconf.h with the
+ right zlib header files.
+ Separated CPPFLAGS and CFLAGS in contrib/pngminim/*/makefile
+
+Version 1.6.3beta07 [June 8, 2013]
+ Removed a redundant test in png_set_IHDR().
+ Added set(CMAKE_CONFIGURATION_TYPES ...) to CMakeLists.txt (Andrew Hundt)
+ Deleted set(CMAKE_BUILD_TYPE) block from CMakeLists.txt
+ Enclose the prototypes for the simplified write API in
+ #ifdef PNG_STDIO_SUPPORTED/#endif
+ Make ARM NEON support work at compile time (not just configure time).
+ This moves the test on __ARM_NEON__ into pngconf.h to avoid issues when
+ using a compiler that compiles for multiple architectures at one time.
+ Removed PNG_FILTER_OPTIMIZATIONS and PNG_ARM_NEON_SUPPORTED from
+ pnglibconf.h, allowing more of the decisions to be made internally
+ (pngpriv.h) during the compile. Without this, symbol prefixing is broken
+ under certain circumstances on ARM platforms. Now only the API parts of
+ the optimizations ('check' vs 'api') are exposed in the public header files
+ except that the new setting PNG_ARM_NEON_OPT documents how libpng makes the
+ decision about whether or not to use the optimizations.
+ Protect symbol prefixing against CC/CPPFLAGS/CFLAGS useage.
+ Previous iOS/Xcode fixes for the ARM NEON optimizations moved the test
+ on __ARM_NEON__ from configure time to compile time. This breaks symbol
+ prefixing because the definition of the special png_init_filter_functions
+ call was hidden at configure time if the relevant compiler arguments are
+ passed in CFLAGS as opposed to CC. This change attempts to avoid all
+ the confusion that would result by declaring the init function even when
+ it is not used, so that it will always get prefixed.
+
+Version 1.6.3beta08 [June 18, 2013]
+ Revised libpng.3 so that "doclifter" can process it.
+
+Version 1.6.3beta09 [June 27, 2013]
+ Revised example.c to illustrate use of PNG_DEFAULT_sRGB and PNG_GAMMA_MAC_18
+ as parameters for png_set_gamma(). These have been available since
+ libpng-1.5.4.
+ Renamed contrib/tools/png-fix-too-far-back.c to pngfix.c and revised it
+ to check all compressed chunks known to libpng.
+
+Version 1.6.3beta10 [July 5, 2013]
+ Updated documentation to show default behavior of benign errors correctly.
+ Only compile ARM code when PNG_READ_SUPPORTED is defined.
+ Fixed undefined behavior in contrib/tools/pngfix.c and added new strip
+ option. pngfix relied on undefined behavior and even a simple change from
+ gcc to g++ caused it to fail. The new strip option 'unsafe' has been
+ implemented and is the default if --max is given. Option names have
+ been clarified, with --strip=transform now stripping the bKGD chunk,
+ which was stripped previously with --strip=unused.
+ Added all documented chunk types to pngpriv.h
+ Unified pngfix.c source with libpng17.
+
+Version 1.6.3rc01 [July 11, 2013]
+ No changes.
+
+Version 1.6.3 [July 18, 2013]
+ Revised manual about changes in iTXt chunk handling made in libpng-1.6.0.
+ Added "/* SAFE */" comments in pngrutil.c and pngrtran.c where warnings
+ may be erroneously issued by code-checking applications.
+
+Version 1.6.4beta01 [August 21, 2013]
+ Added information about png_set_options() to the manual.
+ Delay calling png_init_filter_functions() until a row with nonzero filter
+ is found.
+
+Version 1.6.4beta02 [August 30, 2013]
+ Fixed inconsistent conditional compilation of png_chunk_unknown_handling()
+ prototype, definition, and usage. Made it depend on
+ PNG_HANDLE_AS_UNKNOWN_SUPPORTED everywhere.
+
+Version 1.6.4rc01 [September 5, 2013]
+ No changes.
+
+Version 1.6.4 [September 12, 2013]
+ No changes.
+
+Version 1.6.5 [September 14, 2013]
+ Removed two stray lines of code from arm/arm_init.c.
+
+Version 1.6.6 [September 16, 2013]
+ Removed two stray lines of code from arm/arm_init.c, again.
+
+Version 1.6.7beta01 [September 30, 2013]
+ Revised unknown chunk code to correct several bugs in the NO_SAVE_/NO_WRITE
+ combination
+ Allow HANDLE_AS_UNKNOWN to work when other options are configured off. Also
+ fixed the pngminim makefiles to work when $(MAKEFLAGS) contains stuff
+ which terminates the make options (as by default in recent versions of
+ Gentoo).
+ Avoid up-cast warnings in pngvalid.c. On ARM the alignment requirements of
+ png_modifier are greater than that of png_store and as a consequence
+ compilation of pngvalid.c results in a warning about increased alignment
+ requirements because of the bare cast to (png_modifier*). The code is safe,
+ because the pointer is known to point to a stack allocated png_modifier,
+ but this change avoids the warning.
+ Fixed default behavior of ARM_NEON_API. If the ARM NEON API option was
+ compiled without the CHECK option it defaulted to on, not off.
+ Check user callback behavior in pngunknown.c. Previous versions compiled
+ if SAVE_UNKNOWN was not available but did nothing since the callback
+ was never implemented.
+ Merged pngunknown.c with 1.7 version and back ported 1.7 improvements/fixes
+
+Version 1.6.7beta02 [October 12, 2013]
+ Made changes for compatibility with automake 1.14:
+ 1) Added the 'compile' program to the list of programs that must be cleaned
+ in autogen.sh
+ 2) Added 'subdir-objects' which causes .c files in sub-directories to be
+ compiled such that the corresponding .o files are also in the
+ sub-directory. This is because automake 1.14 warns that the
+ current behavior of compiling to the top level directory may be removed
+ in the future.
+ 3) Updated dependencies on pnglibconf.h to match the new .o locations and
+ added all the files in contrib/libtests and contrib/tools that depend
+ on pnglibconf.h
+ 4) Added 'BUILD_SOURCES = pnglibconf.h'; this is the automake recommended
+ way of handling the dependencies of sources that are machine generated;
+ unfortunately it only works if the user does 'make all' or 'make check',
+ so the dependencies (3) are still required.
+ Cleaned up (char*) casts of zlib messages. The latest version of the Intel C
+ compiler complains about casting a string literal as (char*), so copied the
+ treatment of z_const from the library code into pngfix.c
+ Simplified error message code in pngunknown. The simplification has the
+ useful side effect of avoiding a bogus warning generated by the latest
+ version of the Intel C compiler (it objects to
+ condition ? string-literal : string-literal).
+ Make autogen.sh work with automake 1.13 as well as 1.14. Do this by always
+ removing the 1.14 'compile' script but never checking for it.
+
+Version 1.6.7beta03 [October 19, 2013]
+ Added ARMv8 support (James Yu <james.yu at linaro.org>). Added file
+ arm/filter_neon_intrinsics.c; enable with -mfpu=neon.
+ Revised pngvalid to generate size images with as many filters as it can
+ manage, limited by the number of rows.
+ Cleaned up ARM NEON compilation handling. The tests are now in pngpriv.h
+ and detect the broken GCC compilers.
+
+Version 1.6.7beta04 [October 26, 2013]
+ Allow clang derived from older GCC versions to use ARM intrinsics. This
+ causes all clang builds that use -mfpu=neon to use the intrinsics code,
+ not the assembler code. This has only been tested on iOS 7. It may be
+ necessary to exclude some earlier clang versions but this seems unlikely.
+ Changed NEON implementation selection mechanism. This allows assembler
+ or intrinsics to be turned on at compile time during the build by defining
+ PNG_ARM_NEON_IMPLEMENTATION to the correct value (2 or 1). This macro
+ is undefined by default and the build type is selected in pngpriv.h.
+
+Version 1.6.7rc01 [November 2, 2013]
+ No changes.
+
+Version 1.6.7rc02 [November 7, 2013]
+ Fixed #include in filter_neon_intrinsics.c and ctype macros. The ctype char
+ checking macros take an unsigned char argument, not a signed char.
+
+Version 1.6.7 [November 14, 2013]
+ No changes.
+
+Version 1.6.8beta01 [November 24, 2013]
+ Moved prototype for png_handle_unknown() in pngpriv.h outside of
+ the #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED/#endif block.
+ Added "-Wall" to CFLAGS in contrib/pngminim/*/makefile
+ Conditionally compile some unused functions reported by -Wall in
+ pngminim.
+ Fixed 'minimal' builds. Various obviously useful minimal configurations
+ don't build because of missing contrib/libtests test programs and
+ overly complex dependencies in scripts/pnglibconf.dfa. This change
+ adds contrib/conftest/*.dfa files that can be used in automatic build
+ scripts to ensure that these configurations continue to build.
+ Enabled WRITE_INVERT and WRITE_PACK in contrib/pngminim/encoder.
+ Fixed pngvalid 'fail' function declaration on the Intel C Compiler.
+ This reverts to the previous 'static' implementation and works round
+ the 'unused static function' warning by using PNG_UNUSED().
+
+Version 1.6.8beta02 [November 30, 2013]
+ Removed or marked PNG_UNUSED some harmless "dead assignments" reported
+ by clang scan-build.
+ Changed tabs to 3 spaces in png_debug macros and changed '"%s"m'
+ to '"%s" m' to improve portability among compilers.
+ Changed png_free_default() to free() in pngtest.c
+
+Version 1.6.8rc01 [December 12, 2013]
+ Tidied up pngfix inits and fixed pngtest no-write builds.
+
+Version 1.6.8rc02 [December 14, 2013]
+ Handle zero-length PLTE chunk or NULL palette with png_error()
+ instead of png_chunk_report(), which by default issues a warning
+ rather than an error, leading to later reading from a NULL pointer
+ (png_ptr->palette) in png_do_expand_palette(). This is CVE-2013-6954
+ and VU#650142. Libpng-1.6.1 through 1.6.7 are vulnerable.
+ Libpng-1.6.0 and earlier do not have this bug.
+
+Version 1.6.8 [December 19, 2013]
+ No changes.
-Version 1.5.9rc01 [February 17, 2012]
- Fixed CVE-2011-3026 buffer overrun bug. Deal more correctly with the test
- on iCCP chunk length. Also removed spurious casts that may hide problems
- on 16-bit systems.
+Version 1.6.9beta01 [December 26, 2013]
+ Bookkeeping: Moved functions around (no changes). Moved transform
+ function definitions before the place where they are called so that
+ they can be made static. Move the intrapixel functions and the
+ grayscale palette builder out of the png?tran.c files. The latter
+ isn't a transform function and is no longer used internally, and the
+ former MNG specific functions are better placed in pngread/pngwrite.c
+ Made transform implementation functions static. This makes the internal
+ functions called by png_do_{read|write}_transformations static. On an
+ x86-64 DLL build (Gentoo Linux) this reduces the size of the text
+ segment of the DLL by 1208 bytes, about 0.6%. It also simplifies
+ maintenance by removing the declarations from pngpriv.h and allowing
+ easier changes to the internal interfaces.
+ Rebuilt configure scripts with automake-1.14.1 and autoconf-2.69
+ in the tar distributions.
+
+Version 1.6.9beta02 [January 1, 2014]
+ Added checks for libpng 1.5 to pngvalid.c. This supports the use of
+ this version of pngvalid in libpng 1.5
+ Merged with pngvalid.c from libpng-1.7 changes to create a single
+ pngvalid.c
+ Removed #error macro from contrib/tools/pngfix.c (Thomas Klausner).
+ Merged pngrio.c, pngtrans.c, pngwio.c, and pngerror.c with libpng-1.7.0
+ Merged libpng-1.7.0 changes to make no-interlace configurations work
+ with test programs.
+ Revised pngvalid.c to support libpng 1.5, which does not support the
+ PNG_MAXIMUM_INFLATE_WINDOW option, so #define it out when appropriate in
+ pngvalid.c
+ Allow unversioned links created on install to be disabled in configure.
+ In configure builds 'make install' changes/adds links like png.h
+ and libpng.a to point to the newly installed, versioned, files (e.g.
+ libpng17/png.h and libpng17.a). Three new configure options and some
+ rearrangement of Makefile.am allow creation of these links to be disabled.
+
+Version 1.6.9beta03 [January 10, 2014]
+ Removed potentially misleading warning from png_check_IHDR().
+
+Version 1.6.9beta04 [January 20, 2014]
+ Updated scripts/makefile.* to use CPPFLAGS (Cosmin).
+ Added clang attribute support (Cosmin).
+
+Version 1.6.9rc01 [January 28, 2014]
+ No changes.
+
+Version 1.6.9rc02 [January 30, 2014]
+ Quiet an uninitialized memory warning from VC2013 in png_get_png().
+
+Version 1.6.9 [February 6, 2014]
+
+Version 1.6.10beta01 [February 9, 2014]
+ Backported changes from libpng-1.7.0beta30 and beta31:
+ Fixed a large number of instances where PNGCBAPI was omitted from
+ function definitions.
+ Added pngimage test program for png_read_png() and png_write_png()
+ with two new test scripts.
+ Removed dependence on !PNG_READ_EXPAND_SUPPORTED for calling
+ png_set_packing() in png_read_png().
+ Fixed combination of ~alpha with shift. On read invert alpha, processing
+ occurred after shift processing, which causes the final values to be
+ outside the range that should be produced by the shift. Reversing the
+ order on read makes the two transforms work together correctly and mirrors
+ the order used on write.
+ Do not read invalid sBIT chunks. Previously libpng only checked sBIT
+ values on write, so a malicious PNG writer could therefore cause
+ the read code to return an invalid sBIT chunk, which might lead to
+ application errors or crashes. Such chunks are now skipped (with
+ chunk_benign_error).
+ Make png_read_png() and png_write_png() prototypes in png.h depend
+ upon PNG_READ_SUPPORTED and PNG_WRITE_SUPPORTED.
+ Support builds with unsupported PNG_TRANSFORM_* values. All of the
+ PNG_TRANSFORM_* values are always defined in png.h and, because they
+ are used for both read and write in some cases, it is not reliable
+ to #if out ones that are totally unsupported. This change adds error
+ detection in png_read_image() and png_write_image() to do a
+ png_app_error() if the app requests something that cannot be done
+ and it adds corresponding code to pngimage.c to handle such options
+ by not attempting to test them.
+
+Version 1.6.10beta02 [February 23, 2014]
+ Moved redefines of png_error(), png_warning(), png_chunk_error(),
+ and png_chunk_warning() from pngpriv.h to png.h to make them visible
+ to libpng-calling applications.
+ Moved OS dependent code from arm/arm_init.c, to allow the included
+ implementation of the ARM NEON discovery function to be set at
+ build-time and provide sample implementations from the current code in the
+ contrib/arm-neon subdirectory. The __linux__ code has also been changed to
+ compile and link on Android by using /proc/cpuinfo, and the old linux code
+ is in contrib/arm-neon/linux-auxv.c. The new code avoids POSIX and Linux
+ dependencies apart from opening /proc/cpuinfo and is C90 compliant.
+ Check for info_ptr == NULL early in png_read_end() so we don't need to
+ run all the png_handle_*() and depend on them to return if info_ptr == NULL.
+ This improves the performance of png_read_end(png_ptr, NULL) and makes
+ it more robust against future programming errors.
+ Check for __has_extension before using it in pngconf.h, to
+ support older Clang versions (Jeremy Sequoia).
+ Treat CRC error handling with png_set_crc_action(), instead of with
+ png_set_benign_errors(), which has been the case since libpng-1.6.0beta18.
+ Use a user warning handler in contrib/gregbook/readpng2.c instead of default,
+ so warnings will be put on stderr even if libpng has CONSOLE_IO disabled.
+ Added png_ptr->process_mode = PNG_READ_IDAT_MODE in png_push_read_chunk
+ after recognizing the IDAT chunk, which avoids an infinite loop while
+ reading a datastream whose first IDAT chunk is of zero-length.
+ This fixes CERT VU#684412 and CVE-2014-0333.
+ Don't recognize known sRGB profiles as sRGB if they have been hacked,
+ but don't reject them and don't issue a copyright violation warning.
+
+Version 1.6.10beta03 [February 25, 2014]
+ Moved some documentation from png.h to libpng.3 and libpng-manual.txt
+ Minor editing of contrib/arm-neon/README and contrib/examples/*.c
+
+Version 1.6.10rc01 [February 27, 2014]
+ Fixed typos in the manual and in scripts/pnglibconf.dfa (CFLAGS -> CPPFLAGS
+ and PNG_USR_CONFIG -> PNG_USER_CONFIG).
+
+Version 1.6.10rc02 [February 28, 2014]
+ Removed unreachable return statement after png_chunk_error()
+ in pngrutil.c
+
+Version 1.6.10rc03 [March 4, 2014]
+ Un-deprecated png_data_freer().
+
+Version 1.6.10 [March 6, 2014]
+ No changes.
+
+Version 1.6.11beta01 [March 17, 2014]
+ Use "if (value != 0)" instead of "if (value)" consistently.
+ Changed ZlibSrcDir from 1.2.5 to 1.2.8 in projects/vstudio.
+ Moved configuration information from the manual to the INSTALL file.
+
+Version 1.6.11beta02 [April 6, 2014]
+ Removed #if/#else/#endif from inside two pow() calls in pngvalid.c because
+ they were handled improperly by Portland Group's PGI-14.1 - PGI-14.3
+ when using its "__builtin_pow()" function.
+ Silence 'unused parameter' build warnings (Cosmin Truta).
+ $(CP) is now used alongside $(RM_F). Also, use 'copy' instead of 'cp'
+ where applicable, and applied other minor makefile changes (Cosmin).
+ Don't warn about invalid dimensions exceeding user limits (Cosmin).
+ Allow an easy replacement of the default pre-built configuration
+ header with a custom header, via the make PNGLIBCONF_H_PREBUILT
+ macro (Cosmin).
+
+Version 1.6.11beta03 [April 6, 2014]
+ Fixed a typo in pngrutil.c, introduced in libpng-1.5.6, that interferes
+ with "blocky" expansion of sub-8-bit interlaced PNG files (Eric Huss).
+ Optionally use __builtin_bswap16() in png_do_swap().
+
+Version 1.6.11beta04 [April 19, 2014]
+ Made progressive reading of interlaced images consistent with the
+ behavior of the sequential reader and consistent with the manual, by
+ moving some code out of the PNG_READ_INTERLACING_SUPPORTED blocks. The
+ row_callback now receives the proper pass number and unexpanded rows, when
+ png_combine_row() isn't built or used, and png_set_interlace_handling()
+ is not called.
+ Allow PNG_sRGB_PROFILE_CHECKING = (-1) to mean no sRGB profile checking.
+
+Version 1.6.11beta05 [April 26, 2014]
+ Do not reject ICC V2 profiles that lack padding (Kai-Uwe Behrmann).
+ Relocated closing bracket of the sRGB profile test loop to avoid getting
+ "Not recognizing known sRGB profile that has been edited" warning for
+ ICC V2 profiles that lack the MD5 signature in the profile header.
+
+Version 1.6.11beta06 [May 19, 2014]
+ Added PNG_SKIP_sRGB_CHECK_PROFILE choice for png_set_option().
+
+Version 1.6.11rc01 [May 27, 2014]
+ No changes.
+
+Version 1.6.11rc02 [June 3, 2014]
+ Test ZLIB_VERNUM instead of PNG_ZLIB_VERNUM in contrib/tools/pngfix.c
+
+Version 1.6.11 [June 5, 2014]
+ No changes.
+
+Version 1.6.12rc01 [June 6, 2014]
+ Relocated new code from 1.6.11beta06 in png.c to a point after the
+ declarations (Max Stepin).
+
+Version 1.6.12rc02 [June 7, 2014]
+ Changed file permissions of contrib/tools/intgamma.sh,
+ test-driver, and compile from 0644 to 0755 (Cosmin).
+
+Version 1.6.12rc03 [June 8, 2014]
+ Ensure "__has_attribute()" macro exists before trying to use it with
+ old clang compilers (MacPorts Ticket #43939).
+
+Version 1.6.12 [June 12, 2014]
+ No changes.
+
+Version 1.6.13beta01 [July 4, 2014]
+ Quieted -Wsign-compare and -Wclobber compiler warnings in
+ contrib/pngminus/*.c
+ Added "(void) png_ptr;" where needed in contrib/gregbook to quiet
+ compiler complaints about unused pointers.
+ Split a long output string in contrib/gregbook/rpng2-x.c.
+ Added "PNG_SET_OPTION" requirement for sRGB chunk support to pnglibconf.dfa,
+ Needed for write-only support (John Bowler).
+ Changed "if defined(__ARM_NEON__)" to
+ "if (defined(__ARM_NEON__) || defined(__ARM_NEON))" (James Wu).
+ Fixed clang no-warning builds: png_digit was defined but never used.
+
+Version 1.6.13beta02 [July 21, 2014]
+ Fixed an incorrect separator ("/" should be "\") in scripts/makefile.vcwin32
+ (bug report from Wolfgang S. Kechel). Bug was introduced in libpng-1.6.11.
+ Also fixed makefile.bc32, makefile.bor, makefile.msc, makefile.intel, and
+ makefile.tc3 similarly.
+
+Version 1.6.13beta03 [August 3, 2014]
+ Removed scripts/makefile.elf. It has not worked since libpng-1.5.0beta14
+ due to elimination of the PNG_FUNCTION_EXPORT and PNG_DATA_EXPORT
+ definitions from pngconf.h.
+ Ensure that CMakeLists.txt makes the target "lib" directory before making
+ symbolic link into it (SourceForge bug report #226 by Rolf Timmermans).
+
+Version 1.6.13beta04 [August 8, 2014]
+ Added opinion that the ECCN (Export Control Classification Number) for
+ libpng is EAR99 to the README file.
+ Eliminated use of "$<" in makefile explicit rules, when copying
+ $PNGLIBCONF_H_PREBUILT. This does not work on some versions of make;
+ bug introduced in libpng version 1.6.11.
+
+Version 1.6.13rc01 [August 14, 2014]
+ Made "ccopts" agree with "CFLAGS" in scripts/makefile.hp* and makefile.*sunu
+
+Version 1.6.13 [August 21, 2014]
+ No changes.
+
+Version 1.6.14beta01 [September 14, 2014]
+ Guard usage of png_ptr->options with #ifdef PNG_SET_OPTION_SUPPORTED.
+ Do not build contrib/tools/pngfix.c when PNG_SETJMP_NOT_SUPPORTED,
+ to allow "make" to complete without setjmp support (bug report by
+ Claudio Fontana)
+ Add "#include <setjmp.h>" to contrib/tools/pngfix.c (John Bowler)
+
+Version 1.6.14beta02 [September 18, 2014]
+ Use nanosleep() instead of usleep() in contrib/gregbook/rpng2-x.c
+ because usleep() is deprecated.
+ Define usleep() in contrib/gregbook/rpng2-x.c if not already defined
+ in unistd.h and nanosleep() is not available; fixes error introduced
+ in libpng-1.6.13.
+ Disable floating point exception handling in pngvalid.c when
+ PNG_FLOATING_ARITHMETIC is not supported (bug report by "zootus
+ at users.sourceforge.net").
+
+Version 1.6.14beta03 [September 19, 2014]
+ Define FE_DIVBYZERO, FE_INVALID, and FE_OVERFLOW in pngvalid.c if not
+ already defined. Revert floating point exception handling in pngvalid.c
+ to version 1.6.14beta01 behavior.
+
+Version 1.6.14beta04 [September 27, 2014]
+ Fixed incorrect handling of the iTXt compression flag in pngrutil.c
+ (bug report by Shunsaku Hirata). Bug was introduced in libpng-1.6.0.
+
+Version 1.6.14beta05 [October 1, 2014]
+ Added "option READ_iCCP enables READ_COMPRESSED_TEXT" to pnglibconf.dfa
+
+Version 1.6.14beta06 [October 5, 2014]
+ Removed unused "text_len" parameter from private function png_write_zTXt().
+ Conditionally compile some code in png_deflate_claim(), when
+ PNG_WARNINGS_SUPPORTED and PNG_ERROR_TEXT_SUPPORTED are disabled.
+ Replaced repeated code in pngpread.c with PNG_PUSH_SAVE_BUFFER_IF_FULL.
+ Added "chunk iTXt enables TEXT" and "chunk zTXt enables TEXT"
+ to pnglibconf.dfa.
+ Removed "option READ_COMPRESSED_TEXT enables READ_TEXT" from pnglibconf.dfa,
+ to make it possible to configure a libpng that supports iCCP but not TEXT.
+
+Version 1.6.14beta07 [October 7, 2014]
+ Removed "option WRITE_COMPRESSED_TEXT enables WRITE_TEXT" from pnglibconf.dfa
+ Only mark text chunks as written after successfully writing them.
+
+Version 1.6.14rc01 [October 15, 2014]
+ Fixed some typos in comments.
+
+Version 1.6.14rc02 [October 17, 2014]
+ Changed png_convert_to_rfc_1123() to png_convert_to_rfc_1123_buffer()
+ in the manual, to reflect the change made in libpng-1.6.0.
+ Updated README file to explain that direct access to the png_struct
+ and info_struct members has not been permitted since libpng-1.5.0.
+
+Version 1.6.14 [October 23, 2014]
+ No changes.
+
+Version 1.6.15beta01 [October 29, 2014]
+ Changed "if (!x)" to "if (x == 0)" and "if (x)" to "if (x != 0)"
+ Simplified png_free_data().
+ Added missing "ptr = NULL" after some instances of png_free().
+
+Version 1.6.15beta02 [November 1, 2014]
+ Changed remaining "if (!x)" to "if (x == 0)" and "if (x)" to "if (x != 0)"
+
+Version 1.6.15beta03 [November 3, 2014]
+ Added PNG_USE_ARM_NEON configuration flag (Marcin Juszkiewicz).
+
+Version 1.6.15beta04 [November 4, 2014]
+ Removed new PNG_USE_ARM_NEON configuration flag and made a one-line
+ revision to configure.ac to support ARM on aarch64 instead (John Bowler).
+
+Version 1.6.15beta05 [November 5, 2014]
+ Use png_get_libpng_ver(NULL) instead of PNG_LIBPNG_VER_STRING in
+ example.c, pngtest.c, and applications in the contrib directory.
+ Avoid out-of-bounds memory access in png_user_version_check().
+ Simplified and future-proofed png_user_version_check().
+ Fixed GCC unsigned int->float warnings. Various versions of GCC
+ seem to generate warnings when an unsigned value is implicitly
+ converted to double. This is probably a GCC bug but this change
+ avoids the issue by explicitly converting to (int) where safe.
+ Free all allocated memory in pngimage. The file buffer cache was left
+ allocated at the end of the program, harmless but it causes memory
+ leak reports from clang.
+ Fixed array size calculations to avoid warnings. At various points
+ in the code the number of elements in an array is calculated using
+ sizeof. This generates a compile time constant of type (size_t) which
+ is then typically assigned to an (unsigned int) or (int). Some versions
+ of GCC on 64-bit systems warn about the apparent narrowing, even though
+ the same compiler does apparently generate the correct, in-range,
+ numeric constant. This adds appropriate, safe, casts to make the
+ warnings go away.
+
+Version 1.6.15beta06 [November 6, 2014]
+ Reverted use png_get_libpng_ver(NULL) instead of PNG_LIBPNG_VER_STRING
+ in the manual, example.c, pngtest.c, and applications in the contrib
+ directory. It was incorrect advice.
+
+Version 1.6.15beta07 [November 7, 2014]
+ Removed #ifdef PNG_16BIT_SUPPORTED/#endif around png_product2(); it is
+ needed by png_reciprocal2().
+ Added #ifdef PNG_16BIT_SUPPORTED/#endif around png_log16bit() and
+ png_do_swap().
+ Changed all "#endif /* PNG_FEATURE_SUPPORTED */" to "#endif /* FEATURE */"
+
+Version 1.6.15beta08 [November 8, 2014]
+ More housecleaning in *.h
+
+Version 1.6.15rc01 [November 13, 2014]
+
+Version 1.6.15rc02 [November 14, 2014]
+ The macros passed in the command line to Borland make were ignored if
+ similarly-named macros were already defined in makefiles. This behavior
+ is different from POSIX make and other make programs. Surround the
+ macro definitions with ifndef guards (Cosmin).
+
+Version 1.6.15rc03 [November 16, 2014]
+ Added "-D_CRT_SECURE_NO_WARNINGS" to CFLAGS in scripts/makefile.vcwin32.
+ Removed the obsolete $ARCH variable from scripts/makefile.darwin.
+
+Version 1.6.15 [November 20, 2014]
+ No changes.
+
+Version 1.6.16beta01 [December 14, 2014]
+ Added ".align 2" to arm/filter_neon.S to support old GAS assemblers that
+ don't do alignment correctly.
+ Revised Makefile.am and scripts/symbols.dfn to work with MinGW/MSYS
+ (Bob Friesenhahn).
+
+Version 1.6.16beta02 [December 15, 2014]
+ Revised Makefile.am and scripts/*.dfn again to work with MinGW/MSYS;
+ renamed scripts/*.dfn to scripts/*.c (John Bowler).
+
+Version 1.6.16beta03 [December 21, 2014]
+ Quiet a "comparison always true" warning in pngstest.c (John Bowler).
+
+Version 1.6.16rc01 [December 21, 2014]
+ Restored a test on width that was removed from png.c at libpng-1.6.9
+ (Bug report by Alex Eubanks, CVE-2015-0973).
+
+Version 1.6.16rc02 [December 21, 2014]
+ Undid the update to pngrutil.c in 1.6.16rc01.
+
+Version 1.6.16rc03 [December 21, 2014]
+ Fixed an overflow in png_combine_row() with very wide interlaced images
+ (Bug report and fix by John Bowler, CVE-2014-9495).
+
+Version 1.6.16 [December 22, 2014]
+ No changes.
-Version 1.5.9 [February 18, 2012]
+Version 1.6.17beta01 [January 29, 2015]
+ Removed duplicate PNG_SAFE_LIMITS_SUPPORTED handling from pngconf.h
+ Corrected the width limit calculation in png_check_IHDR().
+ Removed user limits from pngfix. Also pass NULL pointers to
+ png_read_row to skip the unnecessary row de-interlace stuff.
+ Added testing of png_set_packing() to pngvalid.c
+ Regenerated configure scripts in the *.tar distributions with libtool-2.4.4
+ Implement previously untested cases of libpng transforms in pngvalid.c
+ Fixed byte order in png_do_read_filler() with 16-bit input. Previously
+ the high and low bytes of the filler, from png_set_filler() or from
+ png_set_add_alpha(), were read in the wrong order.
+ Made the check for out-of-range values in png_set_tRNS() detect
+ values that are exactly 2^bit_depth, and work on 16-bit platforms.
+ Merged some parts of libpng-1.6.17beta01 and libpng-1.7.0beta47.
+ Added #ifndef __COVERITY__ where needed in png.c, pngrutil.c and
+ pngset.c to avoid warnings about dead code.
+ Added "& 0xff" to many instances of expressions that are typecast
+ to (png_byte), to avoid Coverity warnings.
+
+Version 1.6.17beta02 [February 7, 2015]
+ Work around one more Coverity-scan dead-code warning.
+ Do not build png_product2() when it is unused.
+
+Version 1.6.17beta03 [February 17, 2015]
+ Display user limits in the output from pngtest.
+ Eliminated the PNG_SAFE_LIMITS macro and restored the 1-million-column
+ and 1-million-row default limits in pnglibconf.dfa, that can be reset
+ by the user at build time or run time. This provides a more robust
+ defense against DOS and as-yet undiscovered overflows.
+
+Version 1.6.17beta04 [February 21, 2015]
+ Added PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED macro, on by default.
+ Allow user to call png_get_IHDR() with NULL arguments (Reuben Hawkins).
+ Rebuilt configure scripts with automake-1.15 and libtool-2.4.6
+
+Version 1.6.17beta05 [February 25, 2015]
+ Restored compiling of png_reciprocal2 with PNG_NO_16BIT.
+
+Version 1.6.17beta06 [February 27, 2015]
+ Moved png_set_filter() prototype into a PNG_WRITE_SUPPORTED block
+ of png.h.
+ Avoid runtime checks when converting integer to png_byte with
+ Visual Studio (Sergey Kosarevsky)
+
+Version 1.6.17rc01 [March 4, 2015]
No changes.
+Version 1.6.17rc02 [March 9, 2015]
+ Removed some comments that the configure script did not handle
+ properly from scripts/pnglibconf.dfa and pnglibconf.h.prebuilt.
+ Free the unknown_chunks structure even when it contains no data.
+
+Version 1.6.17rc03 [March 12, 2015]
+ Updated CMakeLists.txt to add OSX framework, change YES/NO to ON/OFF
+ for consistency, and remove some useless tests (Alexey Petruchik).
+
+Version 1.6.17rc04 [March 16, 2015]
+ Remove pnglibconf.h, pnglibconf.c, and pnglibconf.out instead of
+ pnglibconf.* in "make clean" (Cosmin).
+ Fix bug in calculation of maxbits, in png_write_sBIT, introduced
+ in libpng-1.6.17beta01 (John Bowler).
+
+Version 1.6.17rc05 [March 21, 2015]
+ Define PNG_FILTER_* and PNG_FILTER_VALUE_* in png.h even when WRITE
+ is not supported (John Bowler). This fixes an error introduced in
+ libpng-1.6.17beta06.
+ Reverted "& 0xff" additions of version 1.6.17beta01. Libpng passes
+ the Coverity scan without them.
+
+Version 1.6.17rc06 [March 23, 2015]
+ Remove pnglibconf.dfn and pnglibconf.pre with "make clean".
+ Reformatted some "&0xff" instances to "& 0xff".
+ Fixed simplified 8-bit-linear to sRGB alpha. The calculated alpha
+ value was wrong. It's not clear if this affected the final stored
+ value; in the obvious code path the upper and lower 8-bits of the
+ alpha value were identical and the alpha was truncated to 8-bits
+ rather than dividing by 257 (John Bowler).
+
+Version 1.6.17 [March 26, 2015]
+ No changes.
+
+Version 1.6.18beta01 [April 1, 2015]
+ Removed PNG_SET_CHUNK_[CACHE|MALLOC]_LIMIT_SUPPORTED macros. They
+ have been combined with PNG_SET_USER_LIMITS_SUPPORTED (resolves
+ bug report by Andrew Church).
+ Fixed rgb_to_gray checks and added tRNS checks to pngvalid.c. This
+ fixes some arithmetic errors that caused some tests to fail on
+ some 32-bit platforms (Bug reports by Peter Breitenlohner [i686]
+ and Petr Gajdos [i586]).
+
+Version 1.6.18beta02 [April 26, 2015]
+ Suppressed some warnings from the Borland C++ 5.5.1/5.82 compiler
+ (Bug report by Viktor Szakats).
+
+Version 1.6.18beta03 [May 6, 2015]
+ Replaced "unexpected" with an integer (0xabadca11) in pngset.c
+ where a long was expected, to avoid a compiler warning when PNG_DEBUG > 1.
+ Added contrib/examples/simpleover.c, to demonstrate how to handle
+ alpha compositing of multiple images, using the "simplified API"
+ and an example PNG generation tool, contrib/examples/genpng.c
+ (John Bowler).
+
+Version 1.6.18beta04 [May 20, 2015]
+ PNG_RELEASE_BUILD replaces tests where the code depended on the build base
+ type and can be defined on the command line, allowing testing in beta
+ builds (John Bowler).
+ Avoid Coverity issue 80858 (REVERSE NULL) in pngtest.c PNG_DEBUG builds.
+ Avoid a harmless potential integer overflow in png_XYZ_from_xy() (Bug
+ report from Christopher Ferris).
+
+Version 1.6.18beta05 [May 31, 2015]
+ Backport filter selection code from libpng-1.7.0beta51, to combine
+ sub_row, up_row, avg_row, and paeth_row into try_row and tst_row.
+ Changed png_voidcast(), etc., to voidcast(), etc., in contrib/tools/pngfix.c
+ to avoid confusion with the libpng private macros.
+ Fixed old cut&paste bug in the weighted filter selection code in
+ pngwutil.c, introduced in libpng-0.95, March 1997.
+
+Version 1.6.18beta06 [June 1, 2015]
+ Removed WRITE_WEIGHTED_FILTERED code, to save a few kbytes of the
+ compiled library size. It never worked properly and as far as we can
+ tell, no one uses it. The png_set_filter_heuristics() and
+ png_set_filter_heuristics_fixed() APIs are retained but deprecated
+ and do nothing.
+
+Version 1.6.18beta07 [June 6, 2015]
+ Removed non-working progressive reader 'skip' function. This
+ function has apparently never been used. It was implemented
+ to support back-door modification of png_struct in libpng-1.4.x
+ but (because it does nothing and cannot do anything) was apparently
+ never tested (John Bowler).
+ Fixed cexcept.h in which GCC 5 now reports that one of the auto
+ variables in the Try macro needs to be volatile to prevent value
+ being lost over the setjmp (John Bowler).
+ Fixed NO_WRITE_FILTER and -Wconversion build breaks (John Bowler).
+ Fix g++ build breaks (John Bowler).
+ Quieted some Coverity issues in pngfix.c, png-fix-itxt.c, pngvalid.c,
+ pngstest.c, and pngimage.c. Most seem harmless, but png-fix-itxt
+ would only work with iTXt chunks with length 255 or less.
+ Added #ifdef's to contrib/examples programs so people don't try
+ to compile them without the minimum required support enabled
+ (suggested by Flavio Medeiros).
+
+Version 1.6.18beta08 [June 30, 2015]
+ Eliminated the final two Coverity defects (insecure temporary file
+ handling in contrib/libtests/pngstest.c; possible overflow of
+ unsigned char in contrib/tools/png-fix-itxt.c). To use the "secure"
+ file handling, define PNG_USE_MKSTEMP, otherwise "tmpfile()" will
+ be used.
+ Removed some unused WEIGHTED_FILTER macros from png.h and pngstruct.h
+
+Version 1.6.18beta09 [July 5, 2015]
+ Removed some useless typecasts from contrib/tools/png-fix-itxt.c
+ Fixed a new signed-unsigned comparison in pngrtran.c (Max Stepin).
+ Replaced arbitrary use of 'extern' with #define PNG_LINKAGE_*. To
+ preserve API compatibility, the new defines all default to "extern"
+ (requested by Jan Nijtmans).
+
+Version 1.6.18rc01 [July 9, 2015]
+ Belatedly added Mans Rullgard and James Yu to the list of Contributing
+ Authors.
+
+Version 1.6.18rc02 [July 12, 2015]
+ Restored unused FILTER_HEURISTIC macros removed at libpng-1.6.18beta08
+ to png.h to avoid compatibility warnings.
+
+Version 1.6.18rc03 [July 15, 2015]
+ Minor changes to the man page
+
+Version 1.6.18 [July 23, 2015]
+ No changes.
+
+Version 1.6.19beta01 [July 30, 2015]
+ Updated obsolete information about the simplified API macros in the
+ manual pages (Bug report by Arc Riley).
+ Avoid potentially dereferencing NULL info_ptr in png_info_init_3().
+ Rearranged png.h to put the major sections in the same order as
+ in libpng17.
+ Eliminated unused PNG_COST_SHIFT, PNG_WEIGHT_SHIFT, PNG_COST_FACTOR, and
+ PNG_WEIGHT_FACTOR macros.
+ Suppressed some warnings from the Borland C++ 5.5.1/5.82 compiler
+ (Bug report by Viktor Szakats). Several warnings remain and are
+ unavoidable, where we test for overflow.
+ Fixed potential leak of png_pixels in contrib/pngminus/pnm2png.c
+ Fixed uninitialized variable in contrib/gregbook/rpng2-x.c
+
+Version 1.6.19beta02 [August 19, 2015]
+ Moved config.h.in~ from the "libpng_autotools_files" list to the
+ "libpng_autotools_extra" list in autogen.sh because it was causing a
+ false positive for missing files (bug report by Robert C. Seacord).
+ Removed unreachable "break" statements in png.c, pngread.c, and pngrtran.c
+ to suppress clang warnings (Bug report by Viktor Szakats).
+ Fixed some bad links in the man page.
+ Changed "n bit" to "n-bit" in comments.
+ Added signed/unsigned 16-bit safety net. This removes the dubious
+ 0x8000 flag definitions on 16-bit systems. They aren't supported
+ yet the defs *probably* work, however it seems much safer to do this
+ and be advised if anyone, contrary to advice, is building libpng 1.6
+ on a 16-bit system. It also adds back various switch default clauses
+ for GCC; GCC errors out if they are not present (with an appropriately
+ high level of warnings).
+ Safely convert num_bytes to a png_byte in png_set_sig_bytes() (Robert
+ Seacord).
+ Fixed the recently reported 1's complement security issue by replacing
+ the value that is illegal in the PNG spec, in both signed and unsigned
+ values, with 0. Illegal unsigned values (anything greater than or equal
+ to 0x80000000) can still pass through, but since these are not illegal
+ in ANSI-C (unlike 0x80000000 in the signed case) the checking that
+ occurs later can catch them (John Bowler).
+
+Version 1.6.19beta03 [September 26, 2015]
+ Fixed png_save_int_32 when int is not 2's complement (John Bowler).
+ Updated libpng16 with all the recent test changes from libpng17,
+ including changes to pngvalid.c to ensure that the original,
+ distributed, version of contrib/visupng/cexcept.h can be used
+ (John Bowler).
+ pngvalid contains the correction to the use of SAVE/STORE_
+ UNKNOWN_CHUNKS; a bug revealed by changes in libpng 1.7. More
+ tests contain the --strict option to detect warnings and the
+ pngvalid-standard test has been corrected so that it does not
+ turn on progressive-read. There is a separate test which does
+ that. (John Bowler)
+ Also made some signed/unsigned fixes.
+ Make pngstest error limits version specific. Splitting the machine
+ generated error structs out to a file allows the values to be updated
+ without changing pngstest.c itself. Since libpng 1.6 and 1.7 have
+ slightly different error limits this simplifies maintenance. The
+ makepngs.sh script has also been updated to more accurately reflect
+ current problems in libpng 1.7 (John Bowler).
+ Incorporated new test PNG files into make check. tests/pngstest-*
+ are changed so that the new test files are divided into 8 groups by
+ gamma and alpha channel. These tests have considerably better code
+ and pixel-value coverage than contrib/pngsuite; however,coverage is
+ still incomplete (John Bowler).
+ Removed the '--strict' in 1.6 because of the double-gamma-correction
+ warning, updated pngstest-errors.h for the errors detected with the
+ new contrib/testspngs PNG test files (John Bowler).
+
+Version 1.6.19beta04 [October 15, 2015]
+ Worked around rgb-to-gray issues in libpng 1.6. The previous
+ attempts to ignore the errors in the code aren't quite enough to
+ deal with the 'channel selection' encoding added to libpng 1.7; abort.
+ pngvalid.c is changed to drop this encoding in prior versions.
+ Fixed 'pow' macros in pngvalid.c. It is legal for 'pow' to be a
+ macro, therefore the argument list cannot contain preprocessing
+ directives. Make sure pow is a function where this happens. This is
+ a minimal safe fix, the issue only arises in non-performance-critical
+ code (bug report by Curtis Leach, fix by John Bowler).
+ Added sPLT support to pngtest.c
+
+Version 1.6.19rc01 [October 23, 2015]
+ No changes.
+
+Version 1.6.19rc02 [October 31, 2015]
+ Prevent setting or writing over-length PLTE chunk (Cosmin Truta).
+ Silently truncate over-length PLTE chunk while reading.
+ Libpng incorrectly calculated the output rowbytes when the application
+ decreased either the number of channels or the bit depth (or both) in
+ a user transform. This was safe; libpng overallocated buffer space
+ (potentially by quite a lot; up to 4 times the amount required) but,
+ from 1.5.4 on, resulted in a png_error (John Bowler).
+
+Version 1.6.19rc03 [November 3, 2015]
+ Fixed some inconsequential cut-and-paste typos in png_set_cHRM_XYZ_fixed().
+ Clarified COPYRIGHT information to state explicitly that versions
+ are derived from previous versions.
+ Removed much of the long list of previous versions from png.h and
+ libpng.3.
+
+Version 1.6.19rc04 [November 5, 2015]
+ Fixed new bug with CRC error after reading an over-length palette
+ (bug report by Cosmin Truta) (CVE-2015-8126).
+
+Version 1.6.19 [November 12, 2015]
+ Cleaned up coding style in png_handle_PLTE().
+
+Version 1.6.20beta01 [November 20, 2015]
+ Avoid potential pointer overflow/underflow in png_handle_sPLT() and
+ png_handle_pCAL() (Bug report by John Regehr).
+
+Version 1.6.20beta02 [November 23, 2015]
+ Fixed incorrect implementation of png_set_PLTE() that uses png_ptr
+ not info_ptr, that left png_set_PLTE() open to the CVE-2015-8126
+ vulnerability. Fixes CVE-2015-8472.
+
+Version 1.6.20beta03 [November 24, 2015]
+ Backported tests from libpng-1.7.0beta69.
+
+Version 1.6.20rc01 [November 26, 2015]
+ Fixed an error in handling of bad zlib CMINFO field in pngfix, found by
+ American Fuzzy Lop, reported by Brian Carpenter. inflate() doesn't
+ immediately fault a bad CMINFO field; instead a 'too far back' error
+ happens later (at least some times). pngfix failed to limit CMINFO to
+ the allowed values but then assumed that window_bits was in range,
+ triggering an assert. The bug is mostly harmless; the PNG file cannot
+ be fixed.
+
+Version 1.6.20rc02 [November 29, 2015]
+ In libpng 1.6 zlib initialization was changed to use the window size
+ in the zlib stream, not a fixed value. This causes some invalid images,
+ where CINFO is too large, to display 'correctly' if the rest of the
+ data is valid. This provides a workaround for zlib versions where the
+ error arises (ones that support the API change to use the window size
+ in the stream).
+
+Version 1.6.20 [December 3, 2015]
+ No changes.
+
+Version 1.6.21beta01 [December 11, 2015]
+ Fixed syntax "$(command)" in tests/pngstest that some shells other than
+ bash could not parse (Bug report by Nelson Beebe). Use `command` instead.
+
+Version 1.6.21beta02 [December 14, 2015]
+ Moved png_check_keyword() from pngwutil.c to pngset.c
+ Removed LE/BE dependencies in pngvalid, to 'fix' the current problem
+ in the BigEndian tests by not testing it, making the BE code the same
+ as the LE version.
+ Fixes to pngvalid for various reduced build configurations (eliminate unused
+ statics) and a fix for the case in rgb_to_gray when the digitize option
+ reduces graylo to 0, producing a large error.
+
+Version 1.6.21beta03 [December 18, 2015]
+ Widened the 'limit' check on the internally calculated error limits in
+ the 'DIGITIZE' case (the code used prior to 1.7 for rgb_to_gray error
+ checks) and changed the check to only operate in non-release builds
+ (base build type not RC or RELEASE.)
+ Fixed undefined behavior in pngvalid.c, undefined because
+ (png_byte) << shift is undefined if it changes the signed bit
+ (because png_byte is promoted to int). The libpng exported functions
+ png_get_uint_32 and png_get_uint_16 handle this. (Bug reported by
+ David Drysdale as a result of reports from UBSAN in clang 3.8).
+ This changes pngvalid to use BE random numbers; this used to produce
+ errors but these should not be fixed as a result of the previous changes.
+
+Version 1.6.21rc01 [January 4, 2016]
+ In projects/vstudio, combined readme.txt and WARNING into README.txt
+
+Version 1.6.21rc02 [January 7, 2016]
+ Relocated assert() in contrib/tools/pngfix.c, bug found by American
+ Fuzzy Lop, reported by Brian Carpenter.
+ Marked 'limit' UNUSED in transform_range_check(). This only affects
+ release builds.
+
+Version 1.6.21 [January 15, 2016]
+ Worked around a false-positive Coverity issue in pngvalid.c.
+
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/thirdparty/libpng/CMakeLists.txt b/thirdparty/libpng/CMakeLists.txt
index 7cf2be90..227688c3 100644
--- a/thirdparty/libpng/CMakeLists.txt
+++ b/thirdparty/libpng/CMakeLists.txt
@@ -1,6 +1,8 @@
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories (
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
-add_library (png_bundled STATIC EXCLUDE_FROM_ALL
+add_convenience_library (png_bundled EXCLUDE_FROM_ALL
png.c
pngerror.c
pngget.c
@@ -18,10 +20,6 @@ add_library (png_bundled STATIC EXCLUDE_FROM_ALL
pngwutil.c
)
-set_target_properties (png_bundled PROPERTIES
- COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}"
-)
-
install (
FILES LICENSE
DESTINATION ${DOC_INSTALL_DIR}
diff --git a/thirdparty/libpng/LICENSE b/thirdparty/libpng/LICENSE
index dd43d3bf..fd93b1b4 100644
--- a/thirdparty/libpng/LICENSE
+++ b/thirdparty/libpng/LICENSE
@@ -10,21 +10,18 @@ this sentence.
This code is released under the libpng license.
-libpng versions 1.2.6, August 15, 2004, through 1.5.9, February 18, 2012, are
-Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
-distributed according to the same disclaimer and license as libpng-1.2.5
-with the following individual added to the list of Contributing Authors
-
- Cosmin Truta
-
-libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are
-Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
-distributed according to the same disclaimer and license as libpng-1.0.6
-with the following individuals added to the list of Contributing Authors
+libpng versions 1.0.7, July 1, 2000, through 1.6.21, January 15, 2016, are
+Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
+derived from libpng-1.0.6, and are distributed according to the same
+disclaimer and license as libpng-1.0.6 with the following individuals
+added to the list of Contributing Authors:
Simon-Pierre Cadieux
Eric S. Raymond
+ Mans Rullgard
+ Cosmin Truta
Gilles Vollant
+ James Yu
and with the following additions to the disclaimer:
@@ -36,18 +33,20 @@ and with the following additions to the disclaimer:
the user.
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
-Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are
-distributed according to the same disclaimer and license as libpng-0.96,
-with the following individuals added to the list of Contributing Authors:
+Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
+libpng-0.96, and are distributed according to the same disclaimer and
+license as libpng-0.96, with the following individuals added to the list
+of Contributing Authors:
Tom Lane
Glenn Randers-Pehrson
Willem van Schaik
libpng versions 0.89, June 1996, through 0.96, May 1997, are
-Copyright (c) 1996, 1997 Andreas Dilger
-Distributed according to the same disclaimer and license as libpng-0.88,
-with the following individuals added to the list of Contributing Authors:
+Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
+and are distributed according to the same disclaimer and license as
+libpng-0.88, with the following individuals added to the list of
+Contributing Authors:
John Bowler
Kevin Bracey
@@ -57,7 +56,7 @@ with the following individuals added to the list of Contributing Authors:
Tom Tanner
libpng versions 0.5, May 1995, through 0.88, January 1996, are
-Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
For the purposes of this copyright and license, "Contributing Authors"
is defined as the following set of individuals:
@@ -80,13 +79,13 @@ Permission is hereby granted to use, copy, modify, and distribute this
source code, or portions hereof, for any purpose, without fee, subject
to the following restrictions:
-1. The origin of this source code must not be misrepresented.
+ 1. The origin of this source code must not be misrepresented.
-2. Altered versions must be plainly marked as such and must not
- be misrepresented as being the original source.
+ 2. Altered versions must be plainly marked as such and must not
+ be misrepresented as being the original source.
-3. This Copyright notice may not be removed or altered from any
- source or altered source distribution.
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
The Contributing Authors and Group 42, Inc. specifically permit, without
fee, and encourage the use of this source code as a component to
@@ -94,18 +93,20 @@ supporting the PNG file format in commercial products. If you use this
source code in a product, acknowledgment is not required but would be
appreciated.
+END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
A "png_get_copyright" function is available, for convenient use in "about"
boxes and the like:
- printf("%s",png_get_copyright(NULL));
+ printf("%s", png_get_copyright(NULL));
Also, the PNG logo (in PNG format, of course) is supplied in the
files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
-Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a
-certification mark of the Open Source Initiative.
+Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
+a certification mark of the Open Source Initiative. OSI has not addressed
+the additional disclaimers inserted at version 1.0.7.
Glenn Randers-Pehrson
glennrp at users.sourceforge.net
-February 18, 2012
+January 15, 2016
diff --git a/thirdparty/libpng/README b/thirdparty/libpng/README
index ac682fec..176928fb 100644
--- a/thirdparty/libpng/README
+++ b/thirdparty/libpng/README
@@ -1,11 +1,11 @@
-README for libpng version 1.5.9 - February 18, 2012 (shared library 15.0)
+README for libpng version 1.6.21 - January 15, 2016 (shared library 16.0)
See the note about version numbers near the top of png.h
See INSTALL for instructions on how to install libpng.
-Libpng comes in several distribution formats. Get libpng-*.tar.gz,
-libpng-*.tar.xz or libpng-*.tar.bz2 if you want UNIX-style line endings
-in the text files, or lpng*.zip if you want DOS-style line endings.
+Libpng comes in several distribution formats. Get libpng-*.tar.gz or
+libpng-*.tar.xz or if you want UNIX-style line endings in the text files,
+or lpng*.7z or lpng*.zip if you want DOS-style line endings.
Version 0.89 was the first official release of libpng. Don't let the
fact that it's the first release fool you. The libpng library has been in
@@ -23,18 +23,25 @@ earlier versions if you are using a shared library. The type of the
png_uint_32, which will affect shared-library applications that use
this function.
-To avoid problems with changes to the internals of png_info_struct,
+To avoid problems with changes to the internals of png info_struct,
new APIs have been made available in 0.95 to avoid direct application
access to info_ptr. These functions are the png_set_<chunk> and
png_get_<chunk> functions. These functions should be used when
accessing/storing the info_struct data, rather than manipulating it
directly, to avoid such problems in the future.
-It is important to note that the APIs do not make current programs
+It is important to note that the APIs did not make current programs
that access the info struct directly incompatible with the new
-library. However, it is strongly suggested that new programs use
-the new APIs (as shown in example.c and pngtest.c), and older programs
-be converted to the new format, to facilitate upgrades in the future.
+library, through libpng-1.2.x. In libpng-1.4.x, which was meant to
+be a transitional release, members of the png_struct and the
+info_struct can still be accessed, but the compiler will issue a
+warning about deprecated usage. Since libpng-1.5.0, direct access
+to these structs is not allowed, and the definitions of the structs
+reside in private pngstruct.h and pnginfo.h header files that are not
+accessible to applications. It is strongly suggested that new
+programs use the new APIs (as shown in example.c and pngtest.c), and
+older programs be converted to the new format, to facilitate upgrades
+in the future.
****
Additions since 0.90 include the ability to compile libpng as a
@@ -77,17 +84,21 @@ compression library that is useful for more things than just PNG files.
You can use zlib as a drop-in replacement for fread() and fwrite() if
you are so inclined.
-zlib should be available at the same place that libpng is, or at.
-ftp://ftp.info-zip.org/pub/infozip/zlib
+zlib should be available at the same place that libpng is, or at zlib.net.
You may also want a copy of the PNG specification. It is available
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
these at http://www.libpng.org/pub/png/documents/
This code is currently being archived at libpng.sf.net in the
-[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT)
-at GO GRAPHSUP. If you can't find it in any of those places,
-e-mail me, and I'll help you find it.
+[DOWNLOAD] area, and at ftp://ftp.simplesystems.org. If you can't find it
+in any of those places, e-mail me, and I'll help you find it.
+
+I am not a lawyer, but I believe that the Export Control Classification
+Number (ECCN) for libpng is EAR99, which means not subject to export
+controls or International Traffic in Arms Regulations (ITAR) because it
+is open source, publicly available software, that does not contain any
+encryption software. See the EAR, paragraphs 734.3(b)(3) and 734.7(b).
If you have any code changes, requests, problems, etc., please e-mail
them to me. Also, I'd appreciate any make files or project files,
@@ -105,7 +116,7 @@ based in a large way on Guy's and Andreas' earlier work), and the PNG
development group.
Send comments/corrections/commendations to png-mng-implement at
-lists.sourceforge.net (subscription required; visit
+lists.sourceforge.net (subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
to subscribe) or to glennrp at users.sourceforge.net
@@ -123,7 +134,7 @@ and ...". If in doubt, send questions to me. I'll bounce them
to others, if necessary.
Please do not send suggestions on how to change PNG. We have
-been discussing PNG for sixteen years now, and it is official and
+been discussing PNG for twenty years now, and it is official and
finished. If you have suggestions for libpng, however, I'll
gladly listen. Even if your suggestion is not used immediately,
it may be used later.
@@ -167,23 +178,25 @@ Files in this distribution:
pngwrite.c => High-level write functions
pngwtran.c => Write data transformations
pngwutil.c => Write utility functions
+ arm => Contains optimized code for the ARM platform
contrib => Contributions
+ examples => Example programs
gregbook => source code for PNG reading and writing, from
Greg Roelofs' "PNG: The Definitive Guide",
O'Reilly, 1999
- msvctest => Builds and runs pngtest using a MSVC workspace
- pngminus => Simple pnm2png and png2pnm programs
- pngsuite => Test images
- visupng => Contains a MSVC workspace for VisualPng
+ libtests => Test programs
+ pngminim => Minimal decoder, encoder, and progressive decoder
+ programs demonstrating use of pngusr.dfa
+ pngminus => Simple pnm2png and png2pnm programs
+ pngsuite => Test images
+ tools => Various tools
+ visupng => Contains a MSVC workspace for VisualPng
projects => Contains project files and workspaces for
building a DLL
- cbuilder5 => Contains a Borland workspace for building
- libpng and zlib
- visualc6 => Contains a Microsoft Visual C++ (MSVC)
- workspace for building libpng and zlib
+ owatcom => Contains a WATCOM project for building libpng
visualc71 => Contains a Microsoft Visual C++ (MSVC)
workspace for building libpng and zlib
- xcode => Contains an Apple xcode
+ vstudio => Contains a Microsoft Visual C++ (MSVC)
workspace for building libpng and zlib
scripts => Directory containing scripts for building libpng:
(see scripts/README.txt for the list of scripts)
diff --git a/thirdparty/libpng/TODO b/thirdparty/libpng/TODO
index 6e1f028b..72633774 100644
--- a/thirdparty/libpng/TODO
+++ b/thirdparty/libpng/TODO
@@ -6,10 +6,12 @@ Better C++ wrapper/full C++ implementation?
Fix problem with C++ and EXTERN "C".
cHRM transformation.
Remove setjmp/longjmp usage in favor of returning error codes.
+Palette creation.
Add "grayscale->palette" transformation and "palette->grayscale" detection.
Improved dithering.
Multi-lingual error and warning message support.
Complete sRGB transformation (presently it simply uses gamma=0.45455).
+Make profile checking optional via a png_set_something() call.
Man pages for function calls.
Better documentation.
Better filter selection
diff --git a/thirdparty/libpng/png.c b/thirdparty/libpng/png.c
index ca1de486..1d1bde58 100644
--- a/thirdparty/libpng/png.c
+++ b/thirdparty/libpng/png.c
@@ -1,8 +1,8 @@
/* png.c - location for general purpose libpng functions
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.19 [November 12, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -14,7 +14,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_5_9 Your_png_h_is_not_version_1_5_9;
+typedef png_libpng_version_1_6_21 Your_png_h_is_not_version_1_6_21;
/* Tells libpng that we have already handled the first "num_bytes" bytes
* of the PNG file signature. If the PNG data is embedded into another
@@ -24,17 +24,22 @@ typedef png_libpng_version_1_5_9 Your_png_h_is_not_version_1_5_9;
#ifdef PNG_READ_SUPPORTED
void PNGAPI
-png_set_sig_bytes(png_structp png_ptr, int num_bytes)
+png_set_sig_bytes(png_structrp png_ptr, int num_bytes)
{
+ unsigned int nb = (unsigned int)num_bytes;
+
png_debug(1, "in png_set_sig_bytes");
if (png_ptr == NULL)
return;
- if (num_bytes > 8)
+ if (num_bytes < 0)
+ nb = 0;
+
+ if (nb > 8)
png_error(png_ptr, "Too many bytes for PNG signature");
- png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);
+ png_ptr->sig_bytes = (png_byte)nb;
}
/* Checks whether the supplied bytes match the PNG signature. We allow
@@ -62,52 +67,46 @@ png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check)
if (start + num_to_check > 8)
num_to_check = 8 - start;
- return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check)));
+ return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
}
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
/* Function to allocate memory for zlib */
PNG_FUNCTION(voidpf /* PRIVATE */,
png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
{
- png_voidp ptr;
- png_structp p=(png_structp)png_ptr;
- png_uint_32 save_flags=p->flags;
- png_alloc_size_t num_bytes;
+ png_alloc_size_t num_bytes = size;
if (png_ptr == NULL)
- return (NULL);
+ return NULL;
- if (items > PNG_UINT_32_MAX/size)
+ if (items >= (~(png_alloc_size_t)0)/size)
{
- png_warning (p, "Potential overflow in png_zalloc()");
- return (NULL);
+ png_warning (png_voidcast(png_structrp, png_ptr),
+ "Potential overflow in png_zalloc()");
+ return NULL;
}
- num_bytes = (png_alloc_size_t)items * size;
- p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
- ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
- p->flags=save_flags;
-
- return ((voidpf)ptr);
+ num_bytes *= items;
+ return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes);
}
/* Function to free memory for zlib */
void /* PRIVATE */
png_zfree(voidpf png_ptr, voidpf ptr)
{
- png_free((png_structp)png_ptr, (png_voidp)ptr);
+ png_free(png_voidcast(png_const_structrp,png_ptr), ptr);
}
/* Reset the CRC variable to 32 bits of 1's. Care must be taken
* in case CRC is > 32 bits to leave the top bits 0.
*/
void /* PRIVATE */
-png_reset_crc(png_structp png_ptr)
+png_reset_crc(png_structrp png_ptr)
{
- /* The cast is safe because the crc is a 32 bit value. */
+ /* The cast is safe because the crc is a 32-bit value. */
png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0);
}
@@ -117,11 +116,11 @@ png_reset_crc(png_structp png_ptr)
* trouble of calculating it.
*/
void /* PRIVATE */
-png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length)
+png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)
{
int need_crc = 1;
- if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name))
+ if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
{
if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
(PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
@@ -130,33 +129,35 @@ png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length)
else /* critical */
{
- if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+ if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
need_crc = 0;
}
- /* 'uLong' is defined as unsigned long, this means that on some systems it is
- * a 64 bit value. crc32, however, returns 32 bits so the following cast is
- * safe. 'uInt' may be no more than 16 bits, so it is necessary to perform a
- * loop here.
+ /* 'uLong' is defined in zlib.h as unsigned long; this means that on some
+ * systems it is a 64-bit value. crc32, however, returns 32 bits so the
+ * following cast is safe. 'uInt' may be no more than 16 bits, so it is
+ * necessary to perform a loop here.
*/
- if (need_crc && length > 0)
+ if (need_crc != 0 && length > 0)
{
uLong crc = png_ptr->crc; /* Should never issue a warning */
do
{
- uInt safeLength = (uInt)length;
- if (safeLength == 0)
- safeLength = (uInt)-1; /* evil, but safe */
+ uInt safe_length = (uInt)length;
+#ifndef __COVERITY__
+ if (safe_length == 0)
+ safe_length = (uInt)-1; /* evil, but safe */
+#endif
- crc = crc32(crc, ptr, safeLength);
+ crc = crc32(crc, ptr, safe_length);
- /* The following should never issue compiler warnings, if they do the
+ /* The following should never issue compiler warnings; if they do the
* target system has characteristics that will probably violate other
* assumptions within the libpng code.
*/
- ptr += safeLength;
- length -= safeLength;
+ ptr += safe_length;
+ length -= safe_length;
}
while (length > 0);
@@ -166,97 +167,205 @@ png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length)
}
/* Check a user supplied version number, called from both read and write
- * functions that create a png_struct
+ * functions that create a png_struct.
*/
int
-png_user_version_check(png_structp png_ptr, png_const_charp user_png_ver)
+png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
{
- if (user_png_ver)
+ /* Libpng versions 1.0.0 and later are binary compatible if the version
+ * string matches through the second '.'; we must recompile any
+ * applications that use any older library version.
+ */
+
+ if (user_png_ver != NULL)
{
- int i = 0;
+ int i = -1;
+ int found_dots = 0;
do
{
- if (user_png_ver[i] != png_libpng_ver[i])
+ i++;
+ if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i])
png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
- } while (png_libpng_ver[i++]);
+ if (user_png_ver[i] == '.')
+ found_dots++;
+ } while (found_dots < 2 && user_png_ver[i] != 0 &&
+ PNG_LIBPNG_VER_STRING[i] != 0);
}
else
png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
- if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+ if ((png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) != 0)
{
- /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
- * we must recompile any applications that use any older library version.
- * For versions after libpng 1.0, we will be compatible, so we need
- * only check the first digit.
- */
- if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
- (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
- (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
- {
#ifdef PNG_WARNINGS_SUPPORTED
- size_t pos = 0;
- char m[128];
+ size_t pos = 0;
+ char m[128];
- pos = png_safecat(m, sizeof m, pos, "Application built with libpng-");
- pos = png_safecat(m, sizeof m, pos, user_png_ver);
- pos = png_safecat(m, sizeof m, pos, " but running with ");
- pos = png_safecat(m, sizeof m, pos, png_libpng_ver);
+ pos = png_safecat(m, (sizeof m), pos,
+ "Application built with libpng-");
+ pos = png_safecat(m, (sizeof m), pos, user_png_ver);
+ pos = png_safecat(m, (sizeof m), pos, " but running with ");
+ pos = png_safecat(m, (sizeof m), pos, PNG_LIBPNG_VER_STRING);
+ PNG_UNUSED(pos)
- png_warning(png_ptr, m);
+ png_warning(png_ptr, m);
#endif
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
- png_ptr->flags = 0;
+ png_ptr->flags = 0;
#endif
- return 0;
- }
+ return 0;
}
/* Success return. */
return 1;
}
-/* Allocate the memory for an info_struct for the application. We don't
- * really need the png_ptr, but it could potentially be useful in the
- * future. This should be used in favour of malloc(png_sizeof(png_info))
- * and png_info_init() so that applications that want to use a shared
- * libpng don't have to be recompiled if png_info changes size.
+/* Generic function to create a png_struct for either read or write - this
+ * contains the common initialization.
*/
+PNG_FUNCTION(png_structp /* PRIVATE */,
+png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+ png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
+{
+ png_struct create_struct;
+# ifdef PNG_SETJMP_SUPPORTED
+ jmp_buf create_jmp_buf;
+# endif
+
+ /* This temporary stack-allocated structure is used to provide a place to
+ * build enough context to allow the user provided memory allocator (if any)
+ * to be called.
+ */
+ memset(&create_struct, 0, (sizeof create_struct));
+
+ /* Added at libpng-1.2.6 */
+# ifdef PNG_USER_LIMITS_SUPPORTED
+ create_struct.user_width_max = PNG_USER_WIDTH_MAX;
+ create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
+
+# ifdef PNG_USER_CHUNK_CACHE_MAX
+ /* Added at libpng-1.2.43 and 1.4.0 */
+ create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
+# endif
+
+# ifdef PNG_USER_CHUNK_MALLOC_MAX
+ /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
+ * in png_struct regardless.
+ */
+ create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
+# endif
+# endif
+
+ /* The following two API calls simply set fields in png_struct, so it is safe
+ * to do them now even though error handling is not yet set up.
+ */
+# ifdef PNG_USER_MEM_SUPPORTED
+ png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);
+# else
+ PNG_UNUSED(mem_ptr)
+ PNG_UNUSED(malloc_fn)
+ PNG_UNUSED(free_fn)
+# endif
+
+ /* (*error_fn) can return control to the caller after the error_ptr is set,
+ * this will result in a memory leak unless the error_fn does something
+ * extremely sophisticated. The design lacks merit but is implicit in the
+ * API.
+ */
+ png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn);
+
+# ifdef PNG_SETJMP_SUPPORTED
+ if (!setjmp(create_jmp_buf))
+# endif
+ {
+# ifdef PNG_SETJMP_SUPPORTED
+ /* Temporarily fake out the longjmp information until we have
+ * successfully completed this function. This only works if we have
+ * setjmp() support compiled in, but it is safe - this stuff should
+ * never happen.
+ */
+ create_struct.jmp_buf_ptr = &create_jmp_buf;
+ create_struct.jmp_buf_size = 0; /*stack allocation*/
+ create_struct.longjmp_fn = longjmp;
+# endif
+ /* Call the general version checker (shared with read and write code):
+ */
+ if (png_user_version_check(&create_struct, user_png_ver) != 0)
+ {
+ png_structrp png_ptr = png_voidcast(png_structrp,
+ png_malloc_warn(&create_struct, (sizeof *png_ptr)));
+
+ if (png_ptr != NULL)
+ {
+ /* png_ptr->zstream holds a back-pointer to the png_struct, so
+ * this can only be done now:
+ */
+ create_struct.zstream.zalloc = png_zalloc;
+ create_struct.zstream.zfree = png_zfree;
+ create_struct.zstream.opaque = png_ptr;
+
+# ifdef PNG_SETJMP_SUPPORTED
+ /* Eliminate the local error handling: */
+ create_struct.jmp_buf_ptr = NULL;
+ create_struct.jmp_buf_size = 0;
+ create_struct.longjmp_fn = 0;
+# endif
+
+ *png_ptr = create_struct;
+
+ /* This is the successful return point */
+ return png_ptr;
+ }
+ }
+ }
+
+ /* A longjmp because of a bug in the application storage allocator or a
+ * simple failure to allocate the png_struct.
+ */
+ return NULL;
+}
+
+/* Allocate the memory for an info_struct for the application. */
PNG_FUNCTION(png_infop,PNGAPI
-png_create_info_struct,(png_structp png_ptr),PNG_ALLOCATED)
+png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED)
{
- png_infop info_ptr;
+ png_inforp info_ptr;
png_debug(1, "in png_create_info_struct");
if (png_ptr == NULL)
- return (NULL);
+ return NULL;
+
+ /* Use the internal API that does not (or at least should not) error out, so
+ * that this call always returns ok. The application typically sets up the
+ * error handling *after* creating the info_struct because this is the way it
+ * has always been done in 'example.c'.
+ */
+ info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,
+ (sizeof *info_ptr)));
-#ifdef PNG_USER_MEM_SUPPORTED
- info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
- png_ptr->malloc_fn, png_ptr->mem_ptr);
-#else
- info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
-#endif
if (info_ptr != NULL)
- png_info_init_3(&info_ptr, png_sizeof(png_info));
+ memset(info_ptr, 0, (sizeof *info_ptr));
- return (info_ptr);
+ return info_ptr;
}
/* This function frees the memory associated with a single info struct.
* Normally, one would use either png_destroy_read_struct() or
* png_destroy_write_struct() to free an info struct, but this may be
- * useful for some applications.
+ * useful for some applications. From libpng 1.6.0 this function is also used
+ * internally to implement the png_info release part of the 'struct' destroy
+ * APIs. This ensures that all possible approaches free the same data (all of
+ * it).
*/
void PNGAPI
-png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
+png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr)
{
- png_infop info_ptr = NULL;
+ png_inforp info_ptr = NULL;
png_debug(1, "in png_destroy_info_struct");
@@ -268,46 +377,59 @@ png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
if (info_ptr != NULL)
{
- png_info_destroy(png_ptr, info_ptr);
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn,
- png_ptr->mem_ptr);
-#else
- png_destroy_struct((png_voidp)info_ptr);
-#endif
+ /* Do this first in case of an error below; if the app implements its own
+ * memory management this can lead to png_free calling png_error, which
+ * will abort this routine and return control to the app error handler.
+ * An infinite loop may result if it then tries to free the same info
+ * ptr.
+ */
*info_ptr_ptr = NULL;
+
+ png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+ memset(info_ptr, 0, (sizeof *info_ptr));
+ png_free(png_ptr, info_ptr);
}
}
/* Initialize the info structure. This is now an internal function (0.89)
* and applications using it are urged to use png_create_info_struct()
- * instead.
+ * instead. Use deprecated in 1.6.0, internal use removed (used internally it
+ * is just a memset).
+ *
+ * NOTE: it is almost inconceivable that this API is used because it bypasses
+ * the user-memory mechanism and the user error handling/warning mechanisms in
+ * those cases where it does anything other than a memset.
*/
-
-void PNGAPI
-png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
+PNG_FUNCTION(void,PNGAPI
+png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size),
+ PNG_DEPRECATED)
{
- png_infop info_ptr = *ptr_ptr;
+ png_inforp info_ptr = *ptr_ptr;
png_debug(1, "in png_info_init_3");
if (info_ptr == NULL)
return;
- if (png_sizeof(png_info) > png_info_struct_size)
+ if ((sizeof (png_info)) > png_info_struct_size)
{
- png_destroy_struct(info_ptr);
- info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
+ *ptr_ptr = NULL;
+ /* The following line is why this API should not be used: */
+ free(info_ptr);
+ info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL,
+ (sizeof *info_ptr)));
+ if (info_ptr == NULL)
+ return;
*ptr_ptr = info_ptr;
}
/* Set everything to 0 */
- png_memset(info_ptr, 0, png_sizeof(png_info));
+ memset(info_ptr, 0, (sizeof *info_ptr));
}
+/* The following API is not called internally */
void PNGAPI
-png_data_freer(png_structp png_ptr, png_infop info_ptr,
+png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
int freer, png_uint_32 mask)
{
png_debug(1, "in png_data_freer");
@@ -322,12 +444,11 @@ png_data_freer(png_structp png_ptr, png_infop info_ptr,
info_ptr->free_me &= ~mask;
else
- png_warning(png_ptr,
- "Unknown freer parameter in png_data_freer");
+ png_error(png_ptr, "Unknown freer parameter in png_data_freer");
}
void PNGAPI
-png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
+png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
int num)
{
png_debug(1, "in png_free_data");
@@ -337,42 +458,43 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_TEXT_SUPPORTED
/* Free text item num or (if num == -1) all text items */
- if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
+ if (info_ptr->text != 0 &&
+ ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0)
{
if (num != -1)
{
- if (info_ptr->text && info_ptr->text[num].key)
- {
- png_free(png_ptr, info_ptr->text[num].key);
- info_ptr->text[num].key = NULL;
- }
+ png_free(png_ptr, info_ptr->text[num].key);
+ info_ptr->text[num].key = NULL;
}
else
{
int i;
+
for (i = 0; i < info_ptr->num_text; i++)
- png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
+ png_free(png_ptr, info_ptr->text[i].key);
+
png_free(png_ptr, info_ptr->text);
info_ptr->text = NULL;
- info_ptr->num_text=0;
+ info_ptr->num_text = 0;
}
}
#endif
#ifdef PNG_tRNS_SUPPORTED
/* Free any tRNS entry */
- if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
+ if (((mask & PNG_FREE_TRNS) & info_ptr->free_me) != 0)
{
+ info_ptr->valid &= ~PNG_INFO_tRNS;
png_free(png_ptr, info_ptr->trans_alpha);
info_ptr->trans_alpha = NULL;
- info_ptr->valid &= ~PNG_INFO_tRNS;
+ info_ptr->num_trans = 0;
}
#endif
#ifdef PNG_sCAL_SUPPORTED
/* Free any sCAL entry */
- if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
+ if (((mask & PNG_FREE_SCAL) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->scal_s_width);
png_free(png_ptr, info_ptr->scal_s_height);
@@ -384,20 +506,20 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_pCAL_SUPPORTED
/* Free any pCAL entry */
- if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
+ if (((mask & PNG_FREE_PCAL) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->pcal_purpose);
png_free(png_ptr, info_ptr->pcal_units);
info_ptr->pcal_purpose = NULL;
info_ptr->pcal_units = NULL;
+
if (info_ptr->pcal_params != NULL)
{
int i;
- for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
- {
+
+ for (i = 0; i < info_ptr->pcal_nparams; i++)
png_free(png_ptr, info_ptr->pcal_params[i]);
- info_ptr->pcal_params[i] = NULL;
- }
+
png_free(png_ptr, info_ptr->pcal_params);
info_ptr->pcal_params = NULL;
}
@@ -406,8 +528,8 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#endif
#ifdef PNG_iCCP_SUPPORTED
- /* Free any iCCP entry */
- if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
+ /* Free any profile entry */
+ if (((mask & PNG_FREE_ICCP) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->iccp_name);
png_free(png_ptr, info_ptr->iccp_profile);
@@ -419,74 +541,62 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_sPLT_SUPPORTED
/* Free a given sPLT entry, or (if num == -1) all sPLT entries */
- if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
+ if (info_ptr->splt_palettes != 0 &&
+ ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0)
{
if (num != -1)
{
- if (info_ptr->splt_palettes)
- {
- png_free(png_ptr, info_ptr->splt_palettes[num].name);
- png_free(png_ptr, info_ptr->splt_palettes[num].entries);
- info_ptr->splt_palettes[num].name = NULL;
- info_ptr->splt_palettes[num].entries = NULL;
- }
+ png_free(png_ptr, info_ptr->splt_palettes[num].name);
+ png_free(png_ptr, info_ptr->splt_palettes[num].entries);
+ info_ptr->splt_palettes[num].name = NULL;
+ info_ptr->splt_palettes[num].entries = NULL;
}
else
{
- if (info_ptr->splt_palettes_num)
- {
- int i;
- for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
- png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
+ int i;
- png_free(png_ptr, info_ptr->splt_palettes);
- info_ptr->splt_palettes = NULL;
- info_ptr->splt_palettes_num = 0;
+ for (i = 0; i < info_ptr->splt_palettes_num; i++)
+ {
+ png_free(png_ptr, info_ptr->splt_palettes[i].name);
+ png_free(png_ptr, info_ptr->splt_palettes[i].entries);
}
+
+ png_free(png_ptr, info_ptr->splt_palettes);
+ info_ptr->splt_palettes = NULL;
+ info_ptr->splt_palettes_num = 0;
info_ptr->valid &= ~PNG_INFO_sPLT;
}
}
#endif
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
- if (png_ptr->unknown_chunk.data)
- {
- png_free(png_ptr, png_ptr->unknown_chunk.data);
- png_ptr->unknown_chunk.data = NULL;
- }
-
- if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+ if (info_ptr->unknown_chunks != 0 &&
+ ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0)
{
if (num != -1)
{
- if (info_ptr->unknown_chunks)
- {
- png_free(png_ptr, info_ptr->unknown_chunks[num].data);
- info_ptr->unknown_chunks[num].data = NULL;
- }
+ png_free(png_ptr, info_ptr->unknown_chunks[num].data);
+ info_ptr->unknown_chunks[num].data = NULL;
}
else
{
int i;
- if (info_ptr->unknown_chunks_num)
- {
- for (i = 0; i < info_ptr->unknown_chunks_num; i++)
- png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
+ for (i = 0; i < info_ptr->unknown_chunks_num; i++)
+ png_free(png_ptr, info_ptr->unknown_chunks[i].data);
- png_free(png_ptr, info_ptr->unknown_chunks);
- info_ptr->unknown_chunks = NULL;
- info_ptr->unknown_chunks_num = 0;
- }
+ png_free(png_ptr, info_ptr->unknown_chunks);
+ info_ptr->unknown_chunks = NULL;
+ info_ptr->unknown_chunks_num = 0;
}
}
#endif
#ifdef PNG_hIST_SUPPORTED
/* Free any hIST entry */
- if ((mask & PNG_FREE_HIST) & info_ptr->free_me)
+ if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->hist);
info_ptr->hist = NULL;
@@ -495,9 +605,9 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#endif
/* Free any PLTE entry that was internally allocated */
- if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
+ if (((mask & PNG_FREE_PLTE) & info_ptr->free_me) != 0)
{
- png_zfree(png_ptr, info_ptr->palette);
+ png_free(png_ptr, info_ptr->palette);
info_ptr->palette = NULL;
info_ptr->valid &= ~PNG_INFO_PLTE;
info_ptr->num_palette = 0;
@@ -505,16 +615,14 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* Free any image bits attached to the info structure */
- if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
+ if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0)
{
- if (info_ptr->row_pointers)
+ if (info_ptr->row_pointers != 0)
{
- int row;
- for (row = 0; row < (int)info_ptr->height; row++)
- {
+ png_uint_32 row;
+ for (row = 0; row < info_ptr->height; row++)
png_free(png_ptr, info_ptr->row_pointers[row]);
- info_ptr->row_pointers[row] = NULL;
- }
+
png_free(png_ptr, info_ptr->row_pointers);
info_ptr->row_pointers = NULL;
}
@@ -527,37 +635,14 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
info_ptr->free_me &= ~mask;
}
-
-/* This is an internal routine to free any memory that the info struct is
- * pointing to before re-using it or freeing the struct itself. Recall
- * that png_free() checks for NULL pointers for us.
- */
-void /* PRIVATE */
-png_info_destroy(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_info_destroy");
-
- png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- if (png_ptr->num_chunk_list)
- {
- png_free(png_ptr, png_ptr->chunk_list);
- png_ptr->chunk_list = NULL;
- png_ptr->num_chunk_list = 0;
- }
-#endif
-
- png_info_init_3(&info_ptr, png_sizeof(png_info));
-}
-#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+#endif /* READ || WRITE */
/* This function returns a pointer to the io_ptr associated with the user
* functions. The application should free any memory associated with this
* pointer before png_write_destroy() or png_read_destroy() are called.
*/
png_voidp PNGAPI
-png_get_io_ptr(png_structp png_ptr)
+png_get_io_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
@@ -574,7 +659,7 @@ png_get_io_ptr(png_structp png_ptr)
* function of your own because "FILE *" isn't necessarily available.
*/
void PNGAPI
-png_init_io(png_structp png_ptr, png_FILE_p fp)
+png_init_io(png_structrp png_ptr, png_FILE_p fp)
{
png_debug(1, "in png_init_io");
@@ -585,42 +670,53 @@ png_init_io(png_structp png_ptr, png_FILE_p fp)
}
# endif
+# ifdef PNG_SAVE_INT_32_SUPPORTED
+/* PNG signed integers are saved in 32-bit 2's complement format. ANSI C-90
+ * defines a cast of a signed integer to an unsigned integer either to preserve
+ * the value, if it is positive, or to calculate:
+ *
+ * (UNSIGNED_MAX+1) + integer
+ *
+ * Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the
+ * negative integral value is added the result will be an unsigned value
+ * correspnding to the 2's complement representation.
+ */
+void PNGAPI
+png_save_int_32(png_bytep buf, png_int_32 i)
+{
+ png_save_uint_32(buf, i);
+}
+# endif
+
# ifdef PNG_TIME_RFC1123_SUPPORTED
/* Convert the supplied time into an RFC 1123 string suitable for use in
* a "Creation Time" or other text-based time string.
*/
-png_const_charp PNGAPI
-png_convert_to_rfc1123(png_structp png_ptr, png_const_timep ptime)
+int PNGAPI
+png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
{
static PNG_CONST char short_months[12][4] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- if (png_ptr == NULL)
- return (NULL);
+ if (out == NULL)
+ return 0;
if (ptime->year > 9999 /* RFC1123 limitation */ ||
ptime->month == 0 || ptime->month > 12 ||
ptime->day == 0 || ptime->day > 31 ||
ptime->hour > 23 || ptime->minute > 59 ||
ptime->second > 60)
- {
- png_warning(png_ptr, "Ignoring invalid time value");
- return (NULL);
- }
+ return 0;
{
size_t pos = 0;
char number_buf[5]; /* enough for a four-digit year */
-# define APPEND_STRING(string)\
- pos = png_safecat(png_ptr->time_buffer, sizeof png_ptr->time_buffer,\
- pos, (string))
+# define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
# define APPEND_NUMBER(format, value)\
APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
-# define APPEND(ch)\
- if (pos < (sizeof png_ptr->time_buffer)-1)\
- png_ptr->time_buffer[pos++] = (ch)
+# define APPEND(ch) if (pos < 28) out[pos++] = (ch)
APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
APPEND(' ');
@@ -634,20 +730,44 @@ png_convert_to_rfc1123(png_structp png_ptr, png_const_timep ptime)
APPEND(':');
APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);
APPEND_STRING(" +0000"); /* This reliably terminates the buffer */
+ PNG_UNUSED (pos)
# undef APPEND
# undef APPEND_NUMBER
# undef APPEND_STRING
}
- return png_ptr->time_buffer;
+ return 1;
}
-# endif /* PNG_TIME_RFC1123_SUPPORTED */
-#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+# if PNG_LIBPNG_VER < 10700
+/* To do: remove the following from libpng-1.7 */
+/* Original API that uses a private buffer in png_struct.
+ * Deprecated because it causes png_struct to carry a spurious temporary
+ * buffer (png_struct::time_buffer), better to have the caller pass this in.
+ */
+png_const_charp PNGAPI
+png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime)
+{
+ if (png_ptr != NULL)
+ {
+ /* The only failure above if png_ptr != NULL is from an invalid ptime */
+ if (png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime) == 0)
+ png_warning(png_ptr, "Ignoring invalid time value");
+
+ else
+ return png_ptr->time_buffer;
+ }
+
+ return NULL;
+}
+# endif /* LIBPNG_VER < 10700 */
+# endif /* TIME_RFC1123 */
+
+#endif /* READ || WRITE */
png_const_charp PNGAPI
-png_get_copyright(png_const_structp png_ptr)
+png_get_copyright(png_const_structrp png_ptr)
{
PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
#ifdef PNG_STRING_COPYRIGHT
@@ -655,14 +775,15 @@ png_get_copyright(png_const_structp png_ptr)
#else
# ifdef __STDC__
return PNG_STRING_NEWLINE \
- "libpng version 1.5.9 - February 18, 2012" PNG_STRING_NEWLINE \
- "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
- "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
- "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
- PNG_STRING_NEWLINE;
+ "libpng version 1.6.21 - January 15, 2016" PNG_STRING_NEWLINE \
+ "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \
+ PNG_STRING_NEWLINE \
+ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
+ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
+ PNG_STRING_NEWLINE;
# else
- return "libpng version 1.5.9 - February 18, 2012\
- Copyright (c) 1998-2011 Glenn Randers-Pehrson\
+ return "libpng version 1.6.21 - January 15, 2016\
+ Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\
Copyright (c) 1996-1997 Andreas Dilger\
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
# endif
@@ -678,14 +799,14 @@ png_get_copyright(png_const_structp png_ptr)
* it is guaranteed that png.c uses the correct version of png.h.
*/
png_const_charp PNGAPI
-png_get_libpng_ver(png_const_structp png_ptr)
+png_get_libpng_ver(png_const_structrp png_ptr)
{
/* Version of *.c files used when building libpng */
return png_get_header_ver(png_ptr);
}
png_const_charp PNGAPI
-png_get_header_ver(png_const_structp png_ptr)
+png_get_header_ver(png_const_structrp png_ptr)
{
/* Version of *.h files used when building libpng */
PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
@@ -693,70 +814,137 @@ png_get_header_ver(png_const_structp png_ptr)
}
png_const_charp PNGAPI
-png_get_header_version(png_const_structp png_ptr)
+png_get_header_version(png_const_structrp png_ptr)
{
/* Returns longer string containing both version and date */
PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
#ifdef __STDC__
return PNG_HEADER_VERSION_STRING
# ifndef PNG_READ_SUPPORTED
- " (NO READ SUPPORT)"
+ " (NO READ SUPPORT)"
# endif
- PNG_STRING_NEWLINE;
+ PNG_STRING_NEWLINE;
#else
return PNG_HEADER_VERSION_STRING;
#endif
}
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
+/* NOTE: this routine is not used internally! */
+/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
+ * large of png_color. This lets grayscale images be treated as
+ * paletted. Most useful for gamma correction and simplification
+ * of code. This API is not used internally.
+ */
+void PNGAPI
+png_build_grayscale_palette(int bit_depth, png_colorp palette)
+{
+ int num_palette;
+ int color_inc;
+ int i;
+ int v;
+
+ png_debug(1, "in png_do_build_grayscale_palette");
+
+ if (palette == NULL)
+ return;
+
+ switch (bit_depth)
+ {
+ case 1:
+ num_palette = 2;
+ color_inc = 0xff;
+ break;
+
+ case 2:
+ num_palette = 4;
+ color_inc = 0x55;
+ break;
+
+ case 4:
+ num_palette = 16;
+ color_inc = 0x11;
+ break;
+
+ case 8:
+ num_palette = 256;
+ color_inc = 1;
+ break;
+
+ default:
+ num_palette = 0;
+ color_inc = 0;
+ break;
+ }
+
+ for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
+ {
+ palette[i].red = (png_byte)(v & 0xff);
+ palette[i].green = (png_byte)(v & 0xff);
+ palette[i].blue = (png_byte)(v & 0xff);
+ }
+}
+#endif
+
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
int PNGAPI
-png_handle_as_unknown(png_structp png_ptr, png_const_bytep chunk_name)
+png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)
{
/* Check chunk_name and return "keep" value if it's on the list, else 0 */
png_const_bytep p, p_end;
- if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list <= 0)
+ if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0)
return PNG_HANDLE_CHUNK_AS_DEFAULT;
p_end = png_ptr->chunk_list;
p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
/* The code is the fifth byte after each four byte string. Historically this
- * code was always searched from the end of the list, so it should continue
- * to do so in case there are duplicated entries.
+ * code was always searched from the end of the list, this is no longer
+ * necessary because the 'set' routine handles duplicate entries correcty.
*/
do /* num_chunk_list > 0, so at least one */
{
p -= 5;
- if (!png_memcmp(chunk_name, p, 4))
+
+ if (memcmp(chunk_name, p, 4) == 0)
return p[4];
}
while (p > p_end);
+ /* This means that known chunks should be processed and unknown chunks should
+ * be handled according to the value of png_ptr->unknown_default; this can be
+ * confusing because, as a result, there are two levels of defaulting for
+ * unknown chunks.
+ */
return PNG_HANDLE_CHUNK_AS_DEFAULT;
}
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
int /* PRIVATE */
-png_chunk_unknown_handling(png_structp png_ptr, png_uint_32 chunk_name)
+png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name)
{
png_byte chunk_string[5];
PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
return png_handle_as_unknown(png_ptr, chunk_string);
}
-#endif
+#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
+#endif /* SET_UNKNOWN_CHUNKS */
#ifdef PNG_READ_SUPPORTED
/* This function, added to libpng-1.0.6g, is untested. */
int PNGAPI
-png_reset_zstream(png_structp png_ptr)
+png_reset_zstream(png_structrp png_ptr)
{
if (png_ptr == NULL)
return Z_STREAM_ERROR;
+ /* WARNING: this resets the window bits to the maximum! */
return (inflateReset(&png_ptr->zstream));
}
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
/* This function was added to libpng-1.0.7 */
png_uint_32 PNGAPI
@@ -766,142 +954,308 @@ png_access_version_number(void)
return((png_uint_32)PNG_LIBPNG_VER);
}
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+/* Ensure that png_ptr->zstream.msg holds some appropriate error message string.
+ * If it doesn't 'ret' is used to set it to something appropriate, even in cases
+ * like Z_OK or Z_STREAM_END where the error code is apparently a success code.
+ */
+void /* PRIVATE */
+png_zstream_error(png_structrp png_ptr, int ret)
+{
+ /* Translate 'ret' into an appropriate error string, priority is given to the
+ * one in zstream if set. This always returns a string, even in cases like
+ * Z_OK or Z_STREAM_END where the error code is a success code.
+ */
+ if (png_ptr->zstream.msg == NULL) switch (ret)
+ {
+ default:
+ case Z_OK:
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code");
+ break;
+ case Z_STREAM_END:
+ /* Normal exit */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream");
+ break;
+
+ case Z_NEED_DICT:
+ /* This means the deflate stream did not have a dictionary; this
+ * indicates a bogus PNG.
+ */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary");
+ break;
+
+ case Z_ERRNO:
+ /* gz APIs only: should not happen */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error");
+ break;
+
+ case Z_STREAM_ERROR:
+ /* internal libpng error */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib");
+ break;
+
+ case Z_DATA_ERROR:
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream");
+ break;
+
+ case Z_MEM_ERROR:
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory");
+ break;
+
+ case Z_BUF_ERROR:
+ /* End of input or output; not a problem if the caller is doing
+ * incremental read or write.
+ */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated");
+ break;
+
+ case Z_VERSION_ERROR:
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version");
+ break;
+
+ case PNG_UNEXPECTED_ZLIB_RETURN:
+ /* Compile errors here mean that zlib now uses the value co-opted in
+ * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above
+ * and change pngpriv.h. Note that this message is "... return",
+ * whereas the default/Z_OK one is "... return code".
+ */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return");
+ break;
+ }
+}
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
* at libpng 1.5.5!
*/
/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
-# ifdef PNG_CHECK_cHRM_SUPPORTED
-
-int /* PRIVATE */
-png_check_cHRM_fixed(png_structp png_ptr,
- png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
- png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
- png_fixed_point blue_x, png_fixed_point blue_y)
+#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
+static int
+png_colorspace_check_gamma(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_fixed_point gAMA, int from)
+ /* This is called to check a new gamma value against an existing one. The
+ * routine returns false if the new gamma value should not be written.
+ *
+ * 'from' says where the new gamma value comes from:
+ *
+ * 0: the new gamma value is the libpng estimate for an ICC profile
+ * 1: the new gamma value comes from a gAMA chunk
+ * 2: the new gamma value comes from an sRGB chunk
+ */
{
- int ret = 1;
- unsigned long xy_hi,xy_lo,yx_hi,yx_lo;
+ png_fixed_point gtest;
- png_debug(1, "in function png_check_cHRM_fixed");
+ if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+ (png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) == 0 ||
+ png_gamma_significant(gtest) != 0))
+ {
+ /* Either this is an sRGB image, in which case the calculated gamma
+ * approximation should match, or this is an image with a profile and the
+ * value libpng calculates for the gamma of the profile does not match the
+ * value recorded in the file. The former, sRGB, case is an error, the
+ * latter is just a warning.
+ */
+ if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
+ {
+ png_chunk_report(png_ptr, "gamma value does not match sRGB",
+ PNG_CHUNK_ERROR);
+ /* Do not overwrite an sRGB value */
+ return from == 2;
+ }
- if (png_ptr == NULL)
- return 0;
+ else /* sRGB tag not involved */
+ {
+ png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
+ PNG_CHUNK_WARNING);
+ return from == 1;
+ }
+ }
+
+ return 1;
+}
- /* (x,y,z) values are first limited to 0..100000 (PNG_FP_1), the white
- * y must also be greater than 0. To test for the upper limit calculate
- * (PNG_FP_1-y) - x must be <= to this for z to be >= 0 (and the expression
- * cannot overflow.) At this point we know x and y are >= 0 and (x+y) is
- * <= PNG_FP_1. The previous test on PNG_MAX_UINT_31 is removed because it
- * pointless (and it produces compiler warnings!)
+void /* PRIVATE */
+png_colorspace_set_gamma(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_fixed_point gAMA)
+{
+ /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
+ * occur. Since the fixed point representation is asymetrical it is
+ * possible for 1/gamma to overflow the limit of 21474 and this means the
+ * gamma value must be at least 5/100000 and hence at most 20000.0. For
+ * safety the limits here are a little narrower. The values are 0.00016 to
+ * 6250.0, which are truly ridiculous gamma values (and will produce
+ * displays that are all black or all white.)
+ *
+ * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
+ * handling code, which only required the value to be >0.
*/
- if (white_x < 0 || white_y <= 0 ||
- red_x < 0 || red_y < 0 ||
- green_x < 0 || green_y < 0 ||
- blue_x < 0 || blue_y < 0)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set negative chromaticity value");
- ret = 0;
- }
- /* And (x+y) must be <= PNG_FP_1 (so z is >= 0) */
- if (white_x > PNG_FP_1 - white_y)
- {
- png_warning(png_ptr, "Invalid cHRM white point");
- ret = 0;
- }
+ png_const_charp errmsg;
+
+ if (gAMA < 16 || gAMA > 625000000)
+ errmsg = "gamma value out of range";
- if (red_x > PNG_FP_1 - red_y)
+# ifdef PNG_READ_gAMA_SUPPORTED
+ /* Allow the application to set the gamma value more than once */
+ else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
+ errmsg = "duplicate";
+# endif
+
+ /* Do nothing if the colorspace is already invalid */
+ else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+ return;
+
+ else
{
- png_warning(png_ptr, "Invalid cHRM red point");
- ret = 0;
+ if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA,
+ 1/*from gAMA*/) != 0)
+ {
+ /* Store this gamma value. */
+ colorspace->gamma = gAMA;
+ colorspace->flags |=
+ (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);
+ }
+
+ /* At present if the check_gamma test fails the gamma of the colorspace is
+ * not updated however the colorspace is not invalidated. This
+ * corresponds to the case where the existing gamma comes from an sRGB
+ * chunk or profile. An error message has already been output.
+ */
+ return;
}
- if (green_x > PNG_FP_1 - green_y)
+ /* Error exit - errmsg has been set. */
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
+}
+
+void /* PRIVATE */
+png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
+{
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
{
- png_warning(png_ptr, "Invalid cHRM green point");
- ret = 0;
+ /* Everything is invalid */
+ info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|
+ PNG_INFO_iCCP);
+
+# ifdef PNG_COLORSPACE_SUPPORTED
+ /* Clean up the iCCP profile now if it won't be used. */
+ png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/);
+# else
+ PNG_UNUSED(png_ptr)
+# endif
}
- if (blue_x > PNG_FP_1 - blue_y)
+ else
{
- png_warning(png_ptr, "Invalid cHRM blue point");
- ret = 0;
- }
+# ifdef PNG_COLORSPACE_SUPPORTED
+ /* Leave the INFO_iCCP flag set if the pngset.c code has already set
+ * it; this allows a PNG to contain a profile which matches sRGB and
+ * yet still have that profile retrievable by the application.
+ */
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0)
+ info_ptr->valid |= PNG_INFO_sRGB;
+
+ else
+ info_ptr->valid &= ~PNG_INFO_sRGB;
- png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo);
- png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo);
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+ info_ptr->valid |= PNG_INFO_cHRM;
- if (xy_hi == yx_hi && xy_lo == yx_lo)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set cHRM RGB triangle with zero area");
- ret = 0;
+ else
+ info_ptr->valid &= ~PNG_INFO_cHRM;
+# endif
+
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0)
+ info_ptr->valid |= PNG_INFO_gAMA;
+
+ else
+ info_ptr->valid &= ~PNG_INFO_gAMA;
}
+}
+
+#ifdef PNG_READ_SUPPORTED
+void /* PRIVATE */
+png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
+{
+ if (info_ptr == NULL) /* reduce code size; check here not in the caller */
+ return;
- return ret;
+ info_ptr->colorspace = png_ptr->colorspace;
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
-# endif /* PNG_CHECK_cHRM_SUPPORTED */
+#endif
+#endif /* GAMMA */
-#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_COLORSPACE_SUPPORTED
/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
* cHRM, as opposed to using chromaticities. These internal APIs return
* non-zero on a parameter error. The X, Y and Z values are required to be
* positive and less than 1.0.
*/
-int png_xy_from_XYZ(png_xy *xy, png_XYZ XYZ)
+static int
+png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
{
png_int_32 d, dwhite, whiteX, whiteY;
- d = XYZ.redX + XYZ.redY + XYZ.redZ;
- if (!png_muldiv(&xy->redx, XYZ.redX, PNG_FP_1, d)) return 1;
- if (!png_muldiv(&xy->redy, XYZ.redY, PNG_FP_1, d)) return 1;
+ d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
+ if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
+ return 1;
+ if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
+ return 1;
dwhite = d;
- whiteX = XYZ.redX;
- whiteY = XYZ.redY;
+ whiteX = XYZ->red_X;
+ whiteY = XYZ->red_Y;
- d = XYZ.greenX + XYZ.greenY + XYZ.greenZ;
- if (!png_muldiv(&xy->greenx, XYZ.greenX, PNG_FP_1, d)) return 1;
- if (!png_muldiv(&xy->greeny, XYZ.greenY, PNG_FP_1, d)) return 1;
+ d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
+ if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
+ return 1;
+ if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
+ return 1;
dwhite += d;
- whiteX += XYZ.greenX;
- whiteY += XYZ.greenY;
+ whiteX += XYZ->green_X;
+ whiteY += XYZ->green_Y;
- d = XYZ.blueX + XYZ.blueY + XYZ.blueZ;
- if (!png_muldiv(&xy->bluex, XYZ.blueX, PNG_FP_1, d)) return 1;
- if (!png_muldiv(&xy->bluey, XYZ.blueY, PNG_FP_1, d)) return 1;
+ d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
+ if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
+ return 1;
+ if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
+ return 1;
dwhite += d;
- whiteX += XYZ.blueX;
- whiteY += XYZ.blueY;
+ whiteX += XYZ->blue_X;
+ whiteY += XYZ->blue_Y;
- /* The reference white is simply the same of the end-point (X,Y,Z) vectors,
+ /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
* thus:
*/
- if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1;
- if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1;
+ if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
+ return 1;
+ if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0)
+ return 1;
return 0;
}
-int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
+static int
+png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
{
png_fixed_point red_inverse, green_inverse, blue_scale;
png_fixed_point left, right, denominator;
/* Check xy and, implicitly, z. Note that wide gamut color spaces typically
* have end points with 0 tristimulus values (these are impossible end
- * points, but they are used to cover the possible colors.)
+ * points, but they are used to cover the possible colors). We check
+ * xy->whitey against 5, not 0, to avoid a possible integer overflow.
*/
- if (xy.redx < 0 || xy.redx > PNG_FP_1) return 1;
- if (xy.redy < 0 || xy.redy > PNG_FP_1-xy.redx) return 1;
- if (xy.greenx < 0 || xy.greenx > PNG_FP_1) return 1;
- if (xy.greeny < 0 || xy.greeny > PNG_FP_1-xy.greenx) return 1;
- if (xy.bluex < 0 || xy.bluex > PNG_FP_1) return 1;
- if (xy.bluey < 0 || xy.bluey > PNG_FP_1-xy.bluex) return 1;
- if (xy.whitex < 0 || xy.whitex > PNG_FP_1) return 1;
- if (xy.whitey < 0 || xy.whitey > PNG_FP_1-xy.whitex) return 1;
+ if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1;
+ if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
+ if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
+ if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
+ if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1;
+ if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
+ if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
+ if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
/* The reverse calculation is more difficult because the original tristimulus
* value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
@@ -969,14 +1323,14 @@ int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
* and it is certain that it becomes unstable where the end points are close
* together.
*
- * So this code uses the perhaps slighly less optimal but more understandable
- * and totally obvious approach of calculating color-scale.
+ * So this code uses the perhaps slightly less optimal but more
+ * understandable and totally obvious approach of calculating color-scale.
*
* This algorithm depends on the precision in white-scale and that is
* (1/white-y), so we can immediately see that as white-y approaches 0 the
* accuracy inherent in the cHRM chunk drops off substantially.
*
- * libpng arithmetic: a simple invertion of the above equations
+ * libpng arithmetic: a simple inversion of the above equations
* ------------------------------------------------------------
*
* white_scale = 1/white-y
@@ -1082,91 +1436,1048 @@ int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
/* By the argument, above overflow should be impossible here. The return
* value of 2 indicates an internal error to the caller.
*/
- if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.redy - xy.bluey, 7)) return 2;
- if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.redx - xy.bluex, 7)) return 2;
+ if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
+ return 2;
+ if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
+ return 2;
denominator = left - right;
/* Now find the red numerator. */
- if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2;
- if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.whitex-xy.bluex, 7)) return 2;
+ if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
+ return 2;
+ if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
+ return 2;
/* Overflow is possible here and it indicates an extreme set of PNG cHRM
* chunk values. This calculation actually returns the reciprocal of the
* scale value because this allows us to delay the multiplication of white-y
* into the denominator, which tends to produce a small number.
*/
- if (!png_muldiv(&red_inverse, xy.whitey, denominator, left-right) ||
- red_inverse <= xy.whitey /* r+g+b scales = white scale */)
+ if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
+ red_inverse <= xy->whitey /* r+g+b scales = white scale */)
return 1;
/* Similarly for green_inverse: */
- if (!png_muldiv(&left, xy.redy-xy.bluey, xy.whitex-xy.bluex, 7)) return 2;
- if (!png_muldiv(&right, xy.redx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2;
- if (!png_muldiv(&green_inverse, xy.whitey, denominator, left-right) ||
- green_inverse <= xy.whitey)
+ if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
+ return 2;
+ if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
+ return 2;
+ if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
+ green_inverse <= xy->whitey)
return 1;
/* And the blue scale, the checks above guarantee this can't overflow but it
* can still produce 0 for extreme cHRM values.
*/
- blue_scale = png_reciprocal(xy.whitey) - png_reciprocal(red_inverse) -
- png_reciprocal(green_inverse);
- if (blue_scale <= 0) return 1;
+ blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
+ png_reciprocal(green_inverse);
+ if (blue_scale <= 0)
+ return 1;
/* And fill in the png_XYZ: */
- if (!png_muldiv(&XYZ->redX, xy.redx, PNG_FP_1, red_inverse)) return 1;
- if (!png_muldiv(&XYZ->redY, xy.redy, PNG_FP_1, red_inverse)) return 1;
- if (!png_muldiv(&XYZ->redZ, PNG_FP_1 - xy.redx - xy.redy, PNG_FP_1,
- red_inverse))
+ if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1,
+ red_inverse) == 0)
return 1;
- if (!png_muldiv(&XYZ->greenX, xy.greenx, PNG_FP_1, green_inverse)) return 1;
- if (!png_muldiv(&XYZ->greenY, xy.greeny, PNG_FP_1, green_inverse)) return 1;
- if (!png_muldiv(&XYZ->greenZ, PNG_FP_1 - xy.greenx - xy.greeny, PNG_FP_1,
- green_inverse))
+ if (png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,
+ green_inverse) == 0)
return 1;
- if (!png_muldiv(&XYZ->blueX, xy.bluex, blue_scale, PNG_FP_1)) return 1;
- if (!png_muldiv(&XYZ->blueY, xy.bluey, blue_scale, PNG_FP_1)) return 1;
- if (!png_muldiv(&XYZ->blueZ, PNG_FP_1 - xy.bluex - xy.bluey, blue_scale,
- PNG_FP_1))
+ if (png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale,
+ PNG_FP_1) == 0)
return 1;
return 0; /*success*/
}
-int png_XYZ_from_xy_checked(png_structp png_ptr, png_XYZ *XYZ, png_xy xy)
+static int
+png_XYZ_normalize(png_XYZ *XYZ)
{
- switch (png_XYZ_from_xy(XYZ, xy))
+ png_int_32 Y;
+
+ if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
+ XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
+ XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
+ return 1;
+
+ /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
+ * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
+ * relying on addition of two positive values producing a negative one is not
+ * safe.
+ */
+ Y = XYZ->red_Y;
+ if (0x7fffffff - Y < XYZ->green_X)
+ return 1;
+ Y += XYZ->green_Y;
+ if (0x7fffffff - Y < XYZ->blue_X)
+ return 1;
+ Y += XYZ->blue_Y;
+
+ if (Y != PNG_FP_1)
{
- case 0: /* success */
+ if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0)
return 1;
+ if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0)
+ return 1;
+
+ if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta)
+{
+ /* Allow an error of +/-0.01 (absolute value) on each chromaticity */
+ if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
+ PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
+ PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) ||
+ PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) ||
+ PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
+ PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
+ PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) ||
+ PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta))
+ return 0;
+ return 1;
+}
+
+/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM
+ * chunk chromaticities. Earlier checks used to simply look for the overflow
+ * condition (where the determinant of the matrix to solve for XYZ ends up zero
+ * because the chromaticity values are not all distinct.) Despite this it is
+ * theoretically possible to produce chromaticities that are apparently valid
+ * but that rapidly degrade to invalid, potentially crashing, sets because of
+ * arithmetic inaccuracies when calculations are performed on them. The new
+ * check is to round-trip xy -> XYZ -> xy and then check that the result is
+ * within a small percentage of the original.
+ */
+static int
+png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy)
+{
+ int result;
+ png_xy xy_test;
+
+ /* As a side-effect this routine also returns the XYZ endpoints. */
+ result = png_XYZ_from_xy(XYZ, xy);
+ if (result != 0)
+ return result;
+
+ result = png_xy_from_XYZ(&xy_test, XYZ);
+ if (result != 0)
+ return result;
+
+ if (png_colorspace_endpoints_match(xy, &xy_test,
+ 5/*actually, the math is pretty accurate*/) != 0)
+ return 0;
+
+ /* Too much slip */
+ return 1;
+}
+
+/* This is the check going the other way. The XYZ is modified to normalize it
+ * (another side-effect) and the xy chromaticities are returned.
+ */
+static int
+png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ)
+{
+ int result;
+ png_XYZ XYZtemp;
+
+ result = png_XYZ_normalize(XYZ);
+ if (result != 0)
+ return result;
+
+ result = png_xy_from_XYZ(xy, XYZ);
+ if (result != 0)
+ return result;
+
+ XYZtemp = *XYZ;
+ return png_colorspace_check_xy(&XYZtemp, xy);
+}
+
+/* Used to check for an endpoint match against sRGB */
+static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
+{
+ /* color x y */
+ /* red */ 64000, 33000,
+ /* green */ 30000, 60000,
+ /* blue */ 15000, 6000,
+ /* white */ 31270, 32900
+};
+
+static int
+png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
+ int preferred)
+{
+ if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+ return 0;
+
+ /* The consistency check is performed on the chromaticities; this factors out
+ * variations because of the normalization (or not) of the end point Y
+ * values.
+ */
+ if (preferred < 2 &&
+ (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+ {
+ /* The end points must be reasonably close to any we already have. The
+ * following allows an error of up to +/-.001
+ */
+ if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy,
+ 100) == 0)
+ {
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_benign_error(png_ptr, "inconsistent chromaticities");
+ return 0; /* failed */
+ }
+
+ /* Only overwrite with preferred values */
+ if (preferred == 0)
+ return 1; /* ok, but no change */
+ }
+
+ colorspace->end_points_xy = *xy;
+ colorspace->end_points_XYZ = *XYZ;
+ colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
+
+ /* The end points are normally quoted to two decimal digits, so allow +/-0.01
+ * on this test.
+ */
+ if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0)
+ colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
+
+ else
+ colorspace->flags &= PNG_COLORSPACE_CANCEL(
+ PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
+
+ return 2; /* ok and changed */
+}
+
+int /* PRIVATE */
+png_colorspace_set_chromaticities(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, const png_xy *xy, int preferred)
+{
+ /* We must check the end points to ensure they are reasonable - in the past
+ * color management systems have crashed as a result of getting bogus
+ * colorant values, while this isn't the fault of libpng it is the
+ * responsibility of libpng because PNG carries the bomb and libpng is in a
+ * position to protect against it.
+ */
+ png_XYZ XYZ;
+
+ switch (png_colorspace_check_xy(&XYZ, xy))
+ {
+ case 0: /* success */
+ return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
+ preferred);
+
case 1:
- /* The chunk may be technically valid, but we got png_fixed_point
- * overflow while trying to get XYZ values out of it. This is
- * entirely benign - the cHRM chunk is pretty extreme.
+ /* We can't invert the chromaticities so we can't produce value XYZ
+ * values. Likely as not a color management system will fail too.
*/
- png_warning(png_ptr,
- "extreme cHRM chunk cannot be converted to tristimulus values");
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_benign_error(png_ptr, "invalid chromaticities");
break;
default:
/* libpng is broken; this should be a warning but if it happens we
* want error reports so for the moment it is an error.
*/
- png_error(png_ptr, "internal error in png_XYZ_from_xy");
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_error(png_ptr, "internal error checking chromaticities");
+ }
+
+ return 0; /* failed */
+}
+
+int /* PRIVATE */
+png_colorspace_set_endpoints(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
+{
+ png_XYZ XYZ = *XYZ_in;
+ png_xy xy;
+
+ switch (png_colorspace_check_XYZ(&xy, &XYZ))
+ {
+ case 0:
+ return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
+ preferred);
+
+ case 1:
+ /* End points are invalid. */
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_benign_error(png_ptr, "invalid end points");
break;
+
+ default:
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_error(png_ptr, "internal error checking chromaticities");
}
- /* ERROR RETURN */
+ return 0; /* failed */
+}
+
+#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED)
+/* Error message generation */
+static char
+png_icc_tag_char(png_uint_32 byte)
+{
+ byte &= 0xff;
+ if (byte >= 32 && byte <= 126)
+ return (char)byte;
+ else
+ return '?';
+}
+
+static void
+png_icc_tag_name(char *name, png_uint_32 tag)
+{
+ name[0] = '\'';
+ name[1] = png_icc_tag_char(tag >> 24);
+ name[2] = png_icc_tag_char(tag >> 16);
+ name[3] = png_icc_tag_char(tag >> 8);
+ name[4] = png_icc_tag_char(tag );
+ name[5] = '\'';
+}
+
+static int
+is_ICC_signature_char(png_alloc_size_t it)
+{
+ return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) ||
+ (it >= 97 && it <= 122);
+}
+
+static int
+is_ICC_signature(png_alloc_size_t it)
+{
+ return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&
+ is_ICC_signature_char((it >> 16) & 0xff) &&
+ is_ICC_signature_char((it >> 8) & 0xff) &&
+ is_ICC_signature_char(it & 0xff);
+}
+
+static int
+png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_alloc_size_t value, png_const_charp reason)
+{
+ size_t pos;
+ char message[196]; /* see below for calculation */
+
+ if (colorspace != NULL)
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+
+ pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
+ pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */
+ pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */
+ if (is_ICC_signature(value) != 0)
+ {
+ /* So 'value' is at most 4 bytes and the following cast is safe */
+ png_icc_tag_name(message+pos, (png_uint_32)value);
+ pos += 6; /* total +8; less than the else clause */
+ message[pos++] = ':';
+ message[pos++] = ' ';
+ }
+# ifdef PNG_WARNINGS_SUPPORTED
+ else
+ {
+ char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
+
+ pos = png_safecat(message, (sizeof message), pos,
+ png_format_number(number, number+(sizeof number),
+ PNG_NUMBER_FORMAT_x, value));
+ pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
+ }
+# endif
+ /* The 'reason' is an arbitrary message, allow +79 maximum 195 */
+ pos = png_safecat(message, (sizeof message), pos, reason);
+ PNG_UNUSED(pos)
+
+ /* This is recoverable, but make it unconditionally an app_error on write to
+ * avoid writing invalid ICC profiles into PNG files (i.e., we handle them
+ * on read, with a warning, but on write unless the app turns off
+ * application errors the PNG won't be written.)
+ */
+ png_chunk_report(png_ptr, message,
+ (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
+
return 0;
}
+#endif /* sRGB || iCCP */
+
+#ifdef PNG_sRGB_SUPPORTED
+int /* PRIVATE */
+png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ int intent)
+{
+ /* sRGB sets known gamma, end points and (from the chunk) intent. */
+ /* IMPORTANT: these are not necessarily the values found in an ICC profile
+ * because ICC profiles store values adapted to a D50 environment; it is
+ * expected that the ICC profile mediaWhitePointTag will be D50; see the
+ * checks and code elsewhere to understand this better.
+ *
+ * These XYZ values, which are accurate to 5dp, produce rgb to gray
+ * coefficients of (6968,23435,2366), which are reduced (because they add up
+ * to 32769 not 32768) to (6968,23434,2366). These are the values that
+ * libpng has traditionally used (and are the best values given the 15bit
+ * algorithm used by the rgb to gray code.)
+ */
+ static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */
+ {
+ /* color X Y Z */
+ /* red */ 41239, 21264, 1933,
+ /* green */ 35758, 71517, 11919,
+ /* blue */ 18048, 7219, 95053
+ };
+
+ /* Do nothing if the colorspace is already invalidated. */
+ if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+ return 0;
+
+ /* Check the intent, then check for existing settings. It is valid for the
+ * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must
+ * be consistent with the correct values. If, however, this function is
+ * called below because an iCCP chunk matches sRGB then it is quite
+ * conceivable that an older app recorded incorrect gAMA and cHRM because of
+ * an incorrect calculation based on the values in the profile - this does
+ * *not* invalidate the profile (though it still produces an error, which can
+ * be ignored.)
+ */
+ if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
+ return png_icc_profile_error(png_ptr, colorspace, "sRGB",
+ (unsigned)intent, "invalid sRGB rendering intent");
+
+ if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
+ colorspace->rendering_intent != intent)
+ return png_icc_profile_error(png_ptr, colorspace, "sRGB",
+ (unsigned)intent, "inconsistent rendering intents");
+
+ if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
+ {
+ png_benign_error(png_ptr, "duplicate sRGB information ignored");
+ return 0;
+ }
+
+ /* If the standard sRGB cHRM chunk does not match the one from the PNG file
+ * warn but overwrite the value with the correct one.
+ */
+ if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 &&
+ !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
+ 100))
+ png_chunk_report(png_ptr, "cHRM chunk does not match sRGB",
+ PNG_CHUNK_ERROR);
+
+ /* This check is just done for the error reporting - the routine always
+ * returns true when the 'from' argument corresponds to sRGB (2).
+ */
+ (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE,
+ 2/*from sRGB*/);
+
+ /* intent: bugs in GCC force 'int' to be used as the parameter type. */
+ colorspace->rendering_intent = (png_uint_16)intent;
+ colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;
+
+ /* endpoints */
+ colorspace->end_points_xy = sRGB_xy;
+ colorspace->end_points_XYZ = sRGB_XYZ;
+ colorspace->flags |=
+ (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
+
+ /* gamma */
+ colorspace->gamma = PNG_GAMMA_sRGB_INVERSE;
+ colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;
+
+ /* Finally record that we have an sRGB profile */
+ colorspace->flags |=
+ (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB);
+
+ return 1; /* set */
+}
+#endif /* sRGB */
+
+#ifdef PNG_iCCP_SUPPORTED
+/* Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value
+ * is XYZ(0.9642,1.0,0.8249), which scales to:
+ *
+ * (63189.8112, 65536, 54060.6464)
+ */
+static const png_byte D50_nCIEXYZ[12] =
+ { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };
+
+int /* PRIVATE */
+png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_uint_32 profile_length)
+{
+ if (profile_length < 132)
+ return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+ "too short");
+
+ return 1;
+}
+
+int /* PRIVATE */
+png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_uint_32 profile_length,
+ png_const_bytep profile/* first 132 bytes only */, int color_type)
+{
+ png_uint_32 temp;
+
+ /* Length check; this cannot be ignored in this code because profile_length
+ * is used later to check the tag table, so even if the profile seems over
+ * long profile_length from the caller must be correct. The caller can fix
+ * this up on read or write by just passing in the profile header length.
+ */
+ temp = png_get_uint_32(profile);
+ if (temp != profile_length)
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "length does not match profile");
+
+ temp = (png_uint_32) (*(profile+8));
+ if (temp > 3 && (profile_length & 3))
+ return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+ "invalid length");
+
+ temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
+ if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
+ profile_length < 132+12*temp) /* truncated tag table */
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "tag count too large");
+
+ /* The 'intent' must be valid or we can't store it, ICC limits the intent to
+ * 16 bits.
+ */
+ temp = png_get_uint_32(profile+64);
+ if (temp >= 0xffff) /* The ICC limit */
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "invalid rendering intent");
+
+ /* This is just a warning because the profile may be valid in future
+ * versions.
+ */
+ if (temp >= PNG_sRGB_INTENT_LAST)
+ (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+ "intent outside defined range");
+
+ /* At this point the tag table can't be checked because it hasn't necessarily
+ * been loaded; however, various header fields can be checked. These checks
+ * are for values permitted by the PNG spec in an ICC profile; the PNG spec
+ * restricts the profiles that can be passed in an iCCP chunk (they must be
+ * appropriate to processing PNG data!)
+ */
+
+ /* Data checks (could be skipped). These checks must be independent of the
+ * version number; however, the version number doesn't accomodate changes in
+ * the header fields (just the known tags and the interpretation of the
+ * data.)
+ */
+ temp = png_get_uint_32(profile+36); /* signature 'ascp' */
+ if (temp != 0x61637370)
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "invalid signature");
+
+ /* Currently the PCS illuminant/adopted white point (the computational
+ * white point) are required to be D50,
+ * however the profile contains a record of the illuminant so perhaps ICC
+ * expects to be able to change this in the future (despite the rationale in
+ * the introduction for using a fixed PCS adopted white.) Consequently the
+ * following is just a warning.
+ */
+ if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
+ (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
+ "PCS illuminant is not D50");
+
+ /* The PNG spec requires this:
+ * "If the iCCP chunk is present, the image samples conform to the colour
+ * space represented by the embedded ICC profile as defined by the
+ * International Color Consortium [ICC]. The colour space of the ICC profile
+ * shall be an RGB colour space for colour images (PNG colour types 2, 3, and
+ * 6), or a greyscale colour space for greyscale images (PNG colour types 0
+ * and 4)."
+ *
+ * This checking code ensures the embedded profile (on either read or write)
+ * conforms to the specification requirements. Notice that an ICC 'gray'
+ * color-space profile contains the information to transform the monochrome
+ * data to XYZ or L*a*b (according to which PCS the profile uses) and this
+ * should be used in preference to the standard libpng K channel replication
+ * into R, G and B channels.
+ *
+ * Previously it was suggested that an RGB profile on grayscale data could be
+ * handled. However it it is clear that using an RGB profile in this context
+ * must be an error - there is no specification of what it means. Thus it is
+ * almost certainly more correct to ignore the profile.
+ */
+ temp = png_get_uint_32(profile+16); /* data colour space field */
+ switch (temp)
+ {
+ case 0x52474220: /* 'RGB ' */
+ if ((color_type & PNG_COLOR_MASK_COLOR) == 0)
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "RGB color space not permitted on grayscale PNG");
+ break;
+
+ case 0x47524159: /* 'GRAY' */
+ if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "Gray color space not permitted on RGB PNG");
+ break;
+
+ default:
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "invalid ICC profile color space");
+ }
+
+ /* It is up to the application to check that the profile class matches the
+ * application requirements; the spec provides no guidance, but it's pretty
+ * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer
+ * ('prtr') or 'spac' (for generic color spaces). Issue a warning in these
+ * cases. Issue an error for device link or abstract profiles - these don't
+ * contain the records necessary to transform the color-space to anything
+ * other than the target device (and not even that for an abstract profile).
+ * Profiles of these classes may not be embedded in images.
+ */
+ temp = png_get_uint_32(profile+12); /* profile/device class */
+ switch (temp)
+ {
+ case 0x73636e72: /* 'scnr' */
+ case 0x6d6e7472: /* 'mntr' */
+ case 0x70727472: /* 'prtr' */
+ case 0x73706163: /* 'spac' */
+ /* All supported */
+ break;
+
+ case 0x61627374: /* 'abst' */
+ /* May not be embedded in an image */
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "invalid embedded Abstract ICC profile");
+
+ case 0x6c696e6b: /* 'link' */
+ /* DeviceLink profiles cannot be interpreted in a non-device specific
+ * fashion, if an app uses the AToB0Tag in the profile the results are
+ * undefined unless the result is sent to the intended device,
+ * therefore a DeviceLink profile should not be found embedded in a
+ * PNG.
+ */
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "unexpected DeviceLink ICC profile class");
+
+ case 0x6e6d636c: /* 'nmcl' */
+ /* A NamedColor profile is also device specific, however it doesn't
+ * contain an AToB0 tag that is open to misinterpretation. Almost
+ * certainly it will fail the tests below.
+ */
+ (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+ "unexpected NamedColor ICC profile class");
+ break;
+
+ default:
+ /* To allow for future enhancements to the profile accept unrecognized
+ * profile classes with a warning, these then hit the test below on the
+ * tag content to ensure they are backward compatible with one of the
+ * understood profiles.
+ */
+ (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+ "unrecognized ICC profile class");
+ break;
+ }
+
+ /* For any profile other than a device link one the PCS must be encoded
+ * either in XYZ or Lab.
+ */
+ temp = png_get_uint_32(profile+20);
+ switch (temp)
+ {
+ case 0x58595a20: /* 'XYZ ' */
+ case 0x4c616220: /* 'Lab ' */
+ break;
+
+ default:
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "unexpected ICC PCS encoding");
+ }
+
+ return 1;
+}
+
+int /* PRIVATE */
+png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_uint_32 profile_length,
+ png_const_bytep profile /* header plus whole tag table */)
+{
+ png_uint_32 tag_count = png_get_uint_32(profile+128);
+ png_uint_32 itag;
+ png_const_bytep tag = profile+132; /* The first tag */
+
+ /* First scan all the tags in the table and add bits to the icc_info value
+ * (temporarily in 'tags').
+ */
+ for (itag=0; itag < tag_count; ++itag, tag += 12)
+ {
+ png_uint_32 tag_id = png_get_uint_32(tag+0);
+ png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */
+ png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */
+
+ /* The ICC specification does not exclude zero length tags, therefore the
+ * start might actually be anywhere if there is no data, but this would be
+ * a clear abuse of the intent of the standard so the start is checked for
+ * being in range. All defined tag types have an 8 byte header - a 4 byte
+ * type signature then 0.
+ */
+ if ((tag_start & 3) != 0)
+ {
+ /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is
+ * only a warning here because libpng does not care about the
+ * alignment.
+ */
+ (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
+ "ICC profile tag start not a multiple of 4");
+ }
+
+ /* This is a hard error; potentially it can cause read outside the
+ * profile.
+ */
+ if (tag_start > profile_length || tag_length > profile_length - tag_start)
+ return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
+ "ICC profile tag outside profile");
+ }
+
+ return 1; /* success, maybe with warnings */
+}
+
+#ifdef PNG_sRGB_SUPPORTED
+#if PNG_sRGB_PROFILE_CHECKS >= 0
+/* Information about the known ICC sRGB profiles */
+static const struct
+{
+ png_uint_32 adler, crc, length;
+ png_uint_32 md5[4];
+ png_byte have_md5;
+ png_byte is_broken;
+ png_uint_16 intent;
+
+# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
+# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\
+ { adler, crc, length, md5, broke, intent },
+
+} png_sRGB_checks[] =
+{
+ /* This data comes from contrib/tools/checksum-icc run on downloads of
+ * all four ICC sRGB profiles from www.color.org.
+ */
+ /* adler32, crc32, MD5[4], intent, date, length, file-name */
+ PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
+ PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
+ "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
+
+ /* ICC sRGB v2 perceptual no black-compensation: */
+ PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
+ PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
+ "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
+
+ PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
+ PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
+ "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
+
+ /* ICC sRGB v4 perceptual */
+ PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
+ PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
+ "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
+
+ /* The following profiles have no known MD5 checksum. If there is a match
+ * on the (empty) MD5 the other fields are used to attempt a match and
+ * a warning is produced. The first two of these profiles have a 'cprt' tag
+ * which suggests that they were also made by Hewlett Packard.
+ */
+ PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
+ PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
+ "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
+
+ /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
+ * match the D50 PCS illuminant in the header (it is in fact the D65 values,
+ * so the white point is recorded as the un-adapted value.) The profiles
+ * below only differ in one byte - the intent - and are basically the same as
+ * the previous profile except for the mediaWhitePointTag error and a missing
+ * chromaticAdaptationTag.
+ */
+ PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
+ PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
+ "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
+
+ PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
+ PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
+ "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
+};
+
+static int
+png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
+ png_const_bytep profile, uLong adler)
+{
+ /* The quick check is to verify just the MD5 signature and trust the
+ * rest of the data. Because the profile has already been verified for
+ * correctness this is safe. png_colorspace_set_sRGB will check the 'intent'
+ * field too, so if the profile has been edited with an intent not defined
+ * by sRGB (but maybe defined by a later ICC specification) the read of
+ * the profile will fail at that point.
+ */
+
+ png_uint_32 length = 0;
+ png_uint_32 intent = 0x10000; /* invalid */
+#if PNG_sRGB_PROFILE_CHECKS > 1
+ uLong crc = 0; /* the value for 0 length data */
+#endif
+ unsigned int i;
+
+#ifdef PNG_SET_OPTION_SUPPORTED
+ /* First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on" */
+ if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) ==
+ PNG_OPTION_ON)
+ return 0;
+#endif
+
+ for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
+ {
+ if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
+ png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
+ png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
+ png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
+ {
+ /* This may be one of the old HP profiles without an MD5, in that
+ * case we can only use the length and Adler32 (note that these
+ * are not used by default if there is an MD5!)
+ */
+# if PNG_sRGB_PROFILE_CHECKS == 0
+ if (png_sRGB_checks[i].have_md5 != 0)
+ return 1+png_sRGB_checks[i].is_broken;
+# endif
+
+ /* Profile is unsigned or more checks have been configured in. */
+ if (length == 0)
+ {
+ length = png_get_uint_32(profile);
+ intent = png_get_uint_32(profile+64);
+ }
+
+ /* Length *and* intent must match */
+ if (length == (png_uint_32) png_sRGB_checks[i].length &&
+ intent == (png_uint_32) png_sRGB_checks[i].intent)
+ {
+ /* Now calculate the adler32 if not done already. */
+ if (adler == 0)
+ {
+ adler = adler32(0, NULL, 0);
+ adler = adler32(adler, profile, length);
+ }
+
+ if (adler == png_sRGB_checks[i].adler)
+ {
+ /* These basic checks suggest that the data has not been
+ * modified, but if the check level is more than 1 perform
+ * our own crc32 checksum on the data.
+ */
+# if PNG_sRGB_PROFILE_CHECKS > 1
+ if (crc == 0)
+ {
+ crc = crc32(0, NULL, 0);
+ crc = crc32(crc, profile, length);
+ }
+
+ /* So this check must pass for the 'return' below to happen.
+ */
+ if (crc == png_sRGB_checks[i].crc)
+# endif
+ {
+ if (png_sRGB_checks[i].is_broken != 0)
+ {
+ /* These profiles are known to have bad data that may cause
+ * problems if they are used, therefore attempt to
+ * discourage their use, skip the 'have_md5' warning below,
+ * which is made irrelevant by this error.
+ */
+ png_chunk_report(png_ptr, "known incorrect sRGB profile",
+ PNG_CHUNK_ERROR);
+ }
+
+ /* Warn that this being done; this isn't even an error since
+ * the profile is perfectly valid, but it would be nice if
+ * people used the up-to-date ones.
+ */
+ else if (png_sRGB_checks[i].have_md5 == 0)
+ {
+ png_chunk_report(png_ptr,
+ "out-of-date sRGB profile with no signature",
+ PNG_CHUNK_WARNING);
+ }
+
+ return 1+png_sRGB_checks[i].is_broken;
+ }
+ }
+
+# if PNG_sRGB_PROFILE_CHECKS > 0
+ /* The signature matched, but the profile had been changed in some
+ * way. This probably indicates a data error or uninformed hacking.
+ * Fall through to "no match".
+ */
+ png_chunk_report(png_ptr,
+ "Not recognizing known sRGB profile that has been edited",
+ PNG_CHUNK_WARNING);
+ break;
+# endif
+ }
+ }
+ }
+
+ return 0; /* no match */
+}
+#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
+
+void /* PRIVATE */
+png_icc_set_sRGB(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_bytep profile, uLong adler)
+{
+ /* Is this profile one of the known ICC sRGB profiles? If it is, just set
+ * the sRGB information.
+ */
+#if PNG_sRGB_PROFILE_CHECKS >= 0
+ if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
#endif
+ (void)png_colorspace_set_sRGB(png_ptr, colorspace,
+ (int)/*already checked*/png_get_uint_32(profile+64));
+}
+#endif /* sRGB */
+
+int /* PRIVATE */
+png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
+ int color_type)
+{
+ if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+ return 0;
+
+ if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
+ png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
+ color_type) != 0 &&
+ png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
+ profile) != 0)
+ {
+# ifdef PNG_sRGB_SUPPORTED
+ /* If no sRGB support, don't try storing sRGB information */
+ png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
+# endif
+ return 1;
+ }
+
+ /* Failure case */
+ return 0;
+}
+#endif /* iCCP */
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
void /* PRIVATE */
-png_check_IHDR(png_structp png_ptr,
+png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
+{
+ /* Set the rgb_to_gray coefficients from the colorspace. */
+ if (png_ptr->rgb_to_gray_coefficients_set == 0 &&
+ (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+ {
+ /* png_set_background has not been called, get the coefficients from the Y
+ * values of the colorspace colorants.
+ */
+ png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
+ png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
+ png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
+ png_fixed_point total = r+g+b;
+
+ if (total > 0 &&
+ r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
+ g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
+ b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
+ r+g+b <= 32769)
+ {
+ /* We allow 0 coefficients here. r+g+b may be 32769 if two or
+ * all of the coefficients were rounded up. Handle this by
+ * reducing the *largest* coefficient by 1; this matches the
+ * approach used for the default coefficients in pngrtran.c
+ */
+ int add = 0;
+
+ if (r+g+b > 32768)
+ add = -1;
+ else if (r+g+b < 32768)
+ add = 1;
+
+ if (add != 0)
+ {
+ if (g >= r && g >= b)
+ g += add;
+ else if (r >= g && r >= b)
+ r += add;
+ else
+ b += add;
+ }
+
+ /* Check for an internal error. */
+ if (r+g+b != 32768)
+ png_error(png_ptr,
+ "internal error handling cHRM coefficients");
+
+ else
+ {
+ png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r;
+ png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
+ }
+ }
+
+ /* This is a png_error at present even though it could be ignored -
+ * it should never happen, but it is important that if it does, the
+ * bug is fixed.
+ */
+ else
+ png_error(png_ptr, "internal error handling cHRM->XYZ");
+ }
+}
+#endif /* READ_RGB_TO_GRAY */
+
+#endif /* COLORSPACE */
+
+#ifdef __GNUC__
+/* This exists solely to work round a warning from GNU C. */
+static int /* PRIVATE */
+png_gt(size_t a, size_t b)
+{
+ return a > b;
+}
+#else
+# define png_gt(a,b) ((a) > (b))
+#endif
+
+void /* PRIVATE */
+png_check_IHDR(png_const_structrp png_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_type, int compression_type,
int filter_type)
@@ -1180,36 +2491,47 @@ png_check_IHDR(png_structp png_ptr,
error = 1;
}
- if (height == 0)
+ if (width > PNG_UINT_31_MAX)
{
- png_warning(png_ptr, "Image height is zero in IHDR");
+ png_warning(png_ptr, "Invalid image width in IHDR");
error = 1;
}
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
- if (width > png_ptr->user_width_max)
-
-# else
- if (width > PNG_USER_WIDTH_MAX)
-# endif
+ if (png_gt(((width + 7) & (~7)),
+ ((PNG_SIZE_MAX
+ - 48 /* big_row_buf hack */
+ - 1) /* filter byte */
+ / 8) /* 8-byte RGBA pixels */
+ - 1)) /* extra max_pixel_depth pad */
{
- png_warning(png_ptr, "Image width exceeds user limit in IHDR");
+ /* The size of the row must be within the limits of this architecture.
+ * Because the read code can perform arbitrary transformations the
+ * maximum size is checked here. Because the code in png_read_start_row
+ * adds extra space "for safety's sake" in several places a conservative
+ * limit is used here.
+ *
+ * NOTE: it would be far better to check the size that is actually used,
+ * but the effect in the real world is minor and the changes are more
+ * extensive, therefore much more dangerous and much more difficult to
+ * write in a way that avoids compiler warnings.
+ */
+ png_warning(png_ptr, "Image width is too large for this architecture");
error = 1;
}
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
- if (height > png_ptr->user_height_max)
-# else
- if (height > PNG_USER_HEIGHT_MAX)
-# endif
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (width > png_ptr->user_width_max)
+#else
+ if (width > PNG_USER_WIDTH_MAX)
+#endif
{
- png_warning(png_ptr, "Image height exceeds user limit in IHDR");
+ png_warning(png_ptr, "Image width exceeds user limit in IHDR");
error = 1;
}
- if (width > PNG_UINT_31_MAX)
+ if (height == 0)
{
- png_warning(png_ptr, "Invalid image width in IHDR");
+ png_warning(png_ptr, "Image height is zero in IHDR");
error = 1;
}
@@ -1219,13 +2541,15 @@ png_check_IHDR(png_structp png_ptr,
error = 1;
}
- if (width > (PNG_UINT_32_MAX
- >> 3) /* 8-byte RGBA pixels */
- - 48 /* bigrowbuf hack */
- - 1 /* filter byte */
- - 7*8 /* rounding of width to multiple of 8 pixels */
- - 8) /* extra max_pixel_depth pad */
- png_warning(png_ptr, "Width is too large for libpng to process pixels");
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (height > png_ptr->user_height_max)
+#else
+ if (height > PNG_USER_HEIGHT_MAX)
+#endif
+ {
+ png_warning(png_ptr, "Image height exceeds user limit in IHDR");
+ error = 1;
+ }
/* Check other values */
if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
@@ -1263,7 +2587,7 @@ png_check_IHDR(png_structp png_ptr,
error = 1;
}
-# ifdef PNG_MNG_FEATURES_SUPPORTED
+#ifdef PNG_MNG_FEATURES_SUPPORTED
/* Accept filter_method 64 (intrapixel differencing) only if
* 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
* 2. Libpng did not read a PNG signature (this filter_method is only
@@ -1273,13 +2597,13 @@ png_check_IHDR(png_structp png_ptr,
* 4. The filter_method is 64 and
* 5. The color_type is RGB or RGBA
*/
- if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&
- png_ptr->mng_features_permitted)
+ if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 &&
+ png_ptr->mng_features_permitted != 0)
png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
if (filter_type != PNG_FILTER_TYPE_BASE)
{
- if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
(color_type == PNG_COLOR_TYPE_RGB ||
@@ -1289,20 +2613,20 @@ png_check_IHDR(png_structp png_ptr,
error = 1;
}
- if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE)
+ if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0)
{
png_warning(png_ptr, "Invalid filter method in IHDR");
error = 1;
}
}
-# else
+#else
if (filter_type != PNG_FILTER_TYPE_BASE)
{
png_warning(png_ptr, "Unknown filter method in IHDR");
error = 1;
}
-# endif
+#endif
if (error == 1)
png_error(png_ptr, "Invalid IHDR data");
@@ -1349,7 +2673,7 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
{
case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
- if (state & PNG_FP_SAW_ANY)
+ if ((state & PNG_FP_SAW_ANY) != 0)
goto PNG_FP_End; /* not a part of the number */
png_fp_add(state, type);
@@ -1357,10 +2681,10 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
/* Ok as trailer, ok as lead of fraction. */
- if (state & PNG_FP_SAW_DOT) /* two dots */
+ if ((state & PNG_FP_SAW_DOT) != 0) /* two dots */
goto PNG_FP_End;
- else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */
+ else if ((state & PNG_FP_SAW_DIGIT) != 0) /* trailing dot? */
png_fp_add(state, type);
else
@@ -1369,7 +2693,7 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
break;
case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
- if (state & PNG_FP_SAW_DOT) /* delayed fraction */
+ if ((state & PNG_FP_SAW_DOT) != 0) /* delayed fraction */
png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
png_fp_add(state, type | PNG_FP_WAS_VALID);
@@ -1407,7 +2731,7 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
break;
case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
- if (state & PNG_FP_SAW_ANY)
+ if ((state & PNG_FP_SAW_ANY) != 0)
goto PNG_FP_End; /* not a part of the number */
png_fp_add(state, PNG_FP_SAW_SIGN);
@@ -1450,15 +2774,15 @@ png_check_fp_string(png_const_charp string, png_size_t size)
int state=0;
png_size_t char_index=0;
- if (png_check_fp_number(string, size, &state, &char_index) &&
+ if (png_check_fp_number(string, size, &state, &char_index) != 0 &&
(char_index == size || string[char_index] == 0))
return state /* must be non-zero - see above */;
return 0; /* i.e. fail */
}
-#endif /* pCAL or sCAL */
+#endif /* pCAL || sCAL */
-#ifdef PNG_READ_sCAL_SUPPORTED
+#ifdef PNG_sCAL_SUPPORTED
# ifdef PNG_FLOATING_POINT_SUPPORTED
/* Utility used below - a simple accurate power of ten from an integral
* exponent.
@@ -1490,7 +2814,7 @@ png_pow10(int power)
}
while (power > 0);
- if (recip) d = 1/d;
+ if (recip != 0) d = 1/d;
}
/* else power is 0 and d is 1 */
@@ -1501,7 +2825,7 @@ png_pow10(int power)
* precision.
*/
void /* PRIVATE */
-png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
+png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
double fp, unsigned int precision)
{
/* We use standard functions from math.h, but not printf because
@@ -1528,7 +2852,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
if (fp >= DBL_MIN && fp <= DBL_MAX)
{
- int exp_b10; /* A base 10 exponent */
+ int exp_b10; /* A base 10 exponent */
double base; /* 10^exp_b10 */
/* First extract a base 10 exponent of the number,
@@ -1576,7 +2900,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
*/
{
- int czero, clead, cdigits;
+ unsigned int czero, clead, cdigits;
char exponent[10];
/* Allow up to two leading zeros - this will not lengthen
@@ -1606,7 +2930,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
* of the loop don't break the number into parts so
* that the final digit is rounded.
*/
- if (cdigits+czero-clead+1 < (int)precision)
+ if (cdigits+czero+1 < precision+clead)
fp = modf(fp, &d);
else
@@ -1704,21 +3028,22 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
if (exp_b10 != (-1))
{
- if (exp_b10 == 0) *ascii++ = 46, --size; /* counted
- above */
+ if (exp_b10 == 0)
+ *ascii++ = 46, --size; /* counted above */
+
--exp_b10;
}
*ascii++ = (char)(48 + (int)d), ++cdigits;
}
}
- while (cdigits+czero-clead < (int)precision && fp > DBL_MIN);
+ while (cdigits+czero < precision+clead && fp > DBL_MIN);
/* The total output count (max) is now 4+precision */
/* Check for an exponent, if we don't need one we are
* done and just need to terminate the string. At
* this point exp_b10==(-1) is effectively if flag - it got
- * to '-1' because of the decrement after outputing
+ * to '-1' because of the decrement after outputting
* the decimal point above (the exponent required is
* *not* -1!)
*/
@@ -1726,7 +3051,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
{
/* The following only happens if we didn't output the
* leading zeros above for negative exponent, so this
- * doest add to the digit requirement. Note that the
+ * doesn't add to the digit requirement. Note that the
* two zeros here can only be output if the two leading
* zeros were *not* output, so this doesn't increase
* the output count.
@@ -1779,7 +3104,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
/* Need another size check here for the exponent digits, so
* this need not be considered above.
*/
- if ((int)size > cdigits)
+ if (size > cdigits)
{
while (cdigits > 0) *ascii++ = exponent[--cdigits];
@@ -1815,8 +3140,8 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
/* Function to format a fixed point value in ASCII.
*/
void /* PRIVATE */
-png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size,
- png_fixed_point fp)
+png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
+ png_size_t size, png_fixed_point fp)
{
/* Require space for 10 decimal digits, a decimal point, a minus sign and a
* trailing \0, 13 characters:
@@ -1827,7 +3152,7 @@ png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size,
/* Avoid overflow here on the minimum integer. */
if (fp < 0)
- *ascii++ = 45, --size, num = -fp;
+ *ascii++ = 45, num = -fp;
else
num = fp;
@@ -1883,24 +3208,33 @@ png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size,
png_error(png_ptr, "ASCII conversion buffer too small");
}
# endif /* FIXED_POINT */
-#endif /* READ_SCAL */
+#endif /* SCAL */
#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
- !defined(PNG_FIXED_POINT_MACRO_SUPPORTED)
+ !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
+ (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
+ defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
+ (defined(PNG_sCAL_SUPPORTED) && \
+ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
png_fixed_point
-png_fixed(png_structp png_ptr, double fp, png_const_charp text)
+png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
{
double r = floor(100000 * fp + .5);
if (r > 2147483647. || r < -2147483648.)
png_fixed_error(png_ptr, text);
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(text)
+# endif
+
return (png_fixed_point)r;
}
#endif
-#if defined(PNG_READ_GAMMA_SUPPORTED) || \
- defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED)
+#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\
+ defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
/* muldiv functions */
/* This API takes signed arguments and rounds the result to the nearest
* integer (or, for a fixed point number - the standard argument - to
@@ -2004,11 +3338,12 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
if (s00 >= (D >> 1))
++result;
- if (negative)
+ if (negative != 0)
result = -result;
/* Check for overflow. */
- if ((negative && result <= 0) || (!negative && result >= 0))
+ if ((negative != 0 && result <= 0) ||
+ (negative == 0 && result >= 0))
{
*res = result;
return 1;
@@ -2027,12 +3362,12 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
* result.
*/
png_fixed_point
-png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times,
+png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times,
png_int_32 divisor)
{
png_fixed_point result;
- if (png_muldiv(&result, a, times, divisor))
+ if (png_muldiv(&result, a, times, divisor) != 0)
return result;
png_warning(png_ptr, "fixed point overflow ignored");
@@ -2040,7 +3375,7 @@ png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times,
}
#endif
-#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */
+#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */
/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
png_fixed_point
png_reciprocal(png_fixed_point a)
@@ -2053,13 +3388,26 @@ png_reciprocal(png_fixed_point a)
#else
png_fixed_point res;
- if (png_muldiv(&res, 100000, 100000, a))
+ if (png_muldiv(&res, 100000, 100000, a) != 0)
return res;
#endif
return 0; /* error/overflow */
}
+/* This is the shared test on whether a gamma value is 'significant' - whether
+ * it is worth doing gamma correction.
+ */
+int /* PRIVATE */
+png_gamma_significant(png_fixed_point gamma_val)
+{
+ return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
+ gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
+}
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+#ifdef PNG_16BIT_SUPPORTED
/* A local convenience routine. */
static png_fixed_point
png_product2(png_fixed_point a, png_fixed_point b)
@@ -2075,12 +3423,13 @@ png_product2(png_fixed_point a, png_fixed_point b)
#else
png_fixed_point res;
- if (png_muldiv(&res, a, b, 100000))
+ if (png_muldiv(&res, a, b, 100000) != 0)
return res;
#endif
return 0; /* overflow */
}
+#endif /* 16BIT */
/* The inverse of the above. */
png_fixed_point
@@ -2088,12 +3437,15 @@ png_reciprocal2(png_fixed_point a, png_fixed_point b)
{
/* The required result is 1/a * 1/b; the following preserves accuracy. */
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
- double r = 1E15/a;
- r /= b;
- r = floor(r+.5);
+ if (a != 0 && b != 0)
+ {
+ double r = 1E15/a;
+ r /= b;
+ r = floor(r+.5);
- if (r <= 2147483647. && r >= -2147483648.)
- return (png_fixed_point)r;
+ if (r <= 2147483647. && r >= -2147483648.)
+ return (png_fixed_point)r;
+ }
#else
/* This may overflow because the range of png_fixed_point isn't symmetric,
* but this API is only used for the product of file and screen gamma so it
@@ -2110,73 +3462,28 @@ png_reciprocal2(png_fixed_point a, png_fixed_point b)
}
#endif /* READ_GAMMA */
-#ifdef PNG_CHECK_cHRM_SUPPORTED
-/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2,
- * 2010: moved from pngset.c) */
-/*
- * Multiply two 32-bit numbers, V1 and V2, using 32-bit
- * arithmetic, to produce a 64-bit result in the HI/LO words.
- *
- * A B
- * x C D
- * ------
- * AD || BD
- * AC || CB || 0
- *
- * where A and B are the high and low 16-bit words of V1,
- * C and D are the 16-bit words of V2, AD is the product of
- * A and D, and X || Y is (X << 16) + Y.
-*/
-
-void /* PRIVATE */
-png_64bit_product (long v1, long v2, unsigned long *hi_product,
- unsigned long *lo_product)
-{
- int a, b, c, d;
- long lo, hi, x, y;
-
- a = (v1 >> 16) & 0xffff;
- b = v1 & 0xffff;
- c = (v2 >> 16) & 0xffff;
- d = v2 & 0xffff;
-
- lo = b * d; /* BD */
- x = a * d + c * b; /* AD + CB */
- y = ((lo >> 16) & 0xffff) + x;
-
- lo = (lo & 0xffff) | ((y & 0xffff) << 16);
- hi = (y >> 16) & 0xffff;
-
- hi += a * c; /* AC */
-
- *hi_product = (unsigned long)hi;
- *lo_product = (unsigned long)lo;
-}
-#endif /* CHECK_cHRM */
-
#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */
#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* Fixed point gamma.
*
+ * The code to calculate the tables used below can be found in the shell script
+ * contrib/tools/intgamma.sh
+ *
* To calculate gamma this code implements fast log() and exp() calls using only
* fixed point arithmetic. This code has sufficient precision for either 8-bit
* or 16-bit sample values.
*
* The tables used here were calculated using simple 'bc' programs, but C double
- * precision floating point arithmetic would work fine. The programs are given
- * at the head of each table.
+ * precision floating point arithmetic would work fine.
*
* 8-bit log table
* This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
* 255, so it's the base 2 logarithm of a normalized 8-bit floating point
* mantissa. The numbers are 32-bit fractions.
*/
-static png_uint_32
+static const png_uint_32
png_8bit_l2[128] =
{
-# ifdef PNG_DO_BC
- for (i=128;i<256;++i) { .5 - l(i/255)/l(2)*65536*65536; }
-# else
4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
@@ -2199,7 +3506,6 @@ png_8bit_l2[128] =
324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
24347096U, 0U
-# endif
#if 0
/* The following are the values for 16-bit tables - these work fine for the
@@ -2222,18 +3528,18 @@ png_8bit_l2[128] =
#endif
};
-PNG_STATIC png_int_32
+static png_int_32
png_log8bit(unsigned int x)
{
unsigned int lg2 = 0;
/* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
* because the log is actually negate that means adding 1. The final
* returned value thus has the range 0 (for 255 input) to 7.994 (for 1
- * input), return 7.99998 for the overflow (log 0) case - so the result is
+ * input), return -1 for the overflow (log 0) case, - so the result is
* always at most 19 bits.
*/
if ((x &= 0xff) == 0)
- return 0xffffffff;
+ return -1;
if ((x & 0xf0) == 0)
lg2 = 4, x <<= 4;
@@ -2278,14 +3584,15 @@ png_log8bit(unsigned int x)
* Zero (257): 0
* End (258): 23499
*/
-PNG_STATIC png_int_32
+#ifdef PNG_16BIT_SUPPORTED
+static png_int_32
png_log16bit(png_uint_32 x)
{
unsigned int lg2 = 0;
/* As above, but now the input has 16 bits. */
if ((x &= 0xffff) == 0)
- return 0xffffffff;
+ return -1;
if ((x & 0xff00) == 0)
lg2 = 8, x <<= 8;
@@ -2328,13 +3635,14 @@ png_log16bit(png_uint_32 x)
/* Safe, because the result can't have more than 20 bits: */
return (png_int_32)((lg2 + 2048) >> 12);
}
+#endif /* 16BIT */
/* The 'exp()' case must invert the above, taking a 20-bit fixed point
* logarithmic value and returning a 16 or 8-bit number as appropriate. In
* each case only the low 16 bits are relevant - the fraction - since the
* integer bits (the top 4) simply determine a shift.
*
- * The worst case is the 16-bit distinction between 65535 and 65534, this
+ * The worst case is the 16-bit distinction between 65535 and 65534. This
* requires perhaps spurious accuracy in the decoding of the logarithm to
* distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance
* of getting this accuracy in practice.
@@ -2343,21 +3651,17 @@ png_log16bit(png_uint_32 x)
* frational part of the logarithm by using an accurate 32-bit value from the
* top four fractional bits then multiplying in the remaining bits.
*/
-static png_uint_32
+static const png_uint_32
png_32bit_exp[16] =
{
-# ifdef PNG_DO_BC
- for (i=0;i<16;++i) { .5 + e(-i/16*l(2))*2^32; }
-# else
/* NOTE: the first entry is deliberately set to the maximum 32-bit value. */
4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
2553802834U, 2445529972U, 2341847524U, 2242560872U
-# endif
};
/* Adjustment table; provided to explain the numbers in the code below. */
-#ifdef PNG_DO_BC
+#if 0
for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
11 44937.64284865548751208448
10 45180.98734845585101160448
@@ -2373,13 +3677,13 @@ for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
0 45425.85339951654943850496
#endif
-PNG_STATIC png_uint_32
+static png_uint_32
png_exp(png_fixed_point x)
{
if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
{
/* Obtain a 4-bit approximation */
- png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf];
+ png_uint_32 e = png_32bit_exp[(x >> 12) & 0x0f];
/* Incorporate the low 12 bits - these decrease the returned value by
* multiplying by a number less than 1 if the bit is set. The multiplier
@@ -2421,21 +3725,22 @@ png_exp(png_fixed_point x)
return 0;
}
-PNG_STATIC png_byte
+static png_byte
png_exp8bit(png_fixed_point lg2)
{
/* Get a 32-bit value: */
png_uint_32 x = png_exp(lg2);
- /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the
+ /* Convert the 32-bit value to 0..255 by multiplying by 256-1. Note that the
* second, rounding, step can't overflow because of the first, subtraction,
* step.
*/
x -= x >> 8;
- return (png_byte)((x + 0x7fffffU) >> 24);
+ return (png_byte)(((x + 0x7fffffU) >> 24) & 0xff);
}
-PNG_STATIC png_uint_16
+#ifdef PNG_16BIT_SUPPORTED
+static png_uint_16
png_exp16bit(png_fixed_point lg2)
{
/* Get a 32-bit value: */
@@ -2445,6 +3750,7 @@ png_exp16bit(png_fixed_point lg2)
x -= x >> 16;
return (png_uint_16)((x + 32767U) >> 16);
}
+#endif /* 16BIT */
#endif /* FLOATING_ARITHMETIC */
png_byte
@@ -2453,13 +3759,37 @@ png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
if (value > 0 && value < 255)
{
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
- double r = floor(255*pow(value/255.,gamma_val*.00001)+.5);
+ /* 'value' is unsigned, ANSI-C90 requires the compiler to correctly
+ * convert this to a floating point value. This includes values that
+ * would overflow if 'value' were to be converted to 'int'.
+ *
+ * Apparently GCC, however, does an intermediate conversion to (int)
+ * on some (ARM) but not all (x86) platforms, possibly because of
+ * hardware FP limitations. (E.g. if the hardware conversion always
+ * assumes the integer register contains a signed value.) This results
+ * in ANSI-C undefined behavior for large values.
+ *
+ * Other implementations on the same machine might actually be ANSI-C90
+ * conformant and therefore compile spurious extra code for the large
+ * values.
+ *
+ * We can be reasonably sure that an unsigned to float conversion
+ * won't be faster than an int to float one. Therefore this code
+ * assumes responsibility for the undefined behavior, which it knows
+ * can't happen because of the check above.
+ *
+ * Note the argument to this routine is an (unsigned int) because, on
+ * 16-bit platforms, it is assigned a value which might be out of
+ * range for an (int); that would result in undefined behavior in the
+ * caller if the *argument* ('value') were to be declared (int).
+ */
+ double r = floor(255*pow((int)/*SAFE*/value/255.,gamma_val*.00001)+.5);
return (png_byte)r;
# else
png_int_32 lg2 = png_log8bit(value);
png_fixed_point res;
- if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
+ if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
return png_exp8bit(res);
/* Overflow. */
@@ -2467,22 +3797,29 @@ png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
# endif
}
- return (png_byte)value;
+ return (png_byte)(value & 0xff);
}
+#ifdef PNG_16BIT_SUPPORTED
png_uint_16
png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
{
if (value > 0 && value < 65535)
{
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
- double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5);
+ /* The same (unsigned int)->(double) constraints apply here as above,
+ * however in this case the (unsigned int) to (int) conversion can
+ * overflow on an ANSI-C90 compliant system so the cast needs to ensure
+ * that this is not possible.
+ */
+ double r = floor(65535*pow((png_int_32)value/65535.,
+ gamma_val*.00001)+.5);
return (png_uint_16)r;
# else
png_int_32 lg2 = png_log16bit(value);
png_fixed_point res;
- if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
+ if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
return png_exp16bit(res);
/* Overflow. */
@@ -2492,6 +3829,7 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
return (png_uint_16)value;
}
+#endif /* 16BIT */
/* This does the right thing based on the bit_depth field of the
* png_struct, interpreting values as 8-bit or 16-bit. While the result
@@ -2499,28 +3837,24 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
* 8-bit (as are the arguments.)
*/
png_uint_16 /* PRIVATE */
-png_gamma_correct(png_structp png_ptr, unsigned int value,
+png_gamma_correct(png_structrp png_ptr, unsigned int value,
png_fixed_point gamma_val)
{
if (png_ptr->bit_depth == 8)
return png_gamma_8bit_correct(value, gamma_val);
+#ifdef PNG_16BIT_SUPPORTED
else
return png_gamma_16bit_correct(value, gamma_val);
+#else
+ /* should not reach this */
+ return 0;
+#endif /* 16BIT */
}
-/* This is the shared test on whether a gamma value is 'significant' - whether
- * it is worth doing gamma correction.
- */
-int /* PRIVATE */
-png_gamma_significant(png_fixed_point gamma_val)
-{
- return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
- gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
-}
-
+#ifdef PNG_16BIT_SUPPORTED
/* Internal function to build a single 16-bit table - the table consists of
- * 'num' 256-entry subtables, where 'num' is determined by 'shift' - the amount
+ * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
* to shift the input values right (or 16-number_of_signifiant_bits).
*
* The caller is responsible for ensuring that the table gets cleaned up on
@@ -2528,27 +3862,33 @@ png_gamma_significant(png_fixed_point gamma_val)
* should be somewhere that will be cleaned.
*/
static void
-png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
+png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
{
/* Various values derived from 'shift': */
PNG_CONST unsigned int num = 1U << (8U - shift);
+#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+ /* CSE the division and work round wacky GCC warnings (see the comments
+ * in png_gamma_8bit_correct for where these come from.)
+ */
+ PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1);
+#endif
PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
PNG_CONST unsigned int max_by_2 = 1U << (15U-shift);
unsigned int i;
png_uint_16pp table = *ptable =
- (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p));
+ (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
for (i = 0; i < num; i++)
{
png_uint_16p sub_table = table[i] =
- (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16));
+ (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16)));
/* The 'threshold' test is repeated here because it can arise for one of
* the 16-bit tables even if the others don't hit it.
*/
- if (png_gamma_significant(gamma_val))
+ if (png_gamma_significant(gamma_val) != 0)
{
/* The old code would overflow at the end and this would cause the
* 'pow' function to return a result >1, resulting in an
@@ -2564,10 +3904,13 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
png_uint_32 ig = (j << (8-shift)) + i;
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* Inline the 'max' scaling operation: */
- double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5);
+ /* See png_gamma_8bit_correct for why the cast to (int) is
+ * required here.
+ */
+ double d = floor(65535.*pow(ig*fmax, gamma_val*.00001)+.5);
sub_table[j] = (png_uint_16)d;
# else
- if (shift)
+ if (shift != 0)
ig = (ig * 65535U + max_by_2)/max;
sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
@@ -2583,7 +3926,7 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
{
png_uint_32 ig = (j << (8-shift)) + i;
- if (shift)
+ if (shift != 0)
ig = (ig * 65535U + max_by_2)/max;
sub_table[j] = (png_uint_16)ig;
@@ -2596,7 +3939,7 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
* required.
*/
static void
-png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
+png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
{
PNG_CONST unsigned int num = 1U << (8U - shift);
@@ -2605,15 +3948,15 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
png_uint_32 last;
png_uint_16pp table = *ptable =
- (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p));
+ (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
- /* 'num' is the number of tables and also the number of low bits of the
- * input 16-bit value used to select a table. Each table is itself indexed
- * by the high 8 bits of the value.
+ /* 'num' is the number of tables and also the number of low bits of low
+ * bits of the input 16-bit value used to select a table. Each table is
+ * itself indexed by the high 8 bits of the value.
*/
for (i = 0; i < num; i++)
table[i] = (png_uint_16p)png_malloc(png_ptr,
- 256 * png_sizeof(png_uint_16));
+ 256 * (sizeof (png_uint_16)));
/* 'gamma_val' is set to the reciprocal of the value calculated above, so
* pow(out,g) is an *input* value. 'last' is the last input value set.
@@ -2657,34 +4000,38 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
last++;
}
}
+#endif /* 16BIT */
/* Build a single 8-bit table: same as the 16-bit case but much simpler (and
* typically much faster). Note that libpng currently does no sBIT processing
* (apparently contrary to the spec) so a 256-entry table is always generated.
*/
static void
-png_build_8bit_table(png_structp png_ptr, png_bytepp ptable,
+png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
PNG_CONST png_fixed_point gamma_val)
{
unsigned int i;
png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
- if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++)
- table[i] = png_gamma_8bit_correct(i, gamma_val);
+ if (png_gamma_significant(gamma_val) != 0)
+ for (i=0; i<256; i++)
+ table[i] = png_gamma_8bit_correct(i, gamma_val);
- else for (i=0; i<256; ++i)
- table[i] = (png_byte)i;
+ else
+ for (i=0; i<256; ++i)
+ table[i] = (png_byte)(i & 0xff);
}
/* Used from png_read_destroy and below to release the memory used by the gamma
* tables.
*/
void /* PRIVATE */
-png_destroy_gamma_table(png_structp png_ptr)
+png_destroy_gamma_table(png_structrp png_ptr)
{
png_free(png_ptr, png_ptr->gamma_table);
png_ptr->gamma_table = NULL;
+#ifdef PNG_16BIT_SUPPORTED
if (png_ptr->gamma_16_table != NULL)
{
int i;
@@ -2696,6 +4043,7 @@ png_destroy_gamma_table(png_structp png_ptr)
png_free(png_ptr, png_ptr->gamma_16_table);
png_ptr->gamma_16_table = NULL;
}
+#endif /* 16BIT */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
@@ -2705,6 +4053,7 @@ png_destroy_gamma_table(png_structp png_ptr)
png_free(png_ptr, png_ptr->gamma_to_1);
png_ptr->gamma_to_1 = NULL;
+#ifdef PNG_16BIT_SUPPORTED
if (png_ptr->gamma_16_from_1 != NULL)
{
int i;
@@ -2727,6 +4076,7 @@ png_destroy_gamma_table(png_structp png_ptr)
png_free(png_ptr, png_ptr->gamma_16_to_1);
png_ptr->gamma_16_to_1 = NULL;
}
+#endif /* 16BIT */
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
}
@@ -2736,7 +4086,7 @@ png_destroy_gamma_table(png_structp png_ptr)
* we don't need to allocate > 64K chunks for a full 16-bit table.
*/
void /* PRIVATE */
-png_build_gamma_table(png_structp png_ptr, int bit_depth)
+png_build_gamma_table(png_structrp png_ptr, int bit_depth)
{
png_debug(1, "in png_build_gamma_table");
@@ -2755,28 +4105,29 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
if (bit_depth <= 8)
{
png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
- png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma,
+ png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma) : PNG_FP_1);
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
- if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
+ if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
{
png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
- png_reciprocal(png_ptr->gamma));
+ png_reciprocal(png_ptr->colorspace.gamma));
png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
- png_ptr->gamma/* Probably doing rgb_to_gray */);
+ png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
}
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
}
+#ifdef PNG_16BIT_SUPPORTED
else
{
png_byte shift, sig_bit;
- if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
sig_bit = png_ptr->sig_bit.red;
@@ -2808,12 +4159,13 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
*
*/
if (sig_bit > 0 && sig_bit < 16U)
- shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */
+ /* shift == insignificant bits */
+ shift = (png_byte)((16U - sig_bit) & 0xff);
else
shift = 0; /* keep all 16 bits */
- if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
+ if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
{
/* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
* the significant bits in the *input* when the output will
@@ -2828,32 +4180,28 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
png_ptr->gamma_shift = shift;
-#ifdef PNG_16BIT_SUPPORTED
/* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
* PNG_COMPOSE). This effectively smashed the background calculation for
* 16-bit output because the 8-bit table assumes the result will be reduced
* to 8 bits.
*/
- if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
-#endif
+ if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
- png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma,
+ png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma) : PNG_FP_1);
-#ifdef PNG_16BIT_SUPPORTED
else
png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
- png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma,
+ png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma) : PNG_FP_1);
-#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
- if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
+ if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
{
png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
- png_reciprocal(png_ptr->gamma));
+ png_reciprocal(png_ptr->colorspace.gamma));
/* Notice that the '16 from 1' table should be full precision, however
* the lookup on this table still uses gamma_shift, so it can't be.
@@ -2861,10 +4209,291 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
*/
png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
- png_ptr->gamma/* Probably doing rgb_to_gray */);
+ png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
}
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
}
+#endif /* 16BIT */
}
#endif /* READ_GAMMA */
-#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+
+/* HARDWARE OR SOFTWARE OPTION SUPPORT */
+#ifdef PNG_SET_OPTION_SUPPORTED
+int PNGAPI
+png_set_option(png_structrp png_ptr, int option, int onoff)
+{
+ if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT &&
+ (option & 1) == 0)
+ {
+ int mask = 3 << option;
+ int setting = (2 + (onoff != 0)) << option;
+ int current = png_ptr->options;
+
+ png_ptr->options = (png_byte)(((current & ~mask) | setting) & 0xff);
+
+ return (current & mask) >> option;
+ }
+
+ return PNG_OPTION_INVALID;
+}
+#endif
+
+/* sRGB support */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+/* sRGB conversion tables; these are machine generated with the code in
+ * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the
+ * specification (see the article at http://en.wikipedia.org/wiki/SRGB)
+ * is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
+ * The sRGB to linear table is exact (to the nearest 16-bit linear fraction).
+ * The inverse (linear to sRGB) table has accuracies as follows:
+ *
+ * For all possible (255*65535+1) input values:
+ *
+ * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact
+ *
+ * For the input values corresponding to the 65536 16-bit values:
+ *
+ * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact
+ *
+ * In all cases the inexact readings are only off by one.
+ */
+
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+/* The convert-to-sRGB table is only currently required for read. */
+const png_uint_16 png_sRGB_table[256] =
+{
+ 0,20,40,60,80,99,119,139,
+ 159,179,199,219,241,264,288,313,
+ 340,367,396,427,458,491,526,562,
+ 599,637,677,718,761,805,851,898,
+ 947,997,1048,1101,1156,1212,1270,1330,
+ 1391,1453,1517,1583,1651,1720,1790,1863,
+ 1937,2013,2090,2170,2250,2333,2418,2504,
+ 2592,2681,2773,2866,2961,3058,3157,3258,
+ 3360,3464,3570,3678,3788,3900,4014,4129,
+ 4247,4366,4488,4611,4736,4864,4993,5124,
+ 5257,5392,5530,5669,5810,5953,6099,6246,
+ 6395,6547,6700,6856,7014,7174,7335,7500,
+ 7666,7834,8004,8177,8352,8528,8708,8889,
+ 9072,9258,9445,9635,9828,10022,10219,10417,
+ 10619,10822,11028,11235,11446,11658,11873,12090,
+ 12309,12530,12754,12980,13209,13440,13673,13909,
+ 14146,14387,14629,14874,15122,15371,15623,15878,
+ 16135,16394,16656,16920,17187,17456,17727,18001,
+ 18277,18556,18837,19121,19407,19696,19987,20281,
+ 20577,20876,21177,21481,21787,22096,22407,22721,
+ 23038,23357,23678,24002,24329,24658,24990,25325,
+ 25662,26001,26344,26688,27036,27386,27739,28094,
+ 28452,28813,29176,29542,29911,30282,30656,31033,
+ 31412,31794,32179,32567,32957,33350,33745,34143,
+ 34544,34948,35355,35764,36176,36591,37008,37429,
+ 37852,38278,38706,39138,39572,40009,40449,40891,
+ 41337,41785,42236,42690,43147,43606,44069,44534,
+ 45002,45473,45947,46423,46903,47385,47871,48359,
+ 48850,49344,49841,50341,50844,51349,51858,52369,
+ 52884,53401,53921,54445,54971,55500,56032,56567,
+ 57105,57646,58190,58737,59287,59840,60396,60955,
+ 61517,62082,62650,63221,63795,64372,64952,65535
+};
+#endif /* SIMPLIFIED_READ */
+
+/* The base/delta tables are required for both read and write (but currently
+ * only the simplified versions.)
+ */
+const png_uint_16 png_sRGB_base[512] =
+{
+ 128,1782,3383,4644,5675,6564,7357,8074,
+ 8732,9346,9921,10463,10977,11466,11935,12384,
+ 12816,13233,13634,14024,14402,14769,15125,15473,
+ 15812,16142,16466,16781,17090,17393,17690,17981,
+ 18266,18546,18822,19093,19359,19621,19879,20133,
+ 20383,20630,20873,21113,21349,21583,21813,22041,
+ 22265,22487,22707,22923,23138,23350,23559,23767,
+ 23972,24175,24376,24575,24772,24967,25160,25352,
+ 25542,25730,25916,26101,26284,26465,26645,26823,
+ 27000,27176,27350,27523,27695,27865,28034,28201,
+ 28368,28533,28697,28860,29021,29182,29341,29500,
+ 29657,29813,29969,30123,30276,30429,30580,30730,
+ 30880,31028,31176,31323,31469,31614,31758,31902,
+ 32045,32186,32327,32468,32607,32746,32884,33021,
+ 33158,33294,33429,33564,33697,33831,33963,34095,
+ 34226,34357,34486,34616,34744,34873,35000,35127,
+ 35253,35379,35504,35629,35753,35876,35999,36122,
+ 36244,36365,36486,36606,36726,36845,36964,37083,
+ 37201,37318,37435,37551,37668,37783,37898,38013,
+ 38127,38241,38354,38467,38580,38692,38803,38915,
+ 39026,39136,39246,39356,39465,39574,39682,39790,
+ 39898,40005,40112,40219,40325,40431,40537,40642,
+ 40747,40851,40955,41059,41163,41266,41369,41471,
+ 41573,41675,41777,41878,41979,42079,42179,42279,
+ 42379,42478,42577,42676,42775,42873,42971,43068,
+ 43165,43262,43359,43456,43552,43648,43743,43839,
+ 43934,44028,44123,44217,44311,44405,44499,44592,
+ 44685,44778,44870,44962,45054,45146,45238,45329,
+ 45420,45511,45601,45692,45782,45872,45961,46051,
+ 46140,46229,46318,46406,46494,46583,46670,46758,
+ 46846,46933,47020,47107,47193,47280,47366,47452,
+ 47538,47623,47709,47794,47879,47964,48048,48133,
+ 48217,48301,48385,48468,48552,48635,48718,48801,
+ 48884,48966,49048,49131,49213,49294,49376,49458,
+ 49539,49620,49701,49782,49862,49943,50023,50103,
+ 50183,50263,50342,50422,50501,50580,50659,50738,
+ 50816,50895,50973,51051,51129,51207,51285,51362,
+ 51439,51517,51594,51671,51747,51824,51900,51977,
+ 52053,52129,52205,52280,52356,52432,52507,52582,
+ 52657,52732,52807,52881,52956,53030,53104,53178,
+ 53252,53326,53400,53473,53546,53620,53693,53766,
+ 53839,53911,53984,54056,54129,54201,54273,54345,
+ 54417,54489,54560,54632,54703,54774,54845,54916,
+ 54987,55058,55129,55199,55269,55340,55410,55480,
+ 55550,55620,55689,55759,55828,55898,55967,56036,
+ 56105,56174,56243,56311,56380,56448,56517,56585,
+ 56653,56721,56789,56857,56924,56992,57059,57127,
+ 57194,57261,57328,57395,57462,57529,57595,57662,
+ 57728,57795,57861,57927,57993,58059,58125,58191,
+ 58256,58322,58387,58453,58518,58583,58648,58713,
+ 58778,58843,58908,58972,59037,59101,59165,59230,
+ 59294,59358,59422,59486,59549,59613,59677,59740,
+ 59804,59867,59930,59993,60056,60119,60182,60245,
+ 60308,60370,60433,60495,60558,60620,60682,60744,
+ 60806,60868,60930,60992,61054,61115,61177,61238,
+ 61300,61361,61422,61483,61544,61605,61666,61727,
+ 61788,61848,61909,61969,62030,62090,62150,62211,
+ 62271,62331,62391,62450,62510,62570,62630,62689,
+ 62749,62808,62867,62927,62986,63045,63104,63163,
+ 63222,63281,63340,63398,63457,63515,63574,63632,
+ 63691,63749,63807,63865,63923,63981,64039,64097,
+ 64155,64212,64270,64328,64385,64443,64500,64557,
+ 64614,64672,64729,64786,64843,64900,64956,65013,
+ 65070,65126,65183,65239,65296,65352,65409,65465
+};
+
+const png_byte png_sRGB_delta[512] =
+{
+ 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54,
+ 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,
+ 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,
+ 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24,
+ 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,
+ 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,
+ 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,
+ 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,
+ 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,
+ 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,
+ 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
+ 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
+ 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+#endif /* SIMPLIFIED READ/WRITE sRGB support */
+
+/* SIMPLIFIED READ/WRITE SUPPORT */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+static int
+png_image_free_function(png_voidp argument)
+{
+ png_imagep image = png_voidcast(png_imagep, argument);
+ png_controlp cp = image->opaque;
+ png_control c;
+
+ /* Double check that we have a png_ptr - it should be impossible to get here
+ * without one.
+ */
+ if (cp->png_ptr == NULL)
+ return 0;
+
+ /* First free any data held in the control structure. */
+# ifdef PNG_STDIO_SUPPORTED
+ if (cp->owned_file != 0)
+ {
+ FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr);
+ cp->owned_file = 0;
+
+ /* Ignore errors here. */
+ if (fp != NULL)
+ {
+ cp->png_ptr->io_ptr = NULL;
+ (void)fclose(fp);
+ }
+ }
+# endif
+
+ /* Copy the control structure so that the original, allocated, version can be
+ * safely freed. Notice that a png_error here stops the remainder of the
+ * cleanup, but this is probably fine because that would indicate bad memory
+ * problems anyway.
+ */
+ c = *cp;
+ image->opaque = &c;
+ png_free(c.png_ptr, cp);
+
+ /* Then the structures, calling the correct API. */
+ if (c.for_write != 0)
+ {
+# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
+ png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
+# else
+ png_error(c.png_ptr, "simplified write not supported");
+# endif
+ }
+ else
+ {
+# ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+ png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
+# else
+ png_error(c.png_ptr, "simplified read not supported");
+# endif
+ }
+
+ /* Success. */
+ return 1;
+}
+
+void PNGAPI
+png_image_free(png_imagep image)
+{
+ /* Safely call the real function, but only if doing so is safe at this point
+ * (if not inside an error handling context). Otherwise assume
+ * png_safe_execute will call this API after the return.
+ */
+ if (image != NULL && image->opaque != NULL &&
+ image->opaque->error_buf == NULL)
+ {
+ /* Ignore errors here: */
+ (void)png_safe_execute(image, png_image_free_function, image);
+ image->opaque = NULL;
+ }
+}
+
+int /* PRIVATE */
+png_image_error(png_imagep image, png_const_charp error_message)
+{
+ /* Utility to log an error. */
+ png_safecat(image->message, (sizeof image->message), 0, error_message);
+ image->warning_or_error |= PNG_IMAGE_ERROR;
+ png_image_free(image);
+ return 0;
+}
+
+#endif /* SIMPLIFIED READ/WRITE */
+#endif /* READ || WRITE */
diff --git a/thirdparty/libpng/png.h b/thirdparty/libpng/png.h
index 5617c972..123201d3 100644
--- a/thirdparty/libpng/png.h
+++ b/thirdparty/libpng/png.h
@@ -1,8 +1,9 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.5.9 - February 18, 2012
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * libpng version 1.6.21, January 15, 2016
+ *
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -10,189 +11,10 @@
*
* Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
- * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- * libpng versions 0.97, January 1998, through 1.5.9 - February 18, 2012: Glenn
+ * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
+ * libpng versions 0.97, January 1998, through 1.6.21, January 15, 2016:
+ * Glenn Randers-Pehrson.
* See also "Contributing Authors", below.
- *
- * Note about libpng version numbers:
- *
- * Due to various miscommunications, unforeseen code incompatibilities
- * and occasional factors outside the authors' control, version numbering
- * on the library has not always been consistent and straightforward.
- * The following table summarizes matters since version 0.89c, which was
- * the first widely used release:
- *
- * source png.h png.h shared-lib
- * version string int version
- * ------- ------ ----- ----------
- * 0.89c "1.0 beta 3" 0.89 89 1.0.89
- * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90]
- * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95]
- * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96]
- * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97]
- * 0.97c 0.97 97 2.0.97
- * 0.98 0.98 98 2.0.98
- * 0.99 0.99 98 2.0.99
- * 0.99a-m 0.99 99 2.0.99
- * 1.00 1.00 100 2.1.0 [100 should be 10000]
- * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000]
- * 1.0.1 png.h string is 10001 2.1.0
- * 1.0.1a-e identical to the 10002 from here on, the shared library
- * 1.0.2 source version) 10002 is 2.V where V is the source code
- * 1.0.2a-b 10003 version, except as noted.
- * 1.0.3 10003
- * 1.0.3a-d 10004
- * 1.0.4 10004
- * 1.0.4a-f 10005
- * 1.0.5 (+ 2 patches) 10005
- * 1.0.5a-d 10006
- * 1.0.5e-r 10100 (not source compatible)
- * 1.0.5s-v 10006 (not binary compatible)
- * 1.0.6 (+ 3 patches) 10006 (still binary incompatible)
- * 1.0.6d-f 10007 (still binary incompatible)
- * 1.0.6g 10007
- * 1.0.6h 10007 10.6h (testing xy.z so-numbering)
- * 1.0.6i 10007 10.6i
- * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0)
- * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible)
- * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible)
- * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
- * 1.0.7 1 10007 (still compatible)
- * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4
- * 1.0.8rc1 1 10008 2.1.0.8rc1
- * 1.0.8 1 10008 2.1.0.8
- * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6
- * 1.0.9rc1 1 10009 2.1.0.9rc1
- * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10
- * 1.0.9rc2 1 10009 2.1.0.9rc2
- * 1.0.9 1 10009 2.1.0.9
- * 1.0.10beta1 1 10010 2.1.0.10beta1
- * 1.0.10rc1 1 10010 2.1.0.10rc1
- * 1.0.10 1 10010 2.1.0.10
- * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3
- * 1.0.11rc1 1 10011 2.1.0.11rc1
- * 1.0.11 1 10011 2.1.0.11
- * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2
- * 1.0.12rc1 2 10012 2.1.0.12rc1
- * 1.0.12 2 10012 2.1.0.12
- * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned)
- * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2
- * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5
- * 1.2.0rc1 3 10200 3.1.2.0rc1
- * 1.2.0 3 10200 3.1.2.0
- * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4
- * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2
- * 1.2.1 3 10201 3.1.2.1
- * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6
- * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1
- * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1
- * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1
- * 1.0.13 10 10013 10.so.0.1.0.13
- * 1.2.2 12 10202 12.so.0.1.2.2
- * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6
- * 1.2.3 12 10203 12.so.0.1.2.3
- * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3
- * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1
- * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1
- * 1.0.14 10 10014 10.so.0.1.0.14
- * 1.2.4 13 10204 12.so.0.1.2.4
- * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2
- * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3
- * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3
- * 1.0.15 10 10015 10.so.0.1.0.15
- * 1.2.5 13 10205 12.so.0.1.2.5
- * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4
- * 1.0.16 10 10016 10.so.0.1.0.16
- * 1.2.6 13 10206 12.so.0.1.2.6
- * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2
- * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1
- * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1
- * 1.0.17 10 10017 12.so.0.1.0.17
- * 1.2.7 13 10207 12.so.0.1.2.7
- * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5
- * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5
- * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5
- * 1.0.18 10 10018 12.so.0.1.0.18
- * 1.2.8 13 10208 12.so.0.1.2.8
- * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3
- * 1.2.9beta4-11 13 10209 12.so.0.9[.0]
- * 1.2.9rc1 13 10209 12.so.0.9[.0]
- * 1.2.9 13 10209 12.so.0.9[.0]
- * 1.2.10beta1-7 13 10210 12.so.0.10[.0]
- * 1.2.10rc1-2 13 10210 12.so.0.10[.0]
- * 1.2.10 13 10210 12.so.0.10[.0]
- * 1.4.0beta1-5 14 10400 14.so.0.0[.0]
- * 1.2.11beta1-4 13 10211 12.so.0.11[.0]
- * 1.4.0beta7-8 14 10400 14.so.0.0[.0]
- * 1.2.11 13 10211 12.so.0.11[.0]
- * 1.2.12 13 10212 12.so.0.12[.0]
- * 1.4.0beta9-14 14 10400 14.so.0.0[.0]
- * 1.2.13 13 10213 12.so.0.13[.0]
- * 1.4.0beta15-36 14 10400 14.so.0.0[.0]
- * 1.4.0beta37-87 14 10400 14.so.14.0[.0]
- * 1.4.0rc01 14 10400 14.so.14.0[.0]
- * 1.4.0beta88-109 14 10400 14.so.14.0[.0]
- * 1.4.0rc02-08 14 10400 14.so.14.0[.0]
- * 1.4.0 14 10400 14.so.14.0[.0]
- * 1.4.1beta01-03 14 10401 14.so.14.1[.0]
- * 1.4.1rc01 14 10401 14.so.14.1[.0]
- * 1.4.1beta04-12 14 10401 14.so.14.1[.0]
- * 1.4.1 14 10401 14.so.14.1[.0]
- * 1.4.2 14 10402 14.so.14.2[.0]
- * 1.4.3 14 10403 14.so.14.3[.0]
- * 1.4.4 14 10404 14.so.14.4[.0]
- * 1.5.0beta01-58 15 10500 15.so.15.0[.0]
- * 1.5.0rc01-07 15 10500 15.so.15.0[.0]
- * 1.5.0 15 10500 15.so.15.0[.0]
- * 1.5.1beta01-11 15 10501 15.so.15.1[.0]
- * 1.5.1rc01-02 15 10501 15.so.15.1[.0]
- * 1.5.1 15 10501 15.so.15.1[.0]
- * 1.5.2beta01-03 15 10502 15.so.15.2[.0]
- * 1.5.2rc01-03 15 10502 15.so.15.2[.0]
- * 1.5.2 15 10502 15.so.15.2[.0]
- * 1.5.3beta01-10 15 10503 15.so.15.3[.0]
- * 1.5.3rc01-02 15 10503 15.so.15.3[.0]
- * 1.5.3beta11 15 10503 15.so.15.3[.0]
- * 1.5.3 [omitted]
- * 1.5.4beta01-08 15 10504 15.so.15.4[.0]
- * 1.5.4rc01 15 10504 15.so.15.4[.0]
- * 1.5.4 15 10504 15.so.15.4[.0]
- * 1.5.5beta01-08 15 10505 15.so.15.5[.0]
- * 1.5.5rc01 15 10505 15.so.15.5[.0]
- * 1.5.5 15 10505 15.so.15.5[.0]
- * 1.5.6beta01-07 15 10506 15.so.15.6[.0]
- * 1.5.6rc01-03 15 10506 15.so.15.6[.0]
- * 1.5.6 15 10506 15.so.15.6[.0]
- * 1.5.7beta01-05 15 10507 15.so.15.7[.0]
- * 1.5.7rc01-03 15 10507 15.so.15.7[.0]
- * 1.5.7 15 10507 15.so.15.7[.0]
- * 1.5.8beta01 15 10508 15.so.15.8[.0]
- * 1.5.8rc01 15 10508 15.so.15.8[.0]
- * 1.5.8 15 10508 15.so.15.8[.0]
- * 1.5.9beta01-02 15 10509 15.so.15.9[.0]
- * 1.5.9rc01 15 10509 15.so.15.9[.0]
- * 1.5.9 15 10509 15.so.15.9[.0]
- *
- * Henceforth the source version will match the shared-library major
- * and minor numbers; the shared-library major version number will be
- * used for changes in backward compatibility, as it is intended. The
- * PNG_LIBPNG_VER macro, which is not used within libpng but is available
- * for applications, is an unsigned integer of the form xyyzz corresponding
- * to the source version x.y.z (leading zeros in y and z). Beta versions
- * were given the previous public release number plus a letter, until
- * version 1.0.6j; from then on they were given the upcoming public
- * release number plus "betaNN" or "rcN".
- *
- * Binary incompatibility exists only when applications make direct access
- * to the info_ptr or png_ptr members through png.h, and the compiled
- * application is loaded with a different version of the library.
- *
- * DLLNUM will change each time there are forward or backward changes
- * in binary compatibility (e.g., when a new feature is added).
- *
- * See libpng-manual.txt or libpng.3 for more information. The PNG
- * specification is available as a W3C Recommendation and as an ISO
- * Specification, <http://www.w3.org/TR/2003/REC-PNG-20031110/
*/
/*
@@ -203,21 +25,18 @@
*
* This code is released under the libpng license.
*
- * libpng versions 1.2.6, August 15, 2004, through 1.5.9, February 18, 2012, are
- * Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are
- * distributed according to the same disclaimer and license as libpng-1.2.5
- * with the following individual added to the list of Contributing Authors:
- *
- * Cosmin Truta
- *
- * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are
- * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
- * distributed according to the same disclaimer and license as libpng-1.0.6
- * with the following individuals added to the list of Contributing Authors:
+ * libpng versions 1.0.7, July 1, 2000, through 1.6.21, January 15, 2016, are
+ * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
+ * derived from libpng-1.0.6, and are distributed according to the same
+ * disclaimer and license as libpng-1.0.6 with the following individuals
+ * added to the list of Contributing Authors:
*
* Simon-Pierre Cadieux
* Eric S. Raymond
+ * Mans Rullgard
+ * Cosmin Truta
* Gilles Vollant
+ * James Yu
*
* and with the following additions to the disclaimer:
*
@@ -229,18 +48,20 @@
* the user.
*
* libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
- * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are
- * distributed according to the same disclaimer and license as libpng-0.96,
- * with the following individuals added to the list of Contributing Authors:
+ * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
+ * libpng-0.96, and are distributed according to the same disclaimer and
+ * license as libpng-0.96, with the following individuals added to the list
+ * of Contributing Authors:
*
* Tom Lane
* Glenn Randers-Pehrson
* Willem van Schaik
*
* libpng versions 0.89, June 1996, through 0.96, May 1997, are
- * Copyright (c) 1996, 1997 Andreas Dilger
- * Distributed according to the same disclaimer and license as libpng-0.88,
- * with the following individuals added to the list of Contributing Authors:
+ * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
+ * and are distributed according to the same disclaimer and license as
+ * libpng-0.88, with the following individuals added to the list of
+ * Contributing Authors:
*
* John Bowler
* Kevin Bracey
@@ -250,7 +71,7 @@
* Tom Tanner
*
* libpng versions 0.5, May 1995, through 0.88, January 1996, are
- * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* For the purposes of this copyright and license, "Contributing Authors"
* is defined as the following set of individuals:
@@ -278,29 +99,32 @@
* 2. Altered versions must be plainly marked as such and must not
* be misrepresented as being the original source.
*
- * 3. This Copyright notice may not be removed or altered from
- * any source or altered source distribution.
+ * 3. This Copyright notice may not be removed or altered from any
+ * source or altered source distribution.
*
* The Contributing Authors and Group 42, Inc. specifically permit, without
* fee, and encourage the use of this source code as a component to
* supporting the PNG file format in commercial products. If you use this
* source code in a product, acknowledgment is not required but would be
* appreciated.
+ *
+ * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
*/
/*
* A "png_get_copyright" function is available, for convenient use in "about"
* boxes and the like:
*
- * printf("%s", png_get_copyright(NULL));
+ * printf("%s", png_get_copyright(NULL));
*
* Also, the PNG logo (in PNG format, of course) is supplied in the
* files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
*/
/*
- * Libpng is OSI Certified Open Source Software. OSI Certified is a
- * certification mark of the Open Source Initiative.
+ * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
+ * a certification mark of the Open Source Initiative. OSI has not addressed
+ * the additional disclaimers inserted at version 1.0.7.
*/
/*
@@ -311,32 +135,109 @@
* Thanks to Frank J. T. Wojcik for helping with the documentation.
*/
+/* Note about libpng version numbers:
+ *
+ * Due to various miscommunications, unforeseen code incompatibilities
+ * and occasional factors outside the authors' control, version numbering
+ * on the library has not always been consistent and straightforward.
+ * The following table summarizes matters since version 0.89c, which was
+ * the first widely used release:
+ *
+ * source png.h png.h shared-lib
+ * version string int version
+ * ------- ------ ----- ----------
+ * 0.89c "1.0 beta 3" 0.89 89 1.0.89
+ * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90]
+ * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95]
+ * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96]
+ * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97]
+ * 0.97c 0.97 97 2.0.97
+ * 0.98 0.98 98 2.0.98
+ * 0.99 0.99 98 2.0.99
+ * 0.99a-m 0.99 99 2.0.99
+ * 1.00 1.00 100 2.1.0 [100 should be 10000]
+ * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000]
+ * 1.0.1 png.h string is 10001 2.1.0
+ * 1.0.1a-e identical to the 10002 from here on, the shared library
+ * 1.0.2 source version) 10002 is 2.V where V is the source code
+ * 1.0.2a-b 10003 version, except as noted.
+ * 1.0.3 10003
+ * 1.0.3a-d 10004
+ * 1.0.4 10004
+ * 1.0.4a-f 10005
+ * 1.0.5 (+ 2 patches) 10005
+ * 1.0.5a-d 10006
+ * 1.0.5e-r 10100 (not source compatible)
+ * 1.0.5s-v 10006 (not binary compatible)
+ * 1.0.6 (+ 3 patches) 10006 (still binary incompatible)
+ * 1.0.6d-f 10007 (still binary incompatible)
+ * 1.0.6g 10007
+ * 1.0.6h 10007 10.6h (testing xy.z so-numbering)
+ * 1.0.6i 10007 10.6i
+ * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0)
+ * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible)
+ * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible)
+ * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
+ * 1.0.7 1 10007 (still compatible)
+ * ...
+ * 1.0.19 10 10019 10.so.0.19[.0]
+ * ...
+ * 1.2.53 13 10253 12.so.0.53[.0]
+ * ...
+ * 1.5.23 15 10523 15.so.15.23[.0]
+ * ...
+ * 1.6.21 16 10621 16.so.16.21[.0]
+ *
+ * Henceforth the source version will match the shared-library major
+ * and minor numbers; the shared-library major version number will be
+ * used for changes in backward compatibility, as it is intended. The
+ * PNG_LIBPNG_VER macro, which is not used within libpng but is available
+ * for applications, is an unsigned integer of the form xyyzz corresponding
+ * to the source version x.y.z (leading zeros in y and z). Beta versions
+ * were given the previous public release number plus a letter, until
+ * version 1.0.6j; from then on they were given the upcoming public
+ * release number plus "betaNN" or "rcNN".
+ *
+ * Binary incompatibility exists only when applications make direct access
+ * to the info_ptr or png_ptr members through png.h, and the compiled
+ * application is loaded with a different version of the library.
+ *
+ * DLLNUM will change each time there are forward or backward changes
+ * in binary compatibility (e.g., when a new feature is added).
+ *
+ * See libpng.txt or libpng.3 for more information. The PNG specification
+ * is available as a W3C Recommendation and as an ISO Specification,
+ * <http://www.w3.org/TR/2003/REC-PNG-20031110/
+ */
+
/*
* Y2K compliance in libpng:
* =========================
*
- * February 18, 2012
+ * January 15, 2016
*
* Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration.
*
* This is your unofficial assurance that libpng from version 0.71 and
- * upward through 1.5.9 are Y2K compliant. It is my belief that
+ * upward through 1.6.21 are Y2K compliant. It is my belief that
* earlier versions were also Y2K compliant.
*
* Libpng only has two year fields. One is a 2-byte unsigned integer
- * that will hold years up to 65535. The other holds the date in text
- * format, and will hold years up to 9999.
+ * that will hold years up to 65535. The other, which is deprecated,
+ * holds the date in text format, and will hold years up to 9999.
*
* The integer is
* "png_uint_16 year" in png_time_struct.
*
* The string is
- * "png_char time_buffer" in png_struct
+ * "char time_buffer[29]" in png_struct. This is no longer used
+ * in libpng-1.6.x and will be removed from libpng-1.7.0.
*
* There are seven time-related functions:
- * png.c: png_convert_to_rfc_1123() in png.c
- * (formerly png_convert_to_rfc_1152() in error)
+ * png.c: png_convert_to_rfc_1123_buffer() in png.c
+ * (formerly png_convert_to_rfc_1123() prior to libpng-1.5.x and
+ * png_convert_to_rfc_1152() in error prior to libpng-0.98)
* png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
* png_convert_from_time_t() in pngwrite.c
* png_get_tIME() in pngget.c
@@ -347,8 +248,8 @@
* All handle dates properly in a Y2K environment. The
* png_convert_from_time_t() function calls gmtime() to convert from system
* clock time, which returns (year - 1900), which we properly convert to
- * the full 4-digit year. There is a possibility that applications using
- * libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+ * the full 4-digit year. There is a possibility that libpng applications
+ * are not passing 4-digit years into the png_convert_to_rfc_1123_buffer()
* function, or that they are incorrectly passing only a 2-digit year
* instead of "year - 1900" into the png_convert_from_struct_tm() function,
* but this is not under our control. The libpng documentation has always
@@ -372,24 +273,26 @@
/* This is not the place to learn how to use libpng. The file libpng-manual.txt
* describes how to use libpng, and the file example.c summarizes it
* with some code on which to build. This file is useful for looking
- * at the actual function definitions and structure components.
+ * at the actual function definitions and structure components. If that
+ * file has been stripped from your copy of libpng, you can find it at
+ * <http://www.libpng.org/pub/png/libpng-manual.txt>
*
* If you just need to read a PNG file and don't want to read the documentation
* skip to the end of this file and read the section entitled 'simplified API'.
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.5.9"
+#define PNG_LIBPNG_VER_STRING "1.6.21"
#define PNG_HEADER_VERSION_STRING \
- " libpng version 1.5.9 - February 18, 2012\n"
+ " libpng version 1.6.21 - January 15, 2016\n"
-#define PNG_LIBPNG_VER_SONUM 15
-#define PNG_LIBPNG_VER_DLLNUM 15
+#define PNG_LIBPNG_VER_SONUM 16
+#define PNG_LIBPNG_VER_DLLNUM 16
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
-#define PNG_LIBPNG_VER_MINOR 5
-#define PNG_LIBPNG_VER_RELEASE 9
+#define PNG_LIBPNG_VER_MINOR 6
+#define PNG_LIBPNG_VER_RELEASE 21
/* This should match the numeric part of the final component of
* PNG_LIBPNG_VER_STRING, omitting any leading zero:
@@ -412,7 +315,7 @@
#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with
PNG_LIBPNG_BUILD_PRIVATE */
-#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA
+#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
/* Careful here. At one time, Guy wanted to use 082, but that would be octal.
* We must not include leading zeros.
@@ -420,7 +323,7 @@
* version 1.0.0 was mis-numbered 100 instead of 10000). From
* version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
*/
-#define PNG_LIBPNG_VER 10509 /* 1.5.9 */
+#define PNG_LIBPNG_VER 10621 /* 1.6.21 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -433,25 +336,7 @@
#endif
#ifndef PNG_VERSION_INFO_ONLY
-# ifndef PNG_BUILDING_SYMBOL_TABLE
- /*
- * Standard header files (not needed for the version info or while
- * building symbol table -- see scripts/pnglibconf.dfa)
- */
-# ifdef PNG_SETJMP_SUPPORTED
-# include <setjmp.h>
-# endif
-
- /* Need the time information for converting tIME chunks, it
- * defines struct tm:
- */
-# ifdef PNG_CONVERT_tIME_SUPPORTED
- /* "time.h" functions are not supported on all operating systems */
-# include <time.h>
-# endif
-# endif
-
-/* Machine specific configuration. */
+ /* Machine specific configuration. */
# include "pngconf.h"
#endif
@@ -495,16 +380,22 @@ extern "C" {
/* This file is arranged in several sections:
*
- * 1. Any configuration options that can be specified by for the application
+ * 1. [omitted]
+ * 2. Any configuration options that can be specified by for the application
* code when it is built. (Build time configuration is in pnglibconf.h)
- * 2. Type definitions (base types are defined in pngconf.h), structure
+ * 3. Type definitions (base types are defined in pngconf.h), structure
* definitions.
- * 3. Exported library functions.
+ * 4. Exported library functions.
+ * 5. Simplified API.
+ * 6. Implementation options.
*
* The library source code has additional files (principally pngpriv.h) that
* allow configuration of the library.
*/
-/* Section 1: run time configuration
+
+/* Section 1: [omitted] */
+
+/* Section 2: run time configuration
* See pnglibconf.h for build time configuration
*
* Run time configuration allows the application to choose between
@@ -534,7 +425,7 @@ extern "C" {
* Otherwise the calls are mapped to png_error.
*/
-/* Section 2: type definitions, including structures and compile time
+/* Section 3: type definitions, including structures and compile time
* constants.
* See pngconf.h for base types that vary by machine/system
*/
@@ -542,7 +433,48 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_5_9;
+typedef char* png_libpng_version_1_6_21;
+
+/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
+ *
+ * png_struct is the cache of information used while reading or writing a single
+ * PNG file. One of these is always required, although the simplified API
+ * (below) hides the creation and destruction of it.
+ */
+typedef struct png_struct_def png_struct;
+typedef const png_struct * png_const_structp;
+typedef png_struct * png_structp;
+typedef png_struct * * png_structpp;
+
+/* png_info contains information read from or to be written to a PNG file. One
+ * or more of these must exist while reading or creating a PNG file. The
+ * information is not used by libpng during read but is used to control what
+ * gets written when a PNG file is created. "png_get_" function calls read
+ * information during read and "png_set_" functions calls write information
+ * when creating a PNG.
+ * been moved into a separate header file that is not accessible to
+ * applications. Read libpng-manual.txt or libpng.3 for more info.
+ */
+typedef struct png_info_def png_info;
+typedef png_info * png_infop;
+typedef const png_info * png_const_infop;
+typedef png_info * * png_infopp;
+
+/* Types with names ending 'p' are pointer types. The corresponding types with
+ * names ending 'rp' are identical pointer types except that the pointer is
+ * marked 'restrict', which means that it is the only pointer to the object
+ * passed to the function. Applications should not use the 'restrict' types;
+ * it is always valid to pass 'p' to a pointer with a function argument of the
+ * corresponding 'rp' type. Different compilers have different rules with
+ * regard to type matching in the presence of 'restrict'. For backward
+ * compatibility libpng callbacks never have 'restrict' in their parameters and,
+ * consequentially, writing portable application code is extremely difficult if
+ * an attempt is made to use 'restrict'.
+ */
+typedef png_struct * PNG_RESTRICT png_structrp;
+typedef const png_struct * PNG_RESTRICT png_const_structrp;
+typedef png_info * PNG_RESTRICT png_inforp;
+typedef const png_info * PNG_RESTRICT png_const_inforp;
/* Three color definitions. The order of the red, green, and blue, (and the
* exact size) is not important, although the size of the fields need to
@@ -554,9 +486,9 @@ typedef struct png_color_struct
png_byte green;
png_byte blue;
} png_color;
-typedef png_color FAR * png_colorp;
-typedef PNG_CONST png_color FAR * png_const_colorp;
-typedef png_color FAR * FAR * png_colorpp;
+typedef png_color * png_colorp;
+typedef const png_color * png_const_colorp;
+typedef png_color * * png_colorpp;
typedef struct png_color_16_struct
{
@@ -566,9 +498,9 @@ typedef struct png_color_16_struct
png_uint_16 blue;
png_uint_16 gray; /* for use in grayscale files */
} png_color_16;
-typedef png_color_16 FAR * png_color_16p;
-typedef PNG_CONST png_color_16 FAR * png_const_color_16p;
-typedef png_color_16 FAR * FAR * png_color_16pp;
+typedef png_color_16 * png_color_16p;
+typedef const png_color_16 * png_const_color_16p;
+typedef png_color_16 * * png_color_16pp;
typedef struct png_color_8_struct
{
@@ -578,9 +510,9 @@ typedef struct png_color_8_struct
png_byte gray; /* for use in grayscale files */
png_byte alpha; /* for alpha channel files */
} png_color_8;
-typedef png_color_8 FAR * png_color_8p;
-typedef PNG_CONST png_color_8 FAR * png_const_color_8p;
-typedef png_color_8 FAR * FAR * png_color_8pp;
+typedef png_color_8 * png_color_8p;
+typedef const png_color_8 * png_const_color_8p;
+typedef png_color_8 * * png_color_8pp;
/*
* The following two structures are used for the in-core representation
@@ -594,9 +526,9 @@ typedef struct png_sPLT_entry_struct
png_uint_16 alpha;
png_uint_16 frequency;
} png_sPLT_entry;
-typedef png_sPLT_entry FAR * png_sPLT_entryp;
-typedef PNG_CONST png_sPLT_entry FAR * png_const_sPLT_entryp;
-typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp;
+typedef png_sPLT_entry * png_sPLT_entryp;
+typedef const png_sPLT_entry * png_const_sPLT_entryp;
+typedef png_sPLT_entry * * png_sPLT_entrypp;
/* When the depth of the sPLT palette is 8 bits, the color and alpha samples
* occupy the LSB of their respective members, and the MSB of each member
@@ -610,9 +542,9 @@ typedef struct png_sPLT_struct
png_sPLT_entryp entries; /* palette entries */
png_int_32 nentries; /* number of palette entries */
} png_sPLT_t;
-typedef png_sPLT_t FAR * png_sPLT_tp;
-typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp;
-typedef png_sPLT_t FAR * FAR * png_sPLT_tpp;
+typedef png_sPLT_t * png_sPLT_tp;
+typedef const png_sPLT_t * png_const_sPLT_tp;
+typedef png_sPLT_t * * png_sPLT_tpp;
#ifdef PNG_TEXT_SUPPORTED
/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
@@ -649,9 +581,9 @@ typedef struct png_text_struct
png_charp lang_key; /* keyword translated UTF-8 string, 0 or more
chars or a NULL pointer */
} png_text;
-typedef png_text FAR * png_textp;
-typedef PNG_CONST png_text FAR * png_const_textp;
-typedef png_text FAR * FAR * png_textpp;
+typedef png_text * png_textp;
+typedef const png_text * png_const_textp;
+typedef png_text * * png_textpp;
#endif
/* Supported compression types for text in PNG files (tEXt, and zTXt).
@@ -679,49 +611,45 @@ typedef struct png_time_struct
png_byte minute; /* minute of hour, 0 - 59 */
png_byte second; /* second of minute, 0 - 60 (for leap seconds) */
} png_time;
-typedef png_time FAR * png_timep;
-typedef PNG_CONST png_time FAR * png_const_timep;
-typedef png_time FAR * FAR * png_timepp;
+typedef png_time * png_timep;
+typedef const png_time * png_const_timep;
+typedef png_time * * png_timepp;
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \
- defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\
+ defined(PNG_USER_CHUNKS_SUPPORTED)
/* png_unknown_chunk is a structure to hold queued chunks for which there is
* no specific support. The idea is that we can use this to queue
* up private chunks for output even though the library doesn't actually
* know about their semantics.
+ *
+ * The data in the structure is set by libpng on read and used on write.
*/
typedef struct png_unknown_chunk_t
{
- png_byte name[5];
- png_byte *data;
+ png_byte name[5]; /* Textual chunk name with '\0' terminator */
+ png_byte *data; /* Data, should not be modified on read! */
png_size_t size;
- /* libpng-using applications should NOT directly modify this byte. */
+ /* On write 'location' must be set using the flag values listed below.
+ * Notice that on read it is set by libpng however the values stored have
+ * more bits set than are listed below. Always treat the value as a
+ * bitmask. On write set only one bit - setting multiple bits may cause the
+ * chunk to be written in multiple places.
+ */
png_byte location; /* mode of operation at read time */
}
-
-
png_unknown_chunk;
-typedef png_unknown_chunk FAR * png_unknown_chunkp;
-typedef PNG_CONST png_unknown_chunk FAR * png_const_unknown_chunkp;
-typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp;
-#endif
-/* Values for the unknown chunk location byte */
+typedef png_unknown_chunk * png_unknown_chunkp;
+typedef const png_unknown_chunk * png_const_unknown_chunkp;
+typedef png_unknown_chunk * * png_unknown_chunkpp;
+#endif
+/* Flag values for the unknown chunk location byte. */
#define PNG_HAVE_IHDR 0x01
#define PNG_HAVE_PLTE 0x02
#define PNG_AFTER_IDAT 0x08
-/* The complete definition of png_info has, as of libpng-1.5.0,
- * been moved into a separate header file that is not accessible to
- * applications. Read libpng-manual.txt or libpng.3 for more info.
- */
-typedef struct png_info_def png_info;
-typedef png_info FAR * png_infop;
-typedef PNG_CONST png_info FAR * png_const_infop;
-typedef png_info FAR * FAR * png_infopp;
-
/* Maximum positive integer used in PNG is (2^31)-1 */
#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL)
#define PNG_UINT_32_MAX ((png_uint_32)(-1))
@@ -821,7 +749,9 @@ typedef png_info FAR * FAR * png_infopp;
#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */
#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */
#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */
+#if INT_MAX >= 0x8000 /* else this might break */
#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */
+#endif
/* This is used for the transformation routines, as some of them
* change these values for the row. It also should enable using
@@ -837,16 +767,8 @@ typedef struct png_row_info_struct
png_byte pixel_depth; /* bits per pixel (depth * channels) */
} png_row_info;
-typedef png_row_info FAR * png_row_infop;
-typedef png_row_info FAR * FAR * png_row_infopp;
-
-/* The complete definition of png_struct has, as of libpng-1.5.0,
- * been moved into a separate header file that is not accessible to
- * applications. Read libpng-manual.txt or libpng.3 for more info.
- */
-typedef struct png_struct_def png_struct;
-typedef PNG_CONST png_struct FAR * png_const_structp;
-typedef png_struct FAR * png_structp;
+typedef png_row_info * png_row_infop;
+typedef png_row_info * * png_row_infopp;
/* These are the function types for the I/O functions and for the functions
* that allow the user to override the default I/O functions with his or her
@@ -893,7 +815,8 @@ typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp,
png_unknown_chunkp));
#endif
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
-typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp));
+/* not used anywhere */
+/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */
#endif
#ifdef PNG_SETJMP_SUPPORTED
@@ -932,7 +855,9 @@ PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef);
#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */
/* Added to libpng-1.5.4 */
#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */
+#if INT_MAX >= 0x8000 /* else this might break */
#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */
+#endif
/* Flags for MNG supported features */
#define PNG_FLAG_MNG_EMPTY_PLTE 0x01
@@ -949,9 +874,7 @@ typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp,
png_alloc_size_t));
typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp));
-typedef png_struct FAR * FAR * png_structpp;
-
-/* Section 3: exported functions
+/* Section 4: exported functions
* Here are the function definitions most commonly used. This is not
* the place to find out how to use libpng. See libpng-manual.txt for the
* full explanation, see example.c for the summary. This just provides
@@ -986,7 +909,7 @@ PNG_EXPORT(1, png_uint_32, png_access_version_number, (void));
/* Tell lib we have already handled the first <num_bytes> magic bytes.
* Handling more than 8 bytes from the beginning of the file is an error.
*/
-PNG_EXPORT(2, void, png_set_sig_bytes, (png_structp png_ptr, int num_bytes));
+PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes));
/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
* PNG file. Returns zero if the supplied bytes match the 8-byte PNG
@@ -1014,9 +937,9 @@ PNG_EXPORTA(5, png_structp, png_create_write_struct,
PNG_ALLOCATED);
PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
-PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr,
+PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr,
png_size_t size));
/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp
@@ -1030,10 +953,10 @@ PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr,
* allocated by the library - the call will return NULL on a mismatch
* indicating an ABI mismatch.
*/
-PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr,
+PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr,
png_longjmp_ptr longjmp_fn, size_t jmp_buf_size));
# define png_jmpbuf(png_ptr) \
- (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf)))
+ (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf))))
#else
# define png_jmpbuf(png_ptr) \
(LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP)
@@ -1043,12 +966,12 @@ PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr,
* will use it; otherwise it will call PNG_ABORT(). This function was
* added in libpng-1.5.0.
*/
-PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val),
+PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val),
PNG_NORETURN);
#ifdef PNG_READ_SUPPORTED
/* Reset the compression stream */
-PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr));
+PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED);
#endif
/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */
@@ -1066,81 +989,92 @@ PNG_EXPORTA(12, png_structp, png_create_write_struct_2,
#endif
/* Write the PNG file signature. */
-PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr));
+PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr));
/* Write a PNG chunk - size, type, (optional) data, CRC. */
-PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep
+PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep
chunk_name, png_const_bytep data, png_size_t length));
/* Write the start of a PNG chunk - length and chunk name. */
-PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr,
+PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr,
png_const_bytep chunk_name, png_uint_32 length));
/* Write the data of a PNG chunk started with png_write_chunk_start(). */
-PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr,
+PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr,
png_const_bytep data, png_size_t length));
/* Finish a chunk started with png_write_chunk_start() (includes CRC). */
-PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr));
+PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr));
/* Allocate and initialize the info structure */
-PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr),
+PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr),
PNG_ALLOCATED);
-PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr,
- png_size_t png_info_struct_size));
+/* DEPRECATED: this function allowed init structures to be created using the
+ * default allocation method (typically malloc). Use is deprecated in 1.6.0 and
+ * the API will be removed in the future.
+ */
+PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr,
+ png_size_t png_info_struct_size), PNG_DEPRECATED);
/* Writes all the PNG information before the image. */
PNG_EXPORT(20, void, png_write_info_before_PLTE,
- (png_structp png_ptr, png_infop info_ptr));
+ (png_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(21, void, png_write_info,
- (png_structp png_ptr, png_infop info_ptr));
+ (png_structrp png_ptr, png_const_inforp info_ptr));
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the information before the actual image data. */
PNG_EXPORT(22, void, png_read_info,
- (png_structp png_ptr, png_infop info_ptr));
+ (png_structrp png_ptr, png_inforp info_ptr));
#endif
#ifdef PNG_TIME_RFC1123_SUPPORTED
-PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123,
- (png_structp png_ptr,
+ /* Convert to a US string format: there is no localization support in this
+ * routine. The original implementation used a 29 character buffer in
+ * png_struct, this will be removed in future versions.
+ */
+#if PNG_LIBPNG_VER < 10700
+/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */
+PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr,
+ png_const_timep ptime),PNG_DEPRECATED);
+#endif
+PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29],
png_const_timep ptime));
#endif
#ifdef PNG_CONVERT_tIME_SUPPORTED
/* Convert from a struct tm to png_time */
PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime,
- PNG_CONST struct tm FAR * ttime));
+ const struct tm * ttime));
/* Convert from time_t to png_time. Uses gmtime() */
-PNG_EXPORT(25, void, png_convert_from_time_t,
- (png_timep ptime, time_t ttime));
-#endif /* PNG_CONVERT_tIME_SUPPORTED */
+PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime));
+#endif /* CONVERT_tIME */
#ifdef PNG_READ_EXPAND_SUPPORTED
/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
-PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr));
-PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr));
-PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr));
-PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr));
+PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr));
+PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr));
+PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr));
+PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion
* of a tRNS chunk if present.
*/
-PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr));
+PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* Use blue, green, red order for pixels. */
-PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr));
+PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Expand the grayscale to 24-bit RGB if necessary. */
-PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr));
+PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
@@ -1150,12 +1084,12 @@ PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr));
#define PNG_ERROR_ACTION_ERROR 3
#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/
-PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr,
- int error_action, double red, double green));
-PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr,
- int error_action, png_fixed_point red, png_fixed_point green));
+PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr,
+ int error_action, double red, double green))
+PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr,
+ int error_action, png_fixed_point red, png_fixed_point green))
-PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp
+PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp
png_ptr));
#endif
@@ -1165,9 +1099,9 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
#endif
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-/* How the alpha channel is interpreted - this affects how the color channels of
- * a PNG file are returned when an alpha channel, or tRNS chunk in a palette
- * file, is present.
+/* How the alpha channel is interpreted - this affects how the color channels
+ * of a PNG file are returned to the calling application when an alpha channel,
+ * or a tRNS chunk in a palette file, is present.
*
* This has no effect on the way pixels are written into a PNG output
* datastream. The color samples in a PNG datastream are never premultiplied
@@ -1175,33 +1109,19 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
*
* The default is to return data according to the PNG specification: the alpha
* channel is a linear measure of the contribution of the pixel to the
- * corresponding composited pixel. The gamma encoded color channels must be
- * scaled according to the contribution and to do this it is necessary to undo
+ * corresponding composited pixel, and the color channels are unassociated
+ * (not premultiplied). The gamma encoded color channels must be scaled
+ * according to the contribution and to do this it is necessary to undo
* the encoding, scale the color values, perform the composition and reencode
* the values. This is the 'PNG' mode.
*
* The alternative is to 'associate' the alpha with the color information by
- * storing color channel values that have been scaled by the alpha. The
- * advantage is that the color channels can be resampled (the image can be
- * scaled) in this form. The disadvantage is that normal practice is to store
- * linear, not (gamma) encoded, values and this requires 16-bit channels for
- * still images rather than the 8-bit channels that are just about sufficient if
- * gamma encoding is used. In addition all non-transparent pixel values,
- * including completely opaque ones, must be gamma encoded to produce the final
- * image. This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the
- * latter being the two common names for associated alpha color channels.)
- *
- * Since it is not necessary to perform arithmetic on opaque color values so
- * long as they are not to be resampled and are in the final color space it is
- * possible to optimize the handling of alpha by storing the opaque pixels in
- * the PNG format (adjusted for the output color space) while storing partially
- * opaque pixels in the standard, linear, format. The accuracy required for
- * standard alpha composition is relatively low, because the pixels are
- * isolated, therefore typically the accuracy loss in storing 8-bit linear
- * values is acceptable. (This is not true if the alpha channel is used to
- * simulate transparency over large areas - use 16 bits or the PNG mode in
- * this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is
- * treated as opaque only if the alpha value is equal to the maximum value.
+ * storing color channel values that have been scaled by the alpha.
+ * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
+ * (the latter being the two common names for associated alpha color channels).
+ *
+ * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha
+ * value is equal to the maximum value.
*
* The final choice is to gamma encode the alpha channel as well. This is
* broken because, in practice, no implementation that uses this choice
@@ -1220,76 +1140,15 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */
#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */
-PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode,
- double output_gamma));
-PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr,
- int mode, png_fixed_point output_gamma));
+PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode,
+ double output_gamma))
+PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr,
+ int mode, png_fixed_point output_gamma))
#endif
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED)
/* The output_gamma value is a screen gamma in libpng terminology: it expresses
- * how to decode the output values, not how they are encoded. The values used
- * correspond to the normal numbers used to describe the overall gamma of a
- * computer display system; for example 2.2 for an sRGB conformant system. The
- * values are scaled by 100000 in the _fixed version of the API (so 220000 for
- * sRGB.)
- *
- * The inverse of the value is always used to provide a default for the PNG file
- * encoding if it has no gAMA chunk and if png_set_gamma() has not been called
- * to override the PNG gamma information.
- *
- * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode
- * opaque pixels however pixels with lower alpha values are not encoded,
- * regardless of the output gamma setting.
- *
- * When the standard Porter Duff handling is requested with mode 1 the output
- * encoding is set to be linear and the output_gamma value is only relevant
- * as a default for input data that has no gamma information. The linear output
- * encoding will be overridden if png_set_gamma() is called - the results may be
- * highly unexpected!
- *
- * The following numbers are derived from the sRGB standard and the research
- * behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of
- * 0.45455 (1/2.2) for PNG. The value implicitly includes any viewing
- * correction required to take account of any differences in the color
- * environment of the original scene and the intended display environment; the
- * value expresses how to *decode* the image for display, not how the original
- * data was *encoded*.
- *
- * sRGB provides a peg for the PNG standard by defining a viewing environment.
- * sRGB itself, and earlier TV standards, actually use a more complex transform
- * (a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is
- * limited to simple power laws.) By saying that an image for direct display on
- * an sRGB conformant system should be stored with a gAMA chunk value of 45455
- * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification
- * makes it possible to derive values for other display systems and
- * environments.
- *
- * The Mac value is deduced from the sRGB based on an assumption that the actual
- * extra viewing correction used in early Mac display systems was implemented as
- * a power 1.45 lookup table.
- *
- * Any system where a programmable lookup table is used or where the behavior of
- * the final display device characteristics can be changed requires system
- * specific code to obtain the current characteristic. However this can be
- * difficult and most PNG gamma correction only requires an approximate value.
- *
- * By default, if png_set_alpha_mode() is not called, libpng assumes that all
- * values are unencoded, linear, values and that the output device also has a
- * linear characteristic. This is only very rarely correct - it is invariably
- * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the
- * default if you don't know what the right answer is!
- *
- * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS
- * 10.6) which used a correction table to implement a somewhat lower gamma on an
- * otherwise sRGB system.
- *
- * Both these values are reserved (not simple gamma values) in order to allow
- * more precise correction internally in the future.
- *
- * NOTE: the following values can be passed to either the fixed or floating
- * point APIs, but the floating point API will also accept floating point
- * values.
+ * how to decode the output values, not how they are encoded.
*/
#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */
#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */
@@ -1374,51 +1233,50 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr,
*/
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr));
+PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
-PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr));
+PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
-PNG_EXPORT(38, void, png_set_invert_alpha, (png_structp png_ptr));
+PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
-/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */
-PNG_EXPORT(39, void, png_set_filler, (png_structp png_ptr, png_uint_32 filler,
+/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */
+PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler,
int flags));
/* The values of the PNG_FILLER_ defines should NOT be changed */
# define PNG_FILLER_BEFORE 0
# define PNG_FILLER_AFTER 1
-/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */
-PNG_EXPORT(40, void, png_set_add_alpha,
- (png_structp png_ptr, png_uint_32 filler,
- int flags));
-#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */
+/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */
+PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr,
+ png_uint_32 filler, int flags));
+#endif /* READ_FILLER || WRITE_FILLER */
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
/* Swap bytes in 16-bit depth files. */
-PNG_EXPORT(41, void, png_set_swap, (png_structp png_ptr));
+PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
-PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr));
+PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* Swap packing order of pixels in bytes. */
-PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr));
+PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
/* Converts files to legal bit depths. */
-PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p
+PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p
true_bits));
#endif
@@ -1430,12 +1288,12 @@ PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p
* necessary to call png_read_row or png_read_rows png_get_image_height
* times for each pass.
*/
-PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr));
+PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
/* Invert monochrome files */
-PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr));
+PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED
@@ -1444,12 +1302,12 @@ PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr));
* read. Doing so will result in unexpected behavior and possible warnings or
* errors if the PNG file contains a bKGD chunk.
*/
-PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr,
+PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
- int need_expand, double background_gamma));
-PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr,
+ int need_expand, double background_gamma))
+PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
- int need_expand, png_fixed_point background_gamma));
+ int need_expand, png_fixed_point background_gamma))
#endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED
# define PNG_BACKGROUND_GAMMA_UNKNOWN 0
@@ -1460,23 +1318,22 @@ PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr,
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
/* Scale a 16-bit depth file down to 8-bit, accurately. */
-PNG_EXPORT(229, void, png_set_scale_16, (png_structp png_ptr));
+PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */
/* Strip the second byte of information from a 16-bit depth file. */
-PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr));
+PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
/* Turn on quantizing, and reduce the palette to the number of colors
* available.
*/
-PNG_EXPORT(49, void, png_set_quantize,
- (png_structp png_ptr, png_colorp palette,
- int num_palette, int maximum_colors, png_const_uint_16p histogram,
- int full_quantize));
+PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr,
+ png_colorp palette, int num_palette, int maximum_colors,
+ png_const_uint_16p histogram, int full_quantize));
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
@@ -1496,71 +1353,69 @@ PNG_EXPORT(49, void, png_set_quantize,
* API (floating point or fixed.) Notice, however, that the 'file_gamma' value
* is the inverse of a 'screen gamma' value.
*/
-PNG_FP_EXPORT(50, void, png_set_gamma,
- (png_structp png_ptr, double screen_gamma,
- double override_file_gamma));
-PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr,
- png_fixed_point screen_gamma, png_fixed_point override_file_gamma));
+PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr,
+ double screen_gamma, double override_file_gamma))
+PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr,
+ png_fixed_point screen_gamma, png_fixed_point override_file_gamma))
#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
/* Set how many lines between output flushes - 0 for no flushing */
-PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows));
+PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows));
/* Flush the current PNG output buffer */
-PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr));
+PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr));
#endif
/* Optional update palette with requested transformations */
-PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr));
+PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr));
/* Optional call to update the users info structure */
-PNG_EXPORT(54, void, png_read_update_info,
- (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr,
+ png_inforp info_ptr));
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read one or more rows of image data. */
-PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row,
+PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row,
png_bytepp display_row, png_uint_32 num_rows));
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read a row of data. */
-PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row,
+PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row,
png_bytep display_row));
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the whole image into memory at once. */
-PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image));
+PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image));
#endif
/* Write a row of image data */
-PNG_EXPORT(58, void, png_write_row,
- (png_structp png_ptr, png_const_bytep row));
+PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr,
+ png_const_bytep row));
/* Write a few rows of image data: (*row) is not written; however, the type
* is declared as writeable to maintain compatibility with previous versions
* of libpng and to allow the 'display_row' array from read_rows to be passed
* unchanged to write_rows.
*/
-PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row,
+PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row,
png_uint_32 num_rows));
/* Write the image data */
-PNG_EXPORT(60, void, png_write_image,
- (png_structp png_ptr, png_bytepp image));
+PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image));
/* Write the end of the PNG file. */
-PNG_EXPORT(61, void, png_write_end,
- (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr,
+ png_inforp info_ptr));
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the end of the PNG file. */
-PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr));
#endif
/* Free any memory associated with the png_info_struct */
-PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr,
+PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr,
png_infopp info_ptr_ptr));
/* Free any memory associated with the png_struct and the png_info_structs */
@@ -1572,8 +1427,8 @@ PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr,
png_infopp info_ptr_ptr));
/* Set the libpng method of handling chunk CRC errors */
-PNG_EXPORT(66, void, png_set_crc_action,
- (png_structp png_ptr, int crit_action, int ancil_action));
+PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
+ int ancil_action));
/* Values for png_set_crc_action() say how to handle CRC errors in
* ancillary and critical chunks, and whether to use the data contained
@@ -1591,6 +1446,7 @@ PNG_EXPORT(66, void, png_set_crc_action,
#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */
#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */
+#ifdef PNG_WRITE_SUPPORTED
/* These functions give the user control over the scan-line filtering in
* libpng and the compression methods used by zlib. These functions are
* mainly useful for testing, as the defaults should work with most users.
@@ -1602,8 +1458,9 @@ PNG_EXPORT(66, void, png_set_crc_action,
/* Set the filtering method(s) used by libpng. Currently, the only valid
* value for "method" is 0.
*/
-PNG_EXPORT(67, void, png_set_filter,
- (png_structp png_ptr, int method, int filters));
+PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
+ int filters));
+#endif /* WRITE */
/* Flags for png_set_filter() to say which filters to use. The flags
* are chosen so that they don't conflict with real filter types
@@ -1629,53 +1486,23 @@ PNG_EXPORT(67, void, png_set_filter,
#define PNG_FILTER_VALUE_PAETH 4
#define PNG_FILTER_VALUE_LAST 5
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */
-/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_
- * defines, either the default (minimum-sum-of-absolute-differences), or
- * the experimental method (weighted-minimum-sum-of-absolute-differences).
- *
- * Weights are factors >= 1.0, indicating how important it is to keep the
- * filter type consistent between rows. Larger numbers mean the current
- * filter is that many times as likely to be the same as the "num_weights"
- * previous filters. This is cumulative for each previous row with a weight.
- * There needs to be "num_weights" values in "filter_weights", or it can be
- * NULL if the weights aren't being specified. Weights have no influence on
- * the selection of the first row filter. Well chosen weights can (in theory)
- * improve the compression for a given image.
- *
- * Costs are factors >= 1.0 indicating the relative decoding costs of a
- * filter type. Higher costs indicate more decoding expense, and are
- * therefore less likely to be selected over a filter with lower computational
- * costs. There needs to be a value in "filter_costs" for each valid filter
- * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't
- * setting the costs. Costs try to improve the speed of decompression without
- * unduly increasing the compressed image size.
- *
- * A negative weight or cost indicates the default value is to be used, and
- * values in the range [0.0, 1.0) indicate the value is to remain unchanged.
- * The default values for both weights and costs are currently 1.0, but may
- * change if good general weighting/cost heuristics can be found. If both
- * the weights and costs are set to 1.0, this degenerates the WEIGHTED method
- * to the UNWEIGHTED method, but with added encoding time/computation.
- */
-PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr,
+#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
+PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr,
int heuristic_method, int num_weights, png_const_doublep filter_weights,
- png_const_doublep filter_costs));
+ png_const_doublep filter_costs))
PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
- (png_structp png_ptr,
- int heuristic_method, int num_weights, png_const_fixed_point_p
- filter_weights, png_const_fixed_point_p filter_costs));
-#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+ (png_structrp png_ptr, int heuristic_method, int num_weights,
+ png_const_fixed_point_p filter_weights,
+ png_const_fixed_point_p filter_costs))
+#endif /* WRITE_WEIGHTED_FILTER */
-/* Heuristic used for row filter selection. These defines should NOT be
- * changed.
- */
+/* The following are no longer used and will be removed from libpng-1.7: */
#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */
#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */
#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */
#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */
-#ifdef PNG_WRITE_SUPPORTED
/* Set the library compression level. Currently, valid values range from
* 0 - 9, corresponding directly to the zlib compression levels 0 - 9
* (0 - no compression, 9 - "maximal" compression). Note that tests have
@@ -1683,45 +1510,47 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
* for PNG images, and do considerably fewer caclulations. In the future,
* these values may not correspond directly to the zlib compression levels.
*/
-PNG_EXPORT(69, void, png_set_compression_level,
- (png_structp png_ptr, int level));
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
+PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr,
+ int level));
-PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr,
+PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr,
int mem_level));
-PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr,
+PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr,
int strategy));
/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
* smaller value of window_bits if it can do so safely.
*/
-PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr,
+PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr,
int window_bits));
-PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr,
+PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr,
int method));
-#endif
+#endif /* WRITE_CUSTOMIZE_COMPRESSION */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
/* Also set zlib parameters for compressing non-IDAT chunks */
-PNG_EXPORT(222, void, png_set_text_compression_level,
- (png_structp png_ptr, int level));
+PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr,
+ int level));
-PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structp png_ptr,
+PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr,
int mem_level));
-PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structp png_ptr,
+PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr,
int strategy));
/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
* smaller value of window_bits if it can do so safely.
*/
-PNG_EXPORT(225, void, png_set_text_compression_window_bits, (png_structp
- png_ptr, int window_bits));
+PNG_EXPORT(225, void, png_set_text_compression_window_bits,
+ (png_structrp png_ptr, int window_bits));
-PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr,
+PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr,
int method));
-#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
+#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
+#endif /* WRITE */
/* These next functions are called for input/output, memory, and error
* handling. They are in the file pngrio.c, pngwio.c, and pngerror.c,
@@ -1734,7 +1563,7 @@ PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr,
#ifdef PNG_STDIO_SUPPORTED
/* Initialize the input/output for the PNG file to the default functions. */
-PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp));
+PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp));
#endif
/* Replace the (error and abort), and warning functions with user
@@ -1745,12 +1574,11 @@ PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp));
* default function will be used.
*/
-PNG_EXPORT(75, void, png_set_error_fn,
- (png_structp png_ptr, png_voidp error_ptr,
- png_error_ptr error_fn, png_error_ptr warning_fn));
+PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr,
+ png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn));
/* Return the user pointer associated with the error functions */
-PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr));
+PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr));
/* Replace the default data output functions with a user supplied one(s).
* If buffered output is not used, then output_flush_fn can be set to NULL.
@@ -1762,47 +1590,47 @@ PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr));
* default flush function, which uses the standard *FILE structure, will
* be used.
*/
-PNG_EXPORT(77, void, png_set_write_fn, (png_structp png_ptr, png_voidp io_ptr,
+PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
/* Replace the default data input function with a user supplied one. */
-PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr,
+PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr read_data_fn));
/* Return the user pointer associated with the I/O functions */
-PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr));
+PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr));
-PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr,
+PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr,
png_read_status_ptr read_row_fn));
-PNG_EXPORT(81, void, png_set_write_status_fn, (png_structp png_ptr,
+PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr,
png_write_status_ptr write_row_fn));
#ifdef PNG_USER_MEM_SUPPORTED
/* Replace the default memory allocation functions with user supplied one(s). */
-PNG_EXPORT(82, void, png_set_mem_fn, (png_structp png_ptr, png_voidp mem_ptr,
+PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn));
/* Return the user pointer associated with the memory functions */
-PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr));
+PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr));
#endif
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
-PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr,
+PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr,
png_user_transform_ptr read_user_transform_fn));
#endif
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
-PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr,
+PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr,
png_user_transform_ptr write_user_transform_fn));
#endif
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
-PNG_EXPORT(86, void, png_set_user_transform_info, (png_structp png_ptr,
+PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr,
png_voidp user_transform_ptr, int user_transform_depth,
int user_transform_channels));
/* Return the user pointer associated with the user transform functions */
PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
#endif
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
@@ -1817,31 +1645,53 @@ PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr,
* find the output pixel (x,y) given an interlaced sub-image pixel
* (row,col,pass). (See below for these macros.)
*/
-PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp));
-PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp));
+PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp));
+PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
#endif
-#ifdef PNG_USER_CHUNKS_SUPPORTED
-PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr,
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+/* This callback is called only for *unknown* chunks. If
+ * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known
+ * chunks to be treated as unknown, however in this case the callback must do
+ * any processing required by the chunk (e.g. by calling the appropriate
+ * png_set_ APIs.)
+ *
+ * There is no write support - on write, by default, all the chunks in the
+ * 'unknown' list are written in the specified position.
+ *
+ * The integer return from the callback function is interpreted thus:
+ *
+ * negative: An error occurred; png_chunk_error will be called.
+ * zero: The chunk was not handled, the chunk will be saved. A critical
+ * chunk will cause an error at this point unless it is to be saved.
+ * positive: The chunk was handled, libpng will ignore/discard it.
+ *
+ * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about
+ * how this behavior will change in libpng 1.7
+ */
+PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr,
png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
-PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structp png_ptr));
+#endif
+
+#ifdef PNG_USER_CHUNKS_SUPPORTED
+PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr));
#endif
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
/* Sets the function callbacks for the push reader, and a pointer to a
* user-defined structure available to the callback functions.
*/
-PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structp png_ptr,
+PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr,
png_voidp progressive_ptr, png_progressive_info_ptr info_fn,
png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn));
/* Returns the user pointer associated with the push read functions */
-PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr));
+PNG_EXPORT(91, png_voidp, png_get_progressive_ptr,
+ (png_const_structrp png_ptr));
/* Function to be called when data becomes available */
-PNG_EXPORT(92, void, png_process_data,
- (png_structp png_ptr, png_infop info_ptr,
- png_bytep buffer, png_size_t buffer_size));
+PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr,
+ png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size));
/* A function which may be called *only* within png_process_data to stop the
* processing of any more data. The function returns the number of bytes
@@ -1850,7 +1700,7 @@ PNG_EXPORT(92, void, png_process_data,
* 'save' is set to true the routine will first save all the pending data and
* will always return 0.
*/
-PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save));
+PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save));
/* A function which may be called *only* outside (after) a call to
* png_process_data. It returns the number of bytes of data to skip in the
@@ -1858,42 +1708,43 @@ PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save));
* application must skip than number of bytes of input data and pass the
* following data to the next call to png_process_data.
*/
-PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp));
+PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp));
-#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Function that combines rows. 'new_row' is a flag that should come from
* the callback and be non-NULL if anything needs to be done; the library
* stores its own version of the new data internally and ignores the passed
* in value.
*/
-PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr,
+PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr,
png_bytep old_row, png_const_bytep new_row));
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PROGRESSIVE_READ */
-PNG_EXPORTA(94, png_voidp, png_malloc,
- (png_structp png_ptr, png_alloc_size_t size),
- PNG_ALLOCATED);
+PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr,
+ png_alloc_size_t size), PNG_ALLOCATED);
/* Added at libpng version 1.4.0 */
-PNG_EXPORTA(95, png_voidp, png_calloc,
- (png_structp png_ptr, png_alloc_size_t size),
- PNG_ALLOCATED);
+PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr,
+ png_alloc_size_t size), PNG_ALLOCATED);
/* Added at libpng version 1.2.4 */
-PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr,
+PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr,
png_alloc_size_t size), PNG_ALLOCATED);
/* Frees a pointer allocated by png_malloc() */
-PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr));
+PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr));
/* Free data that was allocated internally */
-PNG_EXPORT(98, void, png_free_data,
- (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num));
+PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 free_me, int num));
/* Reassign responsibility for freeing existing data, whether allocated
- * by libpng or by the application */
-PNG_EXPORT(99, void, png_data_freer,
- (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask));
+ * by libpng or by the application; this works on the png_info structure passed
+ * in, it does not change the state for other png_info structures.
+ *
+ * It is unlikely that this function works correctly as of 1.6.0 and using it
+ * may result either in memory leaks or double free of allocated data.
+ */
+PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int freer, png_uint_32 mask));
/* Assignments for png_data_freer */
#define PNG_DESTROY_WILL_FREE_DATA 1
@@ -1906,8 +1757,10 @@ PNG_EXPORT(99, void, png_data_freer,
#define PNG_FREE_ROWS 0x0040
#define PNG_FREE_PCAL 0x0080
#define PNG_FREE_SCAL 0x0100
-#define PNG_FREE_UNKN 0x0200
-#define PNG_FREE_LIST 0x0400
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+# define PNG_FREE_UNKN 0x0200
+#endif
+/* PNG_FREE_LIST 0x0400 removed in 1.6.0 because it is ignored */
#define PNG_FREE_PLTE 0x1000
#define PNG_FREE_TRNS 0x2000
#define PNG_FREE_TEXT 0x4000
@@ -1915,50 +1768,55 @@ PNG_EXPORT(99, void, png_data_freer,
#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
#ifdef PNG_USER_MEM_SUPPORTED
-PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr,
- png_alloc_size_t size), PNG_ALLOCATED);
-PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr));
+PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr,
+ png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED);
+PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr,
+ png_voidp ptr), PNG_DEPRECATED);
#endif
#ifdef PNG_ERROR_TEXT_SUPPORTED
/* Fatal error in PNG image of libpng - can't continue */
-PNG_EXPORTA(102, void, png_error,
- (png_structp png_ptr, png_const_charp error_message),
- PNG_NORETURN);
+PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr,
+ png_const_charp error_message), PNG_NORETURN);
/* The same, but the chunk name is prepended to the error string. */
-PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr,
+PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr,
png_const_charp error_message), PNG_NORETURN);
#else
/* Fatal error in PNG image of libpng - can't continue */
-PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN);
+PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN);
+# define png_error(s1,s2) png_err(s1)
+# define png_chunk_error(s1,s2) png_err(s1)
#endif
#ifdef PNG_WARNINGS_SUPPORTED
/* Non-fatal error in libpng. Can continue, but may have a problem. */
-PNG_EXPORT(105, void, png_warning, (png_structp png_ptr,
+PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr,
png_const_charp warning_message));
/* Non-fatal error in libpng, chunk name is prepended to message. */
-PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr,
+PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr,
png_const_charp warning_message));
+#else
+# define png_warning(s1,s2) ((void)(s1))
+# define png_chunk_warning(s1,s2) ((void)(s1))
#endif
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
/* Benign error in libpng. Can continue, but may have a problem.
* User can choose whether to handle as a fatal error or as a warning. */
-# undef png_benign_error
-PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr,
+PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr,
png_const_charp warning_message));
-/* Same, chunk name is prepended to message. */
-# undef png_chunk_benign_error
-PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr,
+#ifdef PNG_READ_SUPPORTED
+/* Same, chunk name is prepended to message (only during read) */
+PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr,
png_const_charp warning_message));
+#endif
PNG_EXPORT(109, void, png_set_benign_errors,
- (png_structp png_ptr, int allowed));
+ (png_structrp png_ptr, int allowed));
#else
# ifdef PNG_ALLOW_BENIGN_ERRORS
# define png_benign_error png_warning
@@ -1982,289 +1840,274 @@ PNG_EXPORT(109, void, png_set_benign_errors,
* png_info_struct.
*/
/* Returns "flag" if chunk data is valid in info_ptr. */
-PNG_EXPORT(110, png_uint_32, png_get_valid,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_uint_32 flag));
+PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_uint_32 flag));
/* Returns number of bytes needed to hold a transformed row. */
-PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* Returns row_pointers, which is an array of pointers to scanlines that was
* returned from png_read_png().
*/
-PNG_EXPORT(112, png_bytepp, png_get_rows,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
+
/* Set row_pointers, which is an array of pointers to scanlines for use
* by png_write_png().
*/
-PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr,
- png_infop info_ptr, png_bytepp row_pointers));
+PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_bytepp row_pointers));
#endif
/* Returns number of color channels in image. */
-PNG_EXPORT(114, png_byte, png_get_channels,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
#ifdef PNG_EASY_ACCESS_SUPPORTED
/* Returns image width in pixels. */
-PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image height in pixels. */
-PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image bit_depth. */
-PNG_EXPORT(117, png_byte, png_get_bit_depth,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image color_type. */
-PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image filter_type. */
-PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image interlace_type. */
-PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image compression_type. */
-PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image resolution in pixels per meter, from pHYs chunk data. */
PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
/* Returns pixel aspect ratio, computed from pHYs chunk data. */
PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(128, png_int_32, png_get_x_offset_microns,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(129, png_int_32, png_get_y_offset_microns,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
-#endif /* PNG_EASY_ACCESS_SUPPORTED */
+#endif /* EASY_ACCESS */
+#ifdef PNG_READ_SUPPORTED
/* Returns pointer to signature string read from PNG header */
-PNG_EXPORT(130, png_const_bytep, png_get_signature,
- (png_const_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
+#endif
#ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(131, png_uint_32, png_get_bKGD,
- (png_const_structp png_ptr, png_infop info_ptr,
- png_color_16p *background));
+PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_color_16p *background));
#endif
#ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr,
- png_const_color_16p background));
+PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_color_16p background));
#endif
#ifdef PNG_cHRM_SUPPORTED
-PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr,
- png_const_infop info_ptr, double *white_x, double *white_y, double *red_x,
+PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x,
double *red_y, double *green_x, double *green_y, double *blue_x,
- double *blue_y));
-PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_structp png_ptr,
- png_const_infop info_ptr, double *red_X, double *red_Y, double *red_Z,
+ double *blue_y))
+PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z,
double *green_X, double *green_Y, double *green_Z, double *blue_X,
- double *blue_Y, double *blue_Z));
-#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */
+ double *blue_Y, double *blue_Z))
PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed,
- (png_const_structp png_ptr,
- png_const_infop info_ptr, png_fixed_point *int_white_x,
- png_fixed_point *int_white_y, png_fixed_point *int_red_x,
- png_fixed_point *int_red_y, png_fixed_point *int_green_x,
- png_fixed_point *int_green_y, png_fixed_point *int_blue_x,
- png_fixed_point *int_blue_y));
-#endif
+ (png_const_structrp png_ptr, png_const_inforp info_ptr,
+ png_fixed_point *int_white_x, png_fixed_point *int_white_y,
+ png_fixed_point *int_red_x, png_fixed_point *int_red_y,
+ png_fixed_point *int_green_x, png_fixed_point *int_green_y,
+ png_fixed_point *int_blue_x, png_fixed_point *int_blue_y))
PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed,
- (png_structp png_ptr, png_const_infop info_ptr,
+ (png_const_structrp png_ptr, png_const_inforp info_ptr,
png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
- png_fixed_point *int_blue_Z));
+ png_fixed_point *int_blue_Z))
#endif
#ifdef PNG_cHRM_SUPPORTED
-PNG_FP_EXPORT(135, void, png_set_cHRM,
- (png_structp png_ptr, png_infop info_ptr,
+PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr,
+ png_inforp info_ptr,
double white_x, double white_y, double red_x, double red_y, double green_x,
- double green_y, double blue_x, double blue_y));
-PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_structp png_ptr,
- png_infop info_ptr, double red_X, double red_Y, double red_Z,
+ double green_y, double blue_x, double blue_y))
+PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr,
+ png_inforp info_ptr, double red_X, double red_Y, double red_Z,
double green_X, double green_Y, double green_Z, double blue_X,
- double blue_Y, double blue_Z));
-PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr,
- png_infop info_ptr, png_fixed_point int_white_x,
+ double blue_Y, double blue_Z))
+PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_fixed_point int_white_x,
png_fixed_point int_white_y, png_fixed_point int_red_x,
png_fixed_point int_red_y, png_fixed_point int_green_x,
png_fixed_point int_green_y, png_fixed_point int_blue_x,
- png_fixed_point int_blue_y));
-PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_structp png_ptr,
- png_infop info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y,
+ png_fixed_point int_blue_y))
+PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y,
png_fixed_point int_red_Z, png_fixed_point int_green_X,
png_fixed_point int_green_Y, png_fixed_point int_green_Z,
png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
- png_fixed_point int_blue_Z));
+ png_fixed_point int_blue_Z))
#endif
#ifdef PNG_gAMA_SUPPORTED
-PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- double *file_gamma));
+PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, double *file_gamma))
PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_fixed_point *int_file_gamma));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr,
+ png_fixed_point *int_file_gamma))
#endif
#ifdef PNG_gAMA_SUPPORTED
-PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr,
- png_infop info_ptr, double file_gamma));
-PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr,
- png_infop info_ptr, png_fixed_point int_file_gamma));
+PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr,
+ png_inforp info_ptr, double file_gamma))
+PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_fixed_point int_file_gamma))
#endif
#ifdef PNG_hIST_SUPPORTED
-PNG_EXPORT(141, png_uint_32, png_get_hIST,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_uint_16p *hist));
+PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_uint_16p *hist));
#endif
#ifdef PNG_hIST_SUPPORTED
-PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr,
- png_infop info_ptr, png_const_uint_16p hist));
+PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_uint_16p hist));
#endif
-PNG_EXPORT(143, png_uint_32, png_get_IHDR,
- (png_structp png_ptr, png_infop info_ptr,
- png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type,
- int *interlace_method, int *compression_method, int *filter_method));
+PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height,
+ int *bit_depth, int *color_type, int *interlace_method,
+ int *compression_method, int *filter_method));
-PNG_EXPORT(144, void, png_set_IHDR,
- (png_structp png_ptr, png_infop info_ptr,
- png_uint_32 width, png_uint_32 height, int bit_depth, int color_type,
- int interlace_method, int compression_method, int filter_method));
+PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth,
+ int color_type, int interlace_method, int compression_method,
+ int filter_method));
#ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(145, png_uint_32, png_get_oFFs,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type));
+PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
+ int *unit_type));
#endif
#ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(146, void, png_set_oFFs,
- (png_structp png_ptr, png_infop info_ptr,
- png_int_32 offset_x, png_int_32 offset_y, int unit_type));
+PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y,
+ int unit_type));
#endif
#ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(147, png_uint_32, png_get_pCAL,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type,
- int *nparams,
- png_charp *units, png_charpp *params));
+PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_charp *purpose, png_int_32 *X0,
+ png_int_32 *X1, int *type, int *nparams, png_charp *units,
+ png_charpp *params));
#endif
#ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr,
- png_infop info_ptr,
- png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
- int nparams, png_const_charp units, png_charpp params));
+PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1,
+ int type, int nparams, png_const_charp units, png_charpp params));
#endif
#ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(149, png_uint_32, png_get_pHYs,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
+PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
+ int *unit_type));
#endif
#ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(150, void, png_set_pHYs,
- (png_structp png_ptr, png_infop info_ptr,
- png_uint_32 res_x, png_uint_32 res_y, int unit_type));
+PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type));
#endif
-PNG_EXPORT(151, png_uint_32, png_get_PLTE,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_colorp *palette, int *num_palette));
+PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_colorp *palette, int *num_palette));
-PNG_EXPORT(152, void, png_set_PLTE,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_colorp palette, int num_palette));
+PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr,
+ png_inforp info_ptr, png_const_colorp palette, int num_palette));
#ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(153, png_uint_32, png_get_sBIT,
- (png_const_structp png_ptr, png_infop info_ptr,
- png_color_8p *sig_bit));
+PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_color_8p *sig_bit));
#endif
#ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(154, void, png_set_sBIT,
- (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit));
+PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_color_8p sig_bit));
#endif
#ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr,
- png_const_infop info_ptr, int *file_srgb_intent));
+PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, int *file_srgb_intent));
#endif
#ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(156, void, png_set_sRGB,
- (png_structp png_ptr, png_infop info_ptr, int srgb_intent));
-PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr,
- png_infop info_ptr, int srgb_intent));
+PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int srgb_intent));
+PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int srgb_intent));
#endif
#ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(158, png_uint_32, png_get_iCCP,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_charpp name, int *compression_type, png_bytepp profile,
- png_uint_32 *proflen));
+PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_charpp name, int *compression_type,
+ png_bytepp profile, png_uint_32 *proflen));
#endif
#ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(159, void, png_set_iCCP,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_charp name, int compression_type, png_const_bytep profile,
- png_uint_32 proflen));
+PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_charp name, int compression_type,
+ png_const_bytep profile, png_uint_32 proflen));
#endif
#ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(160, png_uint_32, png_get_sPLT,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_sPLT_tpp entries));
+PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_sPLT_tpp entries));
#endif
#ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(161, void, png_set_sPLT,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_sPLT_tp entries, int nentries));
+PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_sPLT_tp entries, int nentries));
#endif
#ifdef PNG_TEXT_SUPPORTED
/* png_get_text also returns the number of text chunks in *num_text */
-PNG_EXPORT(162, png_uint_32, png_get_text,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_textp *text_ptr, int *num_text));
+PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_textp *text_ptr, int *num_text));
#endif
/* Note while png_set_text() will accept a structure whose text,
@@ -2275,122 +2118,220 @@ PNG_EXPORT(162, png_uint_32, png_get_text,
*/
#ifdef PNG_TEXT_SUPPORTED
-PNG_EXPORT(163, void, png_set_text,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_textp text_ptr, int num_text));
+PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_textp text_ptr, int num_text));
#endif
#ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(164, png_uint_32, png_get_tIME,
- (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time));
+PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_timep *mod_time));
#endif
#ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(165, void, png_set_tIME,
- (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time));
+PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_timep mod_time));
#endif
#ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(166, png_uint_32, png_get_tRNS,
- (png_const_structp png_ptr, png_infop info_ptr,
- png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color));
+PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans,
+ png_color_16p *trans_color));
#endif
#ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(167, void, png_set_tRNS,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_bytep trans_alpha, int num_trans,
+PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr,
+ png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans,
png_const_color_16p trans_color));
#endif
#ifdef PNG_sCAL_SUPPORTED
-PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- int *unit, double *width, double *height));
-#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, int *unit, double *width, double *height))
+#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
+ defined(PNG_FLOATING_POINT_SUPPORTED)
/* NOTE: this API is currently implemented using floating point arithmetic,
* consequently it can only be used on systems with floating point support.
* In any case the range of values supported by png_fixed_point is small and it
* is highly recommended that png_get_sCAL_s be used instead.
*/
PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed,
- (png_structp png_ptr, png_const_infop info_ptr, int *unit,
- png_fixed_point *width,
- png_fixed_point *height));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit,
+ png_fixed_point *width, png_fixed_point *height))
#endif
PNG_EXPORT(169, png_uint_32, png_get_sCAL_s,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- int *unit, png_charpp swidth, png_charpp sheight));
-
-PNG_FP_EXPORT(170, void, png_set_sCAL,
- (png_structp png_ptr, png_infop info_ptr,
- int unit, double width, double height));
-PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr,
- png_infop info_ptr, int unit, png_fixed_point width,
- png_fixed_point height));
-PNG_EXPORT(171, void, png_set_sCAL_s,
- (png_structp png_ptr, png_infop info_ptr,
- int unit, png_const_charp swidth, png_const_charp sheight));
-#endif /* PNG_sCAL_SUPPORTED */
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-/* Provide a list of chunks and how they are to be handled, if the built-in
- handling or default unknown chunk handling is not desired. Any chunks not
- listed will be handled in the default manner. The IHDR and IEND chunks
- must not be listed. Because this turns off the default handling for chunks
- that would otherwise be recognized the behavior of libpng transformations may
- well become incorrect!
- keep = 0: PNG_HANDLE_CHUNK_AS_DEFAULT: follow default behavior
- = 1: PNG_HANDLE_CHUNK_NEVER: do not keep
- = 2: PNG_HANDLE_CHUNK_IF_SAFE: keep only if safe-to-copy
- = 3: PNG_HANDLE_CHUNK_ALWAYS: keep even if unsafe-to-copy
-*/
-PNG_EXPORT(172, void, png_set_keep_unknown_chunks,
- (png_structp png_ptr, int keep,
- png_const_bytep chunk_list, int num_chunks));
-
-/* The handling code is returned; the result is therefore true (non-zero) if
- * special handling is required, false for the default handling.
- */
-PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr,
+ (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit,
+ png_charpp swidth, png_charpp sheight));
+
+PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int unit, double width, double height))
+PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int unit, png_fixed_point width,
+ png_fixed_point height))
+PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int unit,
+ png_const_charp swidth, png_const_charp sheight));
+#endif /* sCAL */
+
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+/* Provide the default handling for all unknown chunks or, optionally, for
+ * specific unknown chunks.
+ *
+ * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was
+ * ignored and the default was used, the per-chunk setting only had an effect on
+ * write. If you wish to have chunk-specific handling on read in code that must
+ * work on earlier versions you must use a user chunk callback to specify the
+ * desired handling (keep or discard.)
+ *
+ * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The
+ * parameter is interpreted as follows:
+ *
+ * READ:
+ * PNG_HANDLE_CHUNK_AS_DEFAULT:
+ * Known chunks: do normal libpng processing, do not keep the chunk (but
+ * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+ * Unknown chunks: for a specific chunk use the global default, when used
+ * as the default discard the chunk data.
+ * PNG_HANDLE_CHUNK_NEVER:
+ * Discard the chunk data.
+ * PNG_HANDLE_CHUNK_IF_SAFE:
+ * Keep the chunk data if the chunk is not critical else raise a chunk
+ * error.
+ * PNG_HANDLE_CHUNK_ALWAYS:
+ * Keep the chunk data.
+ *
+ * If the chunk data is saved it can be retrieved using png_get_unknown_chunks,
+ * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent
+ * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks
+ * it simply resets the behavior to the libpng default.
+ *
+ * INTERACTION WTIH USER CHUNK CALLBACKS:
+ * The per-chunk handling is always used when there is a png_user_chunk_ptr
+ * callback and the callback returns 0; the chunk is then always stored *unless*
+ * it is critical and the per-chunk setting is other than ALWAYS. Notice that
+ * the global default is *not* used in this case. (In effect the per-chunk
+ * value is incremented to at least IF_SAFE.)
+ *
+ * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and
+ * per-chunk defaults will be honored. If you want to preserve the current
+ * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE
+ * as the default - if you don't do this libpng 1.6 will issue a warning.
+ *
+ * If you want unhandled unknown chunks to be discarded in libpng 1.6 and
+ * earlier simply return '1' (handled).
+ *
+ * PNG_HANDLE_AS_UNKNOWN_SUPPORTED:
+ * If this is *not* set known chunks will always be handled by libpng and
+ * will never be stored in the unknown chunk list. Known chunks listed to
+ * png_set_keep_unknown_chunks will have no effect. If it is set then known
+ * chunks listed with a keep other than AS_DEFAULT will *never* be processed
+ * by libpng, in addition critical chunks must either be processed by the
+ * callback or saved.
+ *
+ * The IHDR and IEND chunks must not be listed. Because this turns off the
+ * default handling for chunks that would otherwise be recognized the
+ * behavior of libpng transformations may well become incorrect!
+ *
+ * WRITE:
+ * When writing chunks the options only apply to the chunks specified by
+ * png_set_unknown_chunks (below), libpng will *always* write known chunks
+ * required by png_set_ calls and will always write the core critical chunks
+ * (as required for PLTE).
+ *
+ * Each chunk in the png_set_unknown_chunks list is looked up in the
+ * png_set_keep_unknown_chunks list to find the keep setting, this is then
+ * interpreted as follows:
+ *
+ * PNG_HANDLE_CHUNK_AS_DEFAULT:
+ * Write safe-to-copy chunks and write other chunks if the global
+ * default is set to _ALWAYS, otherwise don't write this chunk.
+ * PNG_HANDLE_CHUNK_NEVER:
+ * Do not write the chunk.
+ * PNG_HANDLE_CHUNK_IF_SAFE:
+ * Write the chunk if it is safe-to-copy, otherwise do not write it.
+ * PNG_HANDLE_CHUNK_ALWAYS:
+ * Write the chunk.
+ *
+ * Note that the default behavior is effectively the opposite of the read case -
+ * in read unknown chunks are not stored by default, in write they are written
+ * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different
+ * - on write the safe-to-copy bit is checked, on read the critical bit is
+ * checked and on read if the chunk is critical an error will be raised.
+ *
+ * num_chunks:
+ * ===========
+ * If num_chunks is positive, then the "keep" parameter specifies the manner
+ * for handling only those chunks appearing in the chunk_list array,
+ * otherwise the chunk list array is ignored.
+ *
+ * If num_chunks is 0 the "keep" parameter specifies the default behavior for
+ * unknown chunks, as described above.
+ *
+ * If num_chunks is negative, then the "keep" parameter specifies the manner
+ * for handling all unknown chunks plus all chunks recognized by libpng
+ * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to
+ * be processed by libpng.
+ */
+PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr,
+ int keep, png_const_bytep chunk_list, int num_chunks));
+
+/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned;
+ * the result is therefore true (non-zero) if special handling is required,
+ * false for the default handling.
+ */
+PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr,
png_const_bytep chunk_name));
#endif
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
-PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr,
- png_infop info_ptr, png_const_unknown_chunkp unknowns,
+
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_unknown_chunkp unknowns,
int num_unknowns));
+ /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added
+ * unknowns to the location currently stored in the png_struct. This is
+ * invariably the wrong value on write. To fix this call the following API
+ * for each chunk in the list with the correct location. If you know your
+ * code won't be compiled on earlier versions you can rely on
+ * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing
+ * the correct thing.
+ */
+
PNG_EXPORT(175, void, png_set_unknown_chunk_location,
- (png_structp png_ptr, png_infop info_ptr, int chunk, int location));
-PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr,
- png_const_infop info_ptr, png_unknown_chunkpp entries));
+ (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location));
+
+PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_unknown_chunkpp entries));
#endif
/* Png_free_data() will turn off the "valid" flag for anything it frees.
* If you need to turn it off for a chunk that your application has freed,
* you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK);
*/
-PNG_EXPORT(177, void, png_set_invalid,
- (png_structp png_ptr, png_infop info_ptr, int mask));
+PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int mask));
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* The "params" pointer is currently not used and is for future expansion. */
-PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr,
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr,
int transforms, png_voidp params));
-PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr,
+#endif
+#ifdef PNG_WRITE_SUPPORTED
+PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr,
int transforms, png_voidp params));
#endif
+#endif
PNG_EXPORT(180, png_const_charp, png_get_copyright,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
PNG_EXPORT(181, png_const_charp, png_get_header_ver,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
PNG_EXPORT(182, png_const_charp, png_get_header_version,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
PNG_EXPORT(183, png_const_charp, png_get_libpng_ver,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
#ifdef PNG_MNG_FEATURES_SUPPORTED
-PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr,
+PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr,
png_uint_32 mng_features_permitted));
#endif
@@ -2399,75 +2340,77 @@ PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr,
#define PNG_HANDLE_CHUNK_NEVER 1
#define PNG_HANDLE_CHUNK_IF_SAFE 2
#define PNG_HANDLE_CHUNK_ALWAYS 3
+#define PNG_HANDLE_CHUNK_LAST 4
/* Strip the prepended error numbers ("#nnn ") from error and warning
* messages before passing them to the error or warning handler.
*/
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-PNG_EXPORT(185, void, png_set_strip_error_numbers,
- (png_structp png_ptr,
+PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr,
png_uint_32 strip_mode));
#endif
/* Added in libpng-1.2.6 */
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr,
+PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr,
png_uint_32 user_width_max, png_uint_32 user_height_max));
PNG_EXPORT(187, png_uint_32, png_get_user_width_max,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
PNG_EXPORT(188, png_uint_32, png_get_user_height_max,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
/* Added in libpng-1.4.0 */
-PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr,
+PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr,
png_uint_32 user_chunk_cache_max));
PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
/* Added in libpng-1.4.1 */
-PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr,
+PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr,
png_alloc_size_t user_chunk_cache_max));
PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
#endif
#if defined(PNG_INCH_CONVERSIONS_SUPPORTED)
PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_FP_EXPORT(196, float, png_get_x_offset_inches,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed,
- (png_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
#endif
-PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr))
#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed,
- (png_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
#endif
# ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr,
- png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
+PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
int *unit_type));
-# endif /* PNG_pHYs_SUPPORTED */
-#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */
+# endif /* pHYs */
+#endif /* INCH_CONVERSIONS */
/* Added in libpng-1.4.0 */
#ifdef PNG_IO_STATE_SUPPORTED
-PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr));
+PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr));
+
+/* Removed from libpng 1.6; use png_get_io_chunk_type. */
+PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr),
+ PNG_DEPRECATED)
-PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name,
- (png_structp png_ptr), PNG_DEPRECATED);
PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
/* The flags returned by png_get_io_state() are the following: */
# define PNG_IO_NONE 0x0000 /* no I/O at this moment */
@@ -2479,7 +2422,7 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */
# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */
# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */
-#endif /* ?PNG_IO_STATE_SUPPORTED */
+#endif /* IO_STATE */
/* Interlace support. The following macros are always defined so that if
* libpng interlace handling is turned off the macros may be used to handle
@@ -2523,10 +2466,10 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
* necessary to find the row in the output image given a row in an interlaced
* image, so two more macros:
*/
-#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \
- (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
-#define PNG_COL_FROM_PASS_COL(xIn, pass) \
- (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
+#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \
+ (((y_in)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
+#define PNG_COL_FROM_PASS_COL(x_in, pass) \
+ (((x_in)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
/* Two macros which return a boolean (0 or 1) saying whether the given row
* or column is in a particular pass. These use a common utility macro that
@@ -2563,27 +2506,29 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
* (png_uint_16)(alpha) \
+ (png_uint_16)(bg)*(png_uint_16)(255 \
- (png_uint_16)(alpha)) + 128); \
- (composite) = (png_byte)((temp + (temp >> 8)) >> 8); }
+ (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); }
# define png_composite_16(composite, fg, alpha, bg) \
{ png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \
* (png_uint_32)(alpha) \
+ (png_uint_32)(bg)*(65535 \
- (png_uint_32)(alpha)) + 32768); \
- (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
+ (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); }
#else /* Standard method using integer division */
-# define png_composite(composite, fg, alpha, bg) \
- (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \
- (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
- 127) / 255)
+# define png_composite(composite, fg, alpha, bg) \
+ (composite) = \
+ (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \
+ (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
+ 127) / 255))
# define png_composite_16(composite, fg, alpha, bg) \
- (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \
- (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \
- 32767) / 65535)
-#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */
+ (composite) = \
+ (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \
+ (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \
+ 32767) / 65535))
+#endif /* READ_COMPOSITE_NODIV */
#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf));
@@ -2591,7 +2536,7 @@ PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf));
PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf));
#endif
-PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr,
+PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr,
png_const_bytep buf));
/* No png_get_int_16 -- may be added if there's a real need for it. */
@@ -2617,7 +2562,7 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
* The png_get_int_32() routine assumes we are using two's complement
* format for negative values, which is almost certainly true.
*/
-# define png_get_uint_32(buf) \
+# define PNG_get_uint_32(buf) \
(((png_uint_32)(*(buf)) << 24) + \
((png_uint_32)(*((buf) + 1)) << 16) + \
((png_uint_32)(*((buf) + 2)) << 8) + \
@@ -2626,27 +2571,554 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
/* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the
* function) incorrectly returned a value of type png_uint_32.
*/
-# define png_get_uint_16(buf) \
+# define PNG_get_uint_16(buf) \
((png_uint_16) \
(((unsigned int)(*(buf)) << 8) + \
((unsigned int)(*((buf) + 1)))))
-# define png_get_int_32(buf) \
+# define PNG_get_int_32(buf) \
((png_int_32)((*(buf) & 0x80) \
- ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \
+ ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \
: (png_int_32)png_get_uint_32(buf)))
+
+ /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h,
+ * but defining a macro name prefixed with PNG_PREFIX.
+ */
+# ifndef PNG_PREFIX
+# define png_get_uint_32(buf) PNG_get_uint_32(buf)
+# define png_get_uint_16(buf) PNG_get_uint_16(buf)
+# define png_get_int_32(buf) PNG_get_int_32(buf)
+# endif
+#else
+# ifdef PNG_PREFIX
+ /* No macros; revert to the (redefined) function */
+# define PNG_get_uint_32 (png_get_uint_32)
+# define PNG_get_uint_16 (png_get_uint_16)
+# define PNG_get_int_32 (png_get_int_32)
+# endif
#endif
-/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
- * defs
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+PNG_EXPORT(242, void, png_set_check_for_invalid_index,
+ (png_structrp png_ptr, int allowed));
+# ifdef PNG_GET_PALETTE_MAX_SUPPORTED
+PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr,
+ png_const_infop info_ptr));
+# endif
+#endif /* CHECK_FOR_INVALID_INDEX */
+
+/*******************************************************************************
+ * Section 5: SIMPLIFIED API
+ *******************************************************************************
+ *
+ * Please read the documentation in libpng-manual.txt (TODO: write said
+ * documentation) if you don't understand what follows.
+ *
+ * The simplified API hides the details of both libpng and the PNG file format
+ * itself. It allows PNG files to be read into a very limited number of
+ * in-memory bitmap formats or to be written from the same formats. If these
+ * formats do not accomodate your needs then you can, and should, use the more
+ * sophisticated APIs above - these support a wide variety of in-memory formats
+ * and a wide variety of sophisticated transformations to those formats as well
+ * as a wide variety of APIs to manipulate ancillary information.
+ *
+ * To read a PNG file using the simplified API:
+ *
+ * 1) Declare a 'png_image' structure (see below) on the stack, set the
+ * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL
+ * (this is REQUIRED, your program may crash if you don't do it.)
+ * 2) Call the appropriate png_image_begin_read... function.
+ * 3) Set the png_image 'format' member to the required sample format.
+ * 4) Allocate a buffer for the image and, if required, the color-map.
+ * 5) Call png_image_finish_read to read the image and, if required, the
+ * color-map into your buffers.
+ *
+ * There are no restrictions on the format of the PNG input itself; all valid
+ * color types, bit depths, and interlace methods are acceptable, and the
+ * input image is transformed as necessary to the requested in-memory format
+ * during the png_image_finish_read() step. The only caveat is that if you
+ * request a color-mapped image from a PNG that is full-color or makes
+ * complex use of an alpha channel the transformation is extremely lossy and the
+ * result may look terrible.
+ *
+ * To write a PNG file using the simplified API:
+ *
+ * 1) Declare a 'png_image' structure on the stack and memset() it to all zero.
+ * 2) Initialize the members of the structure that describe the image, setting
+ * the 'format' member to the format of the image samples.
+ * 3) Call the appropriate png_image_write... function with a pointer to the
+ * image and, if necessary, the color-map to write the PNG data.
+ *
+ * png_image is a structure that describes the in-memory format of an image
+ * when it is being read or defines the in-memory format of an image that you
+ * need to write:
+ */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+
+#define PNG_IMAGE_VERSION 1
+
+typedef struct png_control *png_controlp;
+typedef struct
+{
+ png_controlp opaque; /* Initialize to NULL, free with png_image_free */
+ png_uint_32 version; /* Set to PNG_IMAGE_VERSION */
+ png_uint_32 width; /* Image width in pixels (columns) */
+ png_uint_32 height; /* Image height in pixels (rows) */
+ png_uint_32 format; /* Image format as defined below */
+ png_uint_32 flags; /* A bit mask containing informational flags */
+ png_uint_32 colormap_entries;
+ /* Number of entries in the color-map */
+
+ /* In the event of an error or warning the following field will be set to a
+ * non-zero value and the 'message' field will contain a '\0' terminated
+ * string with the libpng error or warning message. If both warnings and
+ * an error were encountered, only the error is recorded. If there
+ * are multiple warnings, only the first one is recorded.
+ *
+ * The upper 30 bits of this value are reserved, the low two bits contain
+ * a value as follows:
+ */
+# define PNG_IMAGE_WARNING 1
+# define PNG_IMAGE_ERROR 2
+ /*
+ * The result is a two-bit code such that a value more than 1 indicates
+ * a failure in the API just called:
+ *
+ * 0 - no warning or error
+ * 1 - warning
+ * 2 - error
+ * 3 - error preceded by warning
+ */
+# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1)
+
+ png_uint_32 warning_or_error;
+
+ char message[64];
+} png_image, *png_imagep;
+
+/* The samples of the image have one to four channels whose components have
+ * original values in the range 0 to 1.0:
+ *
+ * 1: A single gray or luminance channel (G).
+ * 2: A gray/luminance channel and an alpha channel (GA).
+ * 3: Three red, green, blue color channels (RGB).
+ * 4: Three color channels and an alpha channel (RGBA).
+ *
+ * The components are encoded in one of two ways:
+ *
+ * a) As a small integer, value 0..255, contained in a single byte. For the
+ * alpha channel the original value is simply value/255. For the color or
+ * luminance channels the value is encoded according to the sRGB specification
+ * and matches the 8-bit format expected by typical display devices.
+ *
+ * The color/gray channels are not scaled (pre-multiplied) by the alpha
+ * channel and are suitable for passing to color management software.
+ *
+ * b) As a value in the range 0..65535, contained in a 2-byte integer. All
+ * channels can be converted to the original value by dividing by 65535; all
+ * channels are linear. Color channels use the RGB encoding (RGB end-points) of
+ * the sRGB specification. This encoding is identified by the
+ * PNG_FORMAT_FLAG_LINEAR flag below.
+ *
+ * When the simplified API needs to convert between sRGB and linear colorspaces,
+ * the actual sRGB transfer curve defined in the sRGB specification (see the
+ * article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2
+ * approximation used elsewhere in libpng.
+ *
+ * When an alpha channel is present it is expected to denote pixel coverage
+ * of the color or luminance channels and is returned as an associated alpha
+ * channel: the color/gray channels are scaled (pre-multiplied) by the alpha
+ * value.
+ *
+ * The samples are either contained directly in the image data, between 1 and 8
+ * bytes per pixel according to the encoding, or are held in a color-map indexed
+ * by bytes in the image data. In the case of a color-map the color-map entries
+ * are individual samples, encoded as above, and the image data has one byte per
+ * pixel to select the relevant sample from the color-map.
+ */
+
+/* PNG_FORMAT_*
+ *
+ * #defines to be used in png_image::format. Each #define identifies a
+ * particular layout of sample data and, if present, alpha values. There are
+ * separate defines for each of the two component encodings.
+ *
+ * A format is built up using single bit flag values. All combinations are
+ * valid. Formats can be built up from the flag values or you can use one of
+ * the predefined values below. When testing formats always use the FORMAT_FLAG
+ * macros to test for individual features - future versions of the library may
+ * add new flags.
+ *
+ * When reading or writing color-mapped images the format should be set to the
+ * format of the entries in the color-map then png_image_{read,write}_colormap
+ * called to read or write the color-map and set the format correctly for the
+ * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly!
+ *
+ * NOTE: libpng can be built with particular features disabled. If you see
+ * compiler errors because the definition of one of the following flags has been
+ * compiled out it is because libpng does not have the required support. It is
+ * possible, however, for the libpng configuration to enable the format on just
+ * read or just write; in that case you may see an error at run time. You can
+ * guard against this by checking for the definition of the appropriate
+ * "_SUPPORTED" macro, one of:
+ *
+ * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED
+ */
+#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */
+#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */
+#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */
+#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */
+
+#ifdef PNG_FORMAT_BGR_SUPPORTED
+# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */
+#endif
+
+#ifdef PNG_FORMAT_AFIRST_SUPPORTED
+# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */
+#endif
+
+/* Commonly used formats have predefined macros.
+ *
+ * First the single byte (sRGB) formats:
+ */
+#define PNG_FORMAT_GRAY 0
+#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA
+#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST)
+#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR
+#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR)
+#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA)
+#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST)
+#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA)
+#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST)
+
+/* Then the linear 2-byte formats. When naming these "Y" is used to
+ * indicate a luminance (gray) channel.
+ */
+#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR
+#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA)
+#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR)
+#define PNG_FORMAT_LINEAR_RGB_ALPHA \
+ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA)
+
+/* With color-mapped formats the image data is one byte for each pixel, the byte
+ * is an index into the color-map which is formatted as above. To obtain a
+ * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP
+ * to one of the above definitions, or you can use one of the definitions below.
+ */
+#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP)
+
+/* PNG_IMAGE macros
+ *
+ * These are convenience macros to derive information from a png_image
+ * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the
+ * actual image sample values - either the entries in the color-map or the
+ * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values
+ * for the pixels and will always return 1 for color-mapped formats. The
+ * remaining macros return information about the rows in the image and the
+ * complete image.
+ *
+ * NOTE: All the macros that take a png_image::format parameter are compile time
+ * constants if the format parameter is, itself, a constant. Therefore these
+ * macros can be used in array declarations and case labels where required.
+ * Similarly the macros are also pre-processor constants (sizeof is not used) so
+ * they can be used in #if tests.
+ *
+ * First the information about the samples.
+ */
+#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\
+ (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1)
+ /* Return the total number of channels in a given format: 1..4 */
+
+#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\
+ ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1)
+ /* Return the size in bytes of a single component of a pixel or color-map
+ * entry (as appropriate) in the image: 1 or 2.
+ */
+
+#define PNG_IMAGE_SAMPLE_SIZE(fmt)\
+ (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt))
+ /* This is the size of the sample data for one sample. If the image is
+ * color-mapped it is the size of one color-map entry (and image pixels are
+ * one byte in size), otherwise it is the size of one image pixel.
+ */
+
+#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\
+ (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256)
+ /* The maximum size of the color-map required by the format expressed in a
+ * count of components. This can be used to compile-time allocate a
+ * color-map:
+ *
+ * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)];
+ *
+ * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)];
+ *
+ * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the
+ * information from one of the png_image_begin_read_ APIs and dynamically
+ * allocate the required memory.
+ */
+
+/* Corresponding information about the pixels */
+#define PNG_IMAGE_PIXEL_(test,fmt)\
+ (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt))
+
+#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\
+ PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt)
+ /* The number of separate channels (components) in a pixel; 1 for a
+ * color-mapped image.
+ */
+
+#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\
+ PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt)
+ /* The size, in bytes, of each component in a pixel; 1 for a color-mapped
+ * image.
+ */
+
+#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt)
+ /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */
+
+/* Information about the whole row, or whole image */
+#define PNG_IMAGE_ROW_STRIDE(image)\
+ (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width)
+ /* Return the total number of components in a single row of the image; this
+ * is the minimum 'row stride', the minimum count of components between each
+ * row. For a color-mapped image this is the minimum number of bytes in a
+ * row.
+ */
+
+#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
+ (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
+ /* Return the size, in bytes, of an image buffer given a png_image and a row
+ * stride - the number of components to leave space for in each row.
+ */
+
+#define PNG_IMAGE_SIZE(image)\
+ PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image))
+ /* Return the size, in bytes, of the image in memory given just a png_image;
+ * the row stride is the minimum stride required for the image.
+ */
+
+#define PNG_IMAGE_COLORMAP_SIZE(image)\
+ (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries)
+ /* Return the size, in bytes, of the color-map of this image. If the image
+ * format is not a color-map format this will return a size sufficient for
+ * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if
+ * you don't want to allocate a color-map in this case.
+ */
+
+/* PNG_IMAGE_FLAG_*
+ *
+ * Flags containing additional information about the image are held in the
+ * 'flags' field of png_image.
+ */
+#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01
+ /* This indicates the the RGB values of the in-memory bitmap do not
+ * correspond to the red, green and blue end-points defined by sRGB.
+ */
+
+#define PNG_IMAGE_FLAG_FAST 0x02
+ /* On write emphasise speed over compression; the resultant PNG file will be
+ * larger but will be produced significantly faster, particular for large
+ * images. Do not use this option for images which will be distributed, only
+ * used it when producing intermediate files that will be read back in
+ * repeatedly. For a typical 24-bit image the option will double the read
+ * speed at the cost of increasing the image size by 25%, however for many
+ * more compressible images the PNG file can be 10 times larger with only a
+ * slight speed gain.
+ */
+
+#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04
+ /* On read if the image is a 16-bit per component image and there is no gAMA
+ * or sRGB chunk assume that the components are sRGB encoded. Notice that
+ * images output by the simplified API always have gamma information; setting
+ * this flag only affects the interpretation of 16-bit images from an
+ * external source. It is recommended that the application expose this flag
+ * to the user; the user can normally easily recognize the difference between
+ * linear and sRGB encoding. This flag has no effect on write - the data
+ * passed to the write APIs must have the correct encoding (as defined
+ * above.)
+ *
+ * If the flag is not set (the default) input 16-bit per component data is
+ * assumed to be linear.
+ *
+ * NOTE: the flag can only be set after the png_image_begin_read_ call,
+ * because that call initializes the 'flags' field.
+ */
+
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+/* READ APIs
+ * ---------
+ *
+ * The png_image passed to the read APIs must have been initialized by setting
+ * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.)
+ */
+#ifdef PNG_STDIO_SUPPORTED
+PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image,
+ const char *file_name));
+ /* The named file is opened for read and the image header is filled in
+ * from the PNG header in the file.
+ */
+
+PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image,
+ FILE* file));
+ /* The PNG header is read from the stdio FILE object. */
+#endif /* STDIO */
+
+PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image,
+ png_const_voidp memory, png_size_t size));
+ /* The PNG header is read from the given memory buffer. */
+
+PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
+ png_const_colorp background, void *buffer, png_int_32 row_stride,
+ void *colormap));
+ /* Finish reading the image into the supplied buffer and clean up the
+ * png_image structure.
+ *
+ * row_stride is the step, in byte or 2-byte units as appropriate,
+ * between adjacent rows. A positive stride indicates that the top-most row
+ * is first in the buffer - the normal top-down arrangement. A negative
+ * stride indicates that the bottom-most row is first in the buffer.
+ *
+ * background need only be supplied if an alpha channel must be removed from
+ * a png_byte format and the removal is to be done by compositing on a solid
+ * color; otherwise it may be NULL and any composition will be done directly
+ * onto the buffer. The value is an sRGB color to use for the background,
+ * for grayscale output the green channel is used.
+ *
+ * background must be supplied when an alpha channel must be removed from a
+ * single byte color-mapped output format, in other words if:
+ *
+ * 1) The original format from png_image_begin_read_from_* had
+ * PNG_FORMAT_FLAG_ALPHA set.
+ * 2) The format set by the application does not.
+ * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and
+ * PNG_FORMAT_FLAG_LINEAR *not* set.
+ *
+ * For linear output removing the alpha channel is always done by compositing
+ * on black and background is ignored.
+ *
+ * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must
+ * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE.
+ * image->colormap_entries will be updated to the actual number of entries
+ * written to the colormap; this may be less than the original value.
+ */
+
+PNG_EXPORT(238, void, png_image_free, (png_imagep image));
+ /* Free any data allocated by libpng in image->opaque, setting the pointer to
+ * NULL. May be called at any time after the structure is initialized.
+ */
+#endif /* SIMPLIFIED_READ */
+
+#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
+#ifdef PNG_STDIO_SUPPORTED
+/* WRITE APIS
+ * ----------
+ * For write you must initialize a png_image structure to describe the image to
+ * be written. To do this use memset to set the whole structure to 0 then
+ * initialize fields describing your image.
+ *
+ * version: must be set to PNG_IMAGE_VERSION
+ * opaque: must be initialized to NULL
+ * width: image width in pixels
+ * height: image height in rows
+ * format: the format of the data (image and color-map) you wish to write
+ * flags: set to 0 unless one of the defined flags applies; set
+ * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB
+ * values do not correspond to the colors in sRGB.
+ * colormap_entries: set to the number of entries in the color-map (0 to 256)
+ */
+PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
+ const char *file, int convert_to_8bit, const void *buffer,
+ png_int_32 row_stride, const void *colormap));
+ /* Write the image to the named file. */
+
+PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
+ int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
+ const void *colormap));
+ /* Write the image to the given (FILE*). */
+
+/* With both write APIs if image is in one of the linear formats with 16-bit
+ * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
+ * gamma encoded according to the sRGB specification, otherwise a 16-bit linear
+ * encoded PNG file is written.
+ *
+ * With color-mapped data formats the colormap parameter point to a color-map
+ * with at least image->colormap_entries encoded in the specified format. If
+ * the format is linear the written PNG color-map will be converted to sRGB
+ * regardless of the convert_to_8_bit flag.
+ *
+ * With all APIs row_stride is handled as in the read APIs - it is the spacing
+ * from one row to the next in component sized units (1 or 2 bytes) and if
+ * negative indicates a bottom-up row layout in the buffer. If row_stride is zero,
+ * libpng will calculate it for you from the image width and number of channels.
+ *
+ * Note that the write API does not support interlacing, sub-8-bit pixels, indexed
+ * PNG (color_type 3) or most ancillary chunks.
+ */
+#endif /* STDIO */
+#endif /* SIMPLIFIED_WRITE */
+/*******************************************************************************
+ * END OF SIMPLIFIED API
+ ******************************************************************************/
+#endif /* SIMPLIFIED_{READ|WRITE} */
+
+/*******************************************************************************
+ * Section 6: IMPLEMENTATION OPTIONS
+ *******************************************************************************
+ *
+ * Support for arbitrary implementation-specific optimizations. The API allows
+ * particular options to be turned on or off. 'Option' is the number of the
+ * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given
+ * by the PNG_OPTION_ defines below.
+ *
+ * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions,
+ * are detected at run time, however sometimes it may be impossible
+ * to do this in user mode, in which case it is necessary to discover
+ * the capabilities in an OS specific way. Such capabilities are
+ * listed here when libpng has support for them and must be turned
+ * ON by the application if present.
+ *
+ * SOFTWARE: sometimes software optimizations actually result in performance
+ * decrease on some architectures or systems, or with some sets of
+ * PNG images. 'Software' options allow such optimizations to be
+ * selected at run time.
+ */
+#ifdef PNG_SET_OPTION_SUPPORTED
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */
+#endif
+#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */
+#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */
+#define PNG_OPTION_NEXT 6 /* Next option - numbers must be even */
+
+/* Return values: NOTE: there are four values and 'off' is *not* zero */
+#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */
+#define PNG_OPTION_INVALID 1 /* Option number out of range */
+#define PNG_OPTION_OFF 2
+#define PNG_OPTION_ON 3
+
+PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
+ int onoff));
+#endif /* SET_OPTION */
+
+/*******************************************************************************
+ * END OF HARDWARE AND SOFTWARE OPTIONS
+ ******************************************************************************/
+
+/* Maintainer: Put new public prototypes here ^, in libpng.3, in project
+ * defs, and in scripts/symbols.def.
*/
/* The last ordinal number (this is the *last* one already used; the next
- * one to use is one more than this.) Maintainer, remember to add an entry to
- * scripts/symbols.def as well.
+ * one to use is one more than this.)
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
- PNG_EXPORT_LAST_ORDINAL(233);
+ PNG_EXPORT_LAST_ORDINAL(244);
#endif
#ifdef __cplusplus
diff --git a/thirdparty/libpng/pngconf.h b/thirdparty/libpng/pngconf.h
index 1aa268be..93446545 100644
--- a/thirdparty/libpng/pngconf.h
+++ b/thirdparty/libpng/pngconf.h
@@ -1,9 +1,9 @@
/* pngconf.h - machine configurable file for libpng
*
- * libpng version 1.5.9 - February 18, 2012
+ * libpng version 1.6.21, January 15, 2016
*
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -11,9 +11,7 @@
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*
- */
-
-/* Any machine specific code is near the front of this file, so if you
+ * Any machine specific code is near the front of this file, so if you
* are configuring libpng for a machine, you may want to read the section
* starting here down to where it starts to typedef png_color, png_text,
* and png_info.
@@ -22,37 +20,53 @@
#ifndef PNGCONF_H
#define PNGCONF_H
-#ifndef PNG_BUILDING_SYMBOL_TABLE
-/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C
- * definition file for machine specific limits, this may impact the
- * correctness of the definitons below (see uses of INT_MAX).
- */
-# ifndef PNG_NO_LIMITS_H
-# include <limits.h>
-# endif
+#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */
-/* For the memory copy APIs (i.e. the standard definitions of these),
- * because this file defines png_memcpy and so on the base APIs must
- * be defined here.
+/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C
+ * compiler for correct compilation. The following header files are required by
+ * the standard. If your compiler doesn't provide these header files, or they
+ * do not match the standard, you will need to provide/improve them.
*/
-# ifdef BSD
-# include <strings.h>
-# else
-# include <string.h>
-# endif
-
-/* For png_FILE_p - this provides the standard definition of a
- * FILE
+#include <limits.h>
+#include <stddef.h>
+
+/* Library header files. These header files are all defined by ISOC90; libpng
+ * expects conformant implementations, however, an ISOC90 conformant system need
+ * not provide these header files if the functionality cannot be implemented.
+ * In this case it will be necessary to disable the relevant parts of libpng in
+ * the build of pnglibconf.h.
+ *
+ * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not
+ * include this unnecessary header file.
*/
-# ifdef PNG_STDIO_SUPPORTED
-# include <stdio.h>
-# endif
+
+#ifdef PNG_STDIO_SUPPORTED
+ /* Required for the definition of FILE: */
+# include <stdio.h>
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+ /* Required for the definition of jmp_buf and the declaration of longjmp: */
+# include <setjmp.h>
#endif
-/* This controls optimization of the reading of 16 and 32 bit values
+#ifdef PNG_CONVERT_tIME_SUPPORTED
+ /* Required for struct tm: */
+# include <time.h>
+#endif
+
+#endif /* PNG_BUILDING_SYMBOL_TABLE */
+
+/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using
+ * PNG_NO_CONST; this is no longer supported except for data declarations which
+ * apparently still cause problems in 2011 on some compilers.
+ */
+#define PNG_CONST const /* backward compatibility only */
+
+/* This controls optimization of the reading of 16-bit and 32-bit values
* from PNG files. It can be set on a per-app-file basis - it
- * just changes whether a macro is used to the function is called.
- * The library builder sets the default, if read functions are not
+ * just changes whether a macro is used when the function is called.
+ * The library builder sets the default; if read functions are not
* built into the library the macro implementation is forced on.
*/
#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED
@@ -72,28 +86,13 @@
* may be changed on a per-file basis when compiling against libpng.
*/
-/* The PNGARG macro protects us against machines that don't have function
- * prototypes (ie K&R style headers). If your compiler does not handle
- * function prototypes, define this macro and use the included ansi2knr.
- * I've always been able to use _NO_PROTO as the indicator, but you may
- * need to drag the empty declaration out in front of here, or change the
- * ifdef to suit your own needs.
+/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect
+ * against legacy (pre ISOC90) compilers that did not understand function
+ * prototypes. It is not required for modern C compilers.
*/
#ifndef PNGARG
-
-# ifdef OF /* zlib prototype munger */
-# define PNGARG(arglist) OF(arglist)
-# else
-
-# ifdef _NO_PROTO
-# define PNGARG(arglist) ()
-# else
-# define PNGARG(arglist) arglist
-# endif /* _NO_PROTO */
-
-# endif /* OF */
-
-#endif /* PNGARG */
+# define PNGARG(arglist) arglist
+#endif
/* Function calling conventions.
* =============================
@@ -177,18 +176,16 @@
* ==========================
* This code is used at build time to find PNG_IMPEXP, the API settings
* and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL
- * import processing is possible. On Windows/x86 systems it also sets
+ * import processing is possible. On Windows systems it also sets
* compiler-specific macros to the values required to change the calling
* conventions of the various functions.
*/
-#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
- defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\
- ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\
- defined(_M_X64) || defined(_M_IA64) )
- /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes
- * builds under Cygwin or MinGW. Also includes Watcom builds but these need
- * special treatment because they are not compatible with GCC or Visual C
- * because of different calling conventions.
+#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
+ defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+ /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or
+ * MinGW on any architecture currently supported by Windows. Also includes
+ * Watcom builds but these need special treatment because they are not
+ * compatible with GCC or Visual C because of different calling conventions.
*/
# if PNG_API_RULE == 2
/* If this line results in an error, either because __watcall is not
@@ -199,9 +196,12 @@
# define PNGCAPI __watcall
# endif
-# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
+# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800))
# define PNGCAPI __cdecl
# if PNG_API_RULE == 1
+ /* If this line results in an error __stdcall is not understood and
+ * PNG_API_RULE should not have been set to '1'.
+ */
# define PNGAPI __stdcall
# endif
# else
@@ -216,10 +216,11 @@
# define PNGAPI _stdcall
# endif
# endif /* compiler/api */
+
/* NOTE: PNGCBAPI always defaults to PNGCAPI. */
# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
- ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed
+# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed"
# endif
# if (defined(_MSC_VER) && _MSC_VER < 800) ||\
@@ -239,7 +240,7 @@
# endif
# endif /* compiler */
-#else /* !Windows/x86 */
+#else /* !Windows */
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
# define PNGAPI _System
# else /* !Windows/x86 && !OS/2 */
@@ -294,11 +295,11 @@
* table entries, so we discard it here. See the .dfn files in the
* scripts directory.
*/
-#ifndef PNG_EXPORTA
-# define PNG_EXPORTA(ordinal, type, name, args, attributes)\
- PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \
- extern attributes)
+#ifndef PNG_EXPORTA
+# define PNG_EXPORTA(ordinal, type, name, args, attributes) \
+ PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \
+ PNG_LINKAGE_API attributes)
#endif
/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument,
@@ -306,7 +307,7 @@
*/
#define PNG_EMPTY /*empty list*/
-#define PNG_EXPORT(ordinal, type, name, args)\
+#define PNG_EXPORT(ordinal, type, name, args) \
PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY)
/* Use PNG_REMOVED to comment out a removed interface. */
@@ -333,40 +334,73 @@
#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
/* Support for compiler specific function attributes. These are used
- * so that where compiler support is available incorrect use of API
+ * so that where compiler support is available, incorrect use of API
* functions in png.h will generate compiler warnings. Added at libpng
- * version 1.2.41.
+ * version 1.2.41. Disabling these removes the warnings but may also produce
+ * less efficient code.
*/
-# if defined(__GNUC__)
-# ifndef PNG_USE_RESULT
+# if defined(__clang__) && defined(__has_attribute)
+ /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */
+# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__)
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
# endif
-# ifndef PNG_NORETURN
-# define PNG_NORETURN __attribute__((__noreturn__))
+# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__)
+# define PNG_NORETURN __attribute__((__noreturn__))
# endif
-# ifndef PNG_ALLOCATED
-# define PNG_ALLOCATED __attribute__((__malloc__))
+# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__)
+# define PNG_ALLOCATED __attribute__((__malloc__))
# endif
-# ifndef PNG_DEPRECATED
+# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__)
# define PNG_DEPRECATED __attribute__((__deprecated__))
# endif
-# ifndef PNG_PRIVATE
-# if 0 /* Doesn't work so we use deprecated instead*/
-# define PNG_PRIVATE \
- __attribute__((warning("This function is not exported by libpng.")))
-# else
-# define PNG_PRIVATE \
- __attribute__((__deprecated__))
+# if !defined(PNG_PRIVATE)
+# ifdef __has_extension
+# if __has_extension(attribute_unavailable_with_message)
+# define PNG_PRIVATE __attribute__((__unavailable__(\
+ "This function is not exported by libpng.")))
+# endif
# endif
# endif
-# endif /* __GNUC__ */
+# ifndef PNG_RESTRICT
+# define PNG_RESTRICT __restrict
+# endif
-# if defined(_MSC_VER) && (_MSC_VER >= 1300)
+# elif defined(__GNUC__)
+# ifndef PNG_USE_RESULT
+# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
+# endif
+# ifndef PNG_NORETURN
+# define PNG_NORETURN __attribute__((__noreturn__))
+# endif
+# if __GNUC__ >= 3
+# ifndef PNG_ALLOCATED
+# define PNG_ALLOCATED __attribute__((__malloc__))
+# endif
+# ifndef PNG_DEPRECATED
+# define PNG_DEPRECATED __attribute__((__deprecated__))
+# endif
+# ifndef PNG_PRIVATE
+# if 0 /* Doesn't work so we use deprecated instead*/
+# define PNG_PRIVATE \
+ __attribute__((warning("This function is not exported by libpng.")))
+# else
+# define PNG_PRIVATE \
+ __attribute__((__deprecated__))
+# endif
+# endif
+# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1))
+# ifndef PNG_RESTRICT
+# define PNG_RESTRICT __restrict
+# endif
+# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */
+# endif /* __GNUC__ >= 3 */
+
+# elif defined(_MSC_VER) && (_MSC_VER >= 1300)
# ifndef PNG_USE_RESULT
# define PNG_USE_RESULT /* not supported */
# endif
# ifndef PNG_NORETURN
-# define PNG_NORETURN __declspec(noreturn)
+# define PNG_NORETURN __declspec(noreturn)
# endif
# ifndef PNG_ALLOCATED
# if (_MSC_VER >= 1400)
@@ -379,7 +413,17 @@
# ifndef PNG_PRIVATE
# define PNG_PRIVATE __declspec(deprecated)
# endif
-# endif /* _MSC_VER */
+# ifndef PNG_RESTRICT
+# if (_MSC_VER >= 1400)
+# define PNG_RESTRICT __restrict
+# endif
+# endif
+
+# elif defined(__WATCOMC__)
+# ifndef PNG_RESTRICT
+# define PNG_RESTRICT __restrict
+# endif
+# endif
#endif /* PNG_PEDANTIC_WARNINGS */
#ifndef PNG_DEPRECATED
@@ -397,10 +441,14 @@
#ifndef PNG_PRIVATE
# define PNG_PRIVATE /* This is a private libpng function */
#endif
+#ifndef PNG_RESTRICT
+# define PNG_RESTRICT /* The C99 "restrict" feature */
+#endif
+
#ifndef PNG_FP_EXPORT /* A floating point API. */
# ifdef PNG_FLOATING_POINT_SUPPORTED
# define PNG_FP_EXPORT(ordinal, type, name, args)\
- PNG_EXPORT(ordinal, type, name, args)
+ PNG_EXPORT(ordinal, type, name, args);
# else /* No floating point APIs */
# define PNG_FP_EXPORT(ordinal, type, name, args)
# endif
@@ -408,189 +456,167 @@
#ifndef PNG_FIXED_EXPORT /* A fixed point API. */
# ifdef PNG_FIXED_POINT_SUPPORTED
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
- PNG_EXPORT(ordinal, type, name, args)
+ PNG_EXPORT(ordinal, type, name, args);
# else /* No fixed point APIs */
# define PNG_FIXED_EXPORT(ordinal, type, name, args)
# endif
#endif
-/* The following uses const char * instead of char * for error
- * and warning message functions, so some compilers won't complain.
- * If you do not want to use const, define PNG_NO_CONST here.
+#ifndef PNG_BUILDING_SYMBOL_TABLE
+/* Some typedefs to get us started. These should be safe on most of the common
+ * platforms.
+ *
+ * png_uint_32 and png_int_32 may, currently, be larger than required to hold a
+ * 32-bit value however this is not normally advisable.
+ *
+ * png_uint_16 and png_int_16 should always be two bytes in size - this is
+ * verified at library build time.
*
- * This should not change how the APIs are called, so it can be done
- * on a per-file basis in the application.
+ * png_byte must always be one byte in size.
+ *
+ * The checks below use constants from limits.h, as defined by the ISOC90
+ * standard.
*/
-#ifndef PNG_CONST
-# ifndef PNG_NO_CONST
-# define PNG_CONST const
-# else
-# define PNG_CONST
-# endif
+#if CHAR_BIT == 8 && UCHAR_MAX == 255
+ typedef unsigned char png_byte;
+#else
+# error "libpng requires 8-bit bytes"
#endif
-/* Some typedefs to get us started. These should be safe on most of the
- * common platforms. The typedefs should be at least as large as the
- * numbers suggest (a png_uint_32 must be at least 32 bits long), but they
- * don't have to be exactly that size. Some compilers dislike passing
- * unsigned shorts as function parameters, so you may be better off using
- * unsigned int for png_uint_16.
- */
+#if INT_MIN == -32768 && INT_MAX == 32767
+ typedef int png_int_16;
+#elif SHRT_MIN == -32768 && SHRT_MAX == 32767
+ typedef short png_int_16;
+#else
+# error "libpng requires a signed 16-bit type"
+#endif
-#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL)
-typedef unsigned int png_uint_32;
-typedef int png_int_32;
+#if UINT_MAX == 65535
+ typedef unsigned int png_uint_16;
+#elif USHRT_MAX == 65535
+ typedef unsigned short png_uint_16;
#else
-typedef unsigned long png_uint_32;
-typedef long png_int_32;
+# error "libpng requires an unsigned 16-bit type"
#endif
-typedef unsigned short png_uint_16;
-typedef short png_int_16;
-typedef unsigned char png_byte;
-#ifdef PNG_NO_SIZE_T
-typedef unsigned int png_size_t;
+#if INT_MIN < -2147483646 && INT_MAX > 2147483646
+ typedef int png_int_32;
+#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646
+ typedef long int png_int_32;
#else
-typedef size_t png_size_t;
+# error "libpng requires a signed 32-bit (or more) type"
#endif
-#define png_sizeof(x) (sizeof (x))
-/* The following is needed for medium model support. It cannot be in the
- * pngpriv.h header. Needs modification for other compilers besides
- * MSC. Model independent support declares all arrays and pointers to be
- * large using the far keyword. The zlib version used must also support
- * model independent data. As of version zlib 1.0.4, the necessary changes
- * have been made in zlib. The USE_FAR_KEYWORD define triggers other
- * changes that are needed. (Tim Wegner)
- */
+#if UINT_MAX > 4294967294
+ typedef unsigned int png_uint_32;
+#elif ULONG_MAX > 4294967294
+ typedef unsigned long int png_uint_32;
+#else
+# error "libpng requires an unsigned 32-bit (or more) type"
+#endif
-/* Separate compiler dependencies (problem here is that zlib.h always
- * defines FAR. (SJT)
- */
-#ifdef __BORLANDC__
-# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
-# define LDATA 1
-# else
-# define LDATA 0
-# endif
- /* GRR: why is Cygwin in here? Cygwin is not Borland C... */
-# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__)
-# define PNG_MAX_MALLOC_64K /* only used in build */
-# if (LDATA != 1)
-# ifndef FAR
-# define FAR __far
-# endif
-# define USE_FAR_KEYWORD
-# endif /* LDATA != 1 */
- /* Possibly useful for moving data out of default segment.
- * Uncomment it if you want. Could also define FARDATA as
- * const if your compiler supports it. (SJT)
-# define FARDATA FAR
- */
-# endif /* __WIN32__, __FLAT__, __CYGWIN__ */
-#endif /* __BORLANDC__ */
-
-
-/* Suggest testing for specific compiler first before testing for
- * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM,
- * making reliance oncertain keywords suspect. (SJT)
+/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however,
+ * requires an ISOC90 compiler and relies on consistent behavior of sizeof.
*/
+typedef size_t png_size_t;
+typedef ptrdiff_t png_ptrdiff_t;
-/* MSC Medium model */
-#ifdef FAR
-# ifdef M_I86MM
-# define USE_FAR_KEYWORD
-# define FARDATA FAR
-# include <dos.h>
+/* libpng needs to know the maximum value of 'size_t' and this controls the
+ * definition of png_alloc_size_t, below. This maximum value of size_t limits
+ * but does not control the maximum allocations the library makes - there is
+ * direct application control of this through png_set_user_limits().
+ */
+#ifndef PNG_SMALL_SIZE_T
+ /* Compiler specific tests for systems where size_t is known to be less than
+ * 32 bits (some of these systems may no longer work because of the lack of
+ * 'far' support; see above.)
+ */
+# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\
+ (defined(_MSC_VER) && defined(MAXSEG_64K))
+# define PNG_SMALL_SIZE_T
# endif
#endif
-/* SJT: default case */
-#ifndef FAR
-# define FAR
+/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no
+ * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to
+ * png_alloc_size_t are not necessary; in fact, it is recommended not to use
+ * them at all so that the compiler can complain when something turns out to be
+ * problematic.
+ *
+ * Casts in the other direction (from png_alloc_size_t to png_size_t or
+ * png_uint_32) should be explicitly applied; however, we do not expect to
+ * encounter practical situations that require such conversions.
+ *
+ * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than
+ * 4294967295 - i.e. less than the maximum value of png_uint_32.
+ */
+#ifdef PNG_SMALL_SIZE_T
+ typedef png_uint_32 png_alloc_size_t;
+#else
+ typedef png_size_t png_alloc_size_t;
#endif
-/* At this point FAR is always defined */
-#ifndef FARDATA
-# define FARDATA
-#endif
+/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler
+ * implementations of Intel CPU specific support of user-mode segmented address
+ * spaces, where 16-bit pointers address more than 65536 bytes of memory using
+ * separate 'segment' registers. The implementation requires two different
+ * types of pointer (only one of which includes the segment value.)
+ *
+ * If required this support is available in version 1.2 of libpng and may be
+ * available in versions through 1.5, although the correctness of the code has
+ * not been verified recently.
+ */
-/* Typedef for floating-point numbers that are converted
- * to fixed-point with a multiple of 100,000, e.g., gamma
+/* Typedef for floating-point numbers that are converted to fixed-point with a
+ * multiple of 100,000, e.g., gamma
*/
typedef png_int_32 png_fixed_point;
/* Add typedefs for pointers */
-typedef void FAR * png_voidp;
-typedef PNG_CONST void FAR * png_const_voidp;
-typedef png_byte FAR * png_bytep;
-typedef PNG_CONST png_byte FAR * png_const_bytep;
-typedef png_uint_32 FAR * png_uint_32p;
-typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p;
-typedef png_int_32 FAR * png_int_32p;
-typedef PNG_CONST png_int_32 FAR * png_const_int_32p;
-typedef png_uint_16 FAR * png_uint_16p;
-typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p;
-typedef png_int_16 FAR * png_int_16p;
-typedef PNG_CONST png_int_16 FAR * png_const_int_16p;
-typedef char FAR * png_charp;
-typedef PNG_CONST char FAR * png_const_charp;
-typedef png_fixed_point FAR * png_fixed_point_p;
-typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p;
-typedef png_size_t FAR * png_size_tp;
-typedef PNG_CONST png_size_t FAR * png_const_size_tp;
+typedef void * png_voidp;
+typedef const void * png_const_voidp;
+typedef png_byte * png_bytep;
+typedef const png_byte * png_const_bytep;
+typedef png_uint_32 * png_uint_32p;
+typedef const png_uint_32 * png_const_uint_32p;
+typedef png_int_32 * png_int_32p;
+typedef const png_int_32 * png_const_int_32p;
+typedef png_uint_16 * png_uint_16p;
+typedef const png_uint_16 * png_const_uint_16p;
+typedef png_int_16 * png_int_16p;
+typedef const png_int_16 * png_const_int_16p;
+typedef char * png_charp;
+typedef const char * png_const_charp;
+typedef png_fixed_point * png_fixed_point_p;
+typedef const png_fixed_point * png_const_fixed_point_p;
+typedef png_size_t * png_size_tp;
+typedef const png_size_t * png_const_size_tp;
#ifdef PNG_STDIO_SUPPORTED
typedef FILE * png_FILE_p;
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
-typedef double FAR * png_doublep;
-typedef PNG_CONST double FAR * png_const_doublep;
+typedef double * png_doublep;
+typedef const double * png_const_doublep;
#endif
/* Pointers to pointers; i.e. arrays */
-typedef png_byte FAR * FAR * png_bytepp;
-typedef png_uint_32 FAR * FAR * png_uint_32pp;
-typedef png_int_32 FAR * FAR * png_int_32pp;
-typedef png_uint_16 FAR * FAR * png_uint_16pp;
-typedef png_int_16 FAR * FAR * png_int_16pp;
-typedef PNG_CONST char FAR * FAR * png_const_charpp;
-typedef char FAR * FAR * png_charpp;
-typedef png_fixed_point FAR * FAR * png_fixed_point_pp;
+typedef png_byte * * png_bytepp;
+typedef png_uint_32 * * png_uint_32pp;
+typedef png_int_32 * * png_int_32pp;
+typedef png_uint_16 * * png_uint_16pp;
+typedef png_int_16 * * png_int_16pp;
+typedef const char * * png_const_charpp;
+typedef char * * png_charpp;
+typedef png_fixed_point * * png_fixed_point_pp;
#ifdef PNG_FLOATING_POINT_SUPPORTED
-typedef double FAR * FAR * png_doublepp;
+typedef double * * png_doublepp;
#endif
/* Pointers to pointers to pointers; i.e., pointer to array */
-typedef char FAR * FAR * FAR * png_charppp;
+typedef char * * * png_charppp;
-/* png_alloc_size_t is guaranteed to be no smaller than png_size_t,
- * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32
- * to png_alloc_size_t are not necessary; in fact, it is recommended
- * not to use them at all so that the compiler can complain when something
- * turns out to be problematic.
- * Casts in the other direction (from png_alloc_size_t to png_size_t or
- * png_uint_32) should be explicitly applied; however, we do not expect
- * to encounter practical situations that require such conversions.
- */
-#if defined(__TURBOC__) && !defined(__FLAT__)
- typedef unsigned long png_alloc_size_t;
-#else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- typedef unsigned long png_alloc_size_t;
-# else
- /* This is an attempt to detect an old Windows system where (int) is
- * actually 16 bits, in that case png_malloc must have an argument with a
- * bigger size to accomodate the requirements of the library.
- */
-# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \
- (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL)
- typedef DWORD png_alloc_size_t;
-# else
- typedef png_size_t png_alloc_size_t;
-# endif
-# endif
-#endif
+#endif /* PNG_BUILDING_SYMBOL_TABLE */
#endif /* PNGCONF_H */
diff --git a/thirdparty/libpng/pngdebug.h b/thirdparty/libpng/pngdebug.h
index 16f81fdd..15a7ed0c 100644
--- a/thirdparty/libpng/pngdebug.h
+++ b/thirdparty/libpng/pngdebug.h
@@ -1,12 +1,11 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.8 [December 19, 2013]
+ * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -25,7 +24,7 @@
* (actually ((void)0)).
*
* level: level of detail of message, starting at 0. A level 'n'
- * message is preceded by 'n' tab characters (not implemented
+ * message is preceded by 'n' 3-space indentations (not implemented
* on Microsoft compilers unless PNG_DEBUG_FILE is also
* defined, to allow debug DLL compilation with no standard IO).
* message: a printf(3) style text string. A trailing '\n' is added
@@ -77,32 +76,29 @@
# endif /* PNG_DEBUG_FILE */
# if (PNG_DEBUG > 1)
-/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on
- * non-ISO compilers
- */
# ifdef __STDC__
# ifndef png_debug
# define png_debug(l,m) \
do { \
int num_tabs=l; \
- fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
- (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : "")))); \
} while (0)
# endif
# ifndef png_debug1
# define png_debug1(l,m,p1) \
do { \
int num_tabs=l; \
- fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
- (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1); \
} while (0)
# endif
# ifndef png_debug2
# define png_debug2(l,m,p1,p2) \
do { \
int num_tabs=l; \
- fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
- (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1,p2);\
} while (0)
# endif
# else /* __STDC __ */
diff --git a/thirdparty/libpng/pngerror.c b/thirdparty/libpng/pngerror.c
index 95002f84..6904bea1 100644
--- a/thirdparty/libpng/pngerror.c
+++ b/thirdparty/libpng/pngerror.c
@@ -1,8 +1,8 @@
/* pngerror.c - stub functions for i/o and memory allocation
*
- * Last changed in libpng 1.5.8 [February 1, 2011]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -20,14 +20,14 @@
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-static PNG_FUNCTION(void, png_default_error,PNGARG((png_structp png_ptr,
+static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr,
png_const_charp error_message)),PNG_NORETURN);
#ifdef PNG_WARNINGS_SUPPORTED
static void /* PRIVATE */
-png_default_warning PNGARG((png_structp png_ptr,
+png_default_warning PNGARG((png_const_structrp png_ptr,
png_const_charp warning_message));
-#endif /* PNG_WARNINGS_SUPPORTED */
+#endif /* WARNINGS */
/* This function is called whenever there is a fatal error. This function
* should not be changed. If there is a need to handle errors differently,
@@ -36,14 +36,15 @@ png_default_warning PNGARG((png_structp png_ptr,
*/
#ifdef PNG_ERROR_TEXT_SUPPORTED
PNG_FUNCTION(void,PNGAPI
-png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
+png_error,(png_const_structrp png_ptr, png_const_charp error_message),
+ PNG_NORETURN)
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
char msg[16];
if (png_ptr != NULL)
{
- if (png_ptr->flags&
- (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+ if ((png_ptr->flags &
+ (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0
{
if (*error_message == PNG_LITERAL_SHARP)
{
@@ -53,7 +54,7 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
if (error_message[offset] == ' ')
break;
- if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+ if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
{
int i;
for (i = 0; i < offset - 1; i++)
@@ -68,7 +69,7 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
else
{
- if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+ if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
{
msg[0] = '0';
msg[1] = '\0';
@@ -79,7 +80,8 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
}
#endif
if (png_ptr != NULL && png_ptr->error_fn != NULL)
- (*(png_ptr->error_fn))(png_ptr, error_message);
+ (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
+ error_message);
/* If the custom handler doesn't exist, or if it returns,
use the default handler, which will not return. */
@@ -87,7 +89,7 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
}
#else
PNG_FUNCTION(void,PNGAPI
-png_err,(png_structp png_ptr),PNG_NORETURN)
+png_err,(png_const_structrp png_ptr),PNG_NORETURN)
{
/* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
* erroneously as '\0', instead of the empty string "". This was
@@ -95,13 +97,13 @@ png_err,(png_structp png_ptr),PNG_NORETURN)
* will crash in this case.
*/
if (png_ptr != NULL && png_ptr->error_fn != NULL)
- (*(png_ptr->error_fn))(png_ptr, "");
+ (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), "");
/* If the custom handler doesn't exist, or if it returns,
use the default handler, which will not return. */
png_default_error(png_ptr, "");
}
-#endif /* PNG_ERROR_TEXT_SUPPORTED */
+#endif /* ERROR_TEXT */
/* Utility to safely appends strings to a buffer. This never errors out so
* error checking is not required in the caller.
@@ -150,7 +152,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_fixed:
/* Needs five digits (the fraction) */
mincount = 5;
- if (output || number % 10 != 0)
+ if (output != 0 || number % 10 != 0)
{
*--end = digits[number % 10];
output = 1;
@@ -161,7 +163,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02u:
/* Expects at least 2 digits. */
mincount = 2;
- /* fall through */
+ /* FALL THROUGH */
case PNG_NUMBER_FORMAT_u:
*--end = digits[number % 10];
@@ -171,7 +173,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02x:
/* This format expects at least two digits */
mincount = 2;
- /* fall through */
+ /* FALL THROUGH */
case PNG_NUMBER_FORMAT_x:
*--end = digits[number & 0xf];
@@ -187,13 +189,13 @@ png_format_number(png_const_charp start, png_charp end, int format,
++count;
/* Float a fixed number here: */
- if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start)
+ if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
{
/* End of the fraction, but maybe nothing was output? In that case
* drop the decimal point. If the number is a true zero handle that
* here.
*/
- if (output)
+ if (output != 0)
*--end = '.';
else if (number == 0) /* and !output */
*--end = '0';
@@ -211,14 +213,14 @@ png_format_number(png_const_charp start, png_charp end, int format,
* png_set_error_fn() to replace the warning function at run-time.
*/
void PNGAPI
-png_warning(png_structp png_ptr, png_const_charp warning_message)
+png_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
int offset = 0;
if (png_ptr != NULL)
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
- if (png_ptr->flags&
- (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+ if ((png_ptr->flags &
+ (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
#endif
{
if (*warning_message == PNG_LITERAL_SHARP)
@@ -230,7 +232,8 @@ png_warning(png_structp png_ptr, png_const_charp warning_message)
}
}
if (png_ptr != NULL && png_ptr->warning_fn != NULL)
- (*(png_ptr->warning_fn))(png_ptr, warning_message + offset);
+ (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
+ warning_message + offset);
else
png_default_warning(png_ptr, warning_message + offset);
}
@@ -278,7 +281,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format,
}
void
-png_formatted_warning(png_structp png_ptr, png_warning_parameters p,
+png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p,
png_const_charp message)
{
/* The internal buffer is just 192 bytes - enough for all our messages,
@@ -346,29 +349,79 @@ png_formatted_warning(png_structp png_ptr, png_warning_parameters p,
/* i is always less than (sizeof msg), so: */
msg[i] = '\0';
- /* And this is the formatted message, it may be larger than
- * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these are
- * not (currently) formatted.
+ /* And this is the formatted message. It may be larger than
+ * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
+ * are not (currently) formatted.
*/
png_warning(png_ptr, msg);
}
-#endif /* PNG_WARNINGS_SUPPORTED */
+#endif /* WARNINGS */
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
-png_benign_error(png_structp png_ptr, png_const_charp error_message)
+png_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
{
- if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN)
+ if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
+ {
+# ifdef PNG_READ_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ png_ptr->chunk_name != 0)
+ png_chunk_warning(png_ptr, error_message);
+ else
+# endif
+ png_warning(png_ptr, error_message);
+ }
+
+ else
+ {
+# ifdef PNG_READ_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ png_ptr->chunk_name != 0)
+ png_chunk_error(png_ptr, error_message);
+ else
+# endif
+ png_error(png_ptr, error_message);
+ }
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
+}
+
+void /* PRIVATE */
+png_app_warning(png_const_structrp png_ptr, png_const_charp error_message)
+{
+ if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0)
png_warning(png_ptr, error_message);
else
png_error(png_ptr, error_message);
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
}
-#endif
+void /* PRIVATE */
+png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
+{
+ if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0)
+ png_warning(png_ptr, error_message);
+ else
+ png_error(png_ptr, error_message);
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
+}
+#endif /* BENIGN_ERRORS */
+
+#define PNG_MAX_ERROR_TEXT 196 /* Currently limited by profile_error in png.c */
+#if defined(PNG_WARNINGS_SUPPORTED) || \
+ (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED))
/* These utilities are used internally to build an error message that relates
* to the current chunk. The chunk name comes from png_ptr->chunk_name,
- * this is used to prefix the message. The message is limited in length
- * to 63 bytes, the name characters are output as hex digits wrapped in []
+ * which is used to prefix the message. The message is limited in length
+ * to 63 bytes. The name characters are output as hex digits wrapped in []
* if the character is invalid.
*/
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
@@ -377,10 +430,8 @@ static PNG_CONST char png_digit[16] = {
'A', 'B', 'C', 'D', 'E', 'F'
};
-#define PNG_MAX_ERROR_TEXT 64
-#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
static void /* PRIVATE */
-png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
+png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
error_message)
{
png_uint_32 chunk_name = png_ptr->chunk_name;
@@ -391,7 +442,7 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
int c = (int)(chunk_name >> ishift) & 0xff;
ishift -= 8;
- if (isnonalpha(c))
+ if (isnonalpha(c) != 0)
{
buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
buffer[iout++] = png_digit[(c & 0xf0) >> 4];
@@ -422,11 +473,11 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
buffer[iout] = '\0';
}
}
-#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */
+#endif /* WARNINGS || ERROR_TEXT */
#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
PNG_FUNCTION(void,PNGAPI
-png_chunk_error,(png_structp png_ptr, png_const_charp error_message),
+png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN)
{
char msg[18+PNG_MAX_ERROR_TEXT];
@@ -439,11 +490,11 @@ png_chunk_error,(png_structp png_ptr, png_const_charp error_message),
png_error(png_ptr, msg);
}
}
-#endif /* PNG_READ_SUPPORTED && PNG_ERROR_TEXT_SUPPORTED */
+#endif /* READ && ERROR_TEXT */
#ifdef PNG_WARNINGS_SUPPORTED
void PNGAPI
-png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
+png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
char msg[18+PNG_MAX_ERROR_TEXT];
if (png_ptr == NULL)
@@ -455,38 +506,83 @@ png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
png_warning(png_ptr, msg);
}
}
-#endif /* PNG_WARNINGS_SUPPORTED */
+#endif /* WARNINGS */
#ifdef PNG_READ_SUPPORTED
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
-png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message)
+png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
+ error_message)
{
- if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN)
+ if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
png_chunk_warning(png_ptr, error_message);
else
png_chunk_error(png_ptr, error_message);
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
}
#endif
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
+
+void /* PRIVATE */
+png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
+{
+# ifndef PNG_WARNINGS_SUPPORTED
+ PNG_UNUSED(message)
+# endif
+
+ /* This is always supported, but for just read or just write it
+ * unconditionally does the right thing.
+ */
+# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+# endif
+
+# ifdef PNG_READ_SUPPORTED
+ {
+ if (error < PNG_CHUNK_ERROR)
+ png_chunk_warning(png_ptr, message);
+
+ else
+ png_chunk_benign_error(png_ptr, message);
+ }
+# endif
+
+# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
+ else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+# endif
+
+# ifdef PNG_WRITE_SUPPORTED
+ {
+ if (error < PNG_CHUNK_WRITE_ERROR)
+ png_app_warning(png_ptr, message);
+
+ else
+ png_app_error(png_ptr, message);
+ }
+# endif
+}
#ifdef PNG_ERROR_TEXT_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_FUNCTION(void,
-png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN)
+png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
{
# define fixed_message "fixed point overflow in "
# define fixed_message_ln ((sizeof fixed_message)-1)
int iin;
char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
- png_memcpy(msg, fixed_message, fixed_message_ln);
+ memcpy(msg, fixed_message, fixed_message_ln);
iin = 0;
- if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
- {
- msg[fixed_message_ln + iin] = name[iin];
- ++iin;
- }
+ if (name != NULL)
+ while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
+ {
+ msg[fixed_message_ln + iin] = name[iin];
+ ++iin;
+ }
msg[fixed_message_ln + iin] = 0;
png_error(png_ptr, msg);
}
@@ -498,14 +594,111 @@ png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN)
* otherwise it is necessary for png_default_error to be overridden.
*/
jmp_buf* PNGAPI
-png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn,
+png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn,
size_t jmp_buf_size)
{
- if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf))
+ /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
+ * and it must not change after that. Libpng doesn't care how big the
+ * buffer is, just that it doesn't change.
+ *
+ * If the buffer size is no *larger* than the size of jmp_buf when libpng is
+ * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
+ * semantics that this call will not fail. If the size is larger, however,
+ * the buffer is allocated and this may fail, causing the function to return
+ * NULL.
+ */
+ if (png_ptr == NULL)
return NULL;
+ if (png_ptr->jmp_buf_ptr == NULL)
+ {
+ png_ptr->jmp_buf_size = 0; /* not allocated */
+
+ if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
+ png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
+
+ else
+ {
+ png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *,
+ png_malloc_warn(png_ptr, jmp_buf_size));
+
+ if (png_ptr->jmp_buf_ptr == NULL)
+ return NULL; /* new NULL return on OOM */
+
+ png_ptr->jmp_buf_size = jmp_buf_size;
+ }
+ }
+
+ else /* Already allocated: check the size */
+ {
+ size_t size = png_ptr->jmp_buf_size;
+
+ if (size == 0)
+ {
+ size = (sizeof png_ptr->jmp_buf_local);
+ if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
+ {
+ /* This is an internal error in libpng: somehow we have been left
+ * with a stack allocated jmp_buf when the application regained
+ * control. It's always possible to fix this up, but for the moment
+ * this is a png_error because that makes it easy to detect.
+ */
+ png_error(png_ptr, "Libpng jmp_buf still allocated");
+ /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
+ }
+ }
+
+ if (size != jmp_buf_size)
+ {
+ png_warning(png_ptr, "Application jmp_buf size changed");
+ return NULL; /* caller will probably crash: no choice here */
+ }
+ }
+
+ /* Finally fill in the function, now we have a satisfactory buffer. It is
+ * valid to change the function on every call.
+ */
png_ptr->longjmp_fn = longjmp_fn;
- return &png_ptr->longjmp_buffer;
+ return png_ptr->jmp_buf_ptr;
+}
+
+void /* PRIVATE */
+png_free_jmpbuf(png_structrp png_ptr)
+{
+ if (png_ptr != NULL)
+ {
+ jmp_buf *jb = png_ptr->jmp_buf_ptr;
+
+ /* A size of 0 is used to indicate a local, stack, allocation of the
+ * pointer; used here and in png.c
+ */
+ if (jb != NULL && png_ptr->jmp_buf_size > 0)
+ {
+
+ /* This stuff is so that a failure to free the error control structure
+ * does not leave libpng in a state with no valid error handling: the
+ * free always succeeds, if there is an error it gets ignored.
+ */
+ if (jb != &png_ptr->jmp_buf_local)
+ {
+ /* Make an internal, libpng, jmp_buf to return here */
+ jmp_buf free_jmp_buf;
+
+ if (!setjmp(free_jmp_buf))
+ {
+ png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
+ png_ptr->jmp_buf_size = 0; /* stack allocation */
+ png_ptr->longjmp_fn = longjmp;
+ png_free(png_ptr, jb); /* Return to setjmp on error */
+ }
+ }
+ }
+
+ /* *Always* cancel everything out: */
+ png_ptr->jmp_buf_size = 0;
+ png_ptr->jmp_buf_ptr = NULL;
+ png_ptr->longjmp_fn = 0;
+ }
}
#endif
@@ -515,7 +708,7 @@ png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn,
* error function pointer in png_set_error_fn().
*/
static PNG_FUNCTION(void /* PRIVATE */,
-png_default_error,(png_structp png_ptr, png_const_charp error_message),
+png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN)
{
#ifdef PNG_CONSOLE_IO_SUPPORTED
@@ -562,24 +755,23 @@ png_default_error,(png_structp png_ptr, png_const_charp error_message),
}
PNG_FUNCTION(void,PNGAPI
-png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN)
+png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN)
{
#ifdef PNG_SETJMP_SUPPORTED
- if (png_ptr && png_ptr->longjmp_fn)
- {
-# ifdef USE_FAR_KEYWORD
- {
- jmp_buf tmp_jmpbuf;
- png_memcpy(tmp_jmpbuf, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
- png_ptr->longjmp_fn(tmp_jmpbuf, val);
- }
-
-# else
- png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val);
-# endif
- }
+ if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
+ png_ptr->jmp_buf_ptr != NULL)
+ png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val);
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(val)
#endif
- /* Here if not setjmp support or if png_ptr is null. */
+
+ /* If control reaches this point, png_longjmp() must not return. The only
+ * choice is to terminate the whole process (or maybe the thread); to do
+ * this the ANSI-C abort() function is used unless a different method is
+ * implemented by overriding the default configuration setting for
+ * PNG_ABORT().
+ */
PNG_ABORT();
}
@@ -590,7 +782,7 @@ png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN)
* not used, but it is passed in case it may be useful.
*/
static void /* PRIVATE */
-png_default_warning(png_structp png_ptr, png_const_charp warning_message)
+png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
#ifdef PNG_CONSOLE_IO_SUPPORTED
# ifdef PNG_ERROR_NUMBERS_SUPPORTED
@@ -632,15 +824,15 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message)
#endif
PNG_UNUSED(png_ptr) /* Make compiler happy */
}
-#endif /* PNG_WARNINGS_SUPPORTED */
+#endif /* WARNINGS */
/* This function is called when the application wants to use another method
* of handling errors and warnings. Note that the error function MUST NOT
* return to the calling routine or serious problems will occur. The return
- * method used in the default routine calls longjmp(png_ptr->longjmp_buffer, 1)
+ * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
*/
void PNGAPI
-png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
+png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warning_fn)
{
if (png_ptr == NULL)
@@ -661,7 +853,7 @@ png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
* pointer before png_write_destroy and png_read_destroy are called.
*/
png_voidp PNGAPI
-png_get_error_ptr(png_const_structp png_ptr)
+png_get_error_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return NULL;
@@ -672,7 +864,7 @@ png_get_error_ptr(png_const_structp png_ptr)
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
void PNGAPI
-png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
+png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
{
if (png_ptr != NULL)
{
@@ -682,4 +874,90 @@ png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
}
}
#endif
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+ /* Currently the above both depend on SETJMP_SUPPORTED, however it would be
+ * possible to implement without setjmp support just so long as there is some
+ * way to handle the error return here:
+ */
+PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
+png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
+ PNG_NORETURN)
+{
+ const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
+
+ /* An error is always logged here, overwriting anything (typically a warning)
+ * that is already there:
+ */
+ if (image != NULL)
+ {
+ png_safecat(image->message, (sizeof image->message), 0, error_message);
+ image->warning_or_error |= PNG_IMAGE_ERROR;
+
+ /* Retrieve the jmp_buf from within the png_control, making this work for
+ * C++ compilation too is pretty tricky: C++ wants a pointer to the first
+ * element of a jmp_buf, but C doesn't tell us the type of that.
+ */
+ if (image->opaque != NULL && image->opaque->error_buf != NULL)
+ longjmp(png_control_jmp_buf(image->opaque), 1);
+
+ /* Missing longjmp buffer, the following is to help debugging: */
+ {
+ size_t pos = png_safecat(image->message, (sizeof image->message), 0,
+ "bad longjmp: ");
+ png_safecat(image->message, (sizeof image->message), pos,
+ error_message);
+ }
+ }
+
+ /* Here on an internal programming error. */
+ abort();
+}
+
+#ifdef PNG_WARNINGS_SUPPORTED
+void /* PRIVATE */ PNGCBAPI
+png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
+{
+ const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
+
+ /* A warning is only logged if there is no prior warning or error. */
+ if (image->warning_or_error == 0)
+ {
+ png_safecat(image->message, (sizeof image->message), 0, warning_message);
+ image->warning_or_error |= PNG_IMAGE_WARNING;
+ }
+}
+#endif
+
+int /* PRIVATE */
+png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
+{
+ volatile png_imagep image = image_in;
+ volatile int result;
+ volatile png_voidp saved_error_buf;
+ jmp_buf safe_jmpbuf;
+
+ /* Safely execute function(arg) with png_error returning to this function. */
+ saved_error_buf = image->opaque->error_buf;
+ result = setjmp(safe_jmpbuf) == 0;
+
+ if (result != 0)
+ {
+
+ image->opaque->error_buf = safe_jmpbuf;
+ result = function(arg);
+ }
+
+ image->opaque->error_buf = saved_error_buf;
+
+ /* And do the cleanup prior to any failure return. */
+ if (result == 0)
+ png_image_free(image);
+
+ return result;
+}
+#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
+#endif /* READ || WRITE */
diff --git a/thirdparty/libpng/pngget.c b/thirdparty/libpng/pngget.c
index 43400cda..ca44982a 100644
--- a/thirdparty/libpng/pngget.c
+++ b/thirdparty/libpng/pngget.c
@@ -1,8 +1,8 @@
/* pngget.c - retrieval of values from info struct
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -17,7 +17,7 @@
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
png_uint_32 PNGAPI
-png_get_valid(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32 flag)
{
if (png_ptr != NULL && info_ptr != NULL)
@@ -27,7 +27,7 @@ png_get_valid(png_const_structp png_ptr, png_const_infop info_ptr,
}
png_size_t PNGAPI
-png_get_rowbytes(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->rowbytes);
@@ -37,7 +37,7 @@ png_get_rowbytes(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_INFO_IMAGE_SUPPORTED
png_bytepp PNGAPI
-png_get_rows(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->row_pointers);
@@ -49,7 +49,7 @@ png_get_rows(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_EASY_ACCESS_SUPPORTED
/* Easy access to info, added in libpng-0.99 */
png_uint_32 PNGAPI
-png_get_image_width(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->width;
@@ -58,7 +58,7 @@ png_get_image_width(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_uint_32 PNGAPI
-png_get_image_height(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->height;
@@ -67,7 +67,7 @@ png_get_image_height(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_bit_depth(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->bit_depth;
@@ -76,7 +76,7 @@ png_get_bit_depth(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_color_type(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->color_type;
@@ -85,7 +85,7 @@ png_get_color_type(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_filter_type(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->filter_type;
@@ -94,7 +94,7 @@ png_get_filter_type(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_interlace_type(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->interlace_type;
@@ -103,7 +103,7 @@ png_get_interlace_type(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_compression_type(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->compression_type;
@@ -112,10 +112,12 @@ png_get_compression_type(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_uint_32 PNGAPI
-png_get_x_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
+ info_ptr)
{
#ifdef PNG_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function",
"png_get_x_pixels_per_meter");
@@ -123,16 +125,21 @@ png_get_x_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
return (info_ptr->x_pixels_per_unit);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_uint_32 PNGAPI
-png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
+ info_ptr)
{
#ifdef PNG_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function",
"png_get_y_pixels_per_meter");
@@ -140,16 +147,20 @@ png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
return (info_ptr->y_pixels_per_unit);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_uint_32 PNGAPI
-png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter");
@@ -157,6 +168,9 @@ png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit)
return (info_ptr->x_pixels_per_unit);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -164,10 +178,12 @@ png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_FLOATING_POINT_SUPPORTED
float PNGAPI
-png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp
+ info_ptr)
{
#ifdef PNG_READ_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio");
@@ -175,6 +191,9 @@ png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr)
return ((float)((float)info_ptr->y_pixels_per_unit
/(float)info_ptr->x_pixels_per_unit));
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return ((float)0.0);
@@ -183,14 +202,15 @@ png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_FIXED_POINT_SUPPORTED
png_fixed_point PNGAPI
-png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr,
- png_const_infop info_ptr)
+png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
+ png_const_inforp info_ptr)
{
#ifdef PNG_READ_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)
- && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0
- && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX
- && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0 &&
+ info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 &&
+ info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX &&
+ info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX)
{
png_fixed_point res;
@@ -200,9 +220,12 @@ png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr,
* range of 0..2^31-1; otherwise the cast might overflow.
*/
if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1,
- (png_int_32)info_ptr->x_pixels_per_unit))
+ (png_int_32)info_ptr->x_pixels_per_unit) != 0)
return res;
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return 0;
@@ -210,64 +233,80 @@ png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr,
#endif
png_int_32 PNGAPI
-png_get_x_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_oFFs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
return (info_ptr->x_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_int_32 PNGAPI
-png_get_y_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_oFFs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
return (info_ptr->y_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_int_32 PNGAPI
-png_get_x_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_oFFs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels");
if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
return (info_ptr->x_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_int_32 PNGAPI
-png_get_y_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_oFFs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels");
if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
return (info_ptr->y_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -298,7 +337,7 @@ ppi_from_ppm(png_uint_32 ppm)
*/
png_fixed_point result;
if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127,
- 5000))
+ 5000) != 0)
return result;
/* Overflow. */
@@ -307,26 +346,26 @@ ppi_from_ppm(png_uint_32 ppm)
}
png_uint_32 PNGAPI
-png_get_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr));
}
png_uint_32 PNGAPI
-png_get_x_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr));
}
png_uint_32 PNGAPI
-png_get_y_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr));
}
#ifdef PNG_FIXED_POINT_SUPPORTED
static png_fixed_point
-png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns)
+png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns)
{
/* Convert from metres * 1,000,000 to inches * 100,000, meters to
* inches is simply *(100/2.54), so we want *(10/2.54) == 500/127.
@@ -337,8 +376,8 @@ png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns)
}
png_fixed_point PNGAPI
-png_get_x_offset_inches_fixed(png_structp png_ptr,
- png_const_infop info_ptr)
+png_get_x_offset_inches_fixed(png_const_structrp png_ptr,
+ png_const_inforp info_ptr)
{
return png_fixed_inches_from_microns(png_ptr,
png_get_x_offset_microns(png_ptr, info_ptr));
@@ -347,8 +386,8 @@ png_get_x_offset_inches_fixed(png_structp png_ptr,
#ifdef PNG_FIXED_POINT_SUPPORTED
png_fixed_point PNGAPI
-png_get_y_offset_inches_fixed(png_structp png_ptr,
- png_const_infop info_ptr)
+png_get_y_offset_inches_fixed(png_const_structrp png_ptr,
+ png_const_inforp info_ptr)
{
return png_fixed_inches_from_microns(png_ptr,
png_get_y_offset_microns(png_ptr, info_ptr));
@@ -357,7 +396,7 @@ png_get_y_offset_inches_fixed(png_structp png_ptr,
#ifdef PNG_FLOATING_POINT_SUPPORTED
float PNGAPI
-png_get_x_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
/* To avoid the overflow do the conversion directly in floating
* point.
@@ -368,7 +407,7 @@ png_get_x_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_FLOATING_POINT_SUPPORTED
float PNGAPI
-png_get_y_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
/* To avoid the overflow do the conversion directly in floating
* point.
@@ -379,12 +418,13 @@ png_get_y_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_pHYs_SUPPORTED
png_uint_32 PNGAPI
-png_get_pHYs_dpi(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
{
png_uint_32 retval = 0;
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function", "pHYs");
@@ -415,15 +455,16 @@ png_get_pHYs_dpi(png_const_structp png_ptr, png_const_infop info_ptr,
return (retval);
}
-#endif /* PNG_pHYs_SUPPORTED */
-#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */
+#endif /* pHYs */
+#endif /* INCH_CONVERSIONS */
/* png_get_channels really belongs in here, too, but it's been around longer */
-#endif /* PNG_EASY_ACCESS_SUPPORTED */
+#endif /* EASY_ACCESS */
+
png_byte PNGAPI
-png_get_channels(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->channels);
@@ -431,22 +472,25 @@ png_get_channels(png_const_structp png_ptr, png_const_infop info_ptr)
return (0);
}
+#ifdef PNG_READ_SUPPORTED
png_const_bytep PNGAPI
-png_get_signature(png_const_structp png_ptr, png_infop info_ptr)
+png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->signature);
return (NULL);
}
+#endif
#ifdef PNG_bKGD_SUPPORTED
png_uint_32 PNGAPI
-png_get_bKGD(png_const_structp png_ptr, png_infop info_ptr,
+png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
png_color_16p *background)
{
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)
- && background != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_bKGD) != 0 &&
+ background != NULL)
{
png_debug1(1, "in %s retrieval function", "bKGD");
@@ -463,87 +507,47 @@ png_get_bKGD(png_const_structp png_ptr, png_infop info_ptr,
* same time to correct the rgb grayscale coefficient defaults obtained from the
* cHRM chunk in 1.5.4
*/
-png_uint_32 PNGFAPI
-png_get_cHRM_XYZ_fixed(png_structp png_ptr, png_const_infop info_ptr,
- png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
- png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
- png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
- png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
- png_fixed_point *int_blue_Z)
-{
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
- {
- png_xy xy;
- png_XYZ XYZ;
-
- png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
-
- xy.whitex = info_ptr->x_white;
- xy.whitey = info_ptr->y_white;
- xy.redx = info_ptr->x_red;
- xy.redy = info_ptr->y_red;
- xy.greenx = info_ptr->x_green;
- xy.greeny = info_ptr->y_green;
- xy.bluex = info_ptr->x_blue;
- xy.bluey = info_ptr->y_blue;
-
- /* The *_checked function handles error reporting, so just return 0 if
- * there is a failure here.
- */
- if (png_XYZ_from_xy_checked(png_ptr, &XYZ, xy))
- {
- if (int_red_X != NULL)
- *int_red_X = XYZ.redX;
- if (int_red_Y != NULL)
- *int_red_Y = XYZ.redY;
- if (int_red_Z != NULL)
- *int_red_Z = XYZ.redZ;
- if (int_green_X != NULL)
- *int_green_X = XYZ.greenX;
- if (int_green_Y != NULL)
- *int_green_Y = XYZ.greenY;
- if (int_green_Z != NULL)
- *int_green_Z = XYZ.greenZ;
- if (int_blue_X != NULL)
- *int_blue_X = XYZ.blueX;
- if (int_blue_Y != NULL)
- *int_blue_Y = XYZ.blueY;
- if (int_blue_Z != NULL)
- *int_blue_Z = XYZ.blueZ;
-
- return (PNG_INFO_cHRM);
- }
- }
-
- return (0);
-}
-
# ifdef PNG_FLOATING_POINT_SUPPORTED
png_uint_32 PNGAPI
-png_get_cHRM(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
double *white_x, double *white_y, double *red_x, double *red_y,
double *green_x, double *green_y, double *blue_x, double *blue_y)
{
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+ /* Quiet API change: this code used to only return the end points if a cHRM
+ * chunk was present, but the end points can also come from iCCP or sRGB
+ * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
+ * the png_set_ APIs merely check that set end points are mutually
+ * consistent.
+ */
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
{
png_debug1(1, "in %s retrieval function", "cHRM");
if (white_x != NULL)
- *white_x = png_float(png_ptr, info_ptr->x_white, "cHRM white X");
+ *white_x = png_float(png_ptr,
+ info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
if (white_y != NULL)
- *white_y = png_float(png_ptr, info_ptr->y_white, "cHRM white Y");
+ *white_y = png_float(png_ptr,
+ info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y");
if (red_x != NULL)
- *red_x = png_float(png_ptr, info_ptr->x_red, "cHRM red X");
+ *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx,
+ "cHRM red X");
if (red_y != NULL)
- *red_y = png_float(png_ptr, info_ptr->y_red, "cHRM red Y");
+ *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy,
+ "cHRM red Y");
if (green_x != NULL)
- *green_x = png_float(png_ptr, info_ptr->x_green, "cHRM green X");
+ *green_x = png_float(png_ptr,
+ info_ptr->colorspace.end_points_xy.greenx, "cHRM green X");
if (green_y != NULL)
- *green_y = png_float(png_ptr, info_ptr->y_green, "cHRM green Y");
+ *green_y = png_float(png_ptr,
+ info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y");
if (blue_x != NULL)
- *blue_x = png_float(png_ptr, info_ptr->x_blue, "cHRM blue X");
+ *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex,
+ "cHRM blue X");
if (blue_y != NULL)
- *blue_y = png_float(png_ptr, info_ptr->y_blue, "cHRM blue Y");
+ *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
+ "cHRM blue Y");
return (PNG_INFO_cHRM);
}
@@ -551,35 +555,43 @@ png_get_cHRM(png_const_structp png_ptr, png_const_infop info_ptr,
}
png_uint_32 PNGAPI
-png_get_cHRM_XYZ(png_structp png_ptr, png_const_infop info_ptr,
+png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
double *red_X, double *red_Y, double *red_Z, double *green_X,
double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
double *blue_Z)
{
- png_XYZ XYZ;
-
- if (png_get_cHRM_XYZ_fixed(png_ptr, info_ptr,
- &XYZ.redX, &XYZ.redY, &XYZ.redZ, &XYZ.greenX, &XYZ.greenY, &XYZ.greenZ,
- &XYZ.blueX, &XYZ.blueY, &XYZ.blueZ) & PNG_INFO_cHRM)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
{
+ png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
+
if (red_X != NULL)
- *red_X = png_float(png_ptr, XYZ.redX, "cHRM red X");
+ *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
+ "cHRM red X");
if (red_Y != NULL)
- *red_Y = png_float(png_ptr, XYZ.redY, "cHRM red Y");
+ *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y,
+ "cHRM red Y");
if (red_Z != NULL)
- *red_Z = png_float(png_ptr, XYZ.redZ, "cHRM red Z");
+ *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z,
+ "cHRM red Z");
if (green_X != NULL)
- *green_X = png_float(png_ptr, XYZ.greenX, "cHRM green X");
+ *green_X = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X");
if (green_Y != NULL)
- *green_Y = png_float(png_ptr, XYZ.greenY, "cHRM green Y");
+ *green_Y = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y");
if (green_Z != NULL)
- *green_Z = png_float(png_ptr, XYZ.greenZ, "cHRM green Z");
+ *green_Z = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
if (blue_X != NULL)
- *blue_X = png_float(png_ptr, XYZ.blueX, "cHRM blue X");
+ *blue_X = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
if (blue_Y != NULL)
- *blue_Y = png_float(png_ptr, XYZ.blueY, "cHRM blue Y");
+ *blue_Y = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
if (blue_Z != NULL)
- *blue_Z = png_float(png_ptr, XYZ.blueZ, "cHRM blue Z");
+ *blue_Z = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
return (PNG_INFO_cHRM);
}
@@ -589,31 +601,69 @@ png_get_cHRM_XYZ(png_structp png_ptr, png_const_infop info_ptr,
# ifdef PNG_FIXED_POINT_SUPPORTED
png_uint_32 PNGAPI
-png_get_cHRM_fixed(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
+ png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
+ png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
+ png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
+ png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
+ png_fixed_point *int_blue_Z)
+{
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+ {
+ png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
+
+ if (int_red_X != NULL)
+ *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
+ if (int_red_Y != NULL)
+ *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y;
+ if (int_red_Z != NULL)
+ *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z;
+ if (int_green_X != NULL)
+ *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X;
+ if (int_green_Y != NULL)
+ *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y;
+ if (int_green_Z != NULL)
+ *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z;
+ if (int_blue_X != NULL)
+ *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X;
+ if (int_blue_Y != NULL)
+ *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
+ if (int_blue_Z != NULL)
+ *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
+ return (PNG_INFO_cHRM);
+ }
+
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
png_fixed_point *blue_x, png_fixed_point *blue_y)
{
png_debug1(1, "in %s retrieval function", "cHRM");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
{
if (white_x != NULL)
- *white_x = info_ptr->x_white;
+ *white_x = info_ptr->colorspace.end_points_xy.whitex;
if (white_y != NULL)
- *white_y = info_ptr->y_white;
+ *white_y = info_ptr->colorspace.end_points_xy.whitey;
if (red_x != NULL)
- *red_x = info_ptr->x_red;
+ *red_x = info_ptr->colorspace.end_points_xy.redx;
if (red_y != NULL)
- *red_y = info_ptr->y_red;
+ *red_y = info_ptr->colorspace.end_points_xy.redy;
if (green_x != NULL)
- *green_x = info_ptr->x_green;
+ *green_x = info_ptr->colorspace.end_points_xy.greenx;
if (green_y != NULL)
- *green_y = info_ptr->y_green;
+ *green_y = info_ptr->colorspace.end_points_xy.greeny;
if (blue_x != NULL)
- *blue_x = info_ptr->x_blue;
+ *blue_x = info_ptr->colorspace.end_points_xy.bluex;
if (blue_y != NULL)
- *blue_y = info_ptr->y_blue;
+ *blue_y = info_ptr->colorspace.end_points_xy.bluey;
return (PNG_INFO_cHRM);
}
@@ -623,49 +673,57 @@ png_get_cHRM_fixed(png_const_structp png_ptr, png_const_infop info_ptr,
#endif
#ifdef PNG_gAMA_SUPPORTED
-png_uint_32 PNGFAPI
-png_get_gAMA_fixed(png_const_structp png_ptr, png_const_infop info_ptr,
+# ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_fixed_point *file_gamma)
{
png_debug1(1, "in %s retrieval function", "gAMA");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
- && file_gamma != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+ file_gamma != NULL)
{
- *file_gamma = info_ptr->gamma;
+ *file_gamma = info_ptr->colorspace.gamma;
return (PNG_INFO_gAMA);
}
return (0);
}
+# endif
+
# ifdef PNG_FLOATING_POINT_SUPPORTED
png_uint_32 PNGAPI
-png_get_gAMA(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
double *file_gamma)
{
- png_fixed_point igamma;
- png_uint_32 ok = png_get_gAMA_fixed(png_ptr, info_ptr, &igamma);
+ png_debug1(1, "in %s retrieval function", "gAMA(float)");
- if (ok)
- *file_gamma = png_float(png_ptr, igamma, "png_get_gAMA");
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+ file_gamma != NULL)
+ {
+ *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
+ "png_get_gAMA");
+ return (PNG_INFO_gAMA);
+ }
- return ok;
+ return (0);
}
-
# endif
#endif
#ifdef PNG_sRGB_SUPPORTED
png_uint_32 PNGAPI
-png_get_sRGB(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
int *file_srgb_intent)
{
png_debug1(1, "in %s retrieval function", "sRGB");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)
- && file_srgb_intent != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
{
- *file_srgb_intent = (int)info_ptr->srgb_intent;
+ *file_srgb_intent = info_ptr->colorspace.rendering_intent;
return (PNG_INFO_sRGB);
}
@@ -675,23 +733,24 @@ png_get_sRGB(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_iCCP_SUPPORTED
png_uint_32 PNGAPI
-png_get_iCCP(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
png_charpp name, int *compression_type,
png_bytepp profile, png_uint_32 *proflen)
{
png_debug1(1, "in %s retrieval function", "iCCP");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)
- && name != NULL && compression_type != NULL && profile != NULL &&
- proflen != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_iCCP) != 0 &&
+ name != NULL && compression_type != NULL && profile != NULL &&
+ proflen != NULL)
{
*name = info_ptr->iccp_name;
*profile = info_ptr->iccp_profile;
- /* Compression_type is a dummy so the API won't have to change
- * if we introduce multiple compression types later.
+ *proflen = png_get_uint_32(info_ptr->iccp_profile);
+ /* This is somewhat irrelevant since the profile data returned has
+ * actually been uncompressed.
*/
- *proflen = info_ptr->iccp_proflen;
- *compression_type = info_ptr->iccp_compression;
+ *compression_type = PNG_COMPRESSION_TYPE_BASE;
return (PNG_INFO_iCCP);
}
@@ -700,14 +759,14 @@ png_get_iCCP(png_const_structp png_ptr, png_const_infop info_ptr,
#endif
#ifdef PNG_sPLT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_sPLT(png_const_structp png_ptr, png_const_infop info_ptr,
+int PNGAPI
+png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
png_sPLT_tpp spalettes)
{
if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
{
*spalettes = info_ptr->splt_palettes;
- return ((png_uint_32)info_ptr->splt_palettes_num);
+ return info_ptr->splt_palettes_num;
}
return (0);
@@ -716,13 +775,13 @@ png_get_sPLT(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_hIST_SUPPORTED
png_uint_32 PNGAPI
-png_get_hIST(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
png_uint_16p *hist)
{
png_debug1(1, "in %s retrieval function", "hIST");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)
- && hist != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL)
{
*hist = info_ptr->hist;
return (PNG_INFO_hIST);
@@ -733,22 +792,27 @@ png_get_hIST(png_const_structp png_ptr, png_const_infop info_ptr,
#endif
png_uint_32 PNGAPI
-png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
+png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32 *width, png_uint_32 *height, int *bit_depth,
int *color_type, int *interlace_type, int *compression_type,
int *filter_type)
-
{
png_debug1(1, "in %s retrieval function", "IHDR");
- if (png_ptr == NULL || info_ptr == NULL || width == NULL ||
- height == NULL || bit_depth == NULL || color_type == NULL)
+ if (png_ptr == NULL || info_ptr == NULL)
return (0);
- *width = info_ptr->width;
- *height = info_ptr->height;
- *bit_depth = info_ptr->bit_depth;
- *color_type = info_ptr->color_type;
+ if (width != NULL)
+ *width = info_ptr->width;
+
+ if (height != NULL)
+ *height = info_ptr->height;
+
+ if (bit_depth != NULL)
+ *bit_depth = info_ptr->bit_depth;
+
+ if (color_type != NULL)
+ *color_type = info_ptr->color_type;
if (compression_type != NULL)
*compression_type = info_ptr->compression_type;
@@ -764,7 +828,7 @@ png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
* application has ignored our advice not to mess with the members
* of info_ptr directly.
*/
- png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
+ png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height,
info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
info_ptr->compression_type, info_ptr->filter_type);
@@ -773,13 +837,14 @@ png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_oFFs_SUPPORTED
png_uint_32 PNGAPI
-png_get_oFFs(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)
{
png_debug1(1, "in %s retrieval function", "oFFs");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)
- && offset_x != NULL && offset_y != NULL && unit_type != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0 &&
+ offset_x != NULL && offset_y != NULL && unit_type != NULL)
{
*offset_x = info_ptr->x_offset;
*offset_y = info_ptr->y_offset;
@@ -793,14 +858,15 @@ png_get_oFFs(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_pCAL_SUPPORTED
png_uint_32 PNGAPI
-png_get_pCAL(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
png_charp *units, png_charpp *params)
{
png_debug1(1, "in %s retrieval function", "pCAL");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)
- && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pCAL) != 0 &&
+ purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
nparams != NULL && units != NULL && params != NULL)
{
*purpose = info_ptr->pcal_purpose;
@@ -819,16 +885,20 @@ png_get_pCAL(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_sCAL_SUPPORTED
# ifdef PNG_FIXED_POINT_SUPPORTED
-# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+# if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
+ defined(PNG_FLOATING_POINT_SUPPORTED)
png_uint_32 PNGAPI
-png_get_sCAL_fixed(png_structp png_ptr, png_const_infop info_ptr,
+png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
int *unit, png_fixed_point *width, png_fixed_point *height)
{
if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_sCAL))
+ (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
*unit = info_ptr->scal_unit;
- /*TODO: make this work without FP support */
+ /*TODO: make this work without FP support; the API is currently eliminated
+ * if neither floating point APIs nor internal floating point arithmetic
+ * are enabled.
+ */
*width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
*height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
"sCAL height");
@@ -841,11 +911,11 @@ png_get_sCAL_fixed(png_structp png_ptr, png_const_infop info_ptr,
# endif /* FIXED_POINT */
# ifdef PNG_FLOATING_POINT_SUPPORTED
png_uint_32 PNGAPI
-png_get_sCAL(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr,
int *unit, double *width, double *height)
{
if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_sCAL))
+ (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
*unit = info_ptr->scal_unit;
*width = atof(info_ptr->scal_s_width);
@@ -857,11 +927,11 @@ png_get_sCAL(png_const_structp png_ptr, png_const_infop info_ptr,
}
# endif /* FLOATING POINT */
png_uint_32 PNGAPI
-png_get_sCAL_s(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr,
int *unit, png_charpp width, png_charpp height)
{
if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_sCAL))
+ (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
*unit = info_ptr->scal_unit;
*width = info_ptr->scal_s_width;
@@ -875,7 +945,7 @@ png_get_sCAL_s(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_pHYs_SUPPORTED
png_uint_32 PNGAPI
-png_get_pHYs(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
{
png_uint_32 retval = 0;
@@ -883,7 +953,7 @@ png_get_pHYs(png_const_structp png_ptr, png_const_infop info_ptr,
png_debug1(1, "in %s retrieval function", "pHYs");
if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_pHYs))
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
if (res_x != NULL)
{
@@ -909,13 +979,13 @@ png_get_pHYs(png_const_structp png_ptr, png_const_infop info_ptr,
#endif /* pHYs */
png_uint_32 PNGAPI
-png_get_PLTE(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr,
png_colorp *palette, int *num_palette)
{
png_debug1(1, "in %s retrieval function", "PLTE");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE)
- && palette != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_PLTE) != 0 && palette != NULL)
{
*palette = info_ptr->palette;
*num_palette = info_ptr->num_palette;
@@ -928,13 +998,13 @@ png_get_PLTE(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_sBIT_SUPPORTED
png_uint_32 PNGAPI
-png_get_sBIT(png_const_structp png_ptr, png_infop info_ptr,
+png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
png_color_8p *sig_bit)
{
png_debug1(1, "in %s retrieval function", "sBIT");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)
- && sig_bit != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL)
{
*sig_bit = &(info_ptr->sig_bit);
return (PNG_INFO_sBIT);
@@ -945,8 +1015,8 @@ png_get_sBIT(png_const_structp png_ptr, png_infop info_ptr,
#endif
#ifdef PNG_TEXT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_text(png_const_structp png_ptr, png_const_infop info_ptr,
+int PNGAPI
+png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
png_textp *text_ptr, int *num_text)
{
if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
@@ -960,7 +1030,7 @@ png_get_text(png_const_structp png_ptr, png_const_infop info_ptr,
if (num_text != NULL)
*num_text = info_ptr->num_text;
- return ((png_uint_32)info_ptr->num_text);
+ return info_ptr->num_text;
}
if (num_text != NULL)
@@ -972,12 +1042,13 @@ png_get_text(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_tIME_SUPPORTED
png_uint_32 PNGAPI
-png_get_tIME(png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
+png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_timep *mod_time)
{
png_debug1(1, "in %s retrieval function", "tIME");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)
- && mod_time != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL)
{
*mod_time = &(info_ptr->mod_time);
return (PNG_INFO_tIME);
@@ -989,11 +1060,12 @@ png_get_tIME(png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
#ifdef PNG_tRNS_SUPPORTED
png_uint_32 PNGAPI
-png_get_tRNS(png_const_structp png_ptr, png_infop info_ptr,
+png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)
{
png_uint_32 retval = 0;
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_tRNS) != 0)
{
png_debug1(1, "in %s retrieval function", "tRNS");
@@ -1032,9 +1104,9 @@ png_get_tRNS(png_const_structp png_ptr, png_infop info_ptr,
}
#endif
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
int PNGAPI
-png_get_unknown_chunks(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
png_unknown_chunkpp unknowns)
{
if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
@@ -1049,7 +1121,7 @@ png_get_unknown_chunks(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_byte PNGAPI
-png_get_rgb_to_gray_status (png_const_structp png_ptr)
+png_get_rgb_to_gray_status (png_const_structrp png_ptr)
{
return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0);
}
@@ -1057,68 +1129,91 @@ png_get_rgb_to_gray_status (png_const_structp png_ptr)
#ifdef PNG_USER_CHUNKS_SUPPORTED
png_voidp PNGAPI
-png_get_user_chunk_ptr(png_const_structp png_ptr)
+png_get_user_chunk_ptr(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_ptr : NULL);
}
#endif
png_size_t PNGAPI
-png_get_compression_buffer_size(png_const_structp png_ptr)
+png_get_compression_buffer_size(png_const_structrp png_ptr)
{
- return (png_ptr ? png_ptr->zbuf_size : 0);
+ if (png_ptr == NULL)
+ return 0;
+
+#ifdef PNG_WRITE_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+#endif
+ {
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ return png_ptr->IDAT_read_size;
+#else
+ return PNG_IDAT_READ_SIZE;
+#endif
+ }
+
+#ifdef PNG_WRITE_SUPPORTED
+ else
+ return png_ptr->zbuffer_size;
+#endif
}
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* These functions were added to libpng 1.2.6 and were enabled
* by default in libpng-1.4.0 */
png_uint_32 PNGAPI
-png_get_user_width_max (png_const_structp png_ptr)
+png_get_user_width_max (png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_width_max : 0);
}
png_uint_32 PNGAPI
-png_get_user_height_max (png_const_structp png_ptr)
+png_get_user_height_max (png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_height_max : 0);
}
/* This function was added to libpng 1.4.0 */
png_uint_32 PNGAPI
-png_get_chunk_cache_max (png_const_structp png_ptr)
+png_get_chunk_cache_max (png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_cache_max : 0);
}
/* This function was added to libpng 1.4.1 */
png_alloc_size_t PNGAPI
-png_get_chunk_malloc_max (png_const_structp png_ptr)
+png_get_chunk_malloc_max (png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_malloc_max : 0);
}
-#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
+#endif /* SET_USER_LIMITS */
/* These functions were added to libpng 1.4.0 */
#ifdef PNG_IO_STATE_SUPPORTED
png_uint_32 PNGAPI
-png_get_io_state (png_structp png_ptr)
+png_get_io_state (png_const_structrp png_ptr)
{
return png_ptr->io_state;
}
png_uint_32 PNGAPI
-png_get_io_chunk_type (png_const_structp png_ptr)
+png_get_io_chunk_type (png_const_structrp png_ptr)
{
return png_ptr->chunk_name;
}
+#endif /* IO_STATE */
-png_const_bytep PNGAPI
-png_get_io_chunk_name (png_structp png_ptr)
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+# ifdef PNG_GET_PALETTE_MAX_SUPPORTED
+int PNGAPI
+png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
{
- PNG_CSTRING_FROM_CHUNK(png_ptr->io_chunk_string, png_ptr->chunk_name);
- return png_ptr->io_chunk_string;
+ if (png_ptr != NULL && info_ptr != NULL)
+ return png_ptr->num_palette_max;
+
+ return (-1);
}
-#endif /* ?PNG_IO_STATE_SUPPORTED */
+# endif
+#endif
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* READ || WRITE */
diff --git a/thirdparty/libpng/pnginfo.h b/thirdparty/libpng/pnginfo.h
index a33bfab0..361ed8be 100644
--- a/thirdparty/libpng/pnginfo.h
+++ b/thirdparty/libpng/pnginfo.h
@@ -1,12 +1,11 @@
/* pnginfo.h - header file for PNG reference library
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.1 [March 28, 2013]
+ * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -55,7 +54,7 @@
struct png_info_def
{
- /* the following are necessary for every PNG file */
+ /* The following are necessary for every PNG file */
png_uint_32 width; /* width of image in pixels (from IHDR) */
png_uint_32 height; /* height of image in pixels (from IHDR) */
png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */
@@ -70,11 +69,17 @@ struct png_info_def
png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
- /* The following is informational only on read, and not used on writes. */
+ /* The following are set by png_set_IHDR, called from the application on
+ * write, but the are never actually used by the write code.
+ */
png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */
png_byte pixel_depth; /* number of bits per pixel */
png_byte spare_byte; /* to align the data, and for future use */
+
+#ifdef PNG_READ_SUPPORTED
+ /* This is never set during write */
png_byte signature[8]; /* magic bytes read by libpng from start of file */
+#endif
/* The rest of the data is optional. If you are reading, check the
* valid field to see if the information in these are valid. If you
@@ -82,18 +87,25 @@ struct png_info_def
* and initialize the appropriate fields below.
*/
-#if defined(PNG_gAMA_SUPPORTED)
- /* The gAMA chunk describes the gamma characteristics of the system
- * on which the image was created, normally in the range [1.0, 2.5].
- * Data is valid if (valid & PNG_INFO_gAMA) is non-zero.
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+ /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
+ * defined. When COLORSPACE is switched on all the colorspace-defining
+ * chunks should be enabled, when GAMMA is switched on all the gamma-defining
+ * chunks should be enabled. If this is not done it becomes possible to read
+ * inconsistent PNG files and assign a probably incorrect interpretation to
+ * the information. (In other words, by carefully choosing which chunks to
+ * recognize the system configuration can select an interpretation for PNG
+ * files containing ambiguous data and this will result in inconsistent
+ * behavior between different libpng builds!)
*/
- png_fixed_point gamma;
+ png_colorspace colorspace;
#endif
-#ifdef PNG_sRGB_SUPPORTED
- /* GR-P, 0.96a */
- /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */
- png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */
+#ifdef PNG_iCCP_SUPPORTED
+ /* iCCP chunk data. */
+ png_charp iccp_name; /* profile name */
+ png_bytep iccp_profile; /* International Color Consortium profile data */
+ png_uint_32 iccp_proflen; /* ICC profile data length */
#endif
#ifdef PNG_TEXT_SUPPORTED
@@ -108,7 +120,7 @@ struct png_info_def
int num_text; /* number of comments read or comments to write */
int max_text; /* current size of text array */
png_textp text; /* array of comments read or comments to write */
-#endif /* PNG_TEXT_SUPPORTED */
+#endif /* TEXT */
#ifdef PNG_tIME_SUPPORTED
/* The tIME chunk holds the last time the displayed image data was
@@ -183,23 +195,6 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
png_uint_16p hist;
#endif
-#ifdef PNG_cHRM_SUPPORTED
- /* The cHRM chunk describes the CIE color characteristics of the monitor
- * on which the PNG was created. This data allows the viewer to do gamut
- * mapping of the input image to ensure that the viewer sees the same
- * colors in the image as the creator. Values are in the range
- * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero.
- */
- png_fixed_point x_white;
- png_fixed_point y_white;
- png_fixed_point x_red;
- png_fixed_point y_red;
- png_fixed_point x_green;
- png_fixed_point y_green;
- png_fixed_point x_blue;
- png_fixed_point y_blue;
-#endif
-
#ifdef PNG_pCAL_SUPPORTED
/* The pCAL chunk describes a transformation between the stored pixel
* values and original physical data values used to create the image.
@@ -224,25 +219,20 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
/* New members added in libpng-1.0.6 */
png_uint_32 free_me; /* flags items libpng is responsible for freeing */
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \
- defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
/* Storage for unknown chunks that the library doesn't recognize. */
png_unknown_chunkp unknown_chunks;
- int unknown_chunks_num;
-#endif
-#ifdef PNG_iCCP_SUPPORTED
- /* iCCP chunk data. */
- png_charp iccp_name; /* profile name */
- png_bytep iccp_profile; /* International Color Consortium profile data */
- png_uint_32 iccp_proflen; /* ICC profile data length */
- png_byte iccp_compression; /* Always zero */
+ /* The type of this field is limited by the type of
+ * png_struct::user_chunk_cache_max, else overflow can occur.
+ */
+ int unknown_chunks_num;
#endif
#ifdef PNG_sPLT_SUPPORTED
/* Data on sPLT chunks (there may be more than one). */
png_sPLT_tp splt_palettes;
- png_uint_32 splt_palettes_num;
+ int splt_palettes_num; /* Match type returned by png_get API */
#endif
#ifdef PNG_sCAL_SUPPORTED
diff --git a/thirdparty/libpng/pnglibconf.h b/thirdparty/libpng/pnglibconf.h
index 49fcc8cb..ff5d156a 100644
--- a/thirdparty/libpng/pnglibconf.h
+++ b/thirdparty/libpng/pnglibconf.h
@@ -1,51 +1,31 @@
-
-/* libpng STANDARD API DEFINITION */
+/* libpng 1.6.19 STANDARD API DEFINITION */
/* pnglibconf.h - library build configuration */
-/* Libpng 1.5.9 - February 18, 2012 */
+/* Libpng version 1.6.19 - November 12, 2015 */
-/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */
+/* Copyright (c) 1998-2015 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */
/* and license in png.h */
/* pnglibconf.h */
+/* Machine generated file: DO NOT EDIT */
/* Derived from: scripts/pnglibconf.dfa */
-/* If you edit this file by hand you must obey the rules expressed in */
-/* pnglibconf.dfa with respect to the dependencies between the following */
-/* symbols. It is much better to generate a new file using */
-/* scripts/libpngconf.mak */
-
#ifndef PNGLCONF_H
#define PNGLCONF_H
-/* settings */
-#define PNG_API_RULE 0
-#define PNG_CALLOC_SUPPORTED
-#define PNG_COST_SHIFT 3
-#define PNG_DEFAULT_READ_MACROS 1
-#define PNG_GAMMA_THRESHOLD_FIXED 5000
-#define PNG_MAX_GAMMA_8 11
-#define PNG_QUANTIZE_BLUE_BITS 5
-#define PNG_QUANTIZE_GREEN_BITS 5
-#define PNG_QUANTIZE_RED_BITS 5
-#define PNG_sCAL_PRECISION 5
-#define PNG_USER_CHUNK_CACHE_MAX 0
-#define PNG_USER_CHUNK_MALLOC_MAX 0
-#define PNG_USER_HEIGHT_MAX 1000000
-#define PNG_USER_WIDTH_MAX 1000000
-#define PNG_WEIGHT_SHIFT 8
-#define PNG_ZBUF_SIZE 8192
-/* end of settings */
/* options */
#define PNG_16BIT_SUPPORTED
-#define PNG_ALIGN_MEMORY_SUPPORTED
+#define PNG_ALIGNED_MEMORY_SUPPORTED
+/*#undef PNG_ARM_NEON_API_SUPPORTED*/
+/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
#define PNG_BENIGN_ERRORS_SUPPORTED
-#define PNG_bKGD_SUPPORTED
+#define PNG_BENIGN_READ_ERRORS_SUPPORTED
+/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
-#define PNG_CHECK_cHRM_SUPPORTED
-#define PNG_cHRM_SUPPORTED
+#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+#define PNG_COLORSPACE_SUPPORTED
#define PNG_CONSOLE_IO_SUPPORTED
#define PNG_CONVERT_tIME_SUPPORTED
#define PNG_EASY_ACCESS_SUPPORTED
@@ -54,18 +34,15 @@
#define PNG_FIXED_POINT_SUPPORTED
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
#define PNG_FLOATING_POINT_SUPPORTED
-#define PNG_gAMA_SUPPORTED
+#define PNG_FORMAT_AFIRST_SUPPORTED
+#define PNG_FORMAT_BGR_SUPPORTED
+#define PNG_GAMMA_SUPPORTED
+#define PNG_GET_PALETTE_MAX_SUPPORTED
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#define PNG_hIST_SUPPORTED
-#define PNG_iCCP_SUPPORTED
#define PNG_INCH_CONVERSIONS_SUPPORTED
#define PNG_INFO_IMAGE_SUPPORTED
#define PNG_IO_STATE_SUPPORTED
-#define PNG_iTXt_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED
-#define PNG_oFFs_SUPPORTED
-#define PNG_pCAL_SUPPORTED
-#define PNG_pHYs_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED
@@ -73,67 +50,70 @@
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_READ_BACKGROUND_SUPPORTED
#define PNG_READ_BGR_SUPPORTED
-#define PNG_READ_bKGD_SUPPORTED
-#define PNG_READ_cHRM_SUPPORTED
+#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
#define PNG_READ_EXPAND_16_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_FILLER_SUPPORTED
-#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_GAMMA_SUPPORTED
+#define PNG_READ_GET_PALETTE_MAX_SUPPORTED
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
-#define PNG_READ_hIST_SUPPORTED
-#define PNG_READ_iCCP_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
#define PNG_READ_INVERT_ALPHA_SUPPORTED
#define PNG_READ_INVERT_SUPPORTED
-#define PNG_READ_iTXt_SUPPORTED
-#define PNG_READ_oFFs_SUPPORTED
#define PNG_READ_OPT_PLTE_SUPPORTED
-#define PNG_READ_PACK_SUPPORTED
#define PNG_READ_PACKSWAP_SUPPORTED
-#define PNG_READ_pCAL_SUPPORTED
-#define PNG_READ_pHYs_SUPPORTED
+#define PNG_READ_PACK_SUPPORTED
#define PNG_READ_QUANTIZE_SUPPORTED
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
-#define PNG_READ_sBIT_SUPPORTED
#define PNG_READ_SCALE_16_TO_8_SUPPORTED
-#define PNG_READ_sCAL_SUPPORTED
#define PNG_READ_SHIFT_SUPPORTED
-#define PNG_READ_sPLT_SUPPORTED
-#define PNG_READ_sRGB_SUPPORTED
#define PNG_READ_STRIP_16_TO_8_SUPPORTED
#define PNG_READ_STRIP_ALPHA_SUPPORTED
#define PNG_READ_SUPPORTED
#define PNG_READ_SWAP_ALPHA_SUPPORTED
#define PNG_READ_SWAP_SUPPORTED
-#define PNG_READ_tEXt_SUPPORTED
#define PNG_READ_TEXT_SUPPORTED
-#define PNG_READ_tIME_SUPPORTED
#define PNG_READ_TRANSFORMS_SUPPORTED
-#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_READ_USER_CHUNKS_SUPPORTED
#define PNG_READ_USER_TRANSFORM_SUPPORTED
+#define PNG_READ_bKGD_SUPPORTED
+#define PNG_READ_cHRM_SUPPORTED
+#define PNG_READ_gAMA_SUPPORTED
+#define PNG_READ_hIST_SUPPORTED
+#define PNG_READ_iCCP_SUPPORTED
+#define PNG_READ_iTXt_SUPPORTED
+#define PNG_READ_oFFs_SUPPORTED
+#define PNG_READ_pCAL_SUPPORTED
+#define PNG_READ_pHYs_SUPPORTED
+#define PNG_READ_sBIT_SUPPORTED
+#define PNG_READ_sCAL_SUPPORTED
+#define PNG_READ_sPLT_SUPPORTED
+#define PNG_READ_sRGB_SUPPORTED
+#define PNG_READ_tEXt_SUPPORTED
+#define PNG_READ_tIME_SUPPORTED
+#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_zTXt_SUPPORTED
#define PNG_SAVE_INT_32_SUPPORTED
-#define PNG_sBIT_SUPPORTED
-#define PNG_sCAL_SUPPORTED
+#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SEQUENTIAL_READ_SUPPORTED
-#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
-#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
#define PNG_SETJMP_SUPPORTED
+#define PNG_SET_OPTION_SUPPORTED
+#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SET_USER_LIMITS_SUPPORTED
-#define PNG_sPLT_SUPPORTED
-#define PNG_sRGB_SUPPORTED
+#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
+#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
+#define PNG_SIMPLIFIED_READ_SUPPORTED
+#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
+#define PNG_SIMPLIFIED_WRITE_SUPPORTED
#define PNG_STDIO_SUPPORTED
-#define PNG_tEXt_SUPPORTED
+#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_TEXT_SUPPORTED
#define PNG_TIME_RFC1123_SUPPORTED
-#define PNG_tIME_SUPPORTED
-#define PNG_tRNS_SUPPORTED
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_USER_CHUNKS_SUPPORTED
#define PNG_USER_LIMITS_SUPPORTED
@@ -144,44 +124,91 @@
#define PNG_WRITE_16BIT_SUPPORTED
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_WRITE_BGR_SUPPORTED
-#define PNG_WRITE_bKGD_SUPPORTED
-#define PNG_WRITE_cHRM_SUPPORTED
+#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
+#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
#define PNG_WRITE_FILLER_SUPPORTED
#define PNG_WRITE_FILTER_SUPPORTED
#define PNG_WRITE_FLUSH_SUPPORTED
-#define PNG_WRITE_gAMA_SUPPORTED
-#define PNG_WRITE_hIST_SUPPORTED
-#define PNG_WRITE_iCCP_SUPPORTED
+#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
#define PNG_WRITE_INTERLACING_SUPPORTED
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
#define PNG_WRITE_INVERT_SUPPORTED
-#define PNG_WRITE_iTXt_SUPPORTED
-#define PNG_WRITE_oFFs_SUPPORTED
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
-#define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_PACKSWAP_SUPPORTED
-#define PNG_WRITE_pCAL_SUPPORTED
-#define PNG_WRITE_pHYs_SUPPORTED
-#define PNG_WRITE_sBIT_SUPPORTED
-#define PNG_WRITE_sCAL_SUPPORTED
+#define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_SHIFT_SUPPORTED
-#define PNG_WRITE_sPLT_SUPPORTED
-#define PNG_WRITE_sRGB_SUPPORTED
#define PNG_WRITE_SUPPORTED
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
#define PNG_WRITE_SWAP_SUPPORTED
-#define PNG_WRITE_tEXt_SUPPORTED
#define PNG_WRITE_TEXT_SUPPORTED
-#define PNG_WRITE_tIME_SUPPORTED
#define PNG_WRITE_TRANSFORMS_SUPPORTED
-#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+#define PNG_WRITE_bKGD_SUPPORTED
+#define PNG_WRITE_cHRM_SUPPORTED
+#define PNG_WRITE_gAMA_SUPPORTED
+#define PNG_WRITE_hIST_SUPPORTED
+#define PNG_WRITE_iCCP_SUPPORTED
+#define PNG_WRITE_iTXt_SUPPORTED
+#define PNG_WRITE_oFFs_SUPPORTED
+#define PNG_WRITE_pCAL_SUPPORTED
+#define PNG_WRITE_pHYs_SUPPORTED
+#define PNG_WRITE_sBIT_SUPPORTED
+#define PNG_WRITE_sCAL_SUPPORTED
+#define PNG_WRITE_sPLT_SUPPORTED
+#define PNG_WRITE_sRGB_SUPPORTED
+#define PNG_WRITE_tEXt_SUPPORTED
+#define PNG_WRITE_tIME_SUPPORTED
+#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_zTXt_SUPPORTED
+#define PNG_bKGD_SUPPORTED
+#define PNG_cHRM_SUPPORTED
+#define PNG_gAMA_SUPPORTED
+#define PNG_hIST_SUPPORTED
+#define PNG_iCCP_SUPPORTED
+#define PNG_iTXt_SUPPORTED
+#define PNG_oFFs_SUPPORTED
+#define PNG_pCAL_SUPPORTED
+#define PNG_pHYs_SUPPORTED
+#define PNG_sBIT_SUPPORTED
+#define PNG_sCAL_SUPPORTED
+#define PNG_sPLT_SUPPORTED
+#define PNG_sRGB_SUPPORTED
+#define PNG_tEXt_SUPPORTED
+#define PNG_tIME_SUPPORTED
+#define PNG_tRNS_SUPPORTED
#define PNG_zTXt_SUPPORTED
/* end of options */
+/* settings */
+#define PNG_API_RULE 0
+#define PNG_DEFAULT_READ_MACROS 1
+#define PNG_GAMMA_THRESHOLD_FIXED 5000
+#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
+#define PNG_INFLATE_BUF_SIZE 1024
+#define PNG_LINKAGE_API extern
+#define PNG_LINKAGE_CALLBACK extern
+#define PNG_LINKAGE_DATA extern
+#define PNG_LINKAGE_FUNCTION extern
+#define PNG_MAX_GAMMA_8 11
+#define PNG_QUANTIZE_BLUE_BITS 5
+#define PNG_QUANTIZE_GREEN_BITS 5
+#define PNG_QUANTIZE_RED_BITS 5
+#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1)
+#define PNG_TEXT_Z_DEFAULT_STRATEGY 0
+#define PNG_USER_CHUNK_CACHE_MAX 1000
+#define PNG_USER_CHUNK_MALLOC_MAX 8000000
+#define PNG_USER_HEIGHT_MAX 1000000
+#define PNG_USER_WIDTH_MAX 1000000
+#define PNG_ZBUF_SIZE 8192
+#define PNG_ZLIB_VERNUM 0 /* unknown */
+#define PNG_Z_DEFAULT_COMPRESSION (-1)
+#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
+#define PNG_Z_DEFAULT_STRATEGY 1
+#define PNG_sCAL_PRECISION 5
+#define PNG_sRGB_PROFILE_CHECKS 2
+/* end of settings */
#endif /* PNGLCONF_H */
diff --git a/thirdparty/libpng/pngmem.c b/thirdparty/libpng/pngmem.c
index bf5ff037..7bcfd005 100644
--- a/thirdparty/libpng/pngmem.c
+++ b/thirdparty/libpng/pngmem.c
@@ -1,8 +1,8 @@
/* pngmem.c - stub functions for memory allocation
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -20,627 +20,244 @@
#include "pngpriv.h"
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-
-/* Borland DOS special memory handler */
-#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
-/* If you change this, be sure to change the one in png.h also */
-
-/* Allocate memory for a png_struct. The malloc and memset can be replaced
- by a single call to calloc() if this is thought to improve performance. */
-PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct,(int type),PNG_ALLOCATED)
-{
-# ifdef PNG_USER_MEM_SUPPORTED
- return (png_create_struct_2(type, NULL, NULL));
-}
-
-/* Alternate version of png_create_struct, for use with user-defined malloc. */
-PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr),
- PNG_ALLOCATED)
-{
-# endif /* PNG_USER_MEM_SUPPORTED */
- png_size_t size;
- png_voidp struct_ptr;
-
- if (type == PNG_STRUCT_INFO)
- size = png_sizeof(png_info);
-
- else if (type == PNG_STRUCT_PNG)
- size = png_sizeof(png_struct);
-
- else
- return (png_get_copyright(NULL));
-
-# ifdef PNG_USER_MEM_SUPPORTED
- if (malloc_fn != NULL)
- {
- png_struct dummy_struct;
- memset(&dummy_struct, 0, sizeof dummy_struct);
- dummy_struct.mem_ptr=mem_ptr;
- struct_ptr = (*(malloc_fn))(&dummy_struct, (png_alloc_size_t)size);
- }
-
- else
-# endif /* PNG_USER_MEM_SUPPORTED */
- struct_ptr = (png_voidp)farmalloc(size);
- if (struct_ptr != NULL)
- png_memset(struct_ptr, 0, size);
-
- return (struct_ptr);
-}
-
-/* Free memory allocated by a png_create_struct() call */
+/* Free a png_struct */
void /* PRIVATE */
-png_destroy_struct(png_voidp struct_ptr)
+png_destroy_png_struct(png_structrp png_ptr)
{
-# ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2(struct_ptr, NULL, NULL);
-}
-
-/* Free memory allocated by a png_create_struct() call */
-void /* PRIVATE */
-png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
- png_voidp mem_ptr)
-{
-# endif
- if (struct_ptr != NULL)
+ if (png_ptr != NULL)
{
-# ifdef PNG_USER_MEM_SUPPORTED
- if (free_fn != NULL)
- {
- png_struct dummy_struct;
- memset(&dummy_struct, 0, sizeof dummy_struct);
- dummy_struct.mem_ptr=mem_ptr;
- (*(free_fn))(&dummy_struct, struct_ptr);
- return;
- }
-
-# endif /* PNG_USER_MEM_SUPPORTED */
- farfree (struct_ptr);
+ /* png_free might call png_error and may certainly call
+ * png_get_mem_ptr, so fake a temporary png_struct to support this.
+ */
+ png_struct dummy_struct = *png_ptr;
+ memset(png_ptr, 0, (sizeof *png_ptr));
+ png_free(&dummy_struct, png_ptr);
+
+# ifdef PNG_SETJMP_SUPPORTED
+ /* We may have a jmp_buf left to deallocate. */
+ png_free_jmpbuf(&dummy_struct);
+# endif
}
}
/* Allocate memory. For reasonable files, size should never exceed
- * 64K. However, zlib may allocate more then 64K if you don't tell
- * it not to. See zconf.h and png.h for more information. zlib does
+ * 64K. However, zlib may allocate more than 64K if you don't tell
+ * it not to. See zconf.h and png.h for more information. zlib does
* need to allocate exactly 64K, so whatever you call here must
* have the ability to do that.
- *
- * Borland seems to have a problem in DOS mode for exactly 64K.
- * It gives you a segment with an offset of 8 (perhaps to store its
- * memory stuff). zlib doesn't like this at all, so we have to
- * detect and deal with it. This code should not be needed in
- * Windows or OS/2 modes, and only in 16 bit mode. This code has
- * been updated by Alexander Lehmann for version 0.89 to waste less
- * memory.
- *
- * Note that we can't use png_size_t for the "size" declaration,
- * since on some systems a png_size_t is a 16-bit quantity, and as a
- * result, we would be truncating potentially larger memory requests
- * (which should cause a fatal error) and introducing major problems.
*/
PNG_FUNCTION(png_voidp,PNGAPI
-png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
{
png_voidp ret;
- ret = (png_malloc(png_ptr, size));
+ ret = png_malloc(png_ptr, size);
if (ret != NULL)
- png_memset(ret,0,(png_size_t)size);
-
- return (ret);
-}
-
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
-{
- png_voidp ret;
-
- if (png_ptr == NULL || size == 0)
- return (NULL);
-
-# ifdef PNG_USER_MEM_SUPPORTED
- if (png_ptr->malloc_fn != NULL)
- ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
-
- else
- ret = (png_malloc_default(png_ptr, size));
-
- if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of memory");
+ memset(ret, 0, size);
- return (ret);
+ return ret;
}
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of
+ * allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
+ * Checking and error handling must happen outside this routine; it returns NULL
+ * if the allocation cannot be done (for any reason.)
+ */
+PNG_FUNCTION(png_voidp /* PRIVATE */,
+png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
+ PNG_ALLOCATED)
{
- png_voidp ret;
-# endif /* PNG_USER_MEM_SUPPORTED */
-
- if (png_ptr == NULL || size == 0)
- return (NULL);
-
-# ifdef PNG_MAX_MALLOC_64K
- if (size > (png_uint_32)65536L)
- {
- png_warning(png_ptr, "Cannot Allocate > 64K");
- ret = NULL;
- }
-
- else
-# endif
-
- if (size != (size_t)size)
- ret = NULL;
-
- else if (size == (png_uint_32)65536L)
+ /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
+ * allocators have also been removed in 1.6.0, so any 16-bit system now has
+ * to implement a user memory handler. This checks to be sure it isn't
+ * called with big numbers.
+ */
+#ifndef PNG_USER_MEM_SUPPORTED
+ PNG_UNUSED(png_ptr)
+#endif
+
+ /* Some compilers complain that this is always true. However, it
+ * can be false when integer overflow happens.
+ */
+ if (size > 0 && size <= PNG_SIZE_MAX
+# ifdef PNG_MAX_MALLOC_64K
+ && size <= 65536U
+# endif
+ )
{
- if (png_ptr->offset_table == NULL)
- {
- /* Try to see if we need to do any of this fancy stuff */
- ret = farmalloc(size);
- if (ret == NULL || ((png_size_t)ret & 0xffff))
- {
- int num_blocks;
- png_uint_32 total_size;
- png_bytep table;
- int i, mem_level, window_bits;
- png_byte huge * hptr;
- int window_bits
-
- if (ret != NULL)
- {
- farfree(ret);
- ret = NULL;
- }
-
- window_bits =
- png_ptr->zlib_window_bits >= png_ptr->zlib_text_window_bits ?
- png_ptr->zlib_window_bits : png_ptr->zlib_text_window_bits;
-
- if (window_bits > 14)
- num_blocks = (int)(1 << (window_bits - 14));
-
- else
- num_blocks = 1;
-
- mem_level =
- png_ptr->zlib_mem_level >= png_ptr->zlib_text_mem_level ?
- png_ptr->zlib_mem_level : png_ptr->zlib_text_mem_level;
-
- if (mem_level >= 7)
- num_blocks += (int)(1 << (mem_level - 7));
-
- else
- num_blocks++;
-
- total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
-
- table = farmalloc(total_size);
-
- if (table == NULL)
- {
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out Of Memory"); /* Note "O", "M" */
-
- else
- png_warning(png_ptr, "Out Of Memory");
-# endif
- return (NULL);
- }
-
- if ((png_size_t)table & 0xfff0)
- {
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr,
- "Farmalloc didn't return normalized pointer");
-
- else
- png_warning(png_ptr,
- "Farmalloc didn't return normalized pointer");
-# endif
- return (NULL);
- }
-
- png_ptr->offset_table = table;
- png_ptr->offset_table_ptr = farmalloc(num_blocks *
- png_sizeof(png_bytep));
-
- if (png_ptr->offset_table_ptr == NULL)
- {
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out Of memory"); /* Note "O", "m" */
-
- else
- png_warning(png_ptr, "Out Of memory");
-# endif
- return (NULL);
- }
-
- hptr = (png_byte huge *)table;
- if ((png_size_t)hptr & 0xf)
- {
- hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
- hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */
- }
-
- for (i = 0; i < num_blocks; i++)
- {
- png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
- hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */
- }
-
- png_ptr->offset_table_number = num_blocks;
- png_ptr->offset_table_count = 0;
- png_ptr->offset_table_count_free = 0;
- }
- }
-
- if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
- {
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of Memory"); /* Note "O" and "M" */
-
- else
- png_warning(png_ptr, "Out of Memory");
-# endif
- return (NULL);
- }
-
- ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
- }
-
- else
- ret = farmalloc(size);
-
-# ifndef PNG_USER_MEM_SUPPORTED
- if (ret == NULL)
- {
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of memory"); /* Note "o" and "m" */
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
+ return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
else
- png_warning(png_ptr, "Out of memory"); /* Note "o" and "m" */
+#endif
+ return malloc((size_t)size); /* checked for truncation above */
}
-# endif
- return (ret);
+ else
+ return NULL;
}
-/* Free a pointer allocated by png_malloc(). In the default
- * configuration, png_ptr is not used, but is passed in case it
- * is needed. If ptr is NULL, return without taking any action.
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
+ defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
+/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7
+ * that arises because of the checks in png_realloc_array that are repeated in
+ * png_malloc_array.
*/
-void PNGAPI
-png_free(png_structp png_ptr, png_voidp ptr)
+static png_voidp
+png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
+ size_t element_size)
{
- if (png_ptr == NULL || ptr == NULL)
- return;
+ png_alloc_size_t req = nelements; /* known to be > 0 */
-# ifdef PNG_USER_MEM_SUPPORTED
- if (png_ptr->free_fn != NULL)
- {
- (*(png_ptr->free_fn))(png_ptr, ptr);
- return;
- }
+ if (req <= PNG_SIZE_MAX/element_size)
+ return png_malloc_base(png_ptr, req * element_size);
- else
- png_free_default(png_ptr, ptr);
+ /* The failure case when the request is too large */
+ return NULL;
}
-void PNGAPI
-png_free_default(png_structp png_ptr, png_voidp ptr)
-{
-# endif /* PNG_USER_MEM_SUPPORTED */
-
- if (png_ptr == NULL || ptr == NULL)
- return;
-
- if (png_ptr->offset_table != NULL)
- {
- int i;
-
- for (i = 0; i < png_ptr->offset_table_count; i++)
- {
- if (ptr == png_ptr->offset_table_ptr[i])
- {
- ptr = NULL;
- png_ptr->offset_table_count_free++;
- break;
- }
- }
- if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
- {
- farfree(png_ptr->offset_table);
- farfree(png_ptr->offset_table_ptr);
- png_ptr->offset_table = NULL;
- png_ptr->offset_table_ptr = NULL;
- }
- }
-
- if (ptr != NULL)
- farfree(ptr);
-}
-
-#else /* Not the Borland DOS special memory handler */
-
-/* Allocate memory for a png_struct or a png_info. The malloc and
- memset can be replaced by a single call to calloc() if this is thought
- to improve performance noticably. */
PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct,(int type),PNG_ALLOCATED)
+png_malloc_array,(png_const_structrp png_ptr, int nelements,
+ size_t element_size),PNG_ALLOCATED)
{
-# ifdef PNG_USER_MEM_SUPPORTED
- return (png_create_struct_2(type, NULL, NULL));
+ if (nelements <= 0 || element_size == 0)
+ png_error(png_ptr, "internal error: array alloc");
+
+ return png_malloc_array_checked(png_ptr, nelements, element_size);
}
-/* Allocate memory for a png_struct or a png_info. The malloc and
- memset can be replaced by a single call to calloc() if this is thought
- to improve performance noticably. */
PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr),
- PNG_ALLOCATED)
+png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
+ int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
{
-# endif /* PNG_USER_MEM_SUPPORTED */
- png_size_t size;
- png_voidp struct_ptr;
-
- if (type == PNG_STRUCT_INFO)
- size = png_sizeof(png_info);
-
- else if (type == PNG_STRUCT_PNG)
- size = png_sizeof(png_struct);
-
- else
- return (NULL);
-
-# ifdef PNG_USER_MEM_SUPPORTED
- if (malloc_fn != NULL)
+ /* These are internal errors: */
+ if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
+ (old_array == NULL && old_elements > 0))
+ png_error(png_ptr, "internal error: array realloc");
+
+ /* Check for overflow on the elements count (so the caller does not have to
+ * check.)
+ */
+ if (add_elements <= INT_MAX - old_elements)
{
- png_struct dummy_struct;
- png_structp png_ptr = &dummy_struct;
- png_ptr->mem_ptr=mem_ptr;
- struct_ptr = (*(malloc_fn))(png_ptr, size);
-
- if (struct_ptr != NULL)
- png_memset(struct_ptr, 0, size);
-
- return (struct_ptr);
- }
-# endif /* PNG_USER_MEM_SUPPORTED */
-
-# if defined(__TURBOC__) && !defined(__FLAT__)
- struct_ptr = (png_voidp)farmalloc(size);
-# else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- struct_ptr = (png_voidp)halloc(size, 1);
-# else
- struct_ptr = (png_voidp)malloc(size);
-# endif
-# endif
-
- if (struct_ptr != NULL)
- png_memset(struct_ptr, 0, size);
-
- return (struct_ptr);
-}
-
+ png_voidp new_array = png_malloc_array_checked(png_ptr,
+ old_elements+add_elements, element_size);
-/* Free memory allocated by a png_create_struct() call */
-void /* PRIVATE */
-png_destroy_struct(png_voidp struct_ptr)
-{
-# ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2(struct_ptr, NULL, NULL);
-}
-
-/* Free memory allocated by a png_create_struct() call */
-void /* PRIVATE */
-png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
- png_voidp mem_ptr)
-{
-# endif /* PNG_USER_MEM_SUPPORTED */
- if (struct_ptr != NULL)
- {
-# ifdef PNG_USER_MEM_SUPPORTED
- if (free_fn != NULL)
+ if (new_array != NULL)
{
- png_struct dummy_struct;
- png_structp png_ptr = &dummy_struct;
- png_ptr->mem_ptr=mem_ptr;
- (*(free_fn))(png_ptr, struct_ptr);
- return;
- }
-# endif /* PNG_USER_MEM_SUPPORTED */
-# if defined(__TURBOC__) && !defined(__FLAT__)
- farfree(struct_ptr);
-
-# else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- hfree(struct_ptr);
+ /* Because png_malloc_array worked the size calculations below cannot
+ * overflow.
+ */
+ if (old_elements > 0)
+ memcpy(new_array, old_array, element_size*(unsigned)old_elements);
-# else
- free(struct_ptr);
+ memset((char*)new_array + element_size*(unsigned)old_elements, 0,
+ element_size*(unsigned)add_elements);
-# endif
-# endif
+ return new_array;
+ }
}
+
+ return NULL; /* error */
}
+#endif /* TEXT || sPLT || STORE_UNKNOWN_CHUNKS */
-/* Allocate memory. For reasonable files, size should never exceed
- * 64K. However, zlib may allocate more then 64K if you don't tell
- * it not to. See zconf.h and png.h for more information. zlib does
- * need to allocate exactly 64K, so whatever you call here must
- * have the ability to do that.
+/* Various functions that have different error handling are derived from this.
+ * png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
+ * function png_malloc_default is also provided.
*/
-
PNG_FUNCTION(png_voidp,PNGAPI
-png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
{
png_voidp ret;
- ret = (png_malloc(png_ptr, size));
+ if (png_ptr == NULL)
+ return NULL;
- if (ret != NULL)
- png_memset(ret,0,(png_size_t)size);
+ ret = png_malloc_base(png_ptr, size);
- return (ret);
+ if (ret == NULL)
+ png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */
+
+ return ret;
}
+#ifdef PNG_USER_MEM_SUPPORTED
PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size),
+ PNG_ALLOCATED PNG_DEPRECATED)
{
png_voidp ret;
-# ifdef PNG_USER_MEM_SUPPORTED
- if (png_ptr == NULL || size == 0)
- return (NULL);
-
- if (png_ptr->malloc_fn != NULL)
- ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
+ if (png_ptr == NULL)
+ return NULL;
- else
- ret = (png_malloc_default(png_ptr, size));
+ /* Passing 'NULL' here bypasses the application provided memory handler. */
+ ret = png_malloc_base(NULL/*use malloc*/, size);
- if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of Memory");
+ if (ret == NULL)
+ png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */
- return (ret);
+ return ret;
}
+#endif /* USER_MEM */
+/* This function was added at libpng version 1.2.3. The png_malloc_warn()
+ * function will issue a png_warning and return NULL instead of issuing a
+ * png_error, if it fails to allocate the requested memory.
+ */
PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size),
+ PNG_ALLOCATED)
{
- png_voidp ret;
-# endif /* PNG_USER_MEM_SUPPORTED */
-
- if (png_ptr == NULL || size == 0)
- return (NULL);
-
-# ifdef PNG_MAX_MALLOC_64K
- if (size > (png_uint_32)65536L)
+ if (png_ptr != NULL)
{
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Cannot Allocate > 64K");
-
- else
-# endif
- return NULL;
- }
-# endif
-
- /* Check for overflow */
-# if defined(__TURBOC__) && !defined(__FLAT__)
-
- if (size != (unsigned long)size)
- ret = NULL;
-
- else
- ret = farmalloc(size);
-
-# else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- if (size != (unsigned long)size)
- ret = NULL;
-
- else
- ret = halloc(size, 1);
+ png_voidp ret = png_malloc_base(png_ptr, size);
-# else
- if (size != (size_t)size)
- ret = NULL;
+ if (ret != NULL)
+ return ret;
- else
- ret = malloc((size_t)size);
-# endif
-# endif
-
-# ifndef PNG_USER_MEM_SUPPORTED
- if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of Memory");
-# endif
+ png_warning(png_ptr, "Out of memory");
+ }
- return (ret);
+ return NULL;
}
/* Free a pointer allocated by png_malloc(). If ptr is NULL, return
* without taking any action.
*/
void PNGAPI
-png_free(png_structp png_ptr, png_voidp ptr)
+png_free(png_const_structrp png_ptr, png_voidp ptr)
{
if (png_ptr == NULL || ptr == NULL)
return;
-# ifdef PNG_USER_MEM_SUPPORTED
+#ifdef PNG_USER_MEM_SUPPORTED
if (png_ptr->free_fn != NULL)
- {
- (*(png_ptr->free_fn))(png_ptr, ptr);
- return;
- }
+ png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr);
else
png_free_default(png_ptr, ptr);
}
-void PNGAPI
-png_free_default(png_structp png_ptr, png_voidp ptr)
+PNG_FUNCTION(void,PNGAPI
+png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
{
if (png_ptr == NULL || ptr == NULL)
return;
+#endif /* USER_MEM */
-# endif /* PNG_USER_MEM_SUPPORTED */
-
-# if defined(__TURBOC__) && !defined(__FLAT__)
- farfree(ptr);
-
-# else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- hfree(ptr);
-
-# else
free(ptr);
-
-# endif
-# endif
-}
-#endif /* Not Borland DOS special memory handler */
-
-/* This function was added at libpng version 1.2.3. The png_malloc_warn()
- * function will set up png_malloc() to issue a png_warning and return NULL
- * instead of issuing a png_error, if it fails to allocate the requested
- * memory.
- */
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_warn,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
-{
- png_voidp ptr;
- png_uint_32 save_flags;
- if (png_ptr == NULL)
- return (NULL);
-
- save_flags = png_ptr->flags;
- png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
- ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
- png_ptr->flags=save_flags;
- return(ptr);
}
-
#ifdef PNG_USER_MEM_SUPPORTED
/* This function is called when the application wants to use another method
* of allocating and freeing memory.
*/
void PNGAPI
-png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
+png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr
malloc_fn, png_free_ptr free_fn)
{
if (png_ptr != NULL)
@@ -656,12 +273,12 @@ png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
* pointer before png_write_destroy and png_read_destroy are called.
*/
png_voidp PNGAPI
-png_get_mem_ptr(png_const_structp png_ptr)
+png_get_mem_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
- return (NULL);
+ return NULL;
- return ((png_voidp)png_ptr->mem_ptr);
+ return png_ptr->mem_ptr;
}
-#endif /* PNG_USER_MEM_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* USER_MEM */
+#endif /* READ || WRITE */
diff --git a/thirdparty/libpng/pngpread.c b/thirdparty/libpng/pngpread.c
index 95a2082e..0dc1e53c 100644
--- a/thirdparty/libpng/pngpread.c
+++ b/thirdparty/libpng/pngpread.c
@@ -1,8 +1,8 @@
/* pngpread.c - read a png file in push mode
*
- * Last changed in libpng 1.5.9 [February 18, 2012]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.18 [July 23, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -19,15 +19,21 @@
#define PNG_READ_SIG_MODE 0
#define PNG_READ_CHUNK_MODE 1
#define PNG_READ_IDAT_MODE 2
-#define PNG_SKIP_MODE 3
#define PNG_READ_tEXt_MODE 4
#define PNG_READ_zTXt_MODE 5
#define PNG_READ_DONE_MODE 6
#define PNG_READ_iTXt_MODE 7
#define PNG_ERROR_MODE 8
+#define PNG_PUSH_SAVE_BUFFER_IF_FULL \
+if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
+ { png_push_save_buffer(png_ptr); return; }
+#define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
+if (png_ptr->buffer_size < N) \
+ { png_push_save_buffer(png_ptr); return; }
+
void PNGAPI
-png_process_data(png_structp png_ptr, png_infop info_ptr,
+png_process_data(png_structrp png_ptr, png_inforp info_ptr,
png_bytep buffer, png_size_t buffer_size)
{
if (png_ptr == NULL || info_ptr == NULL)
@@ -42,14 +48,14 @@ png_process_data(png_structp png_ptr, png_infop info_ptr,
}
png_size_t PNGAPI
-png_process_data_pause(png_structp png_ptr, int save)
+png_process_data_pause(png_structrp png_ptr, int save)
{
if (png_ptr != NULL)
{
- /* It's easiest for the caller if we do the save, then the caller doesn't
+ /* It's easiest for the caller if we do the save; then the caller doesn't
* have to supply the same data again:
*/
- if (save)
+ if (save != 0)
png_push_save_buffer(png_ptr);
else
{
@@ -69,41 +75,23 @@ png_process_data_pause(png_structp png_ptr, int save)
}
png_uint_32 PNGAPI
-png_process_data_skip(png_structp png_ptr)
+png_process_data_skip(png_structrp png_ptr)
{
- png_uint_32 remaining = 0;
-
- if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE &&
- png_ptr->skip_length > 0)
- {
- /* At the end of png_process_data the buffer size must be 0 (see the loop
- * above) so we can detect a broken call here:
- */
- if (png_ptr->buffer_size != 0)
- png_error(png_ptr,
- "png_process_data_skip called inside png_process_data");
-
- /* If is impossible for there to be a saved buffer at this point -
- * otherwise we could not be in SKIP mode. This will also happen if
- * png_process_skip is called inside png_process_data (but only very
- * rarely.)
- */
- if (png_ptr->save_buffer_size != 0)
- png_error(png_ptr, "png_process_data_skip called with saved data");
-
- remaining = png_ptr->skip_length;
- png_ptr->skip_length = 0;
- png_ptr->process_mode = PNG_READ_CHUNK_MODE;
- }
-
- return remaining;
+ /* TODO: Deprecate and remove this API.
+ * Somewhere the implementation of this seems to have been lost,
+ * or abandoned. It was only to support some internal back-door access
+ * to png_struct) in libpng-1.4.x.
+ */
+ png_app_warning(png_ptr,
+"png_process_data_skip is not implemented in any current version of libpng");
+ return 0;
}
/* What we do with the incoming data depends on what we were previously
* doing before we ran out of data...
*/
void /* PRIVATE */
-png_process_some_data(png_structp png_ptr, png_infop info_ptr)
+png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
{
if (png_ptr == NULL)
return;
@@ -128,36 +116,6 @@ png_process_some_data(png_structp png_ptr, png_infop info_ptr)
break;
}
-#ifdef PNG_READ_tEXt_SUPPORTED
- case PNG_READ_tEXt_MODE:
- {
- png_push_read_tEXt(png_ptr, info_ptr);
- break;
- }
-
-#endif
-#ifdef PNG_READ_zTXt_SUPPORTED
- case PNG_READ_zTXt_MODE:
- {
- png_push_read_zTXt(png_ptr, info_ptr);
- break;
- }
-
-#endif
-#ifdef PNG_READ_iTXt_SUPPORTED
- case PNG_READ_iTXt_MODE:
- {
- png_push_read_iTXt(png_ptr, info_ptr);
- break;
- }
-
-#endif
- case PNG_SKIP_MODE:
- {
- png_push_crc_finish(png_ptr);
- break;
- }
-
default:
{
png_ptr->buffer_size = 0;
@@ -173,10 +131,10 @@ png_process_some_data(png_structp png_ptr, png_infop info_ptr)
* routine.
*/
void /* PRIVATE */
-png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
+png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
{
- png_size_t num_checked = png_ptr->sig_bytes,
- num_to_check = 8 - num_checked;
+ png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
+ num_to_check = 8 - num_checked;
if (png_ptr->buffer_size < num_to_check)
{
@@ -206,27 +164,25 @@ png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
}
void /* PRIVATE */
-png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
+png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
{
png_uint_32 chunk_name;
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ int keep; /* unknown handling method */
+#endif
- /* First we make sure we have enough data for the 4 byte chunk name
- * and the 4 byte chunk length before proceeding with decoding the
+ /* First we make sure we have enough data for the 4-byte chunk name
+ * and the 4-byte chunk length before proceeding with decoding the
* chunk data. To fully decode each of these chunks, we also make
- * sure we have enough data in the buffer for the 4 byte CRC at the
+ * sure we have enough data in the buffer for the 4-byte CRC at the
* end of every chunk (except IDAT, which is handled separately).
*/
- if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+ if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
{
png_byte chunk_length[4];
png_byte chunk_tag[4];
- if (png_ptr->buffer_size < 8)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_LT(8)
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
png_reset_crc(png_ptr);
@@ -240,14 +196,29 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
if (chunk_name == png_IDAT)
{
- /* This is here above the if/else case statement below because if the
- * unknown handling marks 'IDAT' as unknown then the IDAT handling case is
- * completely skipped.
- *
- * TODO: there must be a better way of doing this.
- */
- if (png_ptr->mode & PNG_AFTER_IDAT)
+ if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+
+ /* If we reach an IDAT chunk, this means we have read all of the
+ * header chunks, and we can start reading the image (or if this
+ * is called after the image has been read - we have an error).
+ */
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_error(png_ptr, "Missing IHDR before IDAT");
+
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0)
+ png_error(png_ptr, "Missing PLTE before IDAT");
+
+ png_ptr->mode |= PNG_HAVE_IDAT;
+ png_ptr->process_mode = PNG_READ_IDAT_MODE;
+
+ if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
+ if (png_ptr->push_length == 0)
+ return;
+
+ if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
+ png_benign_error(png_ptr, "Too many IDATs found");
}
if (chunk_name == png_IHDR)
@@ -255,23 +226,13 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
if (png_ptr->push_length != 13)
png_error(png_ptr, "Invalid IHDR length");
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
}
else if (chunk_name == png_IEND)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
png_ptr->process_mode = PNG_READ_DONE_MODE;
@@ -279,70 +240,25 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
}
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- else if (png_chunk_unknown_handling(png_ptr, chunk_name))
+ else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- if (chunk_name == png_IDAT)
- png_ptr->mode |= PNG_HAVE_IDAT;
-
- png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
+ png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
if (chunk_name == png_PLTE)
png_ptr->mode |= PNG_HAVE_PLTE;
-
- else if (chunk_name == png_IDAT)
- {
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before IDAT");
-
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
- png_error(png_ptr, "Missing PLTE before IDAT");
- }
}
-
#endif
+
else if (chunk_name == png_PLTE)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
}
else if (chunk_name == png_IDAT)
{
- /* If we reach an IDAT chunk, this means we have read all of the
- * header chunks, and we can start reading the image (or if this
- * is called after the image has been read - we have an error).
- */
-
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before IDAT");
-
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
- png_error(png_ptr, "Missing PLTE before IDAT");
-
- if (png_ptr->mode & PNG_HAVE_IDAT)
- {
- if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
- if (png_ptr->push_length == 0)
- return;
-
- if (png_ptr->mode & PNG_AFTER_IDAT)
- png_benign_error(png_ptr, "Too many IDATs found");
- }
-
png_ptr->idat_size = png_ptr->push_length;
- png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->process_mode = PNG_READ_IDAT_MODE;
png_push_have_info(png_ptr, info_ptr);
png_ptr->zstream.avail_out =
@@ -355,12 +271,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_gAMA_SUPPORTED
else if (png_ptr->chunk_name == png_gAMA)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -368,12 +279,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_sBIT_SUPPORTED
else if (png_ptr->chunk_name == png_sBIT)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -381,12 +287,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_cHRM_SUPPORTED
else if (png_ptr->chunk_name == png_cHRM)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -394,12 +295,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_sRGB_SUPPORTED
else if (chunk_name == png_sRGB)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -407,12 +303,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_iCCP_SUPPORTED
else if (png_ptr->chunk_name == png_iCCP)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -420,12 +311,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_sPLT_SUPPORTED
else if (chunk_name == png_sPLT)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -433,12 +319,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_tRNS_SUPPORTED
else if (chunk_name == png_tRNS)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -446,12 +327,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_bKGD_SUPPORTED
else if (chunk_name == png_bKGD)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -459,12 +335,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_hIST_SUPPORTED
else if (chunk_name == png_hIST)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -472,12 +343,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_pHYs_SUPPORTED
else if (chunk_name == png_pHYs)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -485,12 +351,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_oFFs_SUPPORTED
else if (chunk_name == png_oFFs)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
@@ -498,12 +359,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_pCAL_SUPPORTED
else if (chunk_name == png_pCAL)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -511,12 +367,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_sCAL_SUPPORTED
else if (chunk_name == png_sCAL)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -524,12 +375,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_tIME_SUPPORTED
else if (chunk_name == png_tIME)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -537,123 +383,37 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_tEXt_SUPPORTED
else if (chunk_name == png_tEXt)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
+ png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_zTXt_SUPPORTED
else if (chunk_name == png_zTXt)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
+ png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_iTXt_SUPPORTED
else if (chunk_name == png_iTXt)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
+ png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
}
-
#endif
+
else
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
- png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
+ png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
+ PNG_HANDLE_CHUNK_AS_DEFAULT);
}
png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
}
-void /* PRIVATE */
-png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
-{
- png_ptr->process_mode = PNG_SKIP_MODE;
- png_ptr->skip_length = skip;
-}
-
-void /* PRIVATE */
-png_push_crc_finish(png_structp png_ptr)
-{
- if (png_ptr->skip_length && png_ptr->save_buffer_size)
- {
- png_size_t save_size = png_ptr->save_buffer_size;
- png_uint_32 skip_length = png_ptr->skip_length;
-
- /* We want the smaller of 'skip_length' and 'save_buffer_size', but
- * they are of different types and we don't know which variable has the
- * fewest bits. Carefully select the smaller and cast it to the type of
- * the larger - this cannot overflow. Do not cast in the following test
- * - it will break on either 16 or 64 bit platforms.
- */
- if (skip_length < save_size)
- save_size = (png_size_t)skip_length;
-
- else
- skip_length = (png_uint_32)save_size;
-
- png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
-
- png_ptr->skip_length -= skip_length;
- png_ptr->buffer_size -= save_size;
- png_ptr->save_buffer_size -= save_size;
- png_ptr->save_buffer_ptr += save_size;
- }
- if (png_ptr->skip_length && png_ptr->current_buffer_size)
- {
- png_size_t save_size = png_ptr->current_buffer_size;
- png_uint_32 skip_length = png_ptr->skip_length;
-
- /* We want the smaller of 'skip_length' and 'current_buffer_size', here,
- * the same problem exists as above and the same solution.
- */
- if (skip_length < save_size)
- save_size = (png_size_t)skip_length;
-
- else
- skip_length = (png_uint_32)save_size;
-
- png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
-
- png_ptr->skip_length -= skip_length;
- png_ptr->buffer_size -= save_size;
- png_ptr->current_buffer_size -= save_size;
- png_ptr->current_buffer_ptr += save_size;
- }
- if (!png_ptr->skip_length)
- {
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_crc_finish(png_ptr, 0);
- png_ptr->process_mode = PNG_READ_CHUNK_MODE;
- }
-}
-
void PNGCBAPI
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
{
@@ -663,7 +423,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
return;
ptr = buffer;
- if (png_ptr->save_buffer_size)
+ if (png_ptr->save_buffer_size != 0)
{
png_size_t save_size;
@@ -673,14 +433,14 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
else
save_size = png_ptr->save_buffer_size;
- png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
+ memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
length -= save_size;
ptr += save_size;
png_ptr->buffer_size -= save_size;
png_ptr->save_buffer_size -= save_size;
png_ptr->save_buffer_ptr += save_size;
}
- if (length && png_ptr->current_buffer_size)
+ if (length != 0 && png_ptr->current_buffer_size != 0)
{
png_size_t save_size;
@@ -690,7 +450,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
else
save_size = png_ptr->current_buffer_size;
- png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
+ memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
png_ptr->buffer_size -= save_size;
png_ptr->current_buffer_size -= save_size;
png_ptr->current_buffer_ptr += save_size;
@@ -698,9 +458,9 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
}
void /* PRIVATE */
-png_push_save_buffer(png_structp png_ptr)
+png_push_save_buffer(png_structrp png_ptr)
{
- if (png_ptr->save_buffer_size)
+ if (png_ptr->save_buffer_size != 0)
{
if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
{
@@ -730,7 +490,8 @@ png_push_save_buffer(png_structp png_ptr)
new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
old_buffer = png_ptr->save_buffer;
- png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, new_max);
+ png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
+ (png_size_t)new_max);
if (png_ptr->save_buffer == NULL)
{
@@ -738,13 +499,13 @@ png_push_save_buffer(png_structp png_ptr)
png_error(png_ptr, "Insufficient memory for save_buffer");
}
- png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
+ memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
png_free(png_ptr, old_buffer);
png_ptr->save_buffer_max = new_max;
}
if (png_ptr->current_buffer_size)
{
- png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
+ memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
png_ptr->save_buffer_size += png_ptr->current_buffer_size;
png_ptr->current_buffer_size = 0;
@@ -754,7 +515,7 @@ png_push_save_buffer(png_structp png_ptr)
}
void /* PRIVATE */
-png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
+png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
png_size_t buffer_length)
{
png_ptr->current_buffer = buffer;
@@ -764,20 +525,15 @@ png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
}
void /* PRIVATE */
-png_push_read_IDAT(png_structp png_ptr)
+png_push_read_IDAT(png_structrp png_ptr)
{
- if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+ if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
{
png_byte chunk_length[4];
png_byte chunk_tag[4];
/* TODO: this code can be commoned up with the same code in push_read */
- if (png_ptr->buffer_size < 8)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_LT(8)
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
png_reset_crc(png_ptr);
@@ -789,7 +545,7 @@ png_push_read_IDAT(png_structp png_ptr)
{
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
png_error(png_ptr, "Not enough compressed data");
return;
@@ -798,7 +554,7 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->idat_size = png_ptr->push_length;
}
- if (png_ptr->idat_size && png_ptr->save_buffer_size)
+ if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
{
png_size_t save_size = png_ptr->save_buffer_size;
png_uint_32 idat_size = png_ptr->idat_size;
@@ -807,7 +563,7 @@ png_push_read_IDAT(png_structp png_ptr)
* are of different types and we don't know which variable has the fewest
* bits. Carefully select the smaller and cast it to the type of the
* larger - this cannot overflow. Do not cast in the following test - it
- * will break on either 16 or 64 bit platforms.
+ * will break on either 16-bit or 64-bit platforms.
*/
if (idat_size < save_size)
save_size = (png_size_t)idat_size;
@@ -825,7 +581,7 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->save_buffer_ptr += save_size;
}
- if (png_ptr->idat_size && png_ptr->current_buffer_size)
+ if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
{
png_size_t save_size = png_ptr->current_buffer_size;
png_uint_32 idat_size = png_ptr->idat_size;
@@ -850,22 +606,19 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->current_buffer_size -= save_size;
png_ptr->current_buffer_ptr += save_size;
}
- if (!png_ptr->idat_size)
- {
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
+ if (png_ptr->idat_size == 0)
+ {
+ PNG_PUSH_SAVE_BUFFER_IF_LT(4)
png_crc_finish(png_ptr, 0);
png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->zowner = 0;
}
}
void /* PRIVATE */
-png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
+png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
png_size_t buffer_length)
{
/* The caller checks for a non-zero buffer length. */
@@ -877,13 +630,14 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
* handle the uncompressed results.
*/
png_ptr->zstream.next_in = buffer;
+ /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
png_ptr->zstream.avail_in = (uInt)buffer_length;
/* Keep going until the decompressed data is all processed
* or the stream marked as finished.
*/
while (png_ptr->zstream.avail_in > 0 &&
- !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+ (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
{
int ret;
@@ -894,9 +648,9 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
*/
if (!(png_ptr->zstream.avail_out > 0))
{
- png_ptr->zstream.avail_out =
- (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
- png_ptr->iwidth) + 1;
+ /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
+ png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
+ png_ptr->iwidth) + 1);
png_ptr->zstream.next_out = png_ptr->row_buf;
}
@@ -908,13 +662,14 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
* change the current behavior (see comments in inflate.c
* for why this doesn't happen at present with zlib 1.2.5).
*/
- ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
+ ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
/* Check for any failure before proceeding. */
if (ret != Z_OK && ret != Z_STREAM_END)
{
/* Terminate the decompression. */
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+ png_ptr->zowner = 0;
/* This may be a truncated stream (missing or
* damaged end code). Treat that as a warning.
@@ -942,7 +697,8 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
{
/* Extra data. */
png_warning(png_ptr, "Extra compressed data in IDAT");
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+ png_ptr->zowner = 0;
/* Do no more processing; skip the unprocessed
* input check below.
@@ -957,7 +713,7 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
/* And check for the end of the stream. */
if (ret == Z_STREAM_END)
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
}
/* All the data should have been processed, if anything
@@ -969,7 +725,7 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
}
void /* PRIVATE */
-png_push_process_row(png_structp png_ptr)
+png_push_process_row(png_structrp png_ptr)
{
/* 1.5.6: row_info moved out of png_struct to a local here. */
png_row_info row_info;
@@ -995,10 +751,10 @@ png_push_process_row(png_structp png_ptr)
* it may not be in the future, so this was changed just to copy the
* interlaced row count:
*/
- png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
+ memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
- if (png_ptr->transformations)
+ if (png_ptr->transformations != 0)
png_do_read_transformations(png_ptr, &row_info);
#endif
@@ -1015,15 +771,16 @@ png_push_process_row(png_structp png_ptr)
#ifdef PNG_READ_INTERLACING_SUPPORTED
- /* Blow up interlaced rows to full size */
- if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ /* Expand interlaced rows to full size */
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
if (png_ptr->pass < 6)
png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
png_ptr->transformations);
- switch (png_ptr->pass)
- {
+ switch (png_ptr->pass)
+ {
case 0:
{
int i;
@@ -1198,26 +955,26 @@ png_push_process_row(png_structp png_ptr)
}
void /* PRIVATE */
-png_read_push_finish_row(png_structp png_ptr)
+png_read_push_finish_row(png_structrp png_ptr)
{
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+ static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+ static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+ static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+ static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
/* Height of interlace block. This is not currently used - if you need
* it, uncomment it here and in png.h
- static PNG_CONST png_byte FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+ static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/
#endif
@@ -1226,10 +983,10 @@ png_read_push_finish_row(png_structp png_ptr)
return;
#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
png_ptr->row_number = 0;
- png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
do
{
@@ -1250,7 +1007,7 @@ png_read_push_finish_row(png_structp png_ptr)
png_pass_start[png_ptr->pass]) /
png_pass_inc[png_ptr->pass];
- if (png_ptr->transformations & PNG_INTERLACE)
+ if ((png_ptr->transformations & PNG_INTERLACE) != 0)
break;
png_ptr->num_rows = (png_ptr->height +
@@ -1260,540 +1017,25 @@ png_read_push_finish_row(png_structp png_ptr)
} while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
}
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
-}
-
-#ifdef PNG_READ_tEXt_SUPPORTED
-void /* PRIVATE */
-png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
- length)
-{
- if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
- {
- PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */
- png_error(png_ptr, "Out of place tEXt");
- /* NOT REACHED */
- }
-
-#ifdef PNG_MAX_MALLOC_64K
- png_ptr->skip_length = 0; /* This may not be necessary */
-
- if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
- {
- png_warning(png_ptr, "tEXt chunk too large to fit in memory");
- png_ptr->skip_length = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
- }
-#endif
-
- png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1);
- png_ptr->current_text[length] = '\0';
- png_ptr->current_text_ptr = png_ptr->current_text;
- png_ptr->current_text_size = (png_size_t)length;
- png_ptr->current_text_left = (png_size_t)length;
- png_ptr->process_mode = PNG_READ_tEXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
-{
- if (png_ptr->buffer_size && png_ptr->current_text_left)
- {
- png_size_t text_size;
-
- if (png_ptr->buffer_size < png_ptr->current_text_left)
- text_size = png_ptr->buffer_size;
-
- else
- text_size = png_ptr->current_text_left;
-
- png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
- png_ptr->current_text_left -= text_size;
- png_ptr->current_text_ptr += text_size;
- }
- if (!(png_ptr->current_text_left))
- {
- png_textp text_ptr;
- png_charp text;
- png_charp key;
- int ret;
-
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_crc_finish(png_ptr);
-
-#ifdef PNG_MAX_MALLOC_64K
- if (png_ptr->skip_length)
- return;
-#endif
-
- key = png_ptr->current_text;
-
- for (text = key; *text; text++)
- /* Empty loop */ ;
-
- if (text < key + png_ptr->current_text_size)
- text++;
-
- text_ptr = (png_textp)png_malloc(png_ptr, png_sizeof(png_text));
- text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
- text_ptr->key = key;
- text_ptr->itxt_length = 0;
- text_ptr->lang = NULL;
- text_ptr->lang_key = NULL;
- text_ptr->text = text;
-
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_free(png_ptr, key);
- png_free(png_ptr, text_ptr);
- png_ptr->current_text = NULL;
-
- if (ret)
- png_warning(png_ptr, "Insufficient memory to store text chunk");
- }
-}
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-void /* PRIVATE */
-png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
- length)
-{
- if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
- {
- PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */
- png_error(png_ptr, "Out of place zTXt");
- /* NOT REACHED */
- }
-
-#ifdef PNG_MAX_MALLOC_64K
- /* We can't handle zTXt chunks > 64K, since we don't have enough space
- * to be able to store the uncompressed data. Actually, the threshold
- * is probably around 32K, but it isn't as definite as 64K is.
- */
- if (length > (png_uint_32)65535L)
- {
- png_warning(png_ptr, "zTXt chunk too large to fit in memory");
- png_push_crc_skip(png_ptr, length);
- return;
- }
-#endif
-
- png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1);
- png_ptr->current_text[length] = '\0';
- png_ptr->current_text_ptr = png_ptr->current_text;
- png_ptr->current_text_size = (png_size_t)length;
- png_ptr->current_text_left = (png_size_t)length;
- png_ptr->process_mode = PNG_READ_zTXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
-{
- if (png_ptr->buffer_size && png_ptr->current_text_left)
- {
- png_size_t text_size;
-
- if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
- text_size = png_ptr->buffer_size;
-
- else
- text_size = png_ptr->current_text_left;
-
- png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
- png_ptr->current_text_left -= text_size;
- png_ptr->current_text_ptr += text_size;
- }
- if (!(png_ptr->current_text_left))
- {
- png_textp text_ptr;
- png_charp text;
- png_charp key;
- int ret;
- png_size_t text_size, key_size;
-
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_crc_finish(png_ptr);
-
- key = png_ptr->current_text;
-
- for (text = key; *text; text++)
- /* Empty loop */ ;
-
- /* zTXt can't have zero text */
- if (text >= key + png_ptr->current_text_size)
- {
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- return;
- }
-
- text++;
-
- if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */
- {
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- return;
- }
-
- text++;
-
- png_ptr->zstream.next_in = (png_bytep)text;
- png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
- (text - key));
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-
- key_size = text - key;
- text_size = 0;
- text = NULL;
- ret = Z_STREAM_END;
-
- while (png_ptr->zstream.avail_in)
- {
- ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
- if (ret != Z_OK && ret != Z_STREAM_END)
- {
- inflateReset(&png_ptr->zstream);
- png_ptr->zstream.avail_in = 0;
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- png_free(png_ptr, text);
- return;
- }
-
- if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
- {
- if (text == NULL)
- {
- text = (png_charp)png_malloc(png_ptr,
- (png_ptr->zbuf_size
- - png_ptr->zstream.avail_out + key_size + 1));
-
- png_memcpy(text + key_size, png_ptr->zbuf,
- png_ptr->zbuf_size - png_ptr->zstream.avail_out);
-
- png_memcpy(text, key, key_size);
-
- text_size = key_size + png_ptr->zbuf_size -
- png_ptr->zstream.avail_out;
-
- *(text + text_size) = '\0';
- }
-
- else
- {
- png_charp tmp;
-
- tmp = text;
- text = (png_charp)png_malloc(png_ptr, text_size +
- (png_ptr->zbuf_size
- - png_ptr->zstream.avail_out + 1));
-
- png_memcpy(text, tmp, text_size);
- png_free(png_ptr, tmp);
-
- png_memcpy(text + text_size, png_ptr->zbuf,
- png_ptr->zbuf_size - png_ptr->zstream.avail_out);
-
- text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
- *(text + text_size) = '\0';
- }
-
- if (ret != Z_STREAM_END)
- {
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- }
- }
- else
- {
- break;
- }
-
- if (ret == Z_STREAM_END)
- break;
- }
-
- inflateReset(&png_ptr->zstream);
- png_ptr->zstream.avail_in = 0;
-
- if (ret != Z_STREAM_END)
- {
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- png_free(png_ptr, text);
- return;
- }
-
- png_ptr->current_text = NULL;
- png_free(png_ptr, key);
- key = text;
- text += key_size;
-
- text_ptr = (png_textp)png_malloc(png_ptr,
- png_sizeof(png_text));
- text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
- text_ptr->key = key;
- text_ptr->itxt_length = 0;
- text_ptr->lang = NULL;
- text_ptr->lang_key = NULL;
- text_ptr->text = text;
-
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_free(png_ptr, key);
- png_free(png_ptr, text_ptr);
-
- if (ret)
- png_warning(png_ptr, "Insufficient memory to store text chunk");
- }
-}
-#endif
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-void /* PRIVATE */
-png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
- length)
-{
- if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
- {
- PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */
- png_error(png_ptr, "Out of place iTXt");
- /* NOT REACHED */
- }
-
-#ifdef PNG_MAX_MALLOC_64K
- png_ptr->skip_length = 0; /* This may not be necessary */
-
- if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
- {
- png_warning(png_ptr, "iTXt chunk too large to fit in memory");
- png_ptr->skip_length = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
- }
-#endif
-
- png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1);
- png_ptr->current_text[length] = '\0';
- png_ptr->current_text_ptr = png_ptr->current_text;
- png_ptr->current_text_size = (png_size_t)length;
- png_ptr->current_text_left = (png_size_t)length;
- png_ptr->process_mode = PNG_READ_iTXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
-{
-
- if (png_ptr->buffer_size && png_ptr->current_text_left)
- {
- png_size_t text_size;
-
- if (png_ptr->buffer_size < png_ptr->current_text_left)
- text_size = png_ptr->buffer_size;
-
- else
- text_size = png_ptr->current_text_left;
-
- png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
- png_ptr->current_text_left -= text_size;
- png_ptr->current_text_ptr += text_size;
- }
-
- if (!(png_ptr->current_text_left))
- {
- png_textp text_ptr;
- png_charp key;
- int comp_flag;
- png_charp lang;
- png_charp lang_key;
- png_charp text;
- int ret;
-
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_crc_finish(png_ptr);
-
-#ifdef PNG_MAX_MALLOC_64K
- if (png_ptr->skip_length)
- return;
-#endif
-
- key = png_ptr->current_text;
-
- for (lang = key; *lang; lang++)
- /* Empty loop */ ;
-
- if (lang < key + png_ptr->current_text_size - 3)
- lang++;
-
- comp_flag = *lang++;
- lang++; /* Skip comp_type, always zero */
-
- for (lang_key = lang; *lang_key; lang_key++)
- /* Empty loop */ ;
-
- lang_key++; /* Skip NUL separator */
-
- text=lang_key;
-
- if (lang_key < key + png_ptr->current_text_size - 1)
- {
- for (; *text; text++)
- /* Empty loop */ ;
- }
-
- if (text < key + png_ptr->current_text_size)
- text++;
-
- text_ptr = (png_textp)png_malloc(png_ptr,
- png_sizeof(png_text));
-
- text_ptr->compression = comp_flag + 2;
- text_ptr->key = key;
- text_ptr->lang = lang;
- text_ptr->lang_key = lang_key;
- text_ptr->text = text;
- text_ptr->text_length = 0;
- text_ptr->itxt_length = png_strlen(text);
-
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_ptr->current_text = NULL;
-
- png_free(png_ptr, text_ptr);
- if (ret)
- png_warning(png_ptr, "Insufficient memory to store iTXt chunk");
- }
-}
-#endif
-
-/* This function is called when we haven't found a handler for this
- * chunk. If there isn't a problem with the chunk itself (ie a bad chunk
- * name or a critical chunk), the chunk is (currently) silently ignored.
- */
-void /* PRIVATE */
-png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
- length)
-{
- png_uint_32 skip = 0;
- png_uint_32 chunk_name = png_ptr->chunk_name;
-
- if (PNG_CHUNK_CRITICAL(chunk_name))
- {
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
- if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
- PNG_HANDLE_CHUNK_ALWAYS
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- && png_ptr->read_user_chunk_fn == NULL
-#endif
- )
-#endif
- png_chunk_error(png_ptr, "unknown critical chunk");
-
- PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */
- }
-
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
- /* TODO: the code below is apparently just using the
- * png_struct::unknown_chunk member as a temporarily variable, it should be
- * possible to eliminate both it and the temporary buffer.
- */
- if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
- {
-#ifdef PNG_MAX_MALLOC_64K
- if (length > 65535)
- {
- png_warning(png_ptr, "unknown chunk too large to fit in memory");
- skip = length - 65535;
- length = 65535;
- }
-#endif
- /* This is just a record for the user; libpng doesn't use the character
- * form of the name.
- */
- PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
-
- png_ptr->unknown_chunk.size = length;
-
- if (length == 0)
- png_ptr->unknown_chunk.data = NULL;
-
- else
- {
- png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr,
- png_ptr->unknown_chunk.size);
- png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data,
- png_ptr->unknown_chunk.size);
- }
-
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- if (png_ptr->read_user_chunk_fn != NULL)
- {
- /* Callback to user unknown chunk handler */
- int ret;
- ret = (*(png_ptr->read_user_chunk_fn))
- (png_ptr, &png_ptr->unknown_chunk);
-
- if (ret < 0)
- png_chunk_error(png_ptr, "error in user chunk");
-
- if (ret == 0)
- {
- if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
- if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
- PNG_HANDLE_CHUNK_ALWAYS)
- png_chunk_error(png_ptr, "unknown critical chunk");
- png_set_unknown_chunks(png_ptr, info_ptr,
- &png_ptr->unknown_chunk, 1);
- }
- }
-
- else
-#endif
- png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
- png_free(png_ptr, png_ptr->unknown_chunk.data);
- png_ptr->unknown_chunk.data = NULL;
- }
-
- else
-#endif
- skip=length;
- png_push_crc_skip(png_ptr, skip);
+#endif /* READ_INTERLACING */
}
void /* PRIVATE */
-png_push_have_info(png_structp png_ptr, png_infop info_ptr)
+png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
{
if (png_ptr->info_fn != NULL)
(*(png_ptr->info_fn))(png_ptr, info_ptr);
}
void /* PRIVATE */
-png_push_have_end(png_structp png_ptr, png_infop info_ptr)
+png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
{
if (png_ptr->end_fn != NULL)
(*(png_ptr->end_fn))(png_ptr, info_ptr);
}
void /* PRIVATE */
-png_push_have_row(png_structp png_ptr, png_bytep row)
+png_push_have_row(png_structrp png_ptr, png_bytep row)
{
if (png_ptr->row_fn != NULL)
(*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
@@ -1802,7 +1044,7 @@ png_push_have_row(png_structp png_ptr, png_bytep row)
#ifdef PNG_READ_INTERLACING_SUPPORTED
void PNGAPI
-png_progressive_combine_row (png_structp png_ptr, png_bytep old_row,
+png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
png_const_bytep new_row)
{
if (png_ptr == NULL)
@@ -1813,12 +1055,12 @@ png_progressive_combine_row (png_structp png_ptr, png_bytep old_row,
* it must be png_ptr->row_buf+1
*/
if (new_row != NULL)
- png_combine_row(png_ptr, old_row, 1/*display*/);
+ png_combine_row(png_ptr, old_row, 1/*blocky display*/);
}
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
+#endif /* READ_INTERLACING */
void PNGAPI
-png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
+png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
png_progressive_end_ptr end_fn)
{
@@ -1833,11 +1075,11 @@ png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
}
png_voidp PNGAPI
-png_get_progressive_ptr(png_const_structp png_ptr)
+png_get_progressive_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
return png_ptr->io_ptr;
}
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PROGRESSIVE_READ */
diff --git a/thirdparty/libpng/pngpriv.h b/thirdparty/libpng/pngpriv.h
index 67e486c5..1295b514 100644
--- a/thirdparty/libpng/pngpriv.h
+++ b/thirdparty/libpng/pngpriv.h
@@ -1,20 +1,18 @@
/* pngpriv.h - private declarations for use inside libpng
*
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.21 [January 15, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* The symbols declared in this file (including the functions declared
- * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public
+ * as extern) are PRIVATE. They are not part of the libpng public
* interface, and are not recommended for use by regular applications.
* Some of them may become public in the future; others may stay private,
* change in an incompatible way, or even disappear.
@@ -39,15 +37,43 @@
*/
#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
-/* This is required for the definition of abort(), used as a last ditch
- * error handler when all else fails.
+#ifndef PNG_VERSION_INFO_ONLY
+/* Standard library headers not required by png.h: */
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#define PNGLIB_BUILD /*libpng is being built, not used*/
+
+/* If HAVE_CONFIG_H is defined during the build then the build system must
+ * provide an appropriate "config.h" file on the include path. The header file
+ * must provide definitions as required below (search for "HAVE_CONFIG_H");
+ * see configure.ac for more details of the requirements. The macro
+ * "PNG_NO_CONFIG_H" is provided for maintainers to test for dependencies on
+ * 'configure'; define this macro to prevent the configure build including the
+ * configure generated config.h. Libpng is expected to compile without *any*
+ * special build system support on a reasonably ANSI-C compliant system.
*/
-#include <stdlib.h>
+#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
+# include <config.h>
-/* This is used to find 'offsetof', used below for alignment tests. */
-#include <stddef.h>
+ /* Pick up the definition of 'restrict' from config.h if it was read: */
+# define PNG_RESTRICT restrict
+#endif
-#define PNGLIB_BUILD /*libpng is being built, not used*/
+/* To support symbol prefixing it is necessary to know *before* including png.h
+ * whether the fixed point (and maybe other) APIs are exported, because if they
+ * are not internal definitions may be required. This is handled below just
+ * before png.h is included, but load the configuration now if it is available.
+ */
+#ifndef PNGLCONF_H
+# include "pnglibconf.h"
+#endif
+
+/* Local renames may change non-exported API functions from png.h */
+#if defined(PNG_PREFIX) && !defined(PNGPREFIX_H)
+# include "pngprefix.h"
+#endif
#ifdef PNG_USER_CONFIG
# include "pngusr.h"
@@ -60,6 +86,102 @@
# endif
#endif
+/* Compile time options.
+ * =====================
+ * In a multi-arch build the compiler may compile the code several times for the
+ * same object module, producing different binaries for different architectures.
+ * When this happens configure-time setting of the target host options cannot be
+ * done and this interferes with the handling of the ARM NEON optimizations, and
+ * possibly other similar optimizations. Put additional tests here; in general
+ * this is needed when the same option can be changed at both compile time and
+ * run time depending on the target OS (i.e. iOS vs Android.)
+ *
+ * NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because
+ * this is not possible with certain compilers (Oracle SUN OS CC), as a result
+ * it is necessary to ensure that all extern functions that *might* be used
+ * regardless of $(CFLAGS) get declared in this file. The test on __ARM_NEON__
+ * below is one example of this behavior because it is controlled by the
+ * presence or not of -mfpu=neon on the GCC command line, it is possible to do
+ * this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely
+ * do this.
+ */
+#ifndef PNG_ARM_NEON_OPT
+ /* ARM NEON optimizations are being controlled by the compiler settings,
+ * typically the target FPU. If the FPU has been set to NEON (-mfpu=neon
+ * with GCC) then the compiler will define __ARM_NEON__ and we can rely
+ * unconditionally on NEON instructions not crashing, otherwise we must
+ * disable use of NEON instructions.
+ *
+ * NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they
+ * can only be turned on automatically if that is supported too. If
+ * PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail
+ * to compile with an appropriate #error if ALIGNED_MEMORY has been turned
+ * off.
+ *
+ * Note that gcc-4.9 defines __ARM_NEON instead of the deprecated
+ * __ARM_NEON__, so we check both variants.
+ *
+ * To disable ARM_NEON optimizations entirely, and skip compiling the
+ * associated assembler code, pass --enable-arm-neon=no to configure
+ * or put -DPNG_ARM_NEON_OPT=0 in CPPFLAGS.
+ */
+# if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \
+ defined(PNG_ALIGNED_MEMORY_SUPPORTED)
+# define PNG_ARM_NEON_OPT 2
+# else
+# define PNG_ARM_NEON_OPT 0
+# endif
+#endif
+
+#if PNG_ARM_NEON_OPT > 0
+ /* NEON optimizations are to be at least considered by libpng, so enable the
+ * callbacks to do this.
+ */
+# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
+
+ /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
+ * if possible - if __ARM_NEON__ is set and the compiler version is not known
+ * to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
+ * be:
+ *
+ * 1 The intrinsics code (the default with __ARM_NEON__)
+ * 2 The hand coded assembler (the default without __ARM_NEON__)
+ *
+ * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
+ * this is *NOT* supported and may cease to work even after a minor revision
+ * to libpng. It *is* valid to do this for testing purposes, e.g. speed
+ * testing or a new compiler, but the results should be communicated to the
+ * libpng implementation list for incorporation in the next minor release.
+ */
+# ifndef PNG_ARM_NEON_IMPLEMENTATION
+# if defined(__ARM_NEON__) || defined(__ARM_NEON)
+# if defined(__clang__)
+ /* At present it is unknown by the libpng developers which versions
+ * of clang support the intrinsics, however some or perhaps all
+ * versions do not work with the assembler so this may be
+ * irrelevant, so just use the default (do nothing here.)
+ */
+# elif defined(__GNUC__)
+ /* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to
+ * work, so if this *is* GCC, or G++, look for a version >4.5
+ */
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
+# define PNG_ARM_NEON_IMPLEMENTATION 2
+# endif /* no GNUC support */
+# endif /* __GNUC__ */
+# else /* !defined __ARM_NEON__ */
+ /* The 'intrinsics' code simply won't compile without this -mfpu=neon:
+ */
+# define PNG_ARM_NEON_IMPLEMENTATION 2
+# endif /* __ARM_NEON__ */
+# endif /* !PNG_ARM_NEON_IMPLEMENTATION */
+
+# ifndef PNG_ARM_NEON_IMPLEMENTATION
+ /* Use the intrinsics code by default. */
+# define PNG_ARM_NEON_IMPLEMENTATION 1
+# endif
+#endif /* PNG_ARM_NEON_OPT > 0 */
+
/* Is this a build of a DLL where compilation of the object modules requires
* different preprocessor settings to those required for a simple library? If
* so PNG_BUILD_DLL must be set.
@@ -124,36 +246,82 @@
# define PNG_PRIVATE
#endif
+/* Symbol preprocessing support.
+ *
+ * To enable listing global, but internal, symbols the following macros should
+ * always be used to declare an extern data or function object in this file.
+ */
+#ifndef PNG_INTERNAL_DATA
+# define PNG_INTERNAL_DATA(type, name, array) PNG_LINKAGE_DATA type name array
+#endif
+
+#ifndef PNG_INTERNAL_FUNCTION
+# define PNG_INTERNAL_FUNCTION(type, name, args, attributes)\
+ PNG_LINKAGE_FUNCTION PNG_FUNCTION(type, name, args, PNG_EMPTY attributes)
+#endif
+
+#ifndef PNG_INTERNAL_CALLBACK
+# define PNG_INTERNAL_CALLBACK(type, name, args, attributes)\
+ PNG_LINKAGE_CALLBACK PNG_FUNCTION(type, (PNGCBAPI name), args,\
+ PNG_EMPTY attributes)
+#endif
+
+/* If floating or fixed point APIs are disabled they may still be compiled
+ * internally. To handle this make sure they are declared as the appropriate
+ * internal extern function (otherwise the symbol prefixing stuff won't work and
+ * the functions will be used without definitions.)
+ *
+ * NOTE: although all the API functions are declared here they are not all
+ * actually built! Because the declarations are still made it is necessary to
+ * fake out types that they depend on.
+ */
+#ifndef PNG_FP_EXPORT
+# ifndef PNG_FLOATING_POINT_SUPPORTED
+# define PNG_FP_EXPORT(ordinal, type, name, args)\
+ PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY);
+# ifndef PNG_VERSION_INFO_ONLY
+ typedef struct png_incomplete png_double;
+ typedef png_double* png_doublep;
+ typedef const png_double* png_const_doublep;
+ typedef png_double** png_doublepp;
+# endif
+# endif
+#endif
+#ifndef PNG_FIXED_EXPORT
+# ifndef PNG_FIXED_POINT_SUPPORTED
+# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
+ PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY);
+# endif
+#endif
+
#include "png.h"
-#include "pnginfo.h"
-#include "pngstruct.h"
/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */
#ifndef PNG_DLL_EXPORT
# define PNG_DLL_EXPORT
#endif
-/* This is used for 16 bit gamma tables - only the top level pointers are const,
- * this could be changed:
- */
-typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
-
-/* Added at libpng-1.2.9 */
-/* Moved to pngpriv.h at libpng-1.5.0 */
-
-/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure"
- * script. We may need it here to get the correct configuration on things
- * like limits.
+/* This is a global switch to set the compilation for an installed system
+ * (a release build). It can be set for testing debug builds to ensure that
+ * they will compile when the build type is switched to RC or STABLE, the
+ * default is just to use PNG_LIBPNG_BUILD_BASE_TYPE. Set this in CPPFLAGS
+ * with either:
+ *
+ * -DPNG_RELEASE_BUILD Turns on the release compile path
+ * -DPNG_RELEASE_BUILD=0 Turns it off
+ * or in your pngusr.h with
+ * #define PNG_RELEASE_BUILD=1 Turns on the release compile path
+ * #define PNG_RELEASE_BUILD=0 Turns it off
*/
-#ifdef PNG_CONFIGURE_LIBPNG
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
+#ifndef PNG_RELEASE_BUILD
+# define PNG_RELEASE_BUILD (PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC)
#endif
-/* Moved to pngpriv.h at libpng-1.5.0 */
-/* NOTE: some of these may have been used in external applications as
- * these definitions were exposed in pngconf.h prior to 1.5.
+/* SECURITY and SAFETY:
+ *
+ * libpng is built with support for internal limits on image dimensions and
+ * memory usage. These are documented in scripts/pnglibconf.dfa of the
+ * source and recorded in the machine generated header file pnglibconf.h.
*/
/* If you are running on a machine where you cannot allocate more
@@ -189,30 +357,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define PNG_ZBUF_SIZE 65536L
#endif
-/* PNG_STATIC is used to mark internal file scope functions if they need to be
- * accessed for implementation tests (see the code in tests/?*).
- */
-#ifndef PNG_STATIC
-# define PNG_STATIC static
-#endif
-
-/* C99 restrict is used where possible, to do this 'restrict' is defined as
- * empty if we can't be sure it is supported. configure builds have already
- * done this work.
- */
-#ifdef PNG_CONFIGURE_LIBPNG
-# define PNG_RESTRICT restrict
-#else
- /* Modern compilers support restrict, but assume not for anything not
- * recognized here:
- */
-# if defined __GNUC__ || defined _MSC_VER || defined __WATCOMC__
-# define PNG_RESTRICT restrict
-# else
-# define PNG_RESTRICT
-# endif
-#endif
-
/* If warnings or errors are turned off the code is disabled or redirected here.
* From 1.5.4 functions have been added to allow very limited formatting of
* error and warning messages - this code will also be disabled here.
@@ -220,8 +364,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#ifdef PNG_WARNINGS_SUPPORTED
# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p;
#else
-# define png_warning(s1,s2) ((void)(s1))
-# define png_chunk_warning(s1,s2) ((void)(s1))
# define png_warning_parameter(p,number,string) ((void)0)
# define png_warning_parameter_unsigned(p,number,format,value) ((void)0)
# define png_warning_parameter_signed(p,number,format,value) ((void)0)
@@ -229,8 +371,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define PNG_WARNING_PARAMETERS(p)
#endif
#ifndef PNG_ERROR_TEXT_SUPPORTED
-# define png_error(s1,s2) png_err(s1)
-# define png_chunk_error(s1,s2) png_err(s1)
# define png_fixed_error(s1,s2) png_err(s1)
#endif
@@ -241,23 +381,18 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
*/
#ifdef __cplusplus
# define png_voidcast(type, value) static_cast<type>(value)
+# define png_constcast(type, value) const_cast<type>(value)
+# define png_aligncast(type, value) \
+ static_cast<type>(static_cast<void*>(value))
+# define png_aligncastconst(type, value) \
+ static_cast<type>(static_cast<const void*>(value))
#else
# define png_voidcast(type, value) (value)
+# define png_constcast(type, value) ((type)(value))
+# define png_aligncast(type, value) ((void*)(value))
+# define png_aligncastconst(type, value) ((const void*)(value))
#endif /* __cplusplus */
-#ifndef PNG_EXTERN
-/* The functions exported by PNG_EXTERN are internal functions, which
- * aren't usually used outside the library (as far as I know), so it is
- * debatable if they should be exported at all. In the future, when it
- * is possible to have run-time registry of chunk-handling functions,
- * some of these might be made available again.
- *
- * 1.5.7: turned the use of 'extern' back on, since it is localized to pngpriv.h
- * it should be safe now (it is unclear why it was turned off.)
- */
-# define PNG_EXTERN extern
-#endif
-
/* Some fixed point APIs are still required even if not exported because
* they get used by the corresponding floating point APIs. This magic
* deals with this:
@@ -268,6 +403,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define PNGFAPI /* PRIVATE */
#endif
+#ifndef PNG_VERSION_INFO_ONLY
/* Other defines specific to compilers can go here. Try to keep
* them inside an appropriate ifdef/endif pair for portability.
*/
@@ -312,6 +448,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
defined(_WIN32) || defined(__WIN32__)
# include <windows.h> /* defines _WINDOWS_ macro */
#endif
+#endif /* PNG_VERSION_INFO_ONLY */
/* Moved here around 1.5.0beta36 from pngconf.h */
/* Users may want to use these so they are not private. Any library
@@ -327,34 +464,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# endif
#endif
-#ifdef USE_FAR_KEYWORD
-/* Use this to make far-to-near assignments */
-# define CHECK 1
-# define NOCHECK 0
-# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK))
-# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK))
-# define png_strlen _fstrlen
-# define png_memcmp _fmemcmp /* SJT: added */
-# define png_memcpy _fmemcpy
-# define png_memset _fmemset
-#else
-# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */
-# define CVT_PTR(ptr) (ptr)
-# define CVT_PTR_NOCHECK(ptr) (ptr)
-# define png_strlen lstrlenA
-# define png_memcmp memcmp
-# define png_memcpy CopyMemory
-# define png_memset memset
-# else
-# define CVT_PTR(ptr) (ptr)
-# define CVT_PTR_NOCHECK(ptr) (ptr)
-# define png_strlen strlen
-# define png_memcmp memcmp /* SJT: added */
-# define png_memcpy memcpy
-# define png_memset memset
-# endif
-#endif
-
/* These macros may need to be architecture dependent. */
#define PNG_ALIGN_NONE 0 /* do not use data alignment */
#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */
@@ -376,7 +485,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE
/* This is used because in some compiler implementations non-aligned
* structure members are supported, so the offsetof approach below fails.
- * Set PNG_ALIGN_TO_SIZE=0 for compiler combinations where unaligned access
+ * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access
* is good for performance. Do not do this unless you have tested the result
* and understand it.
*/
@@ -417,15 +526,17 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_HAVE_IDAT 0x04
/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */
#define PNG_HAVE_IEND 0x10
-#define PNG_HAVE_gAMA 0x20
-#define PNG_HAVE_cHRM 0x40
-#define PNG_HAVE_sRGB 0x80
+ /* 0x20 (unused) */
+ /* 0x40 (unused) */
+ /* 0x80 (unused) */
#define PNG_HAVE_CHUNK_HEADER 0x100
#define PNG_WROTE_tIME 0x200
#define PNG_WROTE_INFO_BEFORE_PLTE 0x400
#define PNG_BACKGROUND_IS_GRAY 0x800
#define PNG_HAVE_PNG_SIGNATURE 0x1000
#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
+ /* 0x4000 (unused) */
+#define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */
/* Flags for the transformations the PNG library does on the image data */
#define PNG_BGR 0x0001
@@ -453,53 +564,49 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_RGB_TO_GRAY_WARN 0x400000
#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */
#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */
-#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */
-#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */
-#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */
- /* 0x8000000 unused */
- /* 0x10000000 unused */
- /* 0x20000000 unused */
- /* 0x40000000 unused */
+#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */
+#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */
+#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */
+ /* 0x8000000 unused */
+ /* 0x10000000 unused */
+ /* 0x20000000 unused */
+ /* 0x40000000 unused */
/* Flags for png_create_struct */
#define PNG_STRUCT_PNG 0x0001
#define PNG_STRUCT_INFO 0x0002
-/* Scaling factor for filter heuristic weighting calculations */
-#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT))
-#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT))
-
/* Flags for the png_ptr->flags rather than declaring a byte for each one */
#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001
-#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002
-#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004
-#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008
-#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010
-#define PNG_FLAG_ZLIB_FINISHED 0x0020
+#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */
+ /* 0x0004 unused */
+#define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */
+ /* 0x0010 unused */
+ /* 0x0020 unused */
#define PNG_FLAG_ROW_INIT 0x0040
#define PNG_FLAG_FILLER_AFTER 0x0080
#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100
#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200
#define PNG_FLAG_CRC_CRITICAL_USE 0x0400
#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800
-#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */
-#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */
-#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */
-#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000
-#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000
-#define PNG_FLAG_LIBRARY_MISMATCH 0x20000
-#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000
-#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000
-#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000
- /* 0x200000 unused */
- /* 0x400000 unused */
-#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000 /* Added to libpng-1.4.0 */
-#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000 /* 5 lines added */
-#define PNG_FLAG_ZTXT_CUSTOM_LEVEL 0x2000000 /* to libpng-1.5.4 */
-#define PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL 0x4000000
-#define PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS 0x8000000
-#define PNG_FLAG_ZTXT_CUSTOM_METHOD 0x10000000
- /* 0x20000000 unused */
- /* 0x40000000 unused */
+#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */
+#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */
+#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */
+/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 */
+/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 */
+#define PNG_FLAG_LIBRARY_MISMATCH 0x20000
+#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000
+#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000
+#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000 /* Added to libpng-1.4.0 */
+#define PNG_FLAG_APP_WARNINGS_WARN 0x200000 /* Added to libpng-1.6.0 */
+#define PNG_FLAG_APP_ERRORS_WARN 0x400000 /* Added to libpng-1.6.0 */
+ /* 0x800000 unused */
+ /* 0x1000000 unused */
+ /* 0x2000000 unused */
+ /* 0x4000000 unused */
+ /* 0x8000000 unused */
+ /* 0x10000000 unused */
+ /* 0x20000000 unused */
+ /* 0x40000000 unused */
#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
PNG_FLAG_CRC_ANCILLARY_NOWARN)
@@ -510,24 +617,23 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \
PNG_FLAG_CRC_CRITICAL_MASK)
-/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib
- * can handle at once. This type need be no larger than 16 bits (so maximum of
- * 65535), this define allows us to discover how big it is, but limited by the
- * maximuum for png_size_t. The value can be overriden in a library build
- * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably
- * lower value (e.g. 255 works). A lower value may help memory usage (slightly)
- * and may even improve performance on some systems (and degrade it on others.)
- */
-#ifndef ZLIB_IO_MAX
-# define ZLIB_IO_MAX ((uInt)-1)
-#endif
-
/* Save typing and make code easier to understand */
#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
abs((int)((c1).green) - (int)((c2).green)) + \
abs((int)((c1).blue) - (int)((c2).blue)))
+/* Added to libpng-1.6.0: scale a 16-bit value in the range 0..65535 to 0..255
+ * by dividing by 257 *with rounding*. This macro is exact for the given range.
+ * See the discourse in pngrtran.c png_do_scale_16_to_8. The values in the
+ * macro were established by experiment (modifying the added value). The macro
+ * has a second variant that takes a value already scaled by 255 and divides by
+ * 65535 - this has a maximum error of .502. Over the range 0..65535*65535 it
+ * only gives off-by-one errors and only for 0.5% (1 in 200) of the values.
+ */
+#define PNG_DIV65535(v24) (((v24) + 32895) >> 16)
+#define PNG_DIV257(v16) PNG_DIV65535((png_uint_32)(v16) * 255)
+
/* Added to libpng-1.2.6 JB */
#define PNG_ROWBYTES(pixel_bits, width) \
((pixel_bits) >= 8 ? \
@@ -559,7 +665,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
/* The fixed point conversion performs range checking and evaluates
* its argument multiple times, so must be used with care. The
* range checking uses the PNG specification values for a signed
- * 32 bit fixed point value except that the values are deliberately
+ * 32-bit fixed point value except that the values are deliberately
* rounded-to-zero to an integral value - 21474 (21474.83 is roughly
* (2^31-1) * 100000). 's' is a string that describes the value being
* converted.
@@ -575,10 +681,10 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED
#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\
((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0))
-#else
-PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp,
- png_const_charp text));
#endif
+/* else the corresponding function is defined below, inside the scope of the
+ * cplusplus test.
+ */
#endif
/* Constants for known chunk types. If you need to add a chunk, define the name
@@ -595,53 +701,82 @@ PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp,
* architectures where (int) is only 16 bits.
*/
#define PNG_32b(b,s) ((png_uint_32)(b) << (s))
-#define PNG_CHUNK(b1,b2,b3,b4) \
+#define PNG_U32(b1,b2,b3,b4) \
(PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0))
-#define png_IHDR PNG_CHUNK( 73, 72, 68, 82)
-#define png_IDAT PNG_CHUNK( 73, 68, 65, 84)
-#define png_IEND PNG_CHUNK( 73, 69, 78, 68)
-#define png_PLTE PNG_CHUNK( 80, 76, 84, 69)
-#define png_bKGD PNG_CHUNK( 98, 75, 71, 68)
-#define png_cHRM PNG_CHUNK( 99, 72, 82, 77)
-#define png_gAMA PNG_CHUNK(103, 65, 77, 65)
-#define png_hIST PNG_CHUNK(104, 73, 83, 84)
-#define png_iCCP PNG_CHUNK(105, 67, 67, 80)
-#define png_iTXt PNG_CHUNK(105, 84, 88, 116)
-#define png_oFFs PNG_CHUNK(111, 70, 70, 115)
-#define png_pCAL PNG_CHUNK(112, 67, 65, 76)
-#define png_sCAL PNG_CHUNK(115, 67, 65, 76)
-#define png_pHYs PNG_CHUNK(112, 72, 89, 115)
-#define png_sBIT PNG_CHUNK(115, 66, 73, 84)
-#define png_sPLT PNG_CHUNK(115, 80, 76, 84)
-#define png_sRGB PNG_CHUNK(115, 82, 71, 66)
-#define png_sTER PNG_CHUNK(115, 84, 69, 82)
-#define png_tEXt PNG_CHUNK(116, 69, 88, 116)
-#define png_tIME PNG_CHUNK(116, 73, 77, 69)
-#define png_tRNS PNG_CHUNK(116, 82, 78, 83)
-#define png_zTXt PNG_CHUNK(122, 84, 88, 116)
+/* Constants for known chunk types.
+ *
+ * MAINTAINERS: If you need to add a chunk, define the name here.
+ * For historical reasons these constants have the form png_<name>; i.e.
+ * the prefix is lower case. Please use decimal values as the parameters to
+ * match the ISO PNG specification and to avoid relying on the C locale
+ * interpretation of character values. Please keep the list sorted.
+ *
+ * Notice that PNG_U32 is used to define a 32-bit value for the 4 byte chunk
+ * type. In fact the specification does not express chunk types this way,
+ * however using a 32-bit value means that the chunk type can be read from the
+ * stream using exactly the same code as used for a 32-bit unsigned value and
+ * can be examined far more efficiently (using one arithmetic compare).
+ *
+ * Prior to 1.5.6 the chunk type constants were expressed as C strings. The
+ * libpng API still uses strings for 'unknown' chunks and a macro,
+ * PNG_STRING_FROM_CHUNK, allows a string to be generated if required. Notice
+ * that for portable code numeric values must still be used; the string "IHDR"
+ * is not portable and neither is PNG_U32('I', 'H', 'D', 'R').
+ *
+ * In 1.7.0 the definitions will be made public in png.h to avoid having to
+ * duplicate the same definitions in application code.
+ */
+#define png_IDAT PNG_U32( 73, 68, 65, 84)
+#define png_IEND PNG_U32( 73, 69, 78, 68)
+#define png_IHDR PNG_U32( 73, 72, 68, 82)
+#define png_PLTE PNG_U32( 80, 76, 84, 69)
+#define png_bKGD PNG_U32( 98, 75, 71, 68)
+#define png_cHRM PNG_U32( 99, 72, 82, 77)
+#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */
+#define png_gAMA PNG_U32(103, 65, 77, 65)
+#define png_gIFg PNG_U32(103, 73, 70, 103)
+#define png_gIFt PNG_U32(103, 73, 70, 116) /* deprecated */
+#define png_gIFx PNG_U32(103, 73, 70, 120)
+#define png_hIST PNG_U32(104, 73, 83, 84)
+#define png_iCCP PNG_U32(105, 67, 67, 80)
+#define png_iTXt PNG_U32(105, 84, 88, 116)
+#define png_oFFs PNG_U32(111, 70, 70, 115)
+#define png_pCAL PNG_U32(112, 67, 65, 76)
+#define png_pHYs PNG_U32(112, 72, 89, 115)
+#define png_sBIT PNG_U32(115, 66, 73, 84)
+#define png_sCAL PNG_U32(115, 67, 65, 76)
+#define png_sPLT PNG_U32(115, 80, 76, 84)
+#define png_sRGB PNG_U32(115, 82, 71, 66)
+#define png_sTER PNG_U32(115, 84, 69, 82)
+#define png_tEXt PNG_U32(116, 69, 88, 116)
+#define png_tIME PNG_U32(116, 73, 77, 69)
+#define png_tRNS PNG_U32(116, 82, 78, 83)
+#define png_zTXt PNG_U32(122, 84, 88, 116)
/* The following will work on (signed char*) strings, whereas the get_uint_32
* macro will fail on top-bit-set values because of the sign extension.
*/
#define PNG_CHUNK_FROM_STRING(s)\
- PNG_CHUNK(0xff&(s)[0], 0xff&(s)[1], 0xff&(s)[2], 0xff&(s)[3])
+ PNG_U32(0xff & (s)[0], 0xff & (s)[1], 0xff & (s)[2], 0xff & (s)[3])
/* This uses (char), not (png_byte) to avoid warnings on systems where (char) is
* signed and the argument is a (char[]) This macro will fail miserably on
* systems where (char) is more than 8 bits.
*/
#define PNG_STRING_FROM_CHUNK(s,c)\
- (void)(((char*)(s))[0]=(char)((c)>>24), ((char*)(s))[1]=(char)((c)>>16),\
- ((char*)(s))[2]=(char)((c)>>8), ((char*)(s))[3]=(char)((c)))
+ (void)(((char*)(s))[0]=(char)(((c)>>24) & 0xff), \
+ ((char*)(s))[1]=(char)(((c)>>16) & 0xff),\
+ ((char*)(s))[2]=(char)(((c)>>8) & 0xff), \
+ ((char*)(s))[3]=(char)((c & 0xff)))
/* Do the same but terminate with a null character. */
#define PNG_CSTRING_FROM_CHUNK(s,c)\
(void)(PNG_STRING_FROM_CHUNK(s,c), ((char*)(s))[4] = 0)
/* Test on flag values as defined in the spec (section 5.4): */
-#define PNG_CHUNK_ANCILLIARY(c) (1 & ((c) >> 29))
-#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLIARY(c))
+#define PNG_CHUNK_ANCILLARY(c) (1 & ((c) >> 29))
+#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLARY(c))
#define PNG_CHUNK_PRIVATE(c) (1 & ((c) >> 21))
#define PNG_CHUNK_RESERVED(c) (1 & ((c) >> 13))
#define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >> 5))
@@ -651,113 +786,212 @@ PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp,
#define PNG_GAMMA_MAC_INVERSE 65909
#define PNG_GAMMA_sRGB_INVERSE 45455
+/* Almost everything below is C specific; the #defines above can be used in
+ * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot.
+ */
+#ifndef PNG_VERSION_INFO_ONLY
+
+#include "pngstruct.h"
+#include "pnginfo.h"
+
+/* Validate the include paths - the include path used to generate pnglibconf.h
+ * must match that used in the build, or we must be using pnglibconf.h.prebuilt:
+ */
+#if PNG_ZLIB_VERNUM != 0 && PNG_ZLIB_VERNUM != ZLIB_VERNUM
+# error ZLIB_VERNUM != PNG_ZLIB_VERNUM \
+ "-I (include path) error: see the notes in pngpriv.h"
+ /* This means that when pnglibconf.h was built the copy of zlib.h that it
+ * used is not the same as the one being used here. Because the build of
+ * libpng makes decisions to use inflateInit2 and inflateReset2 based on the
+ * zlib version number and because this affects handling of certain broken
+ * PNG files the -I directives must match.
+ *
+ * The most likely explanation is that you passed a -I in CFLAGS. This will
+ * not work; all the preprocessor directories and in particular all the -I
+ * directives must be in CPPFLAGS.
+ */
+#endif
+
+/* This is used for 16-bit gamma tables -- only the top level pointers are
+ * const; this could be changed:
+ */
+typedef const png_uint_16p * png_const_uint_16pp;
+
+/* Added to libpng-1.5.7: sRGB conversion tables */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_table, [256]);
+ /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value,
+ * 0..65535. This table gives the closest 16-bit answers (no errors).
+ */
+#endif
+
+PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_base, [512]);
+PNG_INTERNAL_DATA(const png_byte, png_sRGB_delta, [512]);
+
+#define PNG_sRGB_FROM_LINEAR(linear) \
+ ((png_byte)(0xff & ((png_sRGB_base[(linear)>>15] \
+ + ((((linear) & 0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8)))
+ /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB
+ * encoded value with maximum error 0.646365. Note that the input is not a
+ * 16-bit value; it has been multiplied by 255! */
+#endif /* SIMPLIFIED_READ/WRITE */
+
/* Inhibit C++ name-mangling for libpng functions but not for system calls. */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-/* These functions are used internally in the code. They generally
- * shouldn't be used unless you are writing code to add or replace some
- * functionality in libpng. More information about most functions can
- * be found in the files where the functions are located.
+/* Internal functions; these are not exported from a DLL however because they
+ * are used within several of the C source files they have to be C extern.
+ *
+ * All of these functions must be declared with PNG_INTERNAL_FUNCTION.
*/
+/* Zlib support */
+#define PNG_UNEXPECTED_ZLIB_RETURN (-7)
+PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret),
+ PNG_EMPTY);
+ /* Used by the zlib handling functions to ensure that z_stream::msg is always
+ * set before they return.
+ */
+
+#ifdef PNG_WRITE_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr,
+ png_compression_bufferp *list),PNG_EMPTY);
+ /* Free the buffer list used by the compressed write code. */
+#endif
+
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
+ !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
+ (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
+ defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
+ (defined(PNG_sCAL_SUPPORTED) && \
+ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
+PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr,
+ double fp, png_const_charp text),PNG_EMPTY);
+#endif
+
/* Check the user version string for compatibility, returns false if the version
* numbers aren't compatible.
*/
-PNG_EXTERN int png_user_version_check(png_structp png_ptr,
- png_const_charp user_png_ver);
+PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr,
+ png_const_charp user_png_ver),PNG_EMPTY);
-/* Allocate memory for an internal libpng struct */
-PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct,PNGARG((int type)),
- PNG_ALLOCATED);
+/* Internal base allocator - no messages, NULL on failure to allocate. This
+ * does, however, call the application provided allocator and that could call
+ * png_error (although that would be a bug in the application implementation.)
+ */
+PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_base,(png_const_structrp png_ptr,
+ png_alloc_size_t size),PNG_ALLOCATED);
-/* Free memory from internal libpng struct */
-PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr));
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
+ defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
+/* Internal array allocator, outputs no error or warning messages on failure,
+ * just returns NULL.
+ */
+PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_array,(png_const_structrp png_ptr,
+ int nelements, size_t element_size),PNG_ALLOCATED);
-PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct_2,
- PNGARG((int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)),
- PNG_ALLOCATED);
-PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr,
- png_free_ptr free_fn, png_voidp mem_ptr));
+/* The same but an existing array is extended by add_elements. This function
+ * also memsets the new elements to 0 and copies the old elements. The old
+ * array is not freed or altered.
+ */
+PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_const_structrp png_ptr,
+ png_const_voidp array, int old_elements, int add_elements,
+ size_t element_size),PNG_ALLOCATED);
+#endif /* text, sPLT or unknown chunks */
+
+/* Magic to create a struct when there is no struct to call the user supplied
+ * memory allocators. Because error handling has not been set up the memory
+ * handlers can't safely call png_error, but this is an obscure and undocumented
+ * restriction so libpng has to assume that the 'free' handler, at least, might
+ * call png_error.
+ */
+PNG_INTERNAL_FUNCTION(png_structp,png_create_png_struct,
+ (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
+ png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn,
+ png_free_ptr free_fn),PNG_ALLOCATED);
-/* Free any memory that info_ptr points to and reset struct. */
-PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr,
- png_infop info_ptr));
+/* Free memory from internal libpng struct */
+PNG_INTERNAL_FUNCTION(void,png_destroy_png_struct,(png_structrp png_ptr),
+ PNG_EMPTY);
+
+/* Free an allocated jmp_buf (always succeeds) */
+PNG_INTERNAL_FUNCTION(void,png_free_jmpbuf,(png_structrp png_ptr),PNG_EMPTY);
/* Function to allocate memory for zlib. PNGAPI is disallowed. */
-PNG_EXTERN PNG_FUNCTION(voidpf,png_zalloc,PNGARG((voidpf png_ptr, uInt items,
- uInt size)),PNG_ALLOCATED);
+PNG_INTERNAL_FUNCTION(voidpf,png_zalloc,(voidpf png_ptr, uInt items, uInt size),
+ PNG_ALLOCATED);
/* Function to free memory for zlib. PNGAPI is disallowed. */
-PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr));
+PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY);
/* Next four functions are used internally as callbacks. PNGCBAPI is required
* but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to
* PNGCBAPI at 1.5.0
*/
-PNG_EXTERN void PNGCBAPI png_default_read_data PNGARG((png_structp png_ptr,
- png_bytep data, png_size_t length));
+PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr,
+ png_bytep data, png_size_t length),PNG_EMPTY);
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_EXTERN void PNGCBAPI png_push_fill_buffer PNGARG((png_structp png_ptr,
- png_bytep buffer, png_size_t length));
+PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr,
+ png_bytep buffer, png_size_t length),PNG_EMPTY);
#endif
-PNG_EXTERN void PNGCBAPI png_default_write_data PNGARG((png_structp png_ptr,
- png_bytep data, png_size_t length));
+PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr,
+ png_bytep data, png_size_t length),PNG_EMPTY);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
# ifdef PNG_STDIO_SUPPORTED
-PNG_EXTERN void PNGCBAPI png_default_flush PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_flush,(png_structp png_ptr),
+ PNG_EMPTY);
# endif
#endif
/* Reset the CRC variable */
-PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY);
/* Write the "data" buffer to whatever output you are using */
-PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr,
- png_const_bytep data, png_size_t length));
+PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr,
+ png_const_bytep data, png_size_t length),PNG_EMPTY);
/* Read and check the PNG file signature */
-PNG_EXTERN void png_read_sig PNGARG((png_structp png_ptr, png_infop info_ptr));
+PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
/* Read the chunk header (length + type name) */
-PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr),
+ PNG_EMPTY);
/* Read data from whatever input you are using into the "data" buffer */
-PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data,
- png_size_t length));
+PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data,
+ png_size_t length),PNG_EMPTY);
/* Read bytes into buf, and update png_ptr->crc */
-PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf,
- png_size_t length));
-
-/* Decompress data in a chunk that uses compression */
-#if defined(PNG_READ_COMPRESSED_TEXT_SUPPORTED)
-PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr,
- int comp_type, png_size_t chunklength, png_size_t prefix_length,
- png_size_t *data_length));
-#endif
+PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf,
+ png_uint_32 length),PNG_EMPTY);
/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
-PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip));
+PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr,
+ png_uint_32 skip),PNG_EMPTY);
/* Read the CRC from the file and compare it to the libpng calculated CRC */
-PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY);
/* Calculate the CRC over a section of data. Note that we are only
* passing a maximum of 64K on systems that have this as a memory limit,
* since this is the maximum buffer size we can specify.
*/
-PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr,
- png_const_bytep ptr, png_size_t length));
+PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr,
+ png_const_bytep ptr, png_size_t length),PNG_EMPTY);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
-PNG_EXTERN void png_flush PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY);
#endif
/* Write various chunks */
@@ -765,145 +999,130 @@ PNG_EXTERN void png_flush PNGARG((png_structp png_ptr));
/* Write the IHDR chunk, and update the png_struct with the necessary
* information.
*/
-PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width,
- png_uint_32 height,
- int bit_depth, int color_type, int compression_method, int filter_method,
- int interlace_method));
+PNG_INTERNAL_FUNCTION(void,png_write_IHDR,(png_structrp png_ptr,
+ png_uint_32 width, png_uint_32 height, int bit_depth, int color_type,
+ int compression_method, int filter_method, int interlace_method),PNG_EMPTY);
-PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr,
- png_const_colorp palette, png_uint_32 num_pal));
+PNG_INTERNAL_FUNCTION(void,png_write_PLTE,(png_structrp png_ptr,
+ png_const_colorp palette, png_uint_32 num_pal),PNG_EMPTY);
-PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data,
- png_size_t length));
+PNG_INTERNAL_FUNCTION(void,png_compress_IDAT,(png_structrp png_ptr,
+ png_const_bytep row_data, png_alloc_size_t row_data_length, int flush),
+ PNG_EMPTY);
-PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_write_IEND,(png_structrp png_ptr),PNG_EMPTY);
#ifdef PNG_WRITE_gAMA_SUPPORTED
-# ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma));
-# endif
-# ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr,
- png_fixed_point file_gamma));
-# endif
+PNG_INTERNAL_FUNCTION(void,png_write_gAMA_fixed,(png_structrp png_ptr,
+ png_fixed_point file_gamma),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_sBIT_SUPPORTED
-PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr,
- png_const_color_8p sbit, int color_type));
+PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr,
+ png_const_color_8p sbit, int color_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_cHRM_SUPPORTED
-# ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr,
- double white_x, double white_y,
- double red_x, double red_y, double green_x, double green_y,
- double blue_x, double blue_y));
-# endif
-PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr,
- png_fixed_point int_white_x, png_fixed_point int_white_y,
- png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
- int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
- png_fixed_point int_blue_y));
+PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr,
+ const png_xy *xy), PNG_EMPTY);
+ /* The xy value must have been previously validated */
#endif
#ifdef PNG_WRITE_sRGB_SUPPORTED
-PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr,
- int intent));
+PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
+ int intent),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_iCCP_SUPPORTED
-PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr,
- png_const_charp name, int compression_type,
- png_const_charp profile, int proflen));
- /* Note to maintainer: profile should be png_bytep */
+PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr,
+ png_const_charp name, png_const_bytep profile), PNG_EMPTY);
+ /* The profile must have been previously validated for correctness, the
+ * length comes from the first four bytes. Only the base, deflate,
+ * compression is supported.
+ */
#endif
#ifdef PNG_WRITE_sPLT_SUPPORTED
-PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr,
- png_const_sPLT_tp palette));
+PNG_INTERNAL_FUNCTION(void,png_write_sPLT,(png_structrp png_ptr,
+ png_const_sPLT_tp palette),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_tRNS_SUPPORTED
-PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_write_tRNS,(png_structrp png_ptr,
png_const_bytep trans, png_const_color_16p values, int number,
- int color_type));
+ int color_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_bKGD_SUPPORTED
-PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr,
- png_const_color_16p values, int color_type));
+PNG_INTERNAL_FUNCTION(void,png_write_bKGD,(png_structrp png_ptr,
+ png_const_color_16p values, int color_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_hIST_SUPPORTED
-PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr,
- png_const_uint_16p hist, int num_hist));
+PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr,
+ png_const_uint_16p hist, int num_hist),PNG_EMPTY);
#endif
/* Chunks that have keywords */
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
- defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr,
- png_const_charp key, png_charpp new_key));
-#endif
-
#ifdef PNG_WRITE_tEXt_SUPPORTED
-PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_const_charp key,
- png_const_charp text, png_size_t text_len));
+PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr,
+ png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_zTXt_SUPPORTED
-PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_const_charp key,
- png_const_charp text, png_size_t text_len, int compression));
+PNG_INTERNAL_FUNCTION(void,png_write_zTXt,(png_structrp png_ptr, png_const_charp
+ key, png_const_charp text, int compression),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_iTXt_SUPPORTED
-PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_write_iTXt,(png_structrp png_ptr,
int compression, png_const_charp key, png_const_charp lang,
- png_const_charp lang_key, png_const_charp text));
+ png_const_charp lang_key, png_const_charp text),PNG_EMPTY);
#endif
#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */
-PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_const_textp text_ptr, int num_text));
+PNG_INTERNAL_FUNCTION(int,png_set_text_2,(png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_textp text_ptr, int num_text),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_oFFs_SUPPORTED
-PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr,
- png_int_32 x_offset, png_int_32 y_offset, int unit_type));
+PNG_INTERNAL_FUNCTION(void,png_write_oFFs,(png_structrp png_ptr,
+ png_int_32 x_offset, png_int_32 y_offset, int unit_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_pCAL_SUPPORTED
-PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose,
- png_int_32 X0, png_int_32 X1, int type, int nparams,
- png_const_charp units, png_charpp params));
+PNG_INTERNAL_FUNCTION(void,png_write_pCAL,(png_structrp png_ptr,
+ png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
+ png_const_charp units, png_charpp params),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_pHYs_SUPPORTED
-PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_write_pHYs,(png_structrp png_ptr,
png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit,
- int unit_type));
+ int unit_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_tIME_SUPPORTED
-PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr,
- png_const_timep mod_time));
+PNG_INTERNAL_FUNCTION(void,png_write_tIME,(png_structrp png_ptr,
+ png_const_timep mod_time),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_sCAL_SUPPORTED
-PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr,
- int unit, png_const_charp width, png_const_charp height));
+PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr,
+ int unit, png_const_charp width, png_const_charp height),PNG_EMPTY);
#endif
/* Called when finished processing a row of data */
-PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_write_finish_row,(png_structrp png_ptr),
+ PNG_EMPTY);
/* Internal use only. Called before first row of data */
-PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr),
+ PNG_EMPTY);
/* Combine a row of data, dealing with alpha, etc. if requested. 'row' is an
* array of png_ptr->width pixels. If the image is not interlaced or this
- * is the final pass this just does a png_memcpy, otherwise the "display" flag
+ * is the final pass this just does a memcpy, otherwise the "display" flag
* is used to determine whether to copy pixels that are not in the current pass.
*
* Because 'png_do_read_interlace' (below) replicates pixels this allows this
@@ -927,8 +1146,8 @@ PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr));
#ifndef PNG_USE_COMPILE_TIME_MASKS
# define PNG_USE_COMPILE_TIME_MASKS 1
#endif
-PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row,
- int display));
+PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr,
+ png_bytep row, int display),PNG_EMPTY);
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Expand an interlaced row: the 'row_info' describes the pass data that has
@@ -937,188 +1156,107 @@ PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row,
* the pixels are *replicated* to the intervening space. This is essential for
* the correct operation of png_combine_row, above.
*/
-PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info,
- png_bytep row, int pass, png_uint_32 transformations));
+PNG_INTERNAL_FUNCTION(void,png_do_read_interlace,(png_row_infop row_info,
+ png_bytep row, int pass, png_uint_32 transformations),PNG_EMPTY);
#endif
/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Grab pixels out of a row for an interlaced pass */
-PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info,
- png_bytep row, int pass));
+PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info,
+ png_bytep row, int pass),PNG_EMPTY);
#endif
/* Unfilter a row: check the filter value before calling this, there is no point
* calling it for PNG_FILTER_VALUE_NONE.
*/
-PNG_EXTERN void png_read_filter_row PNGARG((png_structp pp, png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row, int filter));
-
-PNG_EXTERN void png_read_filter_row_up_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_sub3_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_sub4_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_avg3_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_avg4_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_paeth3_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_paeth4_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY);
+
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info,
+ png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
/* Choose the best filter to use and filter the row data */
-PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr,
- png_row_infop row_info));
+PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
+ png_row_infop row_info),PNG_EMPTY);
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr,
+ png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY);
+ /* Read 'avail_out' bytes of data from the IDAT stream. If the output buffer
+ * is NULL the function checks, instead, for the end of the stream. In this
+ * case a benign error will be issued if the stream end is not found or if
+ * extra data has to be consumed.
+ */
+PNG_INTERNAL_FUNCTION(void,png_read_finish_IDAT,(png_structrp png_ptr),
+ PNG_EMPTY);
+ /* This cleans up when the IDAT LZ stream does not end when the last image
+ * byte is read; there is still some pending input.
+ */
-/* Finish a row while reading, dealing with interlacing passes, etc. */
-PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr),
+ PNG_EMPTY);
+ /* Finish a row while reading, dealing with interlacing passes, etc. */
+#endif /* SEQUENTIAL_READ */
/* Initialize the row buffers, etc. */
-PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY);
+
+#if PNG_ZLIB_VERNUM >= 0x1240
+PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush),
+ PNG_EMPTY);
+# define PNG_INFLATE(pp, flush) png_zlib_inflate(pp, flush)
+#else /* Zlib < 1.2.4 */
+# define PNG_INFLATE(pp, flush) inflate(&(pp)->zstream, flush)
+#endif /* Zlib < 1.2.4 */
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
/* Optional call to update the users info structure */
-PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-#endif
-
-/* These are the functions that do the transformations */
-#ifdef PNG_READ_FILLER_SUPPORTED
-PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info,
- png_bytep row, png_uint_32 filler, png_uint_32 flags));
-#endif
-
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info,
- png_bytep row));
+PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
#endif
+/* Shared transform functions, defined in pngtran.c */
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
-PNG_EXTERN void png_do_strip_channel PNGARG((png_row_infop row_info,
- png_bytep row, int at_start));
+PNG_INTERNAL_FUNCTION(void,png_do_strip_channel,(png_row_infop row_info,
+ png_bytep row, int at_start),PNG_EMPTY);
#endif
#ifdef PNG_16BIT_SUPPORTED
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info,
- png_bytep row));
+PNG_INTERNAL_FUNCTION(void,png_do_swap,(png_row_infop row_info,
+ png_bytep row),PNG_EMPTY);
#endif
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr,
- png_row_infop row_info, png_bytep row));
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_PACK_SUPPORTED
-PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_SHIFT_SUPPORTED
-PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info,
- png_bytep row, png_const_color_8p sig_bits));
+PNG_INTERNAL_FUNCTION(void,png_do_packswap,(png_row_infop row_info,
+ png_bytep row),PNG_EMPTY);
#endif
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
-PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-PNG_EXTERN void png_do_scale_16_to_8 PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep palette_lookup,
- png_const_bytep quantize_lookup));
-
-# ifdef PNG_CORRECT_PALETTE_SUPPORTED
-PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr,
- png_colorp palette, int num_palette));
-# endif
+PNG_INTERNAL_FUNCTION(void,png_do_invert,(png_row_infop row_info,
+ png_bytep row),PNG_EMPTY);
#endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_WRITE_PACK_SUPPORTED
-PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info,
- png_bytep row, png_uint_32 bit_depth));
-#endif
-
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
-PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info,
- png_bytep row, png_const_color_8p bit_depth));
-#endif
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
- defined(PNG_READ_ALPHA_MODE_SUPPORTED)
-PNG_EXTERN void png_do_compose PNGARG((png_row_infop row_info,
- png_bytep row, png_structp png_ptr));
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info,
- png_bytep row, png_structp png_ptr));
-#endif
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-PNG_EXTERN void png_do_encode_alpha PNGARG((png_row_infop row_info,
- png_bytep row, png_structp png_ptr));
-#endif
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
-PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info,
- png_bytep row, png_const_colorp palette, png_const_bytep trans,
- int num_trans));
-PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info,
- png_bytep row, png_const_color_16p trans_color));
-#endif
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-PNG_EXTERN void png_do_expand_16 PNGARG((png_row_infop row_info,
- png_bytep row));
+PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info,
+ png_bytep row),PNG_EMPTY);
#endif
/* The following decodes the appropriate chunks, and does error correction,
@@ -1126,249 +1264,279 @@ PNG_EXTERN void png_do_expand_16 PNGARG((png_row_infop row_info,
*/
/* Decode the IHDR chunk */
-PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
-PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
-PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_IHDR,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_handle_PLTE,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_handle_IEND,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#ifdef PNG_READ_bKGD_SUPPORTED
-PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_bKGD,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_cHRM_SUPPORTED
-PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_gAMA_SUPPORTED
-PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_hIST_SUPPORTED
-PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_hIST,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_iCCP_SUPPORTED
-PNG_EXTERN void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
-#endif /* PNG_READ_iCCP_SUPPORTED */
+PNG_INTERNAL_FUNCTION(void,png_handle_iCCP,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+#endif /* READ_iCCP */
#ifdef PNG_READ_iTXt_SUPPORTED
-PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_oFFs_SUPPORTED
-PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_pCAL_SUPPORTED
-PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_pCAL,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_pHYs_SUPPORTED
-PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_pHYs,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_sBIT_SUPPORTED
-PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_sBIT,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_sCAL_SUPPORTED
-PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_sCAL,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_sPLT_SUPPORTED
-PNG_EXTERN void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
-#endif /* PNG_READ_sPLT_SUPPORTED */
+PNG_INTERNAL_FUNCTION(void,png_handle_sPLT,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+#endif /* READ_sPLT */
#ifdef PNG_READ_sRGB_SUPPORTED
-PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_sRGB,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_tEXt_SUPPORTED
-PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_tEXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_tIME_SUPPORTED
-PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_tIME,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_tRNS_SUPPORTED
-PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_tRNS,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_zTXt_SUPPORTED
-PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-#endif
+PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr,
+ png_uint_32 chunk_name),PNG_EMPTY);
-PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr,
- png_uint_32 chunk_name));
+PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
+ /* This is the function that gets called for unknown chunks. The 'keep'
+ * argument is either non-zero for a known chunk that has been set to be
+ * handled as unknown or zero for an unknown chunk. By default the function
+ * just skips the chunk or errors out if it is critical.
+ */
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-/* Exactly as png_handle_as_unknown() except that the argument is a 32-bit chunk
- * name, not a string.
- */
-PNG_EXTERN int png_chunk_unknown_handling PNGARG((png_structp png_ptr,
- png_uint_32 chunk_name));
-#endif
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling,
+ (png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY);
+ /* Exactly as the API png_handle_as_unknown() except that the argument is a
+ * 32-bit chunk name, not a string.
+ */
+#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
/* Handle the transformations for reading and writing */
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr,
- png_row_infop row_info));
+PNG_INTERNAL_FUNCTION(void,png_do_read_transformations,(png_structrp png_ptr,
+ png_row_infop row_info),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
-PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr,
- png_row_infop row_info));
+PNG_INTERNAL_FUNCTION(void,png_do_write_transformations,(png_structrp png_ptr,
+ png_row_infop row_info),PNG_EMPTY);
#endif
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_init_read_transformations,(png_structrp png_ptr),
+ PNG_EMPTY);
#endif
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr,
- png_uint_32 length));
-PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr,
- png_bytep buffer, png_size_t buffer_length));
-PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr,
- png_bytep buffer, png_size_t buffer_length));
-PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row));
-PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_push_read_chunk,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_sig,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr,
+ png_bytep buffer, png_size_t buffer_length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr,
+ png_bytep buffer, png_size_t buffer_length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr,
+ png_bytep row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr),
+ PNG_EMPTY);
# ifdef PNG_READ_tEXt_SUPPORTED
-PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr,
- png_infop info_ptr));
+PNG_INTERNAL_FUNCTION(void,png_push_handle_tEXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_tEXt,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
# endif
# ifdef PNG_READ_zTXt_SUPPORTED
-PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr,
- png_infop info_ptr));
+PNG_INTERNAL_FUNCTION(void,png_push_handle_zTXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_zTXt,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
# endif
# ifdef PNG_READ_iTXt_SUPPORTED
-PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr,
- png_infop info_ptr));
+PNG_INTERNAL_FUNCTION(void,png_push_handle_iTXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
# endif
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PROGRESSIVE_READ */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info,
- png_bytep row));
-PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
+/* Added at libpng version 1.6.0 */
+#ifdef PNG_GAMMA_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_fixed_point gAMA), PNG_EMPTY);
+ /* Set the colorspace gamma with a value provided by the application or by
+ * the gAMA chunk on read. The value will override anything set by an ICC
+ * profile.
+ */
-/* Added at libpng version 1.4.0 */
-#ifdef PNG_CHECK_cHRM_SUPPORTED
-PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr,
- png_fixed_point int_white_x, png_fixed_point int_white_y,
- png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
- int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
- png_fixed_point int_blue_y));
-#endif
+PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr,
+ png_inforp info_ptr), PNG_EMPTY);
+ /* Synchronize the info 'valid' flags with the colorspace */
-#ifdef PNG_CHECK_cHRM_SUPPORTED
-/* Added at libpng version 1.2.34 and 1.4.0 */
-/* Currently only used by png_check_cHRM_fixed */
-PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2,
- unsigned long *hi_product, unsigned long *lo_product));
+PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr,
+ png_inforp info_ptr), PNG_EMPTY);
+ /* Copy the png_struct colorspace to the info_struct and call the above to
+ * synchronize the flags. Checks for NULL info_ptr and does nothing.
+ */
#endif
-#ifdef PNG_cHRM_SUPPORTED
-/* Added at libpng version 1.5.5 */
-typedef struct png_xy
-{
- png_fixed_point redx, redy;
- png_fixed_point greenx, greeny;
- png_fixed_point bluex, bluey;
- png_fixed_point whitex, whitey;
-} png_xy;
-
-typedef struct png_XYZ
-{
- png_fixed_point redX, redY, redZ;
- png_fixed_point greenX, greenY, greenZ;
- png_fixed_point blueX, blueY, blueZ;
-} png_XYZ;
-
-/* The conversion APIs return 0 on success, non-zero on a parameter error. They
- * allow conversion between the above representations of a color encoding. When
- * converting from XYZ end points to chromaticities the absolute magnitude of
- * the end points is lost, when converting back the sum of the Y values of the
- * three end points will be 1.0
+/* Added at libpng version 1.4.0 */
+#ifdef PNG_COLORSPACE_SUPPORTED
+/* These internal functions are for maintaining the colorspace structure within
+ * a png_info or png_struct (or, indeed, both).
*/
-PNG_EXTERN int png_xy_from_XYZ PNGARG((png_xy *xy, png_XYZ XYZ));
-PNG_EXTERN int png_XYZ_from_xy PNGARG((png_XYZ *XYZ, png_xy xy));
-PNG_EXTERN int png_XYZ_from_xy_checked PNGARG((png_structp png_ptr,
- png_XYZ *XYZ, png_xy xy));
+PNG_INTERNAL_FUNCTION(int,png_colorspace_set_chromaticities,
+ (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_xy *xy,
+ int preferred), PNG_EMPTY);
+
+PNG_INTERNAL_FUNCTION(int,png_colorspace_set_endpoints,
+ (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_XYZ *XYZ,
+ int preferred), PNG_EMPTY);
+
+#ifdef PNG_sRGB_SUPPORTED
+PNG_INTERNAL_FUNCTION(int,png_colorspace_set_sRGB,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, int intent), PNG_EMPTY);
+ /* This does set the colorspace gAMA and cHRM values too, but doesn't set the
+ * flags to write them, if it returns false there was a problem and an error
+ * message has already been output (but the colorspace may still need to be
+ * synced to record the invalid flag).
+ */
+#endif /* sRGB */
+
+#ifdef PNG_iCCP_SUPPORTED
+PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_charp name,
+ png_uint_32 profile_length, png_const_bytep profile, int color_type),
+ PNG_EMPTY);
+ /* The 'name' is used for information only */
+
+/* Routines for checking parts of an ICC profile. */
+PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_charp name,
+ png_uint_32 profile_length), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_charp name,
+ png_uint_32 profile_length,
+ png_const_bytep profile /* first 132 bytes only */, int color_type),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_charp name,
+ png_uint_32 profile_length,
+ png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY);
+#ifdef PNG_sRGB_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,(
+ png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_bytep profile, uLong adler), PNG_EMPTY);
+ /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may
+ * be zero to indicate that it is not available. It is used, if provided,
+ * as a fast check on the profile when checking to see if it is sRGB.
+ */
#endif
+#endif /* iCCP */
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_colorspace_set_rgb_coefficients,
+ (png_structrp png_ptr), PNG_EMPTY);
+ /* Set the rgb_to_gray coefficients from the colorspace Y values */
+#endif /* READ_RGB_TO_GRAY */
+#endif /* COLORSPACE */
/* Added at libpng version 1.4.0 */
-PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_type, int compression_type,
- int filter_type));
-
-/* Free all memory used by the read (old method - NOT DLL EXPORTED) */
-PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_infop end_info_ptr));
+ int filter_type),PNG_EMPTY);
-/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
-PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr));
-
-#ifdef USE_FAR_KEYWORD /* memory model conversion function */
-PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr, png_voidp ptr,
- int check));
-#endif /* USE_FAR_KEYWORD */
+/* Added at libpng version 1.5.10 */
+#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
+ defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
+PNG_INTERNAL_FUNCTION(void,png_do_check_palette_indexes,
+ (png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY);
+#endif
#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
-PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_fixed_error,(png_const_structrp png_ptr,
png_const_charp name),PNG_NORETURN);
#endif
@@ -1376,8 +1544,8 @@ PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr,
* the end. Always leaves the buffer nul terminated. Never errors out (and
* there is no error code.)
*/
-PNG_EXTERN size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos,
- png_const_charp string);
+PNG_INTERNAL_FUNCTION(size_t,png_safecat,(png_charp buffer, size_t bufsize,
+ size_t pos, png_const_charp string),PNG_EMPTY);
/* Various internal functions to handle formatted warning messages, currently
* only implemented for warnings.
@@ -1388,8 +1556,8 @@ PNG_EXTERN size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos,
* Returns the pointer to the start of the formatted string. This utility only
* does unsigned values.
*/
-PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end,
- int format, png_alloc_size_t number);
+PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start,
+ png_charp end, int format, png_alloc_size_t number),PNG_EMPTY);
/* Convenience macro that takes an array: */
#define PNG_FORMAT_NUMBER(buffer,format,number) \
@@ -1413,7 +1581,7 @@ PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end,
#ifdef PNG_WARNINGS_SUPPORTED
/* New defines and members adding in libpng-1.5.4 */
# define PNG_WARNING_PARAMETER_SIZE 32
-# define PNG_WARNING_PARAMETER_COUNT 8
+# define PNG_WARNING_PARAMETER_COUNT 8 /* Maximum 9; see pngerror.c */
/* An l-value of this type has to be passed to the APIs below to cache the
* values of the parameters to a formatted warning message.
@@ -1421,48 +1589,97 @@ PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end,
typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][
PNG_WARNING_PARAMETER_SIZE];
-PNG_EXTERN void png_warning_parameter(png_warning_parameters p, int number,
- png_const_charp string);
- /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters,
- * including the trailing '\0'.
- */
-PNG_EXTERN void png_warning_parameter_unsigned(png_warning_parameters p,
- int number, int format, png_alloc_size_t value);
- /* Use png_alloc_size_t because it is an unsigned type as big as any we
- * need to output. Use the following for a signed value.
- */
-PNG_EXTERN void png_warning_parameter_signed(png_warning_parameters p,
- int number, int format, png_int_32 value);
-
-PNG_EXTERN void png_formatted_warning(png_structp png_ptr,
- png_warning_parameters p, png_const_charp message);
- /* 'message' follows the X/Open approach of using @1, @2 to insert
- * parameters previously supplied using the above functions. Errors in
- * specifying the paramters will simple result in garbage substitutions.
- */
+PNG_INTERNAL_FUNCTION(void,png_warning_parameter,(png_warning_parameters p,
+ int number, png_const_charp string),PNG_EMPTY);
+ /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters,
+ * including the trailing '\0'.
+ */
+PNG_INTERNAL_FUNCTION(void,png_warning_parameter_unsigned,
+ (png_warning_parameters p, int number, int format, png_alloc_size_t value),
+ PNG_EMPTY);
+ /* Use png_alloc_size_t because it is an unsigned type as big as any we
+ * need to output. Use the following for a signed value.
+ */
+PNG_INTERNAL_FUNCTION(void,png_warning_parameter_signed,
+ (png_warning_parameters p, int number, int format, png_int_32 value),
+ PNG_EMPTY);
+
+PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr,
+ png_warning_parameters p, png_const_charp message),PNG_EMPTY);
+ /* 'message' follows the X/Open approach of using @1, @2 to insert
+ * parameters previously supplied using the above functions. Errors in
+ * specifying the parameters will simply result in garbage substitutions.
+ */
#endif
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+/* Application errors (new in 1.6); use these functions (declared below) for
+ * errors in the parameters or order of API function calls on read. The
+ * 'warning' should be used for an error that can be handled completely; the
+ * 'error' for one which can be handled safely but which may lose application
+ * information or settings.
+ *
+ * By default these both result in a png_error call prior to release, while in a
+ * released version the 'warning' is just a warning. However if the application
+ * explicitly disables benign errors (explicitly permitting the code to lose
+ * information) they both turn into warnings.
+ *
+ * If benign errors aren't supported they end up as the corresponding base call
+ * (png_warning or png_error.)
+ */
+PNG_INTERNAL_FUNCTION(void,png_app_warning,(png_const_structrp png_ptr,
+ png_const_charp message),PNG_EMPTY);
+ /* The application provided invalid parameters to an API function or called
+ * an API function at the wrong time, libpng can completely recover.
+ */
+
+PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr,
+ png_const_charp message),PNG_EMPTY);
+ /* As above but libpng will ignore the call, or attempt some other partial
+ * recovery from the error.
+ */
+#else
+# define png_app_warning(pp,s) png_warning(pp,s)
+# define png_app_error(pp,s) png_error(pp,s)
+#endif
+
+PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr,
+ png_const_charp message, int error),PNG_EMPTY);
+ /* Report a recoverable issue in chunk data. On read this is used to report
+ * a problem found while reading a particular chunk and the
+ * png_chunk_benign_error or png_chunk_warning function is used as
+ * appropriate. On write this is used to report an error that comes from
+ * data set via an application call to a png_set_ API and png_app_error or
+ * png_app_warning is used as appropriate.
+ *
+ * The 'error' parameter must have one of the following values:
+ */
+#define PNG_CHUNK_WARNING 0 /* never an error */
+#define PNG_CHUNK_WRITE_ERROR 1 /* an error only on write */
+#define PNG_CHUNK_ERROR 2 /* always an error */
+
/* ASCII to FP interfaces, currently only implemented if sCAL
* support is required.
*/
-#if defined(PNG_READ_sCAL_SUPPORTED)
+#if defined(PNG_sCAL_SUPPORTED)
/* MAX_DIGITS is actually the maximum number of characters in an sCAL
* width or height, derived from the precision (number of significant
- * digits - a build time settable option) and assumpitions about the
+ * digits - a build time settable option) and assumptions about the
* maximum ridiculous exponent.
*/
#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/)
#ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXTERN void png_ascii_from_fp PNGARG((png_structp png_ptr, png_charp ascii,
- png_size_t size, double fp, unsigned int precision));
+PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr,
+ png_charp ascii, png_size_t size, double fp, unsigned int precision),
+ PNG_EMPTY);
#endif /* FLOATING_POINT */
#ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr,
- png_charp ascii, png_size_t size, png_fixed_point fp));
+PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr,
+ png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY);
#endif /* FIXED_POINT */
-#endif /* READ_sCAL */
+#endif /* sCAL */
#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
/* An internal API to validate the format of a floating point number.
@@ -1486,7 +1703,7 @@ PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr,
* NOTE: The dangling E problem.
* There is a PNG valid floating point number in the following:
*
- * PNG floating point numb1.ers are not greedy.
+ * PNG floating point numbers are not greedy.
*
* Working this out requires *TWO* character lookahead (because of the
* sign), the parser does not do this - it will fail at the 'r' - this
@@ -1536,15 +1753,15 @@ PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr,
#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT)
#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK)
#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK)
-
-/* The actual parser. This can be called repeatedly, it updates
+
+/* The actual parser. This can be called repeatedly. It updates
* the index into the string and the state variable (which must
- * be initialzed to 0). It returns a result code, as above. There
+ * be initialized to 0). It returns a result code, as above. There
* is no point calling the parser any more if it fails to advance to
* the end of the string - it is stuck on an invalid character (or
* terminated by '\0').
*
- * Note that the pointer will consume an E or even an E+ then leave
+ * Note that the pointer will consume an E or even an E+ and then leave
* a 'maybe' state even though a preceding integer.fraction is valid.
* The PNG_FP_WAS_VALID flag indicates that a preceding substring was
* a valid number. It's possible to recover from this by calling
@@ -1552,8 +1769,8 @@ PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr,
* that omits the last character (i.e. set the size to the index of
* the problem character.) This has not been tested within libpng.
*/
-PNG_EXTERN int png_check_fp_number PNGARG((png_const_charp string,
- png_size_t size, int *statep, png_size_tp whereami));
+PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string,
+ png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY);
/* This is the same but it checks a complete string and returns true
* only if it just contains a floating point number. As of 1.5.4 this
@@ -1561,11 +1778,11 @@ PNG_EXTERN int png_check_fp_number PNGARG((png_const_charp string,
* it was valid (otherwise it returns 0.) This can be used for testing
* for negative or zero values using the sticky flag.
*/
-PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string,
- png_size_t size));
+PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
+ png_size_t size),PNG_EMPTY);
#endif /* pCAL || sCAL */
-#if defined(PNG_READ_GAMMA_SUPPORTED) ||\
+#if defined(PNG_GAMMA_SUPPORTED) ||\
defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
/* Added at libpng version 1.5.0 */
/* This is a utility to provide a*times/div (rounded) and indicate
@@ -1573,29 +1790,37 @@ PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string,
* for overflow, true (1) if no overflow, in which case *res
* holds the result.
*/
-PNG_EXTERN int png_muldiv PNGARG((png_fixed_point_p res, png_fixed_point a,
- png_int_32 multiplied_by, png_int_32 divided_by));
+PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a,
+ png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY);
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
/* Same deal, but issue a warning on overflow and return 0. */
-PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr,
- png_fixed_point a, png_int_32 multiplied_by, png_int_32 divided_by));
+PNG_INTERNAL_FUNCTION(png_fixed_point,png_muldiv_warn,
+ (png_const_structrp png_ptr, png_fixed_point a, png_int_32 multiplied_by,
+ png_int_32 divided_by),PNG_EMPTY);
#endif
-#ifdef PNG_READ_GAMMA_SUPPORTED
+#ifdef PNG_GAMMA_SUPPORTED
/* Calculate a reciprocal - used for gamma values. This returns
- * 0 if the argument is 0 in order to maintain an undefined value,
+ * 0 if the argument is 0 in order to maintain an undefined value;
* there are no warnings.
*/
-PNG_EXTERN png_fixed_point png_reciprocal PNGARG((png_fixed_point a));
+PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
+ PNG_EMPTY);
+#ifdef PNG_READ_GAMMA_SUPPORTED
/* The same but gives a reciprocal of the product of two fixed point
* values. Accuracy is suitable for gamma calculations but this is
- * not exact - use png_muldiv for that.
+ * not exact - use png_muldiv for that. Only required at present on read.
*/
-PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a,
- png_fixed_point b));
+PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a,
+ png_fixed_point b),PNG_EMPTY);
+#endif
+
+/* Return true if the gamma value is significantly different from 1.0 */
+PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value),
+ PNG_EMPTY);
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
@@ -1606,19 +1831,96 @@ PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a,
* While the input is an 'unsigned' value it must actually be the
* correct bit value - 0..255 or 0..65535 as required.
*/
-PNG_EXTERN png_uint_16 png_gamma_correct PNGARG((png_structp png_ptr,
- unsigned int value, png_fixed_point gamma_value));
-PNG_EXTERN int png_gamma_significant PNGARG((png_fixed_point gamma_value));
-PNG_EXTERN png_uint_16 png_gamma_16bit_correct PNGARG((unsigned int value,
- png_fixed_point gamma_value));
-PNG_EXTERN png_byte png_gamma_8bit_correct PNGARG((unsigned int value,
- png_fixed_point gamma_value));
-PNG_EXTERN void png_destroy_gamma_table(png_structp png_ptr);
-PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr,
- int bit_depth));
+PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_correct,(png_structrp png_ptr,
+ unsigned int value, png_fixed_point gamma_value),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_16bit_correct,(unsigned int value,
+ png_fixed_point gamma_value),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_byte,png_gamma_8bit_correct,(unsigned int value,
+ png_fixed_point gamma_value),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr,
+ int bit_depth),PNG_EMPTY);
+#endif
+
+/* SIMPLIFIED READ/WRITE SUPPORT */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+/* The internal structure that png_image::opaque points to. */
+typedef struct png_control
+{
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_voidp error_buf; /* Always a jmp_buf at present. */
+
+ png_const_bytep memory; /* Memory buffer. */
+ png_size_t size; /* Size of the memory buffer. */
+
+ unsigned int for_write :1; /* Otherwise it is a read structure */
+ unsigned int owned_file :1; /* We own the file in io_ptr */
+} png_control;
+
+/* Return the pointer to the jmp_buf from a png_control: necessary because C
+ * does not reveal the type of the elements of jmp_buf.
+ */
+#ifdef __cplusplus
+# define png_control_jmp_buf(pc) (((jmp_buf*)((pc)->error_buf))[0])
+#else
+# define png_control_jmp_buf(pc) ((pc)->error_buf)
+#endif
+
+/* Utility to safely execute a piece of libpng code catching and logging any
+ * errors that might occur. Returns true on success, false on failure (either
+ * of the function or as a result of a png_error.)
+ */
+PNG_INTERNAL_CALLBACK(void,png_safe_error,(png_structp png_ptr,
+ png_const_charp error_message),PNG_NORETURN);
+
+#ifdef PNG_WARNINGS_SUPPORTED
+PNG_INTERNAL_CALLBACK(void,png_safe_warning,(png_structp png_ptr,
+ png_const_charp warning_message),PNG_EMPTY);
+#else
+# define png_safe_warning 0/*dummy argument*/
#endif
-/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+PNG_INTERNAL_FUNCTION(int,png_safe_execute,(png_imagep image,
+ int (*function)(png_voidp), png_voidp arg),PNG_EMPTY);
+
+/* Utility to log an error; this also cleans up the png_image; the function
+ * always returns 0 (false).
+ */
+PNG_INTERNAL_FUNCTION(int,png_image_error,(png_imagep image,
+ png_const_charp error_message),PNG_EMPTY);
+
+#ifndef PNG_SIMPLIFIED_READ_SUPPORTED
+/* png_image_free is used by the write code but not exported */
+PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY);
+#endif /* !SIMPLIFIED_READ */
+
+#endif /* SIMPLIFIED READ/WRITE */
+
+/* These are initialization functions for hardware specific PNG filter
+ * optimizations; list these here then select the appropriate one at compile
+ * time using the macro PNG_FILTER_OPTIMIZATIONS. If the macro is not defined
+ * the generic code is used.
+ */
+#ifdef PNG_FILTER_OPTIMIZATIONS
+PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr,
+ unsigned int bpp), PNG_EMPTY);
+ /* Just declare the optimization that will be used */
+#else
+ /* List *all* the possible optimizations here - this branch is required if
+ * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in
+ * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing.
+ */
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
+ (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+#endif
+
+PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
+ png_const_charp key, png_bytep new_key), PNG_EMPTY);
+
+/* Maintainer: Put new private prototypes here ^ */
#include "pngdebug.h"
@@ -1626,4 +1928,5 @@ PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr,
}
#endif
+#endif /* PNG_VERSION_INFO_ONLY */
#endif /* PNGPRIV_H */
diff --git a/thirdparty/libpng/pngread.c b/thirdparty/libpng/pngread.c
index 0643754d..dca3d7d5 100644
--- a/thirdparty/libpng/pngread.c
+++ b/thirdparty/libpng/pngread.c
@@ -1,8 +1,8 @@
/* pngread.c - read a PNG file
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -15,6 +15,9 @@
*/
#include "pngpriv.h"
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+# include <errno.h>
+#endif
#ifdef PNG_READ_SUPPORTED
@@ -23,10 +26,12 @@ PNG_FUNCTION(png_structp,PNGAPI
png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
{
-
-#ifdef PNG_USER_MEM_SUPPORTED
- return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
- warn_fn, NULL, NULL, NULL));
+#ifndef PNG_USER_MEM_SUPPORTED
+ png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, NULL, NULL, NULL);
+#else
+ return png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
+ warn_fn, NULL, NULL, NULL);
}
/* Alternate create PNG structure for reading, and allocate any memory
@@ -37,135 +42,40 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
{
-#endif /* PNG_USER_MEM_SUPPORTED */
-
-#ifdef PNG_SETJMP_SUPPORTED
- volatile
-#endif
- png_structp png_ptr;
- volatile int png_cleanup_needed = 0;
-
-#ifdef PNG_SETJMP_SUPPORTED
-#ifdef USE_FAR_KEYWORD
- jmp_buf tmp_jmpbuf;
-#endif
-#endif
-
- png_debug(1, "in png_create_read_struct");
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
- malloc_fn, mem_ptr);
-#else
- png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
-#endif
- if (png_ptr == NULL)
- return (NULL);
-
- /* Added at libpng-1.2.6 */
-#ifdef PNG_USER_LIMITS_SUPPORTED
- png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
- png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
-
-# ifdef PNG_USER_CHUNK_CACHE_MAX
- /* Added at libpng-1.2.43 and 1.4.0 */
- png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
-# endif
-
-# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX
- /* Added at libpng-1.2.43 and 1.4.1 */
- png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
-# endif
-#endif
-
-#ifdef PNG_SETJMP_SUPPORTED
-/* Applications that neglect to set up their own setjmp() and then
- * encounter a png_error() will longjmp here. Since the jmpbuf is
- * then meaningless we abort instead of returning.
- */
-#ifdef USE_FAR_KEYWORD
- if (setjmp(tmp_jmpbuf))
-#else
- if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */
-#endif
- PNG_ABORT();
-#ifdef USE_FAR_KEYWORD
- png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf));
-#endif
-#endif /* PNG_SETJMP_SUPPORTED */
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
-#endif
+ png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
+#endif /* USER_MEM */
- png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
-
- /* Call the general version checker (shared with read and write code): */
- if (!png_user_version_check(png_ptr, user_png_ver))
- png_cleanup_needed = 1;
-
- if (!png_cleanup_needed)
+ if (png_ptr != NULL)
{
- /* Initialize zbuf - compression buffer */
- png_ptr->zbuf_size = PNG_ZBUF_SIZE;
- png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size);
-
- if (png_ptr->zbuf == NULL)
- png_cleanup_needed = 1;
- }
-
- png_ptr->zstream.zalloc = png_zalloc;
- png_ptr->zstream.zfree = png_zfree;
- png_ptr->zstream.opaque = (voidpf)png_ptr;
+ png_ptr->mode = PNG_IS_READ_STRUCT;
- if (!png_cleanup_needed)
- {
- switch (inflateInit(&png_ptr->zstream))
- {
- case Z_OK:
- break; /* Do nothing */
-
- case Z_MEM_ERROR:
- png_warning(png_ptr, "zlib memory error");
- png_cleanup_needed = 1;
- break;
-
- case Z_STREAM_ERROR:
- png_warning(png_ptr, "zlib stream error");
- png_cleanup_needed = 1;
- break;
-
- case Z_VERSION_ERROR:
- png_warning(png_ptr, "zlib version error");
- png_cleanup_needed = 1;
- break;
+ /* Added in libpng-1.6.0; this can be used to detect a read structure if
+ * required (it will be zero in a write structure.)
+ */
+# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE;
+# endif
- default: png_warning(png_ptr, "Unknown zlib error");
- png_cleanup_needed = 1;
- }
- }
+# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED
+ png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
- if (png_cleanup_needed)
- {
- /* Clean up PNG structure and deallocate any memory. */
- png_free(png_ptr, png_ptr->zbuf);
- png_ptr->zbuf = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)png_ptr,
- (png_free_ptr)free_fn, (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)png_ptr);
-#endif
- return (NULL);
+ /* In stable builds only warn if an application error can be completely
+ * handled.
+ */
+# if PNG_RELEASE_BUILD
+ png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
+# endif
+# endif
+
+ /* TODO: delay this, it can be done in png_init_io (if the app doesn't
+ * do it itself) avoiding setting the default function if it is not
+ * required.
+ */
+ png_set_read_fn(png_ptr, NULL, NULL);
}
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-
- png_set_read_fn(png_ptr, NULL, NULL);
-
-
- return (png_ptr);
+ return png_ptr;
}
@@ -179,8 +89,12 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
* read if it is determined that this isn't a valid PNG file.
*/
void PNGAPI
-png_read_info(png_structp png_ptr, png_infop info_ptr)
+png_read_info(png_structrp png_ptr, png_inforp info_ptr)
{
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ int keep;
+#endif
+
png_debug(1, "in png_read_info");
if (png_ptr == NULL || info_ptr == NULL)
@@ -194,13 +108,30 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
png_uint_32 length = png_read_chunk_header(png_ptr);
png_uint_32 chunk_name = png_ptr->chunk_name;
- /* This should be a binary subdivision search or a hash for
- * matching the chunk name rather than a linear search.
+ /* IDAT logic needs to happen here to simplify getting the two flags
+ * right.
*/
if (chunk_name == png_IDAT)
- if (png_ptr->mode & PNG_AFTER_IDAT)
- png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+ {
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "Missing IHDR before IDAT");
+
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0)
+ png_chunk_error(png_ptr, "Missing PLTE before IDAT");
+
+ else if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
+ png_chunk_benign_error(png_ptr, "Too many IDATs found");
+
+ png_ptr->mode |= PNG_HAVE_IDAT;
+ }
+
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ /* This should be a binary subdivision search or a hash for
+ * matching the chunk name rather than a linear search.
+ */
if (chunk_name == png_IHDR)
png_handle_IHDR(png_ptr, info_ptr, length);
@@ -208,26 +139,16 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
png_handle_IEND(png_ptr, info_ptr, length);
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- else if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
- PNG_HANDLE_CHUNK_AS_DEFAULT)
+ else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
{
- if (chunk_name == png_IDAT)
- png_ptr->mode |= PNG_HAVE_IDAT;
-
- png_handle_unknown(png_ptr, info_ptr, length);
+ png_handle_unknown(png_ptr, info_ptr, length, keep);
if (chunk_name == png_PLTE)
png_ptr->mode |= PNG_HAVE_PLTE;
else if (chunk_name == png_IDAT)
{
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before IDAT");
-
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
- png_error(png_ptr, "Missing PLTE before IDAT");
-
+ png_ptr->idat_size = 0; /* It has been consumed */
break;
}
}
@@ -237,15 +158,7 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
else if (chunk_name == png_IDAT)
{
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before IDAT");
-
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
- png_error(png_ptr, "Missing PLTE before IDAT");
-
png_ptr->idat_size = length;
- png_ptr->mode |= PNG_HAVE_IDAT;
break;
}
@@ -335,27 +248,36 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
#endif
else
- png_handle_unknown(png_ptr, info_ptr, length);
+ png_handle_unknown(png_ptr, info_ptr, length,
+ PNG_HANDLE_CHUNK_AS_DEFAULT);
}
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
/* Optional call to update the users info_ptr structure */
void PNGAPI
-png_read_update_info(png_structp png_ptr, png_infop info_ptr)
+png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
{
png_debug(1, "in png_read_update_info");
- if (png_ptr == NULL)
- return;
+ if (png_ptr != NULL)
+ {
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
+ {
+ png_read_start_row(png_ptr);
- png_read_start_row(png_ptr);
+# ifdef PNG_READ_TRANSFORMS_SUPPORTED
+ png_read_transform_info(png_ptr, info_ptr);
+# else
+ PNG_UNUSED(info_ptr)
+# endif
+ }
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
- png_read_transform_info(png_ptr, info_ptr);
-#else
- PNG_UNUSED(info_ptr)
-#endif
+ /* New in 1.6.0 this avoids the bug of doing the initializations twice */
+ else
+ png_app_error(png_ptr,
+ "png_read_update_info/png_start_read_image: duplicate call");
+ }
}
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
@@ -365,21 +287,93 @@ png_read_update_info(png_structp png_ptr, png_infop info_ptr)
* If the user doesn't call this, we will do it ourselves.
*/
void PNGAPI
-png_start_read_image(png_structp png_ptr)
+png_start_read_image(png_structrp png_ptr)
{
png_debug(1, "in png_start_read_image");
if (png_ptr != NULL)
- png_read_start_row(png_ptr);
+ {
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
+ png_read_start_row(png_ptr);
+
+ /* New in 1.6.0 this avoids the bug of doing the initializations twice */
+ else
+ png_app_error(png_ptr,
+ "png_start_read_image/png_read_update_info: duplicate call");
+ }
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-void PNGAPI
-png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Undoes intrapixel differencing,
+ * NOTE: this is apparently only supported in the 'sequential' reader.
+ */
+static void
+png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
{
- int ret;
+ png_debug(1, "in png_do_read_intrapixel");
+
+ if (
+ (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
+ {
+ int bytes_per_pixel;
+ png_uint_32 row_width = row_info->width;
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 3;
+
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 4;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
+ *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
+ }
+ }
+ else if (row_info->bit_depth == 16)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 6;
+
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 8;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
+ png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
+ png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
+ png_uint_32 red = (s0 + s1 + 65536) & 0xffff;
+ png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
+ *(rp ) = (png_byte)((red >> 8) & 0xff);
+ *(rp + 1) = (png_byte)(red & 0xff);
+ *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
+ *(rp + 5) = (png_byte)(blue & 0xff);
+ }
+ }
+ }
+}
+#endif /* MNG_FEATURES */
+
+void PNGAPI
+png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
+{
png_row_info row_info;
if (png_ptr == NULL)
@@ -391,7 +385,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
/* png_read_start_row sets the information (in particular iwidth) for this
* interlace pass.
*/
- if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
png_read_start_row(png_ptr);
/* 1.5.6: row_info moved out of png_struct to a local here. */
@@ -402,45 +396,47 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
row_info.pixel_depth = png_ptr->pixel_depth;
row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
+#ifdef PNG_WARNINGS_SUPPORTED
if (png_ptr->row_number == 0 && png_ptr->pass == 0)
{
/* Check for transforms that have been set but were defined out */
#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
- if (png_ptr->transformations & PNG_INVERT_MONO)
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
- if (png_ptr->transformations & PNG_FILLER)
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
!defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
- if (png_ptr->transformations & PNG_PACK)
+ if ((png_ptr->transformations & PNG_PACK) != 0)
png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
- if (png_ptr->transformations & PNG_SHIFT)
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
- if (png_ptr->transformations & PNG_BGR)
+ if ((png_ptr->transformations & PNG_BGR) != 0)
png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_SWAP_BYTES)
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined");
#endif
}
+#endif /* WARNINGS */
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* If interlaced and we do not need a new row, combine row and return.
@@ -449,7 +445,8 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
* untransformed) and, because of the libpng API for interlaced images, this
* means we must transform before de-interlacing.
*/
- if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
switch (png_ptr->pass)
{
@@ -506,6 +503,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
return;
}
break;
+
case 5:
if ((png_ptr->row_number & 1) || png_ptr->width < 2)
{
@@ -519,7 +517,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
default:
case 6:
- if (!(png_ptr->row_number & 1))
+ if ((png_ptr->row_number & 1) == 0)
{
png_read_finish_row(png_ptr);
return;
@@ -529,52 +527,11 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IDAT))
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
png_error(png_ptr, "Invalid attempt to read row data");
- png_ptr->zstream.next_out = png_ptr->row_buf;
- png_ptr->zstream.avail_out =
- (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
- png_ptr->iwidth) + 1);
-
- do
- {
- if (!(png_ptr->zstream.avail_in))
- {
- while (!png_ptr->idat_size)
- {
- png_crc_finish(png_ptr, 0);
-
- png_ptr->idat_size = png_read_chunk_header(png_ptr);
- if (png_ptr->chunk_name != png_IDAT)
- png_error(png_ptr, "Not enough image data");
- }
- png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_in = png_ptr->zbuf;
- if (png_ptr->zbuf_size > png_ptr->idat_size)
- png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
- png_crc_read(png_ptr, png_ptr->zbuf,
- (png_size_t)png_ptr->zstream.avail_in);
- png_ptr->idat_size -= png_ptr->zstream.avail_in;
- }
-
- ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
-
- if (ret == Z_STREAM_END)
- {
- if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
- png_ptr->idat_size)
- png_benign_error(png_ptr, "Extra compressed data");
- png_ptr->mode |= PNG_AFTER_IDAT;
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
- break;
- }
-
- if (ret != Z_OK)
- png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
- "Decompression error");
-
- } while (png_ptr->zstream.avail_out);
+ /* Fill the row with IDAT data: */
+ png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);
if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
{
@@ -590,10 +547,10 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
* it may not be in the future, so this was changed just to copy the
* interlaced count:
*/
- png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
+ memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
#ifdef PNG_MNG_FEATURES_SUPPORTED
- if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
{
/* Intrapixel differencing */
@@ -601,7 +558,6 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
}
#endif
-
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
if (png_ptr->transformations)
png_do_read_transformations(png_ptr, &row_info);
@@ -619,9 +575,9 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
png_error(png_ptr, "internal sequential row size calculation error");
#ifdef PNG_READ_INTERLACING_SUPPORTED
- /* Blow up interlaced rows to full size */
- if (png_ptr->interlaced &&
- (png_ptr->transformations & PNG_INTERLACE))
+ /* Expand interlaced rows to full size */
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
if (png_ptr->pass < 6)
png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
@@ -647,8 +603,9 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
if (png_ptr->read_row_fn != NULL)
(*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
+
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read one or more rows of image data. If the image is interlaced,
@@ -676,7 +633,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
*/
void PNGAPI
-png_read_rows(png_structp png_ptr, png_bytepp row,
+png_read_rows(png_structrp png_ptr, png_bytepp row,
png_bytepp display_row, png_uint_32 num_rows)
{
png_uint_32 i;
@@ -715,7 +672,7 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
dp++;
}
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the entire image. If the image has an alpha channel or a tRNS
@@ -731,7 +688,7 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
* [*] png_handle_alpha() does not exist yet, as of this version of libpng
*/
void PNGAPI
-png_read_image(png_structp png_ptr, png_bytepp image)
+png_read_image(png_structrp png_ptr, png_bytepp image)
{
png_uint_32 i, image_height;
int pass, j;
@@ -743,7 +700,7 @@ png_read_image(png_structp png_ptr, png_bytepp image)
return;
#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
{
pass = png_set_interlace_handling(png_ptr);
/* And make sure transforms are initialized. */
@@ -751,7 +708,8 @@ png_read_image(png_structp png_ptr, png_bytepp image)
}
else
{
- if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE))
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) == 0)
{
/* Caller called png_start_read_image or png_read_update_info without
* first turning on the PNG_INTERLACE transform. We can fix this here,
@@ -788,7 +746,7 @@ png_read_image(png_structp png_ptr, png_bytepp image)
}
}
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the end of the PNG file. Will not read past the end of the
@@ -796,36 +754,56 @@ png_read_image(png_structp png_ptr, png_bytepp image)
* or time information at the end of the file, if info is not NULL.
*/
void PNGAPI
-png_read_end(png_structp png_ptr, png_infop info_ptr)
+png_read_end(png_structrp png_ptr, png_inforp info_ptr)
{
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ int keep;
+#endif
+
png_debug(1, "in png_read_end");
if (png_ptr == NULL)
return;
- png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
+ /* If png_read_end is called in the middle of reading the rows there may
+ * still be pending IDAT data and an owned zstream. Deal with this here.
+ */
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ if (png_chunk_unknown_handling(png_ptr, png_IDAT) == 0)
+#endif
+ png_read_finish_IDAT(png_ptr);
+
+#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Report invalid palette index; added at libng-1.5.10 */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max > png_ptr->num_palette)
+ png_benign_error(png_ptr, "Read palette index exceeding num_palette");
+#endif
do
{
png_uint_32 length = png_read_chunk_header(png_ptr);
png_uint_32 chunk_name = png_ptr->chunk_name;
- if (chunk_name == png_IHDR)
+ if (chunk_name == png_IEND)
+ png_handle_IEND(png_ptr, info_ptr, length);
+
+ else if (chunk_name == png_IHDR)
png_handle_IHDR(png_ptr, info_ptr, length);
- else if (chunk_name == png_IEND)
- png_handle_IEND(png_ptr, info_ptr, length);
+ else if (info_ptr == NULL)
+ png_crc_finish(png_ptr, length);
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- else if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
- PNG_HANDLE_CHUNK_AS_DEFAULT)
+ else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
{
if (chunk_name == png_IDAT)
{
- if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
+ if ((length > 0) ||
+ (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
png_benign_error(png_ptr, "Too many IDATs found");
}
- png_handle_unknown(png_ptr, info_ptr, length);
+ png_handle_unknown(png_ptr, info_ptr, length, keep);
if (chunk_name == png_PLTE)
png_ptr->mode |= PNG_HAVE_PLTE;
}
@@ -836,7 +814,7 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
/* Zero length IDATs are legal after the last IDAT has been
* read, but not after other chunks have been read.
*/
- if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
+ if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
png_benign_error(png_ptr, "Too many IDATs found");
png_crc_finish(png_ptr, length);
@@ -930,187 +908,106 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
#endif
else
- png_handle_unknown(png_ptr, info_ptr, length);
- } while (!(png_ptr->mode & PNG_HAVE_IEND));
-}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
-
-/* Free all memory used by the read */
-void PNGAPI
-png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
- png_infopp end_info_ptr_ptr)
-{
- png_structp png_ptr = NULL;
- png_infop info_ptr = NULL, end_info_ptr = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_free_ptr free_fn = NULL;
- png_voidp mem_ptr = NULL;
-#endif
-
- png_debug(1, "in png_destroy_read_struct");
-
- if (png_ptr_ptr != NULL)
- png_ptr = *png_ptr_ptr;
- if (png_ptr == NULL)
- return;
-
-#ifdef PNG_USER_MEM_SUPPORTED
- free_fn = png_ptr->free_fn;
- mem_ptr = png_ptr->mem_ptr;
-#endif
-
- if (info_ptr_ptr != NULL)
- info_ptr = *info_ptr_ptr;
-
- if (end_info_ptr_ptr != NULL)
- end_info_ptr = *end_info_ptr_ptr;
-
- png_read_destroy(png_ptr, info_ptr, end_info_ptr);
-
- if (info_ptr != NULL)
- {
-#ifdef PNG_TEXT_SUPPORTED
- png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
-#endif
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)info_ptr);
-#endif
- *info_ptr_ptr = NULL;
- }
-
- if (end_info_ptr != NULL)
- {
-#ifdef PNG_READ_TEXT_SUPPORTED
- png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
-#endif
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)end_info_ptr);
-#endif
- *end_info_ptr_ptr = NULL;
- }
-
- if (png_ptr != NULL)
- {
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)png_ptr);
-#endif
- *png_ptr_ptr = NULL;
- }
+ png_handle_unknown(png_ptr, info_ptr, length,
+ PNG_HANDLE_CHUNK_AS_DEFAULT);
+ } while ((png_ptr->mode & PNG_HAVE_IEND) == 0);
}
+#endif /* SEQUENTIAL_READ */
-/* Free all memory used by the read (old method) */
-void /* PRIVATE */
-png_read_destroy(png_structp png_ptr, png_infop info_ptr,
- png_infop end_info_ptr)
+/* Free all memory used in the read struct */
+static void
+png_read_destroy(png_structrp png_ptr)
{
-#ifdef PNG_SETJMP_SUPPORTED
- jmp_buf tmp_jmp;
-#endif
- png_error_ptr error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_error_ptr warning_fn;
-#endif
- png_voidp error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_free_ptr free_fn;
-#endif
-
png_debug(1, "in png_read_destroy");
- if (info_ptr != NULL)
- png_info_destroy(png_ptr, info_ptr);
-
- if (end_info_ptr != NULL)
- png_info_destroy(png_ptr, end_info_ptr);
-
#ifdef PNG_READ_GAMMA_SUPPORTED
png_destroy_gamma_table(png_ptr);
#endif
- png_free(png_ptr, png_ptr->zbuf);
png_free(png_ptr, png_ptr->big_row_buf);
+ png_ptr->big_row_buf = NULL;
png_free(png_ptr, png_ptr->big_prev_row);
- png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->big_prev_row = NULL;
+ png_free(png_ptr, png_ptr->read_buffer);
+ png_ptr->read_buffer = NULL;
#ifdef PNG_READ_QUANTIZE_SUPPORTED
png_free(png_ptr, png_ptr->palette_lookup);
+ png_ptr->palette_lookup = NULL;
png_free(png_ptr, png_ptr->quantize_index);
+ png_ptr->quantize_index = NULL;
#endif
- if (png_ptr->free_me & PNG_FREE_PLTE)
+ if ((png_ptr->free_me & PNG_FREE_PLTE) != 0)
+ {
png_zfree(png_ptr, png_ptr->palette);
+ png_ptr->palette = NULL;
+ }
png_ptr->free_me &= ~PNG_FREE_PLTE;
#if defined(PNG_tRNS_SUPPORTED) || \
defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
- if (png_ptr->free_me & PNG_FREE_TRNS)
+ if ((png_ptr->free_me & PNG_FREE_TRNS) != 0)
+ {
png_free(png_ptr, png_ptr->trans_alpha);
+ png_ptr->trans_alpha = NULL;
+ }
png_ptr->free_me &= ~PNG_FREE_TRNS;
#endif
-#ifdef PNG_READ_hIST_SUPPORTED
- if (png_ptr->free_me & PNG_FREE_HIST)
- png_free(png_ptr, png_ptr->hist);
- png_ptr->free_me &= ~PNG_FREE_HIST;
-#endif
-
inflateEnd(&png_ptr->zstream);
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
png_free(png_ptr, png_ptr->save_buffer);
+ png_ptr->save_buffer = NULL;
#endif
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-#ifdef PNG_TEXT_SUPPORTED
- png_free(png_ptr, png_ptr->current_text);
-#endif /* PNG_TEXT_SUPPORTED */
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-
- /* Save the important info out of the png_struct, in case it is
- * being used again.
- */
-#ifdef PNG_SETJMP_SUPPORTED
- png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
+#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) && \
+ defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+ png_free(png_ptr, png_ptr->unknown_chunk.data);
+ png_ptr->unknown_chunk.data = NULL;
#endif
- error_fn = png_ptr->error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- warning_fn = png_ptr->warning_fn;
-#endif
- error_ptr = png_ptr->error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- free_fn = png_ptr->free_fn;
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ png_free(png_ptr, png_ptr->chunk_list);
+ png_ptr->chunk_list = NULL;
#endif
- png_memset(png_ptr, 0, png_sizeof(png_struct));
+ /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
+ * callbacks are still set at this point. They are required to complete the
+ * destruction of the png_struct itself.
+ */
+}
- png_ptr->error_fn = error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_ptr->warning_fn = warning_fn;
-#endif
- png_ptr->error_ptr = error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_ptr->free_fn = free_fn;
-#endif
+/* Free all memory used by the read */
+void PNGAPI
+png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
+ png_infopp end_info_ptr_ptr)
+{
+ png_structrp png_ptr = NULL;
-#ifdef PNG_SETJMP_SUPPORTED
- png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf));
-#endif
+ png_debug(1, "in png_destroy_read_struct");
+
+ if (png_ptr_ptr != NULL)
+ png_ptr = *png_ptr_ptr;
+
+ if (png_ptr == NULL)
+ return;
+
+ /* libpng 1.6.0: use the API to destroy info structs to ensure consistent
+ * behavior. Prior to 1.6.0 libpng did extra 'info' destruction in this API.
+ * The extra was, apparently, unnecessary yet this hides memory leak bugs.
+ */
+ png_destroy_info_struct(png_ptr, end_info_ptr_ptr);
+ png_destroy_info_struct(png_ptr, info_ptr_ptr);
+ *png_ptr_ptr = NULL;
+ png_read_destroy(png_ptr);
+ png_destroy_png_struct(png_ptr);
}
void PNGAPI
-png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
+png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
{
if (png_ptr == NULL)
return;
@@ -1122,12 +1019,10 @@ png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
-png_read_png(png_structp png_ptr, png_infop info_ptr,
+png_read_png(png_structrp png_ptr, png_inforp info_ptr,
int transforms,
voidp params)
{
- int row;
-
if (png_ptr == NULL || info_ptr == NULL)
return;
@@ -1135,130 +1030,153 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
* PNG file before the first IDAT (image data chunk).
*/
png_read_info(png_ptr, info_ptr);
- if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
+ if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep)))
png_error(png_ptr, "Image is too high to process with png_read_png()");
/* -------------- image transformations start here ------------------- */
+ /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM
+ * is not implemented. This will only happen in de-configured (non-default)
+ * libpng builds. The results can be unexpected - png_read_png may return
+ * short or mal-formed rows because the transform is skipped.
+ */
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
/* Tell libpng to strip 16-bit/color files down to 8 bits per color.
*/
- if (transforms & PNG_TRANSFORM_SCALE_16)
- {
- /* Added at libpng-1.5.4. "strip_16" produces the same result that it
- * did in earlier versions, while "scale_16" is now more accurate.
- */
+ if ((transforms & PNG_TRANSFORM_SCALE_16) != 0)
+ /* Added at libpng-1.5.4. "strip_16" produces the same result that it
+ * did in earlier versions, while "scale_16" is now more accurate.
+ */
+#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
png_set_scale_16(png_ptr);
- }
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported");
#endif
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
/* If both SCALE and STRIP are required pngrtran will effectively cancel the
* latter by doing SCALE first. This is ok and allows apps not to check for
* which is supported to get the right answer.
*/
- if (transforms & PNG_TRANSFORM_STRIP_16)
+ if ((transforms & PNG_TRANSFORM_STRIP_16) != 0)
+#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
png_set_strip_16(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported");
#endif
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
/* Strip alpha bytes from the input data without combining with
* the background (not recommended).
*/
- if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
+ if ((transforms & PNG_TRANSFORM_STRIP_ALPHA) != 0)
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
png_set_strip_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported");
#endif
-#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
/* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
* byte into separate bytes (useful for paletted and grayscale images).
*/
- if (transforms & PNG_TRANSFORM_PACKING)
+ if ((transforms & PNG_TRANSFORM_PACKING) != 0)
+#ifdef PNG_READ_PACK_SUPPORTED
png_set_packing(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
#endif
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
/* Change the order of packed pixels to least significant bit first
* (not useful if you are using png_set_packing).
*/
- if (transforms & PNG_TRANSFORM_PACKSWAP)
+ if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
png_set_packswap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
#endif
-#ifdef PNG_READ_EXPAND_SUPPORTED
/* Expand paletted colors into true RGB triplets
* Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
* Expand paletted or RGB images with transparency to full alpha
* channels so the data will be available as RGBA quartets.
*/
- if (transforms & PNG_TRANSFORM_EXPAND)
- if ((png_ptr->bit_depth < 8) ||
- (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
- (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
- png_set_expand(png_ptr);
+ if ((transforms & PNG_TRANSFORM_EXPAND) != 0)
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ png_set_expand(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported");
#endif
/* We don't handle background color or gamma transformation or quantizing.
*/
-#ifdef PNG_READ_INVERT_SUPPORTED
/* Invert monochrome files to have 0 as white and 1 as black
*/
- if (transforms & PNG_TRANSFORM_INVERT_MONO)
+ if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
+#ifdef PNG_READ_INVERT_SUPPORTED
png_set_invert_mono(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
#endif
-#ifdef PNG_READ_SHIFT_SUPPORTED
/* If you want to shift the pixel values from the range [0,255] or
* [0,65535] to the original [0,7] or [0,31], or whatever range the
* colors were originally in:
*/
- if ((transforms & PNG_TRANSFORM_SHIFT)
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
- {
- png_color_8p sig_bit;
-
- png_get_sBIT(png_ptr, info_ptr, &sig_bit);
- png_set_shift(png_ptr, sig_bit);
- }
+ if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
+#ifdef PNG_READ_SHIFT_SUPPORTED
+ if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
+ png_set_shift(png_ptr, &info_ptr->sig_bit);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
#endif
-#ifdef PNG_READ_BGR_SUPPORTED
/* Flip the RGB pixels to BGR (or RGBA to BGRA) */
- if (transforms & PNG_TRANSFORM_BGR)
+ if ((transforms & PNG_TRANSFORM_BGR) != 0)
+#ifdef PNG_READ_BGR_SUPPORTED
png_set_bgr(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
#endif
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
/* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
- if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+ if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
png_set_swap_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
#endif
-#ifdef PNG_READ_SWAP_SUPPORTED
/* Swap bytes of 16-bit files to least significant byte first */
- if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+ if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
+#ifdef PNG_READ_SWAP_SUPPORTED
png_set_swap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
#endif
/* Added at libpng-1.2.41 */
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel from opacity to transparency */
- if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+ if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
png_set_invert_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
#endif
/* Added at libpng-1.2.41 */
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Expand grayscale image to RGB */
- if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
+ if ((transforms & PNG_TRANSFORM_GRAY_TO_RGB) != 0)
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
png_set_gray_to_rgb(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported");
#endif
/* Added at libpng-1.5.4 */
+ if ((transforms & PNG_TRANSFORM_EXPAND_16) != 0)
#ifdef PNG_READ_EXPAND_16_SUPPORTED
- if (transforms & PNG_TRANSFORM_EXPAND_16)
png_set_expand_16(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported");
#endif
/* We don't handle adding filler bytes */
@@ -1281,16 +1199,17 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
{
png_uint_32 iptr;
- info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
- info_ptr->height * png_sizeof(png_bytep));
+ info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr,
+ info_ptr->height * (sizeof (png_bytep))));
+
for (iptr=0; iptr<info_ptr->height; iptr++)
info_ptr->row_pointers[iptr] = NULL;
info_ptr->free_me |= PNG_FREE_ROWS;
- for (row = 0; row < (int)info_ptr->height; row++)
- info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
- png_get_rowbytes(png_ptr, info_ptr));
+ for (iptr = 0; iptr < info_ptr->height; iptr++)
+ info_ptr->row_pointers[iptr] = png_voidcast(png_bytep,
+ png_malloc(png_ptr, info_ptr->rowbytes));
}
png_read_image(png_ptr, info_ptr->row_pointers);
@@ -1299,10 +1218,2919 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
/* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
png_read_end(png_ptr, info_ptr);
- PNG_UNUSED(transforms) /* Quiet compiler warnings */
PNG_UNUSED(params)
+}
+#endif /* INFO_IMAGE */
+#endif /* SEQUENTIAL_READ */
+
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+/* SIMPLIFIED READ
+ *
+ * This code currently relies on the sequential reader, though it could easily
+ * be made to work with the progressive one.
+ */
+/* Arguments to png_image_finish_read: */
+
+/* Encoding of PNG data (used by the color-map code) */
+# define P_NOTSET 0 /* File encoding not yet known */
+# define P_sRGB 1 /* 8-bit encoded to sRGB gamma */
+# define P_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */
+# define P_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */
+# define P_LINEAR8 4 /* 8-bit linear: only from a file value */
+
+/* Color-map processing: after libpng has run on the PNG image further
+ * processing may be needed to convert the data to color-map indices.
+ */
+#define PNG_CMAP_NONE 0
+#define PNG_CMAP_GA 1 /* Process GA data to a color-map with alpha */
+#define PNG_CMAP_TRANS 2 /* Process GA data to a background index */
+#define PNG_CMAP_RGB 3 /* Process RGB data */
+#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */
+
+/* The following document where the background is for each processing case. */
+#define PNG_CMAP_NONE_BACKGROUND 256
+#define PNG_CMAP_GA_BACKGROUND 231
+#define PNG_CMAP_TRANS_BACKGROUND 254
+#define PNG_CMAP_RGB_BACKGROUND 256
+#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216
+
+typedef struct
+{
+ /* Arguments: */
+ png_imagep image;
+ png_voidp buffer;
+ png_int_32 row_stride;
+ png_voidp colormap;
+ png_const_colorp background;
+ /* Local variables: */
+ png_voidp local_row;
+ png_voidp first_row;
+ ptrdiff_t row_bytes; /* step between rows */
+ int file_encoding; /* E_ values above */
+ png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */
+ int colormap_processing; /* PNG_CMAP_ values above */
+} png_image_read_control;
+
+/* Do all the *safe* initialization - 'safe' means that png_error won't be
+ * called, so setting up the jmp_buf is not required. This means that anything
+ * called from here must *not* call png_malloc - it has to call png_malloc_warn
+ * instead so that control is returned safely back to this routine.
+ */
+static int
+png_image_read_init(png_imagep image)
+{
+ if (image->opaque == NULL)
+ {
+ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
+ png_safe_error, png_safe_warning);
+
+ /* And set the rest of the structure to NULL to ensure that the various
+ * fields are consistent.
+ */
+ memset(image, 0, (sizeof *image));
+ image->version = PNG_IMAGE_VERSION;
+
+ if (png_ptr != NULL)
+ {
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+
+ if (info_ptr != NULL)
+ {
+ png_controlp control = png_voidcast(png_controlp,
+ png_malloc_warn(png_ptr, (sizeof *control)));
+
+ if (control != NULL)
+ {
+ memset(control, 0, (sizeof *control));
+
+ control->png_ptr = png_ptr;
+ control->info_ptr = info_ptr;
+ control->for_write = 0;
+
+ image->opaque = control;
+ return 1;
+ }
+
+ /* Error clean up */
+ png_destroy_info_struct(png_ptr, &info_ptr);
+ }
+
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
+ }
+
+ return png_image_error(image, "png_image_read: out of memory");
+ }
+
+ return png_image_error(image, "png_image_read: opaque pointer not NULL");
+}
+
+/* Utility to find the base format of a PNG file from a png_struct. */
+static png_uint_32
+png_image_format(png_structrp png_ptr)
+{
+ png_uint_32 format = 0;
+
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
+ format |= PNG_FORMAT_FLAG_COLOR;
+
+ if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
+ format |= PNG_FORMAT_FLAG_ALPHA;
+
+ /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS
+ * sets the png_struct fields; that's all we are interested in here. The
+ * precise interaction with an app call to png_set_tRNS and PNG file reading
+ * is unclear.
+ */
+ else if (png_ptr->num_trans > 0)
+ format |= PNG_FORMAT_FLAG_ALPHA;
+
+ if (png_ptr->bit_depth == 16)
+ format |= PNG_FORMAT_FLAG_LINEAR;
+
+ if ((png_ptr->color_type & PNG_COLOR_MASK_PALETTE) != 0)
+ format |= PNG_FORMAT_FLAG_COLORMAP;
+ return format;
}
-#endif /* PNG_INFO_IMAGE_SUPPORTED */
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED */
+
+/* Is the given gamma significantly different from sRGB? The test is the same
+ * one used in pngrtran.c when deciding whether to do gamma correction. The
+ * arithmetic optimizes the division by using the fact that the inverse of the
+ * file sRGB gamma is 2.2
+ */
+static int
+png_gamma_not_sRGB(png_fixed_point g)
+{
+ if (g < PNG_FP_1)
+ {
+ /* An uninitialized gamma is assumed to be sRGB for the simplified API. */
+ if (g == 0)
+ return 0;
+
+ return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
+ }
+
+ return 1;
+}
+
+/* Do the main body of a 'png_image_begin_read' function; read the PNG file
+ * header and fill in all the information. This is executed in a safe context,
+ * unlike the init routine above.
+ */
+static int
+png_image_read_header(png_voidp argument)
+{
+ png_imagep image = png_voidcast(png_imagep, argument);
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_inforp info_ptr = image->opaque->info_ptr;
+
+ png_set_benign_errors(png_ptr, 1/*warn*/);
+ png_read_info(png_ptr, info_ptr);
+
+ /* Do this the fast way; just read directly out of png_struct. */
+ image->width = png_ptr->width;
+ image->height = png_ptr->height;
+
+ {
+ png_uint_32 format = png_image_format(png_ptr);
+
+ image->format = format;
+
+#ifdef PNG_COLORSPACE_SUPPORTED
+ /* Does the colorspace match sRGB? If there is no color endpoint
+ * (colorant) information assume yes, otherwise require the
+ * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set. If the
+ * colorspace has been determined to be invalid ignore it.
+ */
+ if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags
+ & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB|
+ PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS))
+ image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
+#endif
+ }
+
+ /* We need the maximum number of entries regardless of the format the
+ * application sets here.
+ */
+ {
+ png_uint_32 cmap_entries;
+
+ switch (png_ptr->color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ cmap_entries = 1U << png_ptr->bit_depth;
+ break;
+
+ case PNG_COLOR_TYPE_PALETTE:
+ cmap_entries = png_ptr->num_palette;
+ break;
+
+ default:
+ cmap_entries = 256;
+ break;
+ }
+
+ if (cmap_entries > 256)
+ cmap_entries = 256;
+
+ image->colormap_entries = cmap_entries;
+ }
+
+ return 1;
+}
+
+#ifdef PNG_STDIO_SUPPORTED
+int PNGAPI
+png_image_begin_read_from_stdio(png_imagep image, FILE* file)
+{
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file != NULL)
+ {
+ if (png_image_read_init(image) != 0)
+ {
+ /* This is slightly evil, but png_init_io doesn't do anything other
+ * than this and we haven't changed the standard IO functions so
+ * this saves a 'safe' function.
+ */
+ image->opaque->png_ptr->io_ptr = file;
+ return png_safe_execute(image, png_image_read_header, image);
+ }
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_begin_read_from_stdio: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");
+
+ return 0;
+}
+
+int PNGAPI
+png_image_begin_read_from_file(png_imagep image, const char *file_name)
+{
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file_name != NULL)
+ {
+ FILE *fp = fopen(file_name, "rb");
+
+ if (fp != NULL)
+ {
+ if (png_image_read_init(image) != 0)
+ {
+ image->opaque->png_ptr->io_ptr = fp;
+ image->opaque->owned_file = 1;
+ return png_safe_execute(image, png_image_read_header, image);
+ }
+
+ /* Clean up: just the opened file. */
+ (void)fclose(fp);
+ }
+
+ else
+ return png_image_error(image, strerror(errno));
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_begin_read_from_file: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");
+
+ return 0;
+}
+#endif /* STDIO */
+
+static void PNGCBAPI
+png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
+{
+ if (png_ptr != NULL)
+ {
+ png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);
+ if (image != NULL)
+ {
+ png_controlp cp = image->opaque;
+ if (cp != NULL)
+ {
+ png_const_bytep memory = cp->memory;
+ png_size_t size = cp->size;
+
+ if (memory != NULL && size >= need)
+ {
+ memcpy(out, memory, need);
+ cp->memory = memory + need;
+ cp->size = size - need;
+ return;
+ }
+
+ png_error(png_ptr, "read beyond end of data");
+ }
+ }
+
+ png_error(png_ptr, "invalid memory read");
+ }
+}
+
+int PNGAPI png_image_begin_read_from_memory(png_imagep image,
+ png_const_voidp memory, png_size_t size)
+{
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (memory != NULL && size > 0)
+ {
+ if (png_image_read_init(image) != 0)
+ {
+ /* Now set the IO functions to read from the memory buffer and
+ * store it into io_ptr. Again do this in-place to avoid calling a
+ * libpng function that requires error handling.
+ */
+ image->opaque->memory = png_voidcast(png_const_bytep, memory);
+ image->opaque->size = size;
+ image->opaque->png_ptr->io_ptr = image;
+ image->opaque->png_ptr->read_data_fn = png_image_memory_read;
+
+ return png_safe_execute(image, png_image_read_header, image);
+ }
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_begin_read_from_memory: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");
+
+ return 0;
+}
+
+/* Utility function to skip chunks that are not used by the simplified image
+ * read functions and an appropriate macro to call it.
+ */
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+static void
+png_image_skip_unused_chunks(png_structrp png_ptr)
+{
+ /* Prepare the reader to ignore all recognized chunks whose data will not
+ * be used, i.e., all chunks recognized by libpng except for those
+ * involved in basic image reading:
+ *
+ * IHDR, PLTE, IDAT, IEND
+ *
+ * Or image data handling:
+ *
+ * tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT.
+ *
+ * This provides a small performance improvement and eliminates any
+ * potential vulnerability to security problems in the unused chunks.
+ *
+ * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored
+ * too. This allows the simplified API to be compiled without iCCP support,
+ * however if the support is there the chunk is still checked to detect
+ * errors (which are unfortunately quite common.)
+ */
+ {
+ static PNG_CONST png_byte chunks_to_process[] = {
+ 98, 75, 71, 68, '\0', /* bKGD */
+ 99, 72, 82, 77, '\0', /* cHRM */
+ 103, 65, 77, 65, '\0', /* gAMA */
+# ifdef PNG_READ_iCCP_SUPPORTED
+ 105, 67, 67, 80, '\0', /* iCCP */
+# endif
+ 115, 66, 73, 84, '\0', /* sBIT */
+ 115, 82, 71, 66, '\0', /* sRGB */
+ };
+
+ /* Ignore unknown chunks and all other chunks except for the
+ * IHDR, PLTE, tRNS, IDAT, and IEND chunks.
+ */
+ png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER,
+ NULL, -1);
+
+ /* But do not ignore image data handling chunks */
+ png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT,
+ chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5);
+ }
+}
+
+# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p)
+#else
+# define PNG_SKIP_CHUNKS(p) ((void)0)
+#endif /* HANDLE_AS_UNKNOWN */
+
+/* The following macro gives the exact rounded answer for all values in the
+ * range 0..255 (it actually divides by 51.2, but the rounding still generates
+ * the correct numbers 0..5
+ */
+#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8)
+
+/* Utility functions to make particular color-maps */
+static void
+set_file_encoding(png_image_read_control *display)
+{
+ png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma;
+ if (png_gamma_significant(g) != 0)
+ {
+ if (png_gamma_not_sRGB(g) != 0)
+ {
+ display->file_encoding = P_FILE;
+ display->gamma_to_linear = png_reciprocal(g);
+ }
+
+ else
+ display->file_encoding = P_sRGB;
+ }
+
+ else
+ display->file_encoding = P_LINEAR8;
+}
+
+static unsigned int
+decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding)
+{
+ if (encoding == P_FILE) /* double check */
+ encoding = display->file_encoding;
+
+ if (encoding == P_NOTSET) /* must be the file encoding */
+ {
+ set_file_encoding(display);
+ encoding = display->file_encoding;
+ }
+
+ switch (encoding)
+ {
+ case P_FILE:
+ value = png_gamma_16bit_correct(value*257, display->gamma_to_linear);
+ break;
+
+ case P_sRGB:
+ value = png_sRGB_table[value];
+ break;
+
+ case P_LINEAR:
+ break;
+
+ case P_LINEAR8:
+ value *= 257;
+ break;
+
+#ifdef __GNUC__
+ default:
+ png_error(display->image->opaque->png_ptr,
+ "unexpected encoding (internal error)");
+#endif
+ }
+
+ return value;
+}
+
+static png_uint_32
+png_colormap_compose(png_image_read_control *display,
+ png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha,
+ png_uint_32 background, int encoding)
+{
+ /* The file value is composed on the background, the background has the given
+ * encoding and so does the result, the file is encoded with P_FILE and the
+ * file and alpha are 8-bit values. The (output) encoding will always be
+ * P_LINEAR or P_sRGB.
+ */
+ png_uint_32 f = decode_gamma(display, foreground, foreground_encoding);
+ png_uint_32 b = decode_gamma(display, background, encoding);
+
+ /* The alpha is always an 8-bit value (it comes from the palette), the value
+ * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires.
+ */
+ f = f * alpha + b * (255-alpha);
+
+ if (encoding == P_LINEAR)
+ {
+ /* Scale to 65535; divide by 255, approximately (in fact this is extremely
+ * accurate, it divides by 255.00000005937181414556, with no overflow.)
+ */
+ f *= 257; /* Now scaled by 65535 */
+ f += f >> 16;
+ f = (f+32768) >> 16;
+ }
+
+ else /* P_sRGB */
+ f = PNG_sRGB_FROM_LINEAR(f);
+
+ return f;
+}
+
+/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must
+ * be 8-bit.
+ */
+static void
+png_create_colormap_entry(png_image_read_control *display,
+ png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,
+ png_uint_32 alpha, int encoding)
+{
+ png_imagep image = display->image;
+ const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ P_LINEAR : P_sRGB;
+ const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
+ (red != green || green != blue);
+
+ if (ip > 255)
+ png_error(image->opaque->png_ptr, "color-map index out of range");
+
+ /* Update the cache with whether the file gamma is significantly different
+ * from sRGB.
+ */
+ if (encoding == P_FILE)
+ {
+ if (display->file_encoding == P_NOTSET)
+ set_file_encoding(display);
+
+ /* Note that the cached value may be P_FILE too, but if it is then the
+ * gamma_to_linear member has been set.
+ */
+ encoding = display->file_encoding;
+ }
+
+ if (encoding == P_FILE)
+ {
+ png_fixed_point g = display->gamma_to_linear;
+
+ red = png_gamma_16bit_correct(red*257, g);
+ green = png_gamma_16bit_correct(green*257, g);
+ blue = png_gamma_16bit_correct(blue*257, g);
+
+ if (convert_to_Y != 0 || output_encoding == P_LINEAR)
+ {
+ alpha *= 257;
+ encoding = P_LINEAR;
+ }
+
+ else
+ {
+ red = PNG_sRGB_FROM_LINEAR(red * 255);
+ green = PNG_sRGB_FROM_LINEAR(green * 255);
+ blue = PNG_sRGB_FROM_LINEAR(blue * 255);
+ encoding = P_sRGB;
+ }
+ }
+
+ else if (encoding == P_LINEAR8)
+ {
+ /* This encoding occurs quite frequently in test cases because PngSuite
+ * includes a gAMA 1.0 chunk with most images.
+ */
+ red *= 257;
+ green *= 257;
+ blue *= 257;
+ alpha *= 257;
+ encoding = P_LINEAR;
+ }
+
+ else if (encoding == P_sRGB &&
+ (convert_to_Y != 0 || output_encoding == P_LINEAR))
+ {
+ /* The values are 8-bit sRGB values, but must be converted to 16-bit
+ * linear.
+ */
+ red = png_sRGB_table[red];
+ green = png_sRGB_table[green];
+ blue = png_sRGB_table[blue];
+ alpha *= 257;
+ encoding = P_LINEAR;
+ }
+
+ /* This is set if the color isn't gray but the output is. */
+ if (encoding == P_LINEAR)
+ {
+ if (convert_to_Y != 0)
+ {
+ /* NOTE: these values are copied from png_do_rgb_to_gray */
+ png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green +
+ (png_uint_32)2366 * blue;
+
+ if (output_encoding == P_LINEAR)
+ y = (y + 16384) >> 15;
+
+ else
+ {
+ /* y is scaled by 32768, we need it scaled by 255: */
+ y = (y + 128) >> 8;
+ y *= 255;
+ y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7);
+ alpha = PNG_DIV257(alpha);
+ encoding = P_sRGB;
+ }
+
+ blue = red = green = y;
+ }
+
+ else if (output_encoding == P_sRGB)
+ {
+ red = PNG_sRGB_FROM_LINEAR(red * 255);
+ green = PNG_sRGB_FROM_LINEAR(green * 255);
+ blue = PNG_sRGB_FROM_LINEAR(blue * 255);
+ alpha = PNG_DIV257(alpha);
+ encoding = P_sRGB;
+ }
+ }
+
+ if (encoding != output_encoding)
+ png_error(image->opaque->png_ptr, "bad encoding (internal error)");
+
+ /* Store the value. */
+ {
+# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
+# else
+# define afirst 0
+# endif
+# ifdef PNG_FORMAT_BGR_SUPPORTED
+ const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+# else
+# define bgr 0
+# endif
+
+ if (output_encoding == P_LINEAR)
+ {
+ png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap);
+
+ entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
+
+ /* The linear 16-bit values must be pre-multiplied by the alpha channel
+ * value, if less than 65535 (this is, effectively, composite on black
+ * if the alpha channel is removed.)
+ */
+ switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
+ {
+ case 4:
+ entry[afirst ? 0 : 3] = (png_uint_16)alpha;
+ /* FALL THROUGH */
+
+ case 3:
+ if (alpha < 65535)
+ {
+ if (alpha > 0)
+ {
+ blue = (blue * alpha + 32767U)/65535U;
+ green = (green * alpha + 32767U)/65535U;
+ red = (red * alpha + 32767U)/65535U;
+ }
+
+ else
+ red = green = blue = 0;
+ }
+ entry[afirst + (2 ^ bgr)] = (png_uint_16)blue;
+ entry[afirst + 1] = (png_uint_16)green;
+ entry[afirst + bgr] = (png_uint_16)red;
+ break;
+
+ case 2:
+ entry[1 ^ afirst] = (png_uint_16)alpha;
+ /* FALL THROUGH */
+
+ case 1:
+ if (alpha < 65535)
+ {
+ if (alpha > 0)
+ green = (green * alpha + 32767U)/65535U;
+
+ else
+ green = 0;
+ }
+ entry[afirst] = (png_uint_16)green;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ else /* output encoding is P_sRGB */
+ {
+ png_bytep entry = png_voidcast(png_bytep, display->colormap);
+
+ entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
+
+ switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
+ {
+ case 4:
+ entry[afirst ? 0 : 3] = (png_byte)alpha;
+ case 3:
+ entry[afirst + (2 ^ bgr)] = (png_byte)blue;
+ entry[afirst + 1] = (png_byte)green;
+ entry[afirst + bgr] = (png_byte)red;
+ break;
+
+ case 2:
+ entry[1 ^ afirst] = (png_byte)alpha;
+ case 1:
+ entry[afirst] = (png_byte)green;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+# ifdef afirst
+# undef afirst
+# endif
+# ifdef bgr
+# undef bgr
+# endif
+ }
+}
+
+static int
+make_gray_file_colormap(png_image_read_control *display)
+{
+ unsigned int i;
+
+ for (i=0; i<256; ++i)
+ png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
+
+ return i;
+}
+
+static int
+make_gray_colormap(png_image_read_control *display)
+{
+ unsigned int i;
+
+ for (i=0; i<256; ++i)
+ png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
+
+ return i;
+}
+#define PNG_GRAY_COLORMAP_ENTRIES 256
+
+static int
+make_ga_colormap(png_image_read_control *display)
+{
+ unsigned int i, a;
+
+ /* Alpha is retained, the output will be a color-map with entries
+ * selected by six levels of alpha. One transparent entry, 6 gray
+ * levels for all the intermediate alpha values, leaving 230 entries
+ * for the opaque grays. The color-map entries are the six values
+ * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the
+ * relevant entry.
+ *
+ * if (alpha > 229) // opaque
+ * {
+ * // The 231 entries are selected to make the math below work:
+ * base = 0;
+ * entry = (231 * gray + 128) >> 8;
+ * }
+ * else if (alpha < 26) // transparent
+ * {
+ * base = 231;
+ * entry = 0;
+ * }
+ * else // partially opaque
+ * {
+ * base = 226 + 6 * PNG_DIV51(alpha);
+ * entry = PNG_DIV51(gray);
+ * }
+ */
+ i = 0;
+ while (i < 231)
+ {
+ unsigned int gray = (i * 256 + 115) / 231;
+ png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB);
+ }
+
+ /* 255 is used here for the component values for consistency with the code
+ * that undoes premultiplication in pngwrite.c.
+ */
+ png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB);
+
+ for (a=1; a<5; ++a)
+ {
+ unsigned int g;
+
+ for (g=0; g<6; ++g)
+ png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,
+ P_sRGB);
+ }
+
+ return i;
+}
+
+#define PNG_GA_COLORMAP_ENTRIES 256
+
+static int
+make_rgb_colormap(png_image_read_control *display)
+{
+ unsigned int i, r;
+
+ /* Build a 6x6x6 opaque RGB cube */
+ for (i=r=0; r<6; ++r)
+ {
+ unsigned int g;
+
+ for (g=0; g<6; ++g)
+ {
+ unsigned int b;
+
+ for (b=0; b<6; ++b)
+ png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,
+ P_sRGB);
+ }
+ }
+
+ return i;
+}
+
+#define PNG_RGB_COLORMAP_ENTRIES 216
+
+/* Return a palette index to the above palette given three 8-bit sRGB values. */
+#define PNG_RGB_INDEX(r,g,b) \
+ ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b)))
+
+static int
+png_image_read_colormap(png_voidp argument)
+{
+ png_image_read_control *display =
+ png_voidcast(png_image_read_control*, argument);
+ const png_imagep image = display->image;
+
+ const png_structrp png_ptr = image->opaque->png_ptr;
+ const png_uint_32 output_format = image->format;
+ const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ P_LINEAR : P_sRGB;
+
+ unsigned int cmap_entries;
+ unsigned int output_processing; /* Output processing option */
+ unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */
+
+ /* Background information; the background color and the index of this color
+ * in the color-map if it exists (else 256).
+ */
+ unsigned int background_index = 256;
+ png_uint_32 back_r, back_g, back_b;
+
+ /* Flags to accumulate things that need to be done to the input. */
+ int expand_tRNS = 0;
+
+ /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is
+ * very difficult to do, the results look awful, and it is difficult to see
+ * what possible use it is because the application can't control the
+ * color-map.
+ */
+ if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 ||
+ png_ptr->num_trans > 0) /* alpha in input */ &&
+ ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */)
+ {
+ if (output_encoding == P_LINEAR) /* compose on black */
+ back_b = back_g = back_r = 0;
+
+ else if (display->background == NULL /* no way to remove it */)
+ png_error(png_ptr,
+ "a background color must be supplied to remove alpha/transparency");
+
+ /* Get a copy of the background color (this avoids repeating the checks
+ * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the
+ * output format.
+ */
+ else
+ {
+ back_g = display->background->green;
+ if ((output_format & PNG_FORMAT_FLAG_COLOR) != 0)
+ {
+ back_r = display->background->red;
+ back_b = display->background->blue;
+ }
+ else
+ back_b = back_r = back_g;
+ }
+ }
+
+ else if (output_encoding == P_LINEAR)
+ back_b = back_r = back_g = 65535;
+
+ else
+ back_b = back_r = back_g = 255;
+
+ /* Default the input file gamma if required - this is necessary because
+ * libpng assumes that if no gamma information is present the data is in the
+ * output format, but the simplified API deduces the gamma from the input
+ * format.
+ */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
+ {
+ /* Do this directly, not using the png_colorspace functions, to ensure
+ * that it happens even if the colorspace is invalid (though probably if
+ * it is the setting will be ignored) Note that the same thing can be
+ * achieved at the application interface with png_set_gAMA.
+ */
+ if (png_ptr->bit_depth == 16 &&
+ (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
+ png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
+
+ else
+ png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
+
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+ }
+
+ /* Decide what to do based on the PNG color type of the input data. The
+ * utility function png_create_colormap_entry deals with most aspects of the
+ * output transformations; this code works out how to produce bytes of
+ * color-map entries from the original format.
+ */
+ switch (png_ptr->color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ if (png_ptr->bit_depth <= 8)
+ {
+ /* There at most 256 colors in the output, regardless of
+ * transparency.
+ */
+ unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0;
+
+ cmap_entries = 1U << png_ptr->bit_depth;
+ if (cmap_entries > image->colormap_entries)
+ png_error(png_ptr, "gray[8] color-map: too few entries");
+
+ step = 255 / (cmap_entries - 1);
+ output_processing = PNG_CMAP_NONE;
+
+ /* If there is a tRNS chunk then this either selects a transparent
+ * value or, if the output has no alpha, the background color.
+ */
+ if (png_ptr->num_trans > 0)
+ {
+ trans = png_ptr->trans_color.gray;
+
+ if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0)
+ back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
+ }
+
+ /* png_create_colormap_entry just takes an RGBA and writes the
+ * corresponding color-map entry using the format from 'image',
+ * including the required conversion to sRGB or linear as
+ * appropriate. The input values are always either sRGB (if the
+ * gamma correction flag is 0) or 0..255 scaled file encoded values
+ * (if the function must gamma correct them).
+ */
+ for (i=val=0; i<cmap_entries; ++i, val += step)
+ {
+ /* 'i' is a file value. While this will result in duplicated
+ * entries for 8-bit non-sRGB encoded files it is necessary to
+ * have non-gamma corrected values to do tRNS handling.
+ */
+ if (i != trans)
+ png_create_colormap_entry(display, i, val, val, val, 255,
+ P_FILE/*8-bit with file gamma*/);
+
+ /* Else this entry is transparent. The colors don't matter if
+ * there is an alpha channel (back_alpha == 0), but it does no
+ * harm to pass them in; the values are not set above so this
+ * passes in white.
+ *
+ * NOTE: this preserves the full precision of the application
+ * supplied background color when it is used.
+ */
+ else
+ png_create_colormap_entry(display, i, back_r, back_g, back_b,
+ back_alpha, output_encoding);
+ }
+
+ /* We need libpng to preserve the original encoding. */
+ data_encoding = P_FILE;
+
+ /* The rows from libpng, while technically gray values, are now also
+ * color-map indices; however, they may need to be expanded to 1
+ * byte per pixel. This is what png_set_packing does (i.e., it
+ * unpacks the bit values into bytes.)
+ */
+ if (png_ptr->bit_depth < 8)
+ png_set_packing(png_ptr);
+ }
+
+ else /* bit depth is 16 */
+ {
+ /* The 16-bit input values can be converted directly to 8-bit gamma
+ * encoded values; however, if a tRNS chunk is present 257 color-map
+ * entries are required. This means that the extra entry requires
+ * special processing; add an alpha channel, sacrifice gray level
+ * 254 and convert transparent (alpha==0) entries to that.
+ *
+ * Use libpng to chop the data to 8 bits. Convert it to sRGB at the
+ * same time to minimize quality loss. If a tRNS chunk is present
+ * this means libpng must handle it too; otherwise it is impossible
+ * to do the exact match on the 16-bit value.
+ *
+ * If the output has no alpha channel *and* the background color is
+ * gray then it is possible to let libpng handle the substitution by
+ * ensuring that the corresponding gray level matches the background
+ * color exactly.
+ */
+ data_encoding = P_sRGB;
+
+ if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "gray[16] color-map: too few entries");
+
+ cmap_entries = make_gray_colormap(display);
+
+ if (png_ptr->num_trans > 0)
+ {
+ unsigned int back_alpha;
+
+ if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ back_alpha = 0;
+
+ else
+ {
+ if (back_r == back_g && back_g == back_b)
+ {
+ /* Background is gray; no special processing will be
+ * required.
+ */
+ png_color_16 c;
+ png_uint_32 gray = back_g;
+
+ if (output_encoding == P_LINEAR)
+ {
+ gray = PNG_sRGB_FROM_LINEAR(gray * 255);
+
+ /* And make sure the corresponding palette entry
+ * matches.
+ */
+ png_create_colormap_entry(display, gray, back_g, back_g,
+ back_g, 65535, P_LINEAR);
+ }
+
+ /* The background passed to libpng, however, must be the
+ * sRGB value.
+ */
+ c.index = 0; /*unused*/
+ c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
+
+ /* NOTE: does this work without expanding tRNS to alpha?
+ * It should be the color->gray case below apparently
+ * doesn't.
+ */
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+
+ output_processing = PNG_CMAP_NONE;
+ break;
+ }
+#ifdef __COVERITY__
+ /* Coverity claims that output_encoding cannot be 2 (P_LINEAR)
+ * here.
+ */
+ back_alpha = 255;
+#else
+ back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
+#endif
+ }
+
+ /* output_processing means that the libpng-processed row will be
+ * 8-bit GA and it has to be processing to single byte color-map
+ * values. Entry 254 is replaced by either a completely
+ * transparent entry or by the background color at full
+ * precision (and the background color is not a simple gray
+ * level in this case.)
+ */
+ expand_tRNS = 1;
+ output_processing = PNG_CMAP_TRANS;
+ background_index = 254;
+
+ /* And set (overwrite) color-map entry 254 to the actual
+ * background color at full precision.
+ */
+ png_create_colormap_entry(display, 254, back_r, back_g, back_b,
+ back_alpha, output_encoding);
+ }
+
+ else
+ output_processing = PNG_CMAP_NONE;
+ }
+ break;
+
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ /* 8-bit or 16-bit PNG with two channels - gray and alpha. A minimum
+ * of 65536 combinations. If, however, the alpha channel is to be
+ * removed there are only 256 possibilities if the background is gray.
+ * (Otherwise there is a subset of the 65536 possibilities defined by
+ * the triangle between black, white and the background color.)
+ *
+ * Reduce 16-bit files to 8-bit and sRGB encode the result. No need to
+ * worry about tRNS matching - tRNS is ignored if there is an alpha
+ * channel.
+ */
+ data_encoding = P_sRGB;
+
+ if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "gray+alpha color-map: too few entries");
+
+ cmap_entries = make_ga_colormap(display);
+
+ background_index = PNG_CMAP_GA_BACKGROUND;
+ output_processing = PNG_CMAP_GA;
+ }
+
+ else /* alpha is removed */
+ {
+ /* Alpha must be removed as the PNG data is processed when the
+ * background is a color because the G and A channels are
+ * independent and the vector addition (non-parallel vectors) is a
+ * 2-D problem.
+ *
+ * This can be reduced to the same algorithm as above by making a
+ * colormap containing gray levels (for the opaque grays), a
+ * background entry (for a transparent pixel) and a set of four six
+ * level color values, one set for each intermediate alpha value.
+ * See the comments in make_ga_colormap for how this works in the
+ * per-pixel processing.
+ *
+ * If the background is gray, however, we only need a 256 entry gray
+ * level color map. It is sufficient to make the entry generated
+ * for the background color be exactly the color specified.
+ */
+ if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 ||
+ (back_r == back_g && back_g == back_b))
+ {
+ /* Background is gray; no special processing will be required. */
+ png_color_16 c;
+ png_uint_32 gray = back_g;
+
+ if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "gray-alpha color-map: too few entries");
+
+ cmap_entries = make_gray_colormap(display);
+
+ if (output_encoding == P_LINEAR)
+ {
+ gray = PNG_sRGB_FROM_LINEAR(gray * 255);
+
+ /* And make sure the corresponding palette entry matches. */
+ png_create_colormap_entry(display, gray, back_g, back_g,
+ back_g, 65535, P_LINEAR);
+ }
+
+ /* The background passed to libpng, however, must be the sRGB
+ * value.
+ */
+ c.index = 0; /*unused*/
+ c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
+
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+
+ output_processing = PNG_CMAP_NONE;
+ }
+
+ else
+ {
+ png_uint_32 i, a;
+
+ /* This is the same as png_make_ga_colormap, above, except that
+ * the entries are all opaque.
+ */
+ if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "ga-alpha color-map: too few entries");
+
+ i = 0;
+ while (i < 231)
+ {
+ png_uint_32 gray = (i * 256 + 115) / 231;
+ png_create_colormap_entry(display, i++, gray, gray, gray,
+ 255, P_sRGB);
+ }
+
+ /* NOTE: this preserves the full precision of the application
+ * background color.
+ */
+ background_index = i;
+ png_create_colormap_entry(display, i++, back_r, back_g, back_b,
+#ifdef __COVERITY__
+ /* Coverity claims that output_encoding cannot be 2 (P_LINEAR)
+ * here.
+ */ 255U,
+#else
+ output_encoding == P_LINEAR ? 65535U : 255U,
+#endif
+ output_encoding);
+
+ /* For non-opaque input composite on the sRGB background - this
+ * requires inverting the encoding for each component. The input
+ * is still converted to the sRGB encoding because this is a
+ * reasonable approximate to the logarithmic curve of human
+ * visual sensitivity, at least over the narrow range which PNG
+ * represents. Consequently 'G' is always sRGB encoded, while
+ * 'A' is linear. We need the linear background colors.
+ */
+ if (output_encoding == P_sRGB) /* else already linear */
+ {
+ /* This may produce a value not exactly matching the
+ * background, but that's ok because these numbers are only
+ * used when alpha != 0
+ */
+ back_r = png_sRGB_table[back_r];
+ back_g = png_sRGB_table[back_g];
+ back_b = png_sRGB_table[back_b];
+ }
+
+ for (a=1; a<5; ++a)
+ {
+ unsigned int g;
+
+ /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled
+ * by an 8-bit alpha value (0..255).
+ */
+ png_uint_32 alpha = 51 * a;
+ png_uint_32 back_rx = (255-alpha) * back_r;
+ png_uint_32 back_gx = (255-alpha) * back_g;
+ png_uint_32 back_bx = (255-alpha) * back_b;
+
+ for (g=0; g<6; ++g)
+ {
+ png_uint_32 gray = png_sRGB_table[g*51] * alpha;
+
+ png_create_colormap_entry(display, i++,
+ PNG_sRGB_FROM_LINEAR(gray + back_rx),
+ PNG_sRGB_FROM_LINEAR(gray + back_gx),
+ PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
+ }
+ }
+
+ cmap_entries = i;
+ output_processing = PNG_CMAP_GA;
+ }
+ }
+ break;
+
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ /* Exclude the case where the output is gray; we can always handle this
+ * with the cases above.
+ */
+ if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0)
+ {
+ /* The color-map will be grayscale, so we may as well convert the
+ * input RGB values to a simple grayscale and use the grayscale
+ * code above.
+ *
+ * NOTE: calling this apparently damages the recognition of the
+ * transparent color in background color handling; call
+ * png_set_tRNS_to_alpha before png_set_background_fixed.
+ */
+ png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,
+ -1);
+ data_encoding = P_sRGB;
+
+ /* The output will now be one or two 8-bit gray or gray+alpha
+ * channels. The more complex case arises when the input has alpha.
+ */
+ if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ png_ptr->num_trans > 0) &&
+ (output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ /* Both input and output have an alpha channel, so no background
+ * processing is required; just map the GA bytes to the right
+ * color-map entry.
+ */
+ expand_tRNS = 1;
+
+ if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "rgb[ga] color-map: too few entries");
+
+ cmap_entries = make_ga_colormap(display);
+ background_index = PNG_CMAP_GA_BACKGROUND;
+ output_processing = PNG_CMAP_GA;
+ }
+
+ else
+ {
+ /* Either the input or the output has no alpha channel, so there
+ * will be no non-opaque pixels in the color-map; it will just be
+ * grayscale.
+ */
+ if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "rgb[gray] color-map: too few entries");
+
+ /* Ideally this code would use libpng to do the gamma correction,
+ * but if an input alpha channel is to be removed we will hit the
+ * libpng bug in gamma+compose+rgb-to-gray (the double gamma
+ * correction bug). Fix this by dropping the gamma correction in
+ * this case and doing it in the palette; this will result in
+ * duplicate palette entries, but that's better than the
+ * alternative of double gamma correction.
+ */
+ if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ png_ptr->num_trans > 0) &&
+ png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0)
+ {
+ cmap_entries = make_gray_file_colormap(display);
+ data_encoding = P_FILE;
+ }
+
+ else
+ cmap_entries = make_gray_colormap(display);
+
+ /* But if the input has alpha or transparency it must be removed
+ */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ png_ptr->num_trans > 0)
+ {
+ png_color_16 c;
+ png_uint_32 gray = back_g;
+
+ /* We need to ensure that the application background exists in
+ * the colormap and that completely transparent pixels map to
+ * it. Achieve this simply by ensuring that the entry
+ * selected for the background really is the background color.
+ */
+ if (data_encoding == P_FILE) /* from the fixup above */
+ {
+ /* The app supplied a gray which is in output_encoding, we
+ * need to convert it to a value of the input (P_FILE)
+ * encoding then set this palette entry to the required
+ * output encoding.
+ */
+ if (output_encoding == P_sRGB)
+ gray = png_sRGB_table[gray]; /* now P_LINEAR */
+
+ gray = PNG_DIV257(png_gamma_16bit_correct(gray,
+ png_ptr->colorspace.gamma)); /* now P_FILE */
+
+ /* And make sure the corresponding palette entry contains
+ * exactly the required sRGB value.
+ */
+ png_create_colormap_entry(display, gray, back_g, back_g,
+ back_g, 0/*unused*/, output_encoding);
+ }
+
+ else if (output_encoding == P_LINEAR)
+ {
+ gray = PNG_sRGB_FROM_LINEAR(gray * 255);
+
+ /* And make sure the corresponding palette entry matches.
+ */
+ png_create_colormap_entry(display, gray, back_g, back_g,
+ back_g, 0/*unused*/, P_LINEAR);
+ }
+
+ /* The background passed to libpng, however, must be the
+ * output (normally sRGB) value.
+ */
+ c.index = 0; /*unused*/
+ c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
+
+ /* NOTE: the following is apparently a bug in libpng. Without
+ * it the transparent color recognition in
+ * png_set_background_fixed seems to go wrong.
+ */
+ expand_tRNS = 1;
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+ }
+
+ output_processing = PNG_CMAP_NONE;
+ }
+ }
+
+ else /* output is color */
+ {
+ /* We could use png_quantize here so long as there is no transparent
+ * color or alpha; png_quantize ignores alpha. Easier overall just
+ * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube.
+ * Consequently we always want libpng to produce sRGB data.
+ */
+ data_encoding = P_sRGB;
+
+ /* Is there any transparency or alpha? */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ png_ptr->num_trans > 0)
+ {
+ /* Is there alpha in the output too? If so all four channels are
+ * processed into a special RGB cube with alpha support.
+ */
+ if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ png_uint_32 r;
+
+ if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
+ png_error(png_ptr, "rgb+alpha color-map: too few entries");
+
+ cmap_entries = make_rgb_colormap(display);
+
+ /* Add a transparent entry. */
+ png_create_colormap_entry(display, cmap_entries, 255, 255,
+ 255, 0, P_sRGB);
+
+ /* This is stored as the background index for the processing
+ * algorithm.
+ */
+ background_index = cmap_entries++;
+
+ /* Add 27 r,g,b entries each with alpha 0.5. */
+ for (r=0; r<256; r = (r << 1) | 0x7f)
+ {
+ png_uint_32 g;
+
+ for (g=0; g<256; g = (g << 1) | 0x7f)
+ {
+ png_uint_32 b;
+
+ /* This generates components with the values 0, 127 and
+ * 255
+ */
+ for (b=0; b<256; b = (b << 1) | 0x7f)
+ png_create_colormap_entry(display, cmap_entries++,
+ r, g, b, 128, P_sRGB);
+ }
+ }
+
+ expand_tRNS = 1;
+ output_processing = PNG_CMAP_RGB_ALPHA;
+ }
+
+ else
+ {
+ /* Alpha/transparency must be removed. The background must
+ * exist in the color map (achieved by setting adding it after
+ * the 666 color-map). If the standard processing code will
+ * pick up this entry automatically that's all that is
+ * required; libpng can be called to do the background
+ * processing.
+ */
+ unsigned int sample_size =
+ PNG_IMAGE_SAMPLE_SIZE(output_format);
+ png_uint_32 r, g, b; /* sRGB background */
+
+ if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
+ png_error(png_ptr, "rgb-alpha color-map: too few entries");
+
+ cmap_entries = make_rgb_colormap(display);
+
+ png_create_colormap_entry(display, cmap_entries, back_r,
+ back_g, back_b, 0/*unused*/, output_encoding);
+
+ if (output_encoding == P_LINEAR)
+ {
+ r = PNG_sRGB_FROM_LINEAR(back_r * 255);
+ g = PNG_sRGB_FROM_LINEAR(back_g * 255);
+ b = PNG_sRGB_FROM_LINEAR(back_b * 255);
+ }
+
+ else
+ {
+ r = back_r;
+ g = back_g;
+ b = back_g;
+ }
+
+ /* Compare the newly-created color-map entry with the one the
+ * PNG_CMAP_RGB algorithm will use. If the two entries don't
+ * match, add the new one and set this as the background
+ * index.
+ */
+ if (memcmp((png_const_bytep)display->colormap +
+ sample_size * cmap_entries,
+ (png_const_bytep)display->colormap +
+ sample_size * PNG_RGB_INDEX(r,g,b),
+ sample_size) != 0)
+ {
+ /* The background color must be added. */
+ background_index = cmap_entries++;
+
+ /* Add 27 r,g,b entries each with created by composing with
+ * the background at alpha 0.5.
+ */
+ for (r=0; r<256; r = (r << 1) | 0x7f)
+ {
+ for (g=0; g<256; g = (g << 1) | 0x7f)
+ {
+ /* This generates components with the values 0, 127
+ * and 255
+ */
+ for (b=0; b<256; b = (b << 1) | 0x7f)
+ png_create_colormap_entry(display, cmap_entries++,
+ png_colormap_compose(display, r, P_sRGB, 128,
+ back_r, output_encoding),
+ png_colormap_compose(display, g, P_sRGB, 128,
+ back_g, output_encoding),
+ png_colormap_compose(display, b, P_sRGB, 128,
+ back_b, output_encoding),
+ 0/*unused*/, output_encoding);
+ }
+ }
+
+ expand_tRNS = 1;
+ output_processing = PNG_CMAP_RGB_ALPHA;
+ }
+
+ else /* background color is in the standard color-map */
+ {
+ png_color_16 c;
+
+ c.index = 0; /*unused*/
+ c.red = (png_uint_16)back_r;
+ c.gray = c.green = (png_uint_16)back_g;
+ c.blue = (png_uint_16)back_b;
+
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+
+ output_processing = PNG_CMAP_RGB;
+ }
+ }
+ }
+
+ else /* no alpha or transparency in the input */
+ {
+ /* Alpha in the output is irrelevant, simply map the opaque input
+ * pixels to the 6x6x6 color-map.
+ */
+ if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "rgb color-map: too few entries");
+
+ cmap_entries = make_rgb_colormap(display);
+ output_processing = PNG_CMAP_RGB;
+ }
+ }
+ break;
+
+ case PNG_COLOR_TYPE_PALETTE:
+ /* It's already got a color-map. It may be necessary to eliminate the
+ * tRNS entries though.
+ */
+ {
+ unsigned int num_trans = png_ptr->num_trans;
+ png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
+ png_const_colorp colormap = png_ptr->palette;
+ const int do_background = trans != NULL &&
+ (output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
+ unsigned int i;
+
+ /* Just in case: */
+ if (trans == NULL)
+ num_trans = 0;
+
+ output_processing = PNG_CMAP_NONE;
+ data_encoding = P_FILE; /* Don't change from color-map indices */
+ cmap_entries = png_ptr->num_palette;
+ if (cmap_entries > 256)
+ cmap_entries = 256;
+
+ if (cmap_entries > image->colormap_entries)
+ png_error(png_ptr, "palette color-map: too few entries");
+
+ for (i=0; i < cmap_entries; ++i)
+ {
+ if (do_background != 0 && i < num_trans && trans[i] < 255)
+ {
+ if (trans[i] == 0)
+ png_create_colormap_entry(display, i, back_r, back_g,
+ back_b, 0, output_encoding);
+
+ else
+ {
+ /* Must compose the PNG file color in the color-map entry
+ * on the sRGB color in 'back'.
+ */
+ png_create_colormap_entry(display, i,
+ png_colormap_compose(display, colormap[i].red, P_FILE,
+ trans[i], back_r, output_encoding),
+ png_colormap_compose(display, colormap[i].green, P_FILE,
+ trans[i], back_g, output_encoding),
+ png_colormap_compose(display, colormap[i].blue, P_FILE,
+ trans[i], back_b, output_encoding),
+ output_encoding == P_LINEAR ? trans[i] * 257U :
+ trans[i],
+ output_encoding);
+ }
+ }
+
+ else
+ png_create_colormap_entry(display, i, colormap[i].red,
+ colormap[i].green, colormap[i].blue,
+ i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);
+ }
+
+ /* The PNG data may have indices packed in fewer than 8 bits, it
+ * must be expanded if so.
+ */
+ if (png_ptr->bit_depth < 8)
+ png_set_packing(png_ptr);
+ }
+ break;
+
+ default:
+ png_error(png_ptr, "invalid PNG color type");
+ /*NOT REACHED*/
+ }
+
+ /* Now deal with the output processing */
+ if (expand_tRNS != 0 && png_ptr->num_trans > 0 &&
+ (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0)
+ png_set_tRNS_to_alpha(png_ptr);
+
+ switch (data_encoding)
+ {
+ case P_sRGB:
+ /* Change to 8-bit sRGB */
+ png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
+ /* FALL THROUGH */
+
+ case P_FILE:
+ if (png_ptr->bit_depth > 8)
+ png_set_scale_16(png_ptr);
+ break;
+
+#ifdef __GNUC__
+ default:
+ png_error(png_ptr, "bad data option (internal error)");
+#endif
+ }
+
+ if (cmap_entries > 256 || cmap_entries > image->colormap_entries)
+ png_error(png_ptr, "color map overflow (BAD internal error)");
+
+ image->colormap_entries = cmap_entries;
+
+ /* Double check using the recorded background index */
+ switch (output_processing)
+ {
+ case PNG_CMAP_NONE:
+ if (background_index != PNG_CMAP_NONE_BACKGROUND)
+ goto bad_background;
+ break;
+
+ case PNG_CMAP_GA:
+ if (background_index != PNG_CMAP_GA_BACKGROUND)
+ goto bad_background;
+ break;
+
+ case PNG_CMAP_TRANS:
+ if (background_index >= cmap_entries ||
+ background_index != PNG_CMAP_TRANS_BACKGROUND)
+ goto bad_background;
+ break;
+
+ case PNG_CMAP_RGB:
+ if (background_index != PNG_CMAP_RGB_BACKGROUND)
+ goto bad_background;
+ break;
+
+ case PNG_CMAP_RGB_ALPHA:
+ if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND)
+ goto bad_background;
+ break;
+
+ default:
+ png_error(png_ptr, "bad processing option (internal error)");
+
+ bad_background:
+ png_error(png_ptr, "bad background index (internal error)");
+ }
+
+ display->colormap_processing = output_processing;
+
+ return 1/*ok*/;
+}
+
+/* The final part of the color-map read called from png_image_finish_read. */
+static int
+png_image_read_and_map(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ int passes;
+
+ /* Called when the libpng data must be transformed into the color-mapped
+ * form. There is a local row buffer in display->local and this routine must
+ * do the interlace handling.
+ */
+ switch (png_ptr->interlaced)
+ {
+ case PNG_INTERLACE_NONE:
+ passes = 1;
+ break;
+
+ case PNG_INTERLACE_ADAM7:
+ passes = PNG_INTERLACE_ADAM7_PASSES;
+ break;
+
+ default:
+ png_error(png_ptr, "unknown interlace type");
+ }
+
+ {
+ png_uint_32 height = image->height;
+ png_uint_32 width = image->width;
+ int proc = display->colormap_processing;
+ png_bytep first_row = png_voidcast(png_bytep, display->first_row);
+ ptrdiff_t step_row = display->row_bytes;
+ int pass;
+
+ for (pass = 0; pass < passes; ++pass)
+ {
+ unsigned int startx, stepx, stepy;
+ png_uint_32 y;
+
+ if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
+ {
+ /* The row may be empty for a short image: */
+ if (PNG_PASS_COLS(width, pass) == 0)
+ continue;
+
+ startx = PNG_PASS_START_COL(pass);
+ stepx = PNG_PASS_COL_OFFSET(pass);
+ y = PNG_PASS_START_ROW(pass);
+ stepy = PNG_PASS_ROW_OFFSET(pass);
+ }
+
+ else
+ {
+ y = 0;
+ startx = 0;
+ stepx = stepy = 1;
+ }
+
+ for (; y<height; y += stepy)
+ {
+ png_bytep inrow = png_voidcast(png_bytep, display->local_row);
+ png_bytep outrow = first_row + y * step_row;
+ png_const_bytep end_row = outrow + width;
+
+ /* Read read the libpng data into the temporary buffer. */
+ png_read_row(png_ptr, inrow, NULL);
+
+ /* Now process the row according to the processing option, note
+ * that the caller verifies that the format of the libpng output
+ * data is as required.
+ */
+ outrow += startx;
+ switch (proc)
+ {
+ case PNG_CMAP_GA:
+ for (; outrow < end_row; outrow += stepx)
+ {
+ /* The data is always in the PNG order */
+ unsigned int gray = *inrow++;
+ unsigned int alpha = *inrow++;
+ unsigned int entry;
+
+ /* NOTE: this code is copied as a comment in
+ * make_ga_colormap above. Please update the
+ * comment if you change this code!
+ */
+ if (alpha > 229) /* opaque */
+ {
+ entry = (231 * gray + 128) >> 8;
+ }
+ else if (alpha < 26) /* transparent */
+ {
+ entry = 231;
+ }
+ else /* partially opaque */
+ {
+ entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray);
+ }
+
+ *outrow = (png_byte)entry;
+ }
+ break;
+
+ case PNG_CMAP_TRANS:
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_byte gray = *inrow++;
+ png_byte alpha = *inrow++;
+
+ if (alpha == 0)
+ *outrow = PNG_CMAP_TRANS_BACKGROUND;
+
+ else if (gray != PNG_CMAP_TRANS_BACKGROUND)
+ *outrow = gray;
+
+ else
+ *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1);
+ }
+ break;
+
+ case PNG_CMAP_RGB:
+ for (; outrow < end_row; outrow += stepx)
+ {
+ *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]);
+ inrow += 3;
+ }
+ break;
+
+ case PNG_CMAP_RGB_ALPHA:
+ for (; outrow < end_row; outrow += stepx)
+ {
+ unsigned int alpha = inrow[3];
+
+ /* Because the alpha entries only hold alpha==0.5 values
+ * split the processing at alpha==0.25 (64) and 0.75
+ * (196).
+ */
+
+ if (alpha >= 196)
+ *outrow = PNG_RGB_INDEX(inrow[0], inrow[1],
+ inrow[2]);
+
+ else if (alpha < 64)
+ *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND;
+
+ else
+ {
+ /* Likewise there are three entries for each of r, g
+ * and b. We could select the entry by popcount on
+ * the top two bits on those architectures that
+ * support it, this is what the code below does,
+ * crudely.
+ */
+ unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1;
+
+ /* Here are how the values map:
+ *
+ * 0x00 .. 0x3f -> 0
+ * 0x40 .. 0xbf -> 1
+ * 0xc0 .. 0xff -> 2
+ *
+ * So, as above with the explicit alpha checks, the
+ * breakpoints are at 64 and 196.
+ */
+ if (inrow[0] & 0x80) back_i += 9; /* red */
+ if (inrow[0] & 0x40) back_i += 9;
+ if (inrow[0] & 0x80) back_i += 3; /* green */
+ if (inrow[0] & 0x40) back_i += 3;
+ if (inrow[0] & 0x80) back_i += 1; /* blue */
+ if (inrow[0] & 0x40) back_i += 1;
+
+ *outrow = (png_byte)back_i;
+ }
+
+ inrow += 4;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int
+png_image_read_colormapped(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_controlp control = image->opaque;
+ png_structrp png_ptr = control->png_ptr;
+ png_inforp info_ptr = control->info_ptr;
+
+ int passes = 0; /* As a flag */
+
+ PNG_SKIP_CHUNKS(png_ptr);
+
+ /* Update the 'info' structure and make sure the result is as required; first
+ * make sure to turn on the interlace handling if it will be required
+ * (because it can't be turned on *after* the call to png_read_update_info!)
+ */
+ if (display->colormap_processing == PNG_CMAP_NONE)
+ passes = png_set_interlace_handling(png_ptr);
+
+ png_read_update_info(png_ptr, info_ptr);
+
+ /* The expected output can be deduced from the colormap_processing option. */
+ switch (display->colormap_processing)
+ {
+ case PNG_CMAP_NONE:
+ /* Output must be one channel and one byte per pixel, the output
+ * encoding can be anything.
+ */
+ if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
+ info_ptr->color_type == PNG_COLOR_TYPE_GRAY) &&
+ info_ptr->bit_depth == 8)
+ break;
+
+ goto bad_output;
+
+ case PNG_CMAP_TRANS:
+ case PNG_CMAP_GA:
+ /* Output must be two channels and the 'G' one must be sRGB, the latter
+ * can be checked with an exact number because it should have been set
+ * to this number above!
+ */
+ if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
+ info_ptr->bit_depth == 8 &&
+ png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
+ image->colormap_entries == 256)
+ break;
+
+ goto bad_output;
+
+ case PNG_CMAP_RGB:
+ /* Output must be 8-bit sRGB encoded RGB */
+ if (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
+ info_ptr->bit_depth == 8 &&
+ png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
+ image->colormap_entries == 216)
+ break;
+
+ goto bad_output;
+
+ case PNG_CMAP_RGB_ALPHA:
+ /* Output must be 8-bit sRGB encoded RGBA */
+ if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
+ info_ptr->bit_depth == 8 &&
+ png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
+ image->colormap_entries == 244 /* 216 + 1 + 27 */)
+ break;
+
+ /* goto bad_output; */
+ /* FALL THROUGH */
+
+ default:
+ bad_output:
+ png_error(png_ptr, "bad color-map processing (internal error)");
+ }
+
+ /* Now read the rows. Do this here if it is possible to read directly into
+ * the output buffer, otherwise allocate a local row buffer of the maximum
+ * size libpng requires and call the relevant processing routine safely.
+ */
+ {
+ png_voidp first_row = display->buffer;
+ ptrdiff_t row_bytes = display->row_stride;
+
+ /* The following expression is designed to work correctly whether it gives
+ * a signed or an unsigned result.
+ */
+ if (row_bytes < 0)
+ {
+ char *ptr = png_voidcast(char*, first_row);
+ ptr += (image->height-1) * (-row_bytes);
+ first_row = png_voidcast(png_voidp, ptr);
+ }
+
+ display->first_row = first_row;
+ display->row_bytes = row_bytes;
+ }
+
+ if (passes == 0)
+ {
+ int result;
+ png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+
+ display->local_row = row;
+ result = png_safe_execute(image, png_image_read_and_map, display);
+ display->local_row = NULL;
+ png_free(png_ptr, row);
+
+ return result;
+ }
+
+ else
+ {
+ png_alloc_size_t row_bytes = display->row_bytes;
+
+ while (--passes >= 0)
+ {
+ png_uint_32 y = image->height;
+ png_bytep row = png_voidcast(png_bytep, display->first_row);
+
+ while (y-- > 0)
+ {
+ png_read_row(png_ptr, row, NULL);
+ row += row_bytes;
+ }
+ }
+
+ return 1;
+ }
+}
+
+/* Just the row reading part of png_image_read. */
+static int
+png_image_read_composite(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ int passes;
+
+ switch (png_ptr->interlaced)
+ {
+ case PNG_INTERLACE_NONE:
+ passes = 1;
+ break;
+
+ case PNG_INTERLACE_ADAM7:
+ passes = PNG_INTERLACE_ADAM7_PASSES;
+ break;
+
+ default:
+ png_error(png_ptr, "unknown interlace type");
+ }
+
+ {
+ png_uint_32 height = image->height;
+ png_uint_32 width = image->width;
+ ptrdiff_t step_row = display->row_bytes;
+ unsigned int channels =
+ (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+ int pass;
+
+ for (pass = 0; pass < passes; ++pass)
+ {
+ unsigned int startx, stepx, stepy;
+ png_uint_32 y;
+
+ if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
+ {
+ /* The row may be empty for a short image: */
+ if (PNG_PASS_COLS(width, pass) == 0)
+ continue;
+
+ startx = PNG_PASS_START_COL(pass) * channels;
+ stepx = PNG_PASS_COL_OFFSET(pass) * channels;
+ y = PNG_PASS_START_ROW(pass);
+ stepy = PNG_PASS_ROW_OFFSET(pass);
+ }
+
+ else
+ {
+ y = 0;
+ startx = 0;
+ stepx = channels;
+ stepy = 1;
+ }
+
+ for (; y<height; y += stepy)
+ {
+ png_bytep inrow = png_voidcast(png_bytep, display->local_row);
+ png_bytep outrow;
+ png_const_bytep end_row;
+
+ /* Read the row, which is packed: */
+ png_read_row(png_ptr, inrow, NULL);
+
+ outrow = png_voidcast(png_bytep, display->first_row);
+ outrow += y * step_row;
+ end_row = outrow + width * channels;
+
+ /* Now do the composition on each pixel in this row. */
+ outrow += startx;
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_byte alpha = inrow[channels];
+
+ if (alpha > 0) /* else no change to the output */
+ {
+ unsigned int c;
+
+ for (c=0; c<channels; ++c)
+ {
+ png_uint_32 component = inrow[c];
+
+ if (alpha < 255) /* else just use component */
+ {
+ /* This is PNG_OPTIMIZED_ALPHA, the component value
+ * is a linear 8-bit value. Combine this with the
+ * current outrow[c] value which is sRGB encoded.
+ * Arithmetic here is 16-bits to preserve the output
+ * values correctly.
+ */
+ component *= 257*255; /* =65535 */
+ component += (255-alpha)*png_sRGB_table[outrow[c]];
+
+ /* So 'component' is scaled by 255*65535 and is
+ * therefore appropriate for the sRGB to linear
+ * conversion table.
+ */
+ component = PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ outrow[c] = (png_byte)component;
+ }
+ }
+
+ inrow += channels+1; /* components and alpha channel */
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+/* The do_local_background case; called when all the following transforms are to
+ * be done:
+ *
+ * PNG_RGB_TO_GRAY
+ * PNG_COMPOSITE
+ * PNG_GAMMA
+ *
+ * This is a work-around for the fact that both the PNG_RGB_TO_GRAY and
+ * PNG_COMPOSITE code performs gamma correction, so we get double gamma
+ * correction. The fix-up is to prevent the PNG_COMPOSITE operation from
+ * happening inside libpng, so this routine sees an 8 or 16-bit gray+alpha
+ * row and handles the removal or pre-multiplication of the alpha channel.
+ */
+static int
+png_image_read_background(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_inforp info_ptr = image->opaque->info_ptr;
+ png_uint_32 height = image->height;
+ png_uint_32 width = image->width;
+ int pass, passes;
+
+ /* Double check the convoluted logic below. We expect to get here with
+ * libpng doing rgb to gray and gamma correction but background processing
+ * left to the png_image_read_background function. The rows libpng produce
+ * might be 8 or 16-bit but should always have two channels; gray plus alpha.
+ */
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
+ png_error(png_ptr, "lost rgb to gray");
+
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
+ png_error(png_ptr, "unexpected compose");
+
+ if (png_get_channels(png_ptr, info_ptr) != 2)
+ png_error(png_ptr, "lost/gained channels");
+
+ /* Expect the 8-bit case to always remove the alpha channel */
+ if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 &&
+ (image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ png_error(png_ptr, "unexpected 8-bit transformation");
+
+ switch (png_ptr->interlaced)
+ {
+ case PNG_INTERLACE_NONE:
+ passes = 1;
+ break;
+
+ case PNG_INTERLACE_ADAM7:
+ passes = PNG_INTERLACE_ADAM7_PASSES;
+ break;
+
+ default:
+ png_error(png_ptr, "unknown interlace type");
+ }
+
+ /* Use direct access to info_ptr here because otherwise the simplified API
+ * would require PNG_EASY_ACCESS_SUPPORTED (just for this.) Note this is
+ * checking the value after libpng expansions, not the original value in the
+ * PNG.
+ */
+ switch (info_ptr->bit_depth)
+ {
+ case 8:
+ /* 8-bit sRGB gray values with an alpha channel; the alpha channel is
+ * to be removed by composing on a background: either the row if
+ * display->background is NULL or display->background->green if not.
+ * Unlike the code above ALPHA_OPTIMIZED has *not* been done.
+ */
+ {
+ png_bytep first_row = png_voidcast(png_bytep, display->first_row);
+ ptrdiff_t step_row = display->row_bytes;
+
+ for (pass = 0; pass < passes; ++pass)
+ {
+ png_bytep row = png_voidcast(png_bytep,
+ display->first_row);
+ unsigned int startx, stepx, stepy;
+ png_uint_32 y;
+
+ if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
+ {
+ /* The row may be empty for a short image: */
+ if (PNG_PASS_COLS(width, pass) == 0)
+ continue;
+
+ startx = PNG_PASS_START_COL(pass);
+ stepx = PNG_PASS_COL_OFFSET(pass);
+ y = PNG_PASS_START_ROW(pass);
+ stepy = PNG_PASS_ROW_OFFSET(pass);
+ }
+
+ else
+ {
+ y = 0;
+ startx = 0;
+ stepx = stepy = 1;
+ }
+
+ if (display->background == NULL)
+ {
+ for (; y<height; y += stepy)
+ {
+ png_bytep inrow = png_voidcast(png_bytep,
+ display->local_row);
+ png_bytep outrow = first_row + y * step_row;
+ png_const_bytep end_row = outrow + width;
+
+ /* Read the row, which is packed: */
+ png_read_row(png_ptr, inrow, NULL);
+
+ /* Now do the composition on each pixel in this row. */
+ outrow += startx;
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_byte alpha = inrow[1];
+
+ if (alpha > 0) /* else no change to the output */
+ {
+ png_uint_32 component = inrow[0];
+
+ if (alpha < 255) /* else just use component */
+ {
+ /* Since PNG_OPTIMIZED_ALPHA was not set it is
+ * necessary to invert the sRGB transfer
+ * function and multiply the alpha out.
+ */
+ component = png_sRGB_table[component] * alpha;
+ component += png_sRGB_table[outrow[0]] *
+ (255-alpha);
+ component = PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ outrow[0] = (png_byte)component;
+ }
+
+ inrow += 2; /* gray and alpha channel */
+ }
+ }
+ }
+
+ else /* constant background value */
+ {
+ png_byte background8 = display->background->green;
+ png_uint_16 background = png_sRGB_table[background8];
+
+ for (; y<height; y += stepy)
+ {
+ png_bytep inrow = png_voidcast(png_bytep,
+ display->local_row);
+ png_bytep outrow = first_row + y * step_row;
+ png_const_bytep end_row = outrow + width;
+
+ /* Read the row, which is packed: */
+ png_read_row(png_ptr, inrow, NULL);
+
+ /* Now do the composition on each pixel in this row. */
+ outrow += startx;
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_byte alpha = inrow[1];
+
+ if (alpha > 0) /* else use background */
+ {
+ png_uint_32 component = inrow[0];
+
+ if (alpha < 255) /* else just use component */
+ {
+ component = png_sRGB_table[component] * alpha;
+ component += background * (255-alpha);
+ component = PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ outrow[0] = (png_byte)component;
+ }
+
+ else
+ outrow[0] = background8;
+
+ inrow += 2; /* gray and alpha channel */
+ }
+
+ row += display->row_bytes;
+ }
+ }
+ }
+ }
+ break;
+
+ case 16:
+ /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must
+ * still be done and, maybe, the alpha channel removed. This code also
+ * handles the alpha-first option.
+ */
+ {
+ png_uint_16p first_row = png_voidcast(png_uint_16p,
+ display->first_row);
+ /* The division by two is safe because the caller passed in a
+ * stride which was multiplied by 2 (below) to get row_bytes.
+ */
+ ptrdiff_t step_row = display->row_bytes / 2;
+ int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
+ unsigned int outchannels = 1+preserve_alpha;
+ int swap_alpha = 0;
+
+# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
+ if (preserve_alpha != 0 &&
+ (image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ swap_alpha = 1;
+# endif
+
+ for (pass = 0; pass < passes; ++pass)
+ {
+ unsigned int startx, stepx, stepy;
+ png_uint_32 y;
+
+ /* The 'x' start and step are adjusted to output components here.
+ */
+ if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
+ {
+ /* The row may be empty for a short image: */
+ if (PNG_PASS_COLS(width, pass) == 0)
+ continue;
+
+ startx = PNG_PASS_START_COL(pass) * outchannels;
+ stepx = PNG_PASS_COL_OFFSET(pass) * outchannels;
+ y = PNG_PASS_START_ROW(pass);
+ stepy = PNG_PASS_ROW_OFFSET(pass);
+ }
+
+ else
+ {
+ y = 0;
+ startx = 0;
+ stepx = outchannels;
+ stepy = 1;
+ }
+
+ for (; y<height; y += stepy)
+ {
+ png_const_uint_16p inrow;
+ png_uint_16p outrow = first_row + y*step_row;
+ png_uint_16p end_row = outrow + width * outchannels;
+
+ /* Read the row, which is packed: */
+ png_read_row(png_ptr, png_voidcast(png_bytep,
+ display->local_row), NULL);
+ inrow = png_voidcast(png_const_uint_16p, display->local_row);
+
+ /* Now do the pre-multiplication on each pixel in this row.
+ */
+ outrow += startx;
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_uint_32 component = inrow[0];
+ png_uint_16 alpha = inrow[1];
+
+ if (alpha > 0) /* else 0 */
+ {
+ if (alpha < 65535) /* else just use component */
+ {
+ component *= alpha;
+ component += 32767;
+ component /= 65535;
+ }
+ }
+
+ else
+ component = 0;
+
+ outrow[swap_alpha] = (png_uint_16)component;
+ if (preserve_alpha != 0)
+ outrow[1 ^ swap_alpha] = alpha;
+
+ inrow += 2; /* components and alpha channel */
+ }
+ }
+ }
+ }
+ break;
+
+#ifdef __GNUC__
+ default:
+ png_error(png_ptr, "unexpected bit depth");
+#endif
+ }
+
+ return 1;
+}
+
+/* The guts of png_image_finish_read as a png_safe_execute callback. */
+static int
+png_image_read_direct(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_inforp info_ptr = image->opaque->info_ptr;
+
+ png_uint_32 format = image->format;
+ int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
+ int do_local_compose = 0;
+ int do_local_background = 0; /* to avoid double gamma correction bug */
+ int passes = 0;
+
+ /* Add transforms to ensure the correct output format is produced then check
+ * that the required implementation support is there. Always expand; always
+ * need 8 bits minimum, no palette and expanded tRNS.
+ */
+ png_set_expand(png_ptr);
+
+ /* Now check the format to see if it was modified. */
+ {
+ png_uint_32 base_format = png_image_format(png_ptr) &
+ ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */;
+ png_uint_32 change = format ^ base_format;
+ png_fixed_point output_gamma;
+ int mode; /* alpha mode */
+
+ /* Do this first so that we have a record if rgb to gray is happening. */
+ if ((change & PNG_FORMAT_FLAG_COLOR) != 0)
+ {
+ /* gray<->color transformation required. */
+ if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
+ png_set_gray_to_rgb(png_ptr);
+
+ else
+ {
+ /* libpng can't do both rgb to gray and
+ * background/pre-multiplication if there is also significant gamma
+ * correction, because both operations require linear colors and
+ * the code only supports one transform doing the gamma correction.
+ * Handle this by doing the pre-multiplication or background
+ * operation in this code, if necessary.
+ *
+ * TODO: fix this by rewriting pngrtran.c (!)
+ *
+ * For the moment (given that fixing this in pngrtran.c is an
+ * enormous change) 'do_local_background' is used to indicate that
+ * the problem exists.
+ */
+ if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ do_local_background = 1/*maybe*/;
+
+ png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
+ PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
+ }
+
+ change &= ~PNG_FORMAT_FLAG_COLOR;
+ }
+
+ /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
+ */
+ {
+ png_fixed_point input_gamma_default;
+
+ if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 &&
+ (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
+ input_gamma_default = PNG_GAMMA_LINEAR;
+ else
+ input_gamma_default = PNG_DEFAULT_sRGB;
+
+ /* Call png_set_alpha_mode to set the default for the input gamma; the
+ * output gamma is set by a second call below.
+ */
+ png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default);
+ }
+
+ if (linear != 0)
+ {
+ /* If there *is* an alpha channel in the input it must be multiplied
+ * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG.
+ */
+ if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ mode = PNG_ALPHA_STANDARD; /* associated alpha */
+
+ else
+ mode = PNG_ALPHA_PNG;
+
+ output_gamma = PNG_GAMMA_LINEAR;
+ }
+
+ else
+ {
+ mode = PNG_ALPHA_PNG;
+ output_gamma = PNG_DEFAULT_sRGB;
+ }
+
+ /* If 'do_local_background' is set check for the presence of gamma
+ * correction; this is part of the work-round for the libpng bug
+ * described above.
+ *
+ * TODO: fix libpng and remove this.
+ */
+ if (do_local_background != 0)
+ {
+ png_fixed_point gtest;
+
+ /* This is 'png_gamma_threshold' from pngrtran.c; the test used for
+ * gamma correction, the screen gamma hasn't been set on png_struct
+ * yet; it's set below. png_struct::gamma, however, is set to the
+ * final value.
+ */
+ if (png_muldiv(&gtest, output_gamma, png_ptr->colorspace.gamma,
+ PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)
+ do_local_background = 0;
+
+ else if (mode == PNG_ALPHA_STANDARD)
+ {
+ do_local_background = 2/*required*/;
+ mode = PNG_ALPHA_PNG; /* prevent libpng doing it */
+ }
+
+ /* else leave as 1 for the checks below */
+ }
+
+ /* If the bit-depth changes then handle that here. */
+ if ((change & PNG_FORMAT_FLAG_LINEAR) != 0)
+ {
+ if (linear != 0 /*16-bit output*/)
+ png_set_expand_16(png_ptr);
+
+ else /* 8-bit output */
+ png_set_scale_16(png_ptr);
+
+ change &= ~PNG_FORMAT_FLAG_LINEAR;
+ }
+
+ /* Now the background/alpha channel changes. */
+ if ((change & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ /* Removing an alpha channel requires composition for the 8-bit
+ * formats; for the 16-bit it is already done, above, by the
+ * pre-multiplication and the channel just needs to be stripped.
+ */
+ if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ /* If RGB->gray is happening the alpha channel must be left and the
+ * operation completed locally.
+ *
+ * TODO: fix libpng and remove this.
+ */
+ if (do_local_background != 0)
+ do_local_background = 2/*required*/;
+
+ /* 16-bit output: just remove the channel */
+ else if (linear != 0) /* compose on black (well, pre-multiply) */
+ png_set_strip_alpha(png_ptr);
+
+ /* 8-bit output: do an appropriate compose */
+ else if (display->background != NULL)
+ {
+ png_color_16 c;
+
+ c.index = 0; /*unused*/
+ c.red = display->background->red;
+ c.green = display->background->green;
+ c.blue = display->background->blue;
+ c.gray = display->background->green;
+
+ /* This is always an 8-bit sRGB value, using the 'green' channel
+ * for gray is much better than calculating the luminance here;
+ * we can get off-by-one errors in that calculation relative to
+ * the app expectations and that will show up in transparent
+ * pixels.
+ */
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+ }
+
+ else /* compose on row: implemented below. */
+ {
+ do_local_compose = 1;
+ /* This leaves the alpha channel in the output, so it has to be
+ * removed by the code below. Set the encoding to the 'OPTIMIZE'
+ * one so the code only has to hack on the pixels that require
+ * composition.
+ */
+ mode = PNG_ALPHA_OPTIMIZED;
+ }
+ }
+
+ else /* output needs an alpha channel */
+ {
+ /* This is tricky because it happens before the swap operation has
+ * been accomplished; however, the swap does *not* swap the added
+ * alpha channel (weird API), so it must be added in the correct
+ * place.
+ */
+ png_uint_32 filler; /* opaque filler */
+ int where;
+
+ if (linear != 0)
+ filler = 65535;
+
+ else
+ filler = 255;
+
+# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ where = PNG_FILLER_BEFORE;
+ change &= ~PNG_FORMAT_FLAG_AFIRST;
+ }
+
+ else
+# endif
+ where = PNG_FILLER_AFTER;
+
+ png_set_add_alpha(png_ptr, filler, where);
+ }
+
+ /* This stops the (irrelevant) call to swap_alpha below. */
+ change &= ~PNG_FORMAT_FLAG_ALPHA;
+ }
+
+ /* Now set the alpha mode correctly; this is always done, even if there is
+ * no alpha channel in either the input or the output because it correctly
+ * sets the output gamma.
+ */
+ png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);
+
+# ifdef PNG_FORMAT_BGR_SUPPORTED
+ if ((change & PNG_FORMAT_FLAG_BGR) != 0)
+ {
+ /* Check only the output format; PNG is never BGR; don't do this if
+ * the output is gray, but fix up the 'format' value in that case.
+ */
+ if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
+ png_set_bgr(png_ptr);
+
+ else
+ format &= ~PNG_FORMAT_FLAG_BGR;
+
+ change &= ~PNG_FORMAT_FLAG_BGR;
+ }
+# endif
+
+# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ if ((change & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ /* Only relevant if there is an alpha channel - it's particularly
+ * important to handle this correctly because do_local_compose may
+ * be set above and then libpng will keep the alpha channel for this
+ * code to remove.
+ */
+ if ((format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ /* Disable this if doing a local background,
+ * TODO: remove this when local background is no longer required.
+ */
+ if (do_local_background != 2)
+ png_set_swap_alpha(png_ptr);
+ }
+
+ else
+ format &= ~PNG_FORMAT_FLAG_AFIRST;
+
+ change &= ~PNG_FORMAT_FLAG_AFIRST;
+ }
+# endif
+
+ /* If the *output* is 16-bit then we need to check for a byte-swap on this
+ * architecture.
+ */
+ if (linear != 0)
+ {
+ PNG_CONST png_uint_16 le = 0x0001;
+
+ if ((*(png_const_bytep) & le) != 0)
+ png_set_swap(png_ptr);
+ }
+
+ /* If change is not now 0 some transformation is missing - error out. */
+ if (change != 0)
+ png_error(png_ptr, "png_read_image: unsupported transformation");
+ }
+
+ PNG_SKIP_CHUNKS(png_ptr);
+
+ /* Update the 'info' structure and make sure the result is as required; first
+ * make sure to turn on the interlace handling if it will be required
+ * (because it can't be turned on *after* the call to png_read_update_info!)
+ *
+ * TODO: remove the do_local_background fixup below.
+ */
+ if (do_local_compose == 0 && do_local_background != 2)
+ passes = png_set_interlace_handling(png_ptr);
+
+ png_read_update_info(png_ptr, info_ptr);
+
+ {
+ png_uint_32 info_format = 0;
+
+ if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
+ info_format |= PNG_FORMAT_FLAG_COLOR;
+
+ if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
+ {
+ /* do_local_compose removes this channel below. */
+ if (do_local_compose == 0)
+ {
+ /* do_local_background does the same if required. */
+ if (do_local_background != 2 ||
+ (format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ info_format |= PNG_FORMAT_FLAG_ALPHA;
+ }
+ }
+
+ else if (do_local_compose != 0) /* internal error */
+ png_error(png_ptr, "png_image_read: alpha channel lost");
+
+ if (info_ptr->bit_depth == 16)
+ info_format |= PNG_FORMAT_FLAG_LINEAR;
+
+# ifdef PNG_FORMAT_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ info_format |= PNG_FORMAT_FLAG_BGR;
+# endif
+
+# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ if (do_local_background == 2)
+ {
+ if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ info_format |= PNG_FORMAT_FLAG_AFIRST;
+ }
+
+ if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 ||
+ ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
+ (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
+ {
+ if (do_local_background == 2)
+ png_error(png_ptr, "unexpected alpha swap transformation");
+
+ info_format |= PNG_FORMAT_FLAG_AFIRST;
+ }
+# endif
+
+ /* This is actually an internal error. */
+ if (info_format != format)
+ png_error(png_ptr, "png_read_image: invalid transformations");
+ }
+
+ /* Now read the rows. If do_local_compose is set then it is necessary to use
+ * a local row buffer. The output will be GA, RGBA or BGRA and must be
+ * converted to G, RGB or BGR as appropriate. The 'local_row' member of the
+ * display acts as a flag.
+ */
+ {
+ png_voidp first_row = display->buffer;
+ ptrdiff_t row_bytes = display->row_stride;
+
+ if (linear != 0)
+ row_bytes *= 2;
+
+ /* The following expression is designed to work correctly whether it gives
+ * a signed or an unsigned result.
+ */
+ if (row_bytes < 0)
+ {
+ char *ptr = png_voidcast(char*, first_row);
+ ptr += (image->height-1) * (-row_bytes);
+ first_row = png_voidcast(png_voidp, ptr);
+ }
+
+ display->first_row = first_row;
+ display->row_bytes = row_bytes;
+ }
+
+ if (do_local_compose != 0)
+ {
+ int result;
+ png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+
+ display->local_row = row;
+ result = png_safe_execute(image, png_image_read_composite, display);
+ display->local_row = NULL;
+ png_free(png_ptr, row);
+
+ return result;
+ }
+
+ else if (do_local_background == 2)
+ {
+ int result;
+ png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+
+ display->local_row = row;
+ result = png_safe_execute(image, png_image_read_background, display);
+ display->local_row = NULL;
+ png_free(png_ptr, row);
+
+ return result;
+ }
+
+ else
+ {
+ png_alloc_size_t row_bytes = display->row_bytes;
+
+ while (--passes >= 0)
+ {
+ png_uint_32 y = image->height;
+ png_bytep row = png_voidcast(png_bytep, display->first_row);
+
+ while (y-- > 0)
+ {
+ png_read_row(png_ptr, row, NULL);
+ row += row_bytes;
+ }
+ }
+
+ return 1;
+ }
+}
+
+int PNGAPI
+png_image_finish_read(png_imagep image, png_const_colorp background,
+ void *buffer, png_int_32 row_stride, void *colormap)
+{
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ png_uint_32 check;
+
+ if (row_stride == 0)
+ row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+
+ if (row_stride < 0)
+ check = -row_stride;
+
+ else
+ check = row_stride;
+
+ if (image->opaque != NULL && buffer != NULL &&
+ check >= PNG_IMAGE_ROW_STRIDE(*image))
+ {
+ if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
+ (image->colormap_entries > 0 && colormap != NULL))
+ {
+ int result;
+ png_image_read_control display;
+
+ memset(&display, 0, (sizeof display));
+ display.image = image;
+ display.buffer = buffer;
+ display.row_stride = row_stride;
+ display.colormap = colormap;
+ display.background = background;
+ display.local_row = NULL;
+
+ /* Choose the correct 'end' routine; for the color-map case all the
+ * setup has already been done.
+ */
+ if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
+ result =
+ png_safe_execute(image, png_image_read_colormap, &display) &&
+ png_safe_execute(image, png_image_read_colormapped, &display);
+
+ else
+ result =
+ png_safe_execute(image, png_image_read_direct, &display);
+
+ png_image_free(image);
+ return result;
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_finish_read[color-map]: no color-map");
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_finish_read: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_finish_read: damaged PNG_IMAGE_VERSION");
+
+ return 0;
+}
+
+#endif /* SIMPLIFIED_READ */
+#endif /* READ */
diff --git a/thirdparty/libpng/pngrio.c b/thirdparty/libpng/pngrio.c
index e9c381c5..5101d54a 100644
--- a/thirdparty/libpng/pngrio.c
+++ b/thirdparty/libpng/pngrio.c
@@ -1,8 +1,8 @@
/* pngrio.c - functions for data input
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -26,10 +26,10 @@
* reads from a file pointer. Note that this routine sometimes gets called
* with very small lengths, so you should implement some kind of simple
* buffering if you are using unbuffered reads. This should never be asked
- * to read more then 64K on a 16 bit machine.
+ * to read more than 64K on a 16-bit machine.
*/
void /* PRIVATE */
-png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length)
{
png_debug1(4, "reading %d bytes", (int)length);
@@ -46,7 +46,6 @@ png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
* read_data function and use it at run time with png_set_read_fn(), rather
* than changing the library.
*/
-# ifndef USE_FAR_KEYWORD
void PNGCBAPI
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
@@ -58,68 +57,11 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
* instead of an int, which is what fread() actually returns.
*/
- check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr);
+ check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
if (check != length)
png_error(png_ptr, "Read Error");
}
-# else
-/* This is the model-independent version. Since the standard I/O library
- can't handle far buffers in the medium and small models, we have to copy
- the data.
-*/
-
-#define NEAR_BUF_SIZE 1024
-#define MIN(a,b) (a <= b ? a : b)
-
-static void PNGCBAPI
-png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
-{
- png_size_t check;
- png_byte *n_data;
- png_FILE_p io_ptr;
-
- if (png_ptr == NULL)
- return;
-
- /* Check if data really is near. If so, use usual code. */
- n_data = (png_byte *)CVT_PTR_NOCHECK(data);
- io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
-
- if ((png_bytep)n_data == data)
- {
- check = fread(n_data, 1, length, io_ptr);
- }
-
- else
- {
- png_byte buf[NEAR_BUF_SIZE];
- png_size_t read, remaining, err;
- check = 0;
- remaining = length;
-
- do
- {
- read = MIN(NEAR_BUF_SIZE, remaining);
- err = fread(buf, 1, read, io_ptr);
- png_memcpy(data, buf, read); /* copy far buffer to near buffer */
-
- if (err != read)
- break;
-
- else
- check += err;
-
- data += read;
- remaining -= read;
- }
- while (remaining != 0);
- }
-
- if ((png_uint_32)check != (png_uint_32)length)
- png_error(png_ptr, "read Error");
-}
-# endif
#endif
/* This function allows the application to supply a new input function
@@ -142,7 +84,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
* be used.
*/
void PNGAPI
-png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
+png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr read_data_fn)
{
if (png_ptr == NULL)
@@ -160,6 +102,7 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
png_ptr->read_data_fn = read_data_fn;
#endif
+#ifdef PNG_WRITE_SUPPORTED
/* It is an error to write to a read device */
if (png_ptr->write_data_fn != NULL)
{
@@ -168,9 +111,10 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
"Can't set both read_data_fn and write_data_fn in the"
" same structure");
}
+#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_ptr->output_flush_fn = NULL;
#endif
}
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
diff --git a/thirdparty/libpng/pngrtran.c b/thirdparty/libpng/pngrtran.c
index 1079595f..e2331788 100644
--- a/thirdparty/libpng/pngrtran.c
+++ b/thirdparty/libpng/pngrtran.c
@@ -1,8 +1,8 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.19 [November 12, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -22,7 +22,7 @@
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
void PNGAPI
-png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
+png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
{
png_debug(1, "in png_set_crc_action");
@@ -88,16 +88,47 @@ png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
}
}
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
+/* Is it OK to set a transformation now? Only if png_start_read_image or
+ * png_read_update_info have not been called. It is not necessary for the IHDR
+ * to have been read in all cases; the need_IHDR parameter allows for this
+ * check too.
+ */
+static int
+png_rtran_ok(png_structrp png_ptr, int need_IHDR)
+{
+ if (png_ptr != NULL)
+ {
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
+ png_app_error(png_ptr,
+ "invalid after png_start_read_image or png_read_update_info");
+
+ else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_app_error(png_ptr, "invalid before the PNG header has been read");
+
+ else
+ {
+ /* Turn on failure to initialize correctly for all transforms. */
+ png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
+
+ return 1; /* Ok */
+ }
+ }
+
+ return 0; /* no png_error possible! */
+}
+#endif
+
#ifdef PNG_READ_BACKGROUND_SUPPORTED
/* Handle alpha and tRNS via a background color */
void PNGFAPI
-png_set_background_fixed(png_structp png_ptr,
+png_set_background_fixed(png_structrp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
int need_expand, png_fixed_point background_gamma)
{
png_debug(1, "in png_set_background_fixed");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL)
return;
if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
@@ -110,11 +141,10 @@ png_set_background_fixed(png_structp png_ptr,
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
- png_memcpy(&(png_ptr->background), background_color,
- png_sizeof(png_color_16));
+ png_ptr->background = *background_color;
png_ptr->background_gamma = background_gamma;
png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
- if (need_expand)
+ if (need_expand != 0)
png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
else
png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
@@ -122,7 +152,7 @@ png_set_background_fixed(png_structp png_ptr,
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_background(png_structp png_ptr,
+png_set_background(png_structrp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
int need_expand, double background_gamma)
{
@@ -138,11 +168,11 @@ png_set_background(png_structp png_ptr,
*/
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
void PNGAPI
-png_set_scale_16(png_structp png_ptr)
+png_set_scale_16(png_structrp png_ptr)
{
png_debug(1, "in png_set_scale_16");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_SCALE_16_TO_8;
@@ -152,11 +182,11 @@ png_set_scale_16(png_structp png_ptr)
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
/* Chop 16-bit depth files to 8-bit depth */
void PNGAPI
-png_set_strip_16(png_structp png_ptr)
+png_set_strip_16(png_structrp png_ptr)
{
png_debug(1, "in png_set_strip_16");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_16_TO_8;
@@ -165,11 +195,11 @@ png_set_strip_16(png_structp png_ptr)
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
void PNGAPI
-png_set_strip_alpha(png_structp png_ptr)
+png_set_strip_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_strip_alpha");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_STRIP_ALPHA;
@@ -178,7 +208,7 @@ png_set_strip_alpha(png_structp png_ptr)
#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
static png_fixed_point
-translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
+translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
int is_screen)
{
/* Check for flag values. The main reason for having the old Mac value as a
@@ -194,8 +224,10 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
*/
# ifdef PNG_READ_sRGB_SUPPORTED
png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
+# else
+ PNG_UNUSED(png_ptr)
# endif
- if (is_screen)
+ if (is_screen != 0)
output_gamma = PNG_GAMMA_sRGB;
else
output_gamma = PNG_GAMMA_sRGB_INVERSE;
@@ -204,7 +236,7 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
else if (output_gamma == PNG_GAMMA_MAC_18 ||
output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
{
- if (is_screen)
+ if (is_screen != 0)
output_gamma = PNG_GAMMA_MAC_OLD;
else
output_gamma = PNG_GAMMA_MAC_INVERSE;
@@ -215,7 +247,7 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
# ifdef PNG_FLOATING_POINT_SUPPORTED
static png_fixed_point
-convert_gamma_value(png_structp png_ptr, double output_gamma)
+convert_gamma_value(png_structrp png_ptr, double output_gamma)
{
/* The following silently ignores cases where fixed point (times 100,000)
* gamma values are passed to the floating point API. This is safe and it
@@ -240,7 +272,7 @@ convert_gamma_value(png_structp png_ptr, double output_gamma)
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
void PNGFAPI
-png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
+png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
png_fixed_point output_gamma)
{
int compose = 0;
@@ -248,7 +280,7 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
png_debug(1, "in png_set_alpha_mode");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
@@ -320,8 +352,11 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
* the side effect that the gamma in a second call to png_set_alpha_mode will
* be ignored.)
*/
- if (png_ptr->gamma == 0)
- png_ptr->gamma = file_gamma;
+ if (png_ptr->colorspace.gamma == 0)
+ {
+ png_ptr->colorspace.gamma = file_gamma;
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+ }
/* But always set the output gamma: */
png_ptr->screen_gamma = output_gamma;
@@ -329,28 +364,25 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
/* Finally, if pre-multiplying, set the background fields to achieve the
* desired result.
*/
- if (compose)
+ if (compose != 0)
{
/* And obtain alpha pre-multiplication by composing on black: */
- png_memset(&png_ptr->background, 0, sizeof png_ptr->background);
- png_ptr->background_gamma = png_ptr->gamma; /* just in case */
+ memset(&png_ptr->background, 0, (sizeof png_ptr->background));
+ png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
- if (png_ptr->transformations & PNG_COMPOSE)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
png_error(png_ptr,
"conflicting calls to set alpha mode and background");
png_ptr->transformations |= PNG_COMPOSE;
}
-
- /* New API, make sure apps call the correct initializers: */
- png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
+png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
{
png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
output_gamma));
@@ -362,7 +394,7 @@ png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
/* Dither file to 8-bit. Supply a palette, the current number
* of elements in the palette, the maximum number of elements
* allowed, and a histogram if possible. If the current number
- * of colors is greater then the maximum number, the palette will be
+ * of colors is greater than the maximum number, the palette will be
* modified to fit in the maximum number. "full_quantize" indicates
* whether we need a quantizing cube set up for RGB images, or if we
* simply are reducing the number of colors in a paletted image.
@@ -370,31 +402,31 @@ png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
typedef struct png_dsort_struct
{
- struct png_dsort_struct FAR * next;
+ struct png_dsort_struct * next;
png_byte left;
png_byte right;
} png_dsort;
-typedef png_dsort FAR * png_dsortp;
-typedef png_dsort FAR * FAR * png_dsortpp;
+typedef png_dsort * png_dsortp;
+typedef png_dsort * * png_dsortpp;
void PNGAPI
-png_set_quantize(png_structp png_ptr, png_colorp palette,
+png_set_quantize(png_structrp png_ptr, png_colorp palette,
int num_palette, int maximum_colors, png_const_uint_16p histogram,
int full_quantize)
{
png_debug(1, "in png_set_quantize");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_QUANTIZE;
- if (!full_quantize)
+ if (full_quantize == 0)
{
int i;
png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ (png_uint_32)(num_palette * (sizeof (png_byte))));
for (i = 0; i < num_palette; i++)
png_ptr->quantize_index[i] = (png_byte)i;
}
@@ -411,7 +443,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
/* Initialize an array to sort colors */
png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ (png_uint_32)(num_palette * (sizeof (png_byte))));
/* Initialize the quantize_sort array */
for (i = 0; i < num_palette; i++)
@@ -444,12 +476,12 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
}
}
- if (done)
+ if (done != 0)
break;
}
/* Swap the palette around, and set up a table, if necessary */
- if (full_quantize)
+ if (full_quantize != 0)
{
int j = num_palette;
@@ -545,9 +577,9 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
/* Initialize palette index arrays */
png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ (png_uint_32)(num_palette * (sizeof (png_byte))));
png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ (png_uint_32)(num_palette * (sizeof (png_byte))));
/* Initialize the sort array */
for (i = 0; i < num_palette; i++)
@@ -557,7 +589,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
}
hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
- png_sizeof(png_dsortp)));
+ (sizeof (png_dsortp))));
num_new_palette = num_palette;
@@ -587,7 +619,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
{
t = (png_dsortp)png_malloc_warn(png_ptr,
- (png_uint_32)(png_sizeof(png_dsort)));
+ (png_uint_32)(sizeof (png_dsort)));
if (t == NULL)
break;
@@ -632,7 +664,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
num_new_palette--;
palette[png_ptr->index_to_palette[j]]
= palette[num_new_palette];
- if (!full_quantize)
+ if (full_quantize == 0)
{
int k;
@@ -700,7 +732,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
}
png_ptr->num_palette = (png_uint_16)num_palette;
- if (full_quantize)
+ if (full_quantize != 0)
{
int i;
png_bytep distance;
@@ -712,12 +744,12 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
png_size_t num_entries = ((png_size_t)1 << total_bits);
png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
- (png_uint_32)(num_entries * png_sizeof(png_byte)));
+ (png_uint_32)(num_entries * (sizeof (png_byte))));
distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
- png_sizeof(png_byte)));
+ (sizeof (png_byte))));
- png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
+ memset(distance, 0xff, num_entries * (sizeof (png_byte)));
for (i = 0; i < num_palette; i++)
{
@@ -762,23 +794,22 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
png_free(png_ptr, distance);
}
}
-#endif /* PNG_READ_QUANTIZE_SUPPORTED */
+#endif /* READ_QUANTIZE */
#ifdef PNG_READ_GAMMA_SUPPORTED
void PNGFAPI
-png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
+png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
png_fixed_point file_gamma)
{
png_debug(1, "in png_set_gamma_fixed");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
/* New in libpng-1.5.4 - reserve particular negative values as flags. */
scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
-#if PNG_LIBPNG_VER >= 10600
/* Checking the gamma values for being >0 was added in 1.5.4 along with the
* premultiplied alpha support; this actually hides an undocumented feature
* of the previous implementation which allowed gamma processing to be
@@ -787,31 +818,32 @@ png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
* accept '0' for the gamma value it takes, because it isn't always used.
*
* Since this is an API change (albeit a very minor one that removes an
- * undocumented API feature) it will not be made until libpng-1.6.0.
+ * undocumented API feature) the following checks were only enabled in
+ * libpng-1.6.0.
*/
if (file_gamma <= 0)
png_error(png_ptr, "invalid file gamma in png_set_gamma");
if (scrn_gamma <= 0)
png_error(png_ptr, "invalid screen gamma in png_set_gamma");
-#endif
/* Set the gamma values unconditionally - this overrides the value in the PNG
* file if a gAMA chunk was present. png_set_alpha_mode provides a
* different, easier, way to default the file gamma.
*/
- png_ptr->gamma = file_gamma;
+ png_ptr->colorspace.gamma = file_gamma;
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
png_ptr->screen_gamma = scrn_gamma;
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
+png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
{
png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
convert_gamma_value(png_ptr, file_gamma));
}
-# endif /* FLOATING_POINT_SUPPORTED */
+# endif /* FLOATING_POINT */
#endif /* READ_GAMMA */
#ifdef PNG_READ_EXPAND_SUPPORTED
@@ -820,15 +852,14 @@ png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
* to alpha channels.
*/
void PNGAPI
-png_set_expand(png_structp png_ptr)
+png_set_expand(png_structrp png_ptr)
{
png_debug(1, "in png_set_expand");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
/* GRR 19990627: the following three functions currently are identical
@@ -851,90 +882,85 @@ png_set_expand(png_structp png_ptr)
/* Expand paletted images to RGB. */
void PNGAPI
-png_set_palette_to_rgb(png_structp png_ptr)
+png_set_palette_to_rgb(png_structrp png_ptr)
{
png_debug(1, "in png_set_palette_to_rgb");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
/* Expand grayscale images of less than 8-bit depth to 8 bits. */
void PNGAPI
-png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
+png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
{
png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_EXPAND;
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
-
-
/* Expand tRNS chunks to alpha channels. */
void PNGAPI
-png_set_tRNS_to_alpha(png_structp png_ptr)
+png_set_tRNS_to_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_tRNS_to_alpha");
+ if (png_rtran_ok(png_ptr, 0) == 0)
+ return;
+
png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
-#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
+#endif /* READ_EXPAND */
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
* it may not work correctly.)
*/
void PNGAPI
-png_set_expand_16(png_structp png_ptr)
+png_set_expand_16(png_structrp png_ptr)
{
png_debug(1, "in png_set_expand_16");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
-
- /* New API, make sure apps call the correct initializers: */
- png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
}
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
void PNGAPI
-png_set_gray_to_rgb(png_structp png_ptr)
+png_set_gray_to_rgb(png_structrp png_ptr)
{
png_debug(1, "in png_set_gray_to_rgb");
- if (png_ptr != NULL)
- {
- /* Because rgb must be 8 bits or more: */
- png_set_expand_gray_1_2_4_to_8(png_ptr);
- png_ptr->transformations |= PNG_GRAY_TO_RGB;
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
- }
+ if (png_rtran_ok(png_ptr, 0) == 0)
+ return;
+
+ /* Because rgb must be 8 bits or more: */
+ png_set_expand_gray_1_2_4_to_8(png_ptr);
+ png_ptr->transformations |= PNG_GRAY_TO_RGB;
}
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
void PNGFAPI
-png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
+png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
png_fixed_point red, png_fixed_point green)
{
png_debug(1, "in png_set_rgb_to_gray");
- if (png_ptr == NULL)
+ /* Need the IHDR here because of the check on color_type below. */
+ /* TODO: fix this */
+ if (png_rtran_ok(png_ptr, 1) == 0)
return;
- switch(error_action)
+ switch (error_action)
{
case PNG_ERROR_ACTION_NONE:
png_ptr->transformations |= PNG_RGB_TO_GRAY;
@@ -950,17 +976,20 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
default:
png_error(png_ptr, "invalid error action to rgb_to_gray");
- break;
}
+
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
#ifdef PNG_READ_EXPAND_SUPPORTED
png_ptr->transformations |= PNG_EXPAND;
#else
{
- png_warning(png_ptr,
+ /* Make this an error in 1.6 because otherwise the application may assume
+ * that it just worked and get a memory overwrite.
+ */
+ png_error(png_ptr,
"Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
- png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
+ /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
}
#endif
{
@@ -969,7 +998,7 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
png_uint_16 red_int, green_int;
/* NOTE: this calculation does not round, but this behavior is retained
- * for consistency, the inaccuracy is very small. The code here always
+ * for consistency; the inaccuracy is very small. The code here always
* overwrites the coefficients, regardless of whether they have been
* defaulted or set already.
*/
@@ -984,7 +1013,7 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
else
{
if (red >= 0 && green >= 0)
- png_warning(png_ptr,
+ png_app_warning(png_ptr,
"ignoring out of range rgb_to_gray coefficients");
/* Use the defaults, from the cHRM chunk if set, else the historical
@@ -1010,31 +1039,25 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
*/
void PNGAPI
-png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
+png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
double green)
{
- if (png_ptr == NULL)
- return;
-
png_set_rgb_to_gray_fixed(png_ptr, error_action,
png_fixed(png_ptr, red, "rgb to gray red coefficient"),
png_fixed(png_ptr, green, "rgb to gray green coefficient"));
}
#endif /* FLOATING POINT */
-#endif
+#endif /* RGB_TO_GRAY */
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
void PNGAPI
-png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
read_user_transform_fn)
{
png_debug(1, "in png_set_read_user_transform_fn");
- if (png_ptr == NULL)
- return;
-
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
png_ptr->transformations |= PNG_USER_TRANSFORM;
png_ptr->read_user_transform_fn = read_user_transform_fn;
@@ -1068,13 +1091,13 @@ png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
* the palette.
*/
-/*For the moment 'png_init_palette_transformations' and
+/* For the moment 'png_init_palette_transformations' and
* 'png_init_rgb_transformations' only do some flag canceling optimizations.
* The intent is that these two routines should have palette or rgb operations
* extracted from 'png_init_read_transformations'.
*/
static void /* PRIVATE */
-png_init_palette_transformations(png_structp png_ptr)
+png_init_palette_transformations(png_structrp png_ptr)
{
/* Called to handle the (input) palette case. In png_do_read_transformations
* the first step is to expand the palette if requested, so this code must
@@ -1093,25 +1116,31 @@ png_init_palette_transformations(png_structp png_ptr)
/* Ignore if all the entries are opaque (unlikely!) */
for (i=0; i<png_ptr->num_trans; ++i)
+ {
if (png_ptr->trans_alpha[i] == 255)
continue;
else if (png_ptr->trans_alpha[i] == 0)
input_has_transparency = 1;
else
+ {
+ input_has_transparency = 1;
input_has_alpha = 1;
+ break;
+ }
+ }
}
/* If no alpha we can optimize. */
- if (!input_has_alpha)
+ if (input_has_alpha == 0)
{
/* Any alpha means background and associative alpha processing is
- * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
+ * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
* and ENCODE_ALPHA are irrelevant.
*/
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
- if (!input_has_transparency)
+ if (input_has_transparency == 0)
png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
}
@@ -1124,8 +1153,8 @@ png_init_palette_transformations(png_structp png_ptr)
/* The following code cannot be entered in the alpha pre-multiplication case
* because PNG_BACKGROUND_EXPAND is cancelled below.
*/
- if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
- (png_ptr->transformations & PNG_EXPAND))
+ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) != 0)
{
{
png_ptr->background.red =
@@ -1136,9 +1165,9 @@ png_init_palette_transformations(png_structp png_ptr)
png_ptr->palette[png_ptr->background.index].blue;
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_ALPHA)
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
{
- if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
+ if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
{
/* Invert the alpha channel (in tRNS) unless the pixels are
* going to be expanded, in which case leave it for later
@@ -1150,14 +1179,14 @@ png_init_palette_transformations(png_structp png_ptr)
png_ptr->trans_alpha[i]);
}
}
-#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */
+#endif /* READ_INVERT_ALPHA */
}
} /* background expand and (therefore) no alpha association. */
-#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* READ_EXPAND && READ_BACKGROUND */
}
static void /* PRIVATE */
-png_init_rgb_transformations(png_structp png_ptr)
+png_init_rgb_transformations(png_structrp png_ptr)
{
/* Added to libpng-1.5.4: check the color type to determine whether there
* is any alpha or transparency in the image and simply cancel the
@@ -1167,10 +1196,10 @@ png_init_rgb_transformations(png_structp png_ptr)
int input_has_transparency = png_ptr->num_trans > 0;
/* If no alpha we can optimize. */
- if (!input_has_alpha)
+ if (input_has_alpha == 0)
{
/* Any alpha means background and associative alpha processing is
- * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
+ * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
* and ENCODE_ALPHA are irrelevant.
*/
# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
@@ -1178,7 +1207,7 @@ png_init_rgb_transformations(png_structp png_ptr)
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
# endif
- if (!input_has_transparency)
+ if (input_has_transparency == 0)
png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
}
@@ -1191,9 +1220,9 @@ png_init_rgb_transformations(png_structp png_ptr)
/* The following code cannot be entered in the alpha pre-multiplication case
* because PNG_BACKGROUND_EXPAND is cancelled below.
*/
- if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
- (png_ptr->transformations & PNG_EXPAND) &&
- !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) != 0 &&
+ (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
/* i.e., GRAY or GRAY_ALPHA */
{
{
@@ -1221,7 +1250,7 @@ png_init_rgb_transformations(png_structp png_ptr)
default:
case 8:
- /* Already 8 bits, fall through */
+ /* FALL THROUGH (Already 8 bits) */
case 16:
/* Already a full 16 bits */
@@ -1231,18 +1260,18 @@ png_init_rgb_transformations(png_structp png_ptr)
png_ptr->background.red = png_ptr->background.green =
png_ptr->background.blue = (png_uint_16)gray;
- if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
+ if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
{
png_ptr->trans_color.red = png_ptr->trans_color.green =
png_ptr->trans_color.blue = (png_uint_16)trans_gray;
}
}
} /* background expand and (therefore) no alpha association. */
-#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* READ_EXPAND && READ_BACKGROUND */
}
void /* PRIVATE */
-png_init_read_transformations(png_structp png_ptr)
+png_init_read_transformations(png_structrp png_ptr)
{
png_debug(1, "in png_init_read_transformations");
@@ -1267,17 +1296,17 @@ png_init_read_transformations(png_structp png_ptr)
*/
int gamma_correction = 0;
- if (png_ptr->gamma != 0) /* has been set */
+ if (png_ptr->colorspace.gamma != 0) /* has been set */
{
if (png_ptr->screen_gamma != 0) /* screen set too */
- gamma_correction = png_gamma_threshold(png_ptr->gamma,
+ gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
png_ptr->screen_gamma);
else
/* Assume the output matches the input; a long time default behavior
* of libpng, although the standard has nothing to say about this.
*/
- png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma);
+ png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
}
else if (png_ptr->screen_gamma != 0)
@@ -1286,7 +1315,7 @@ png_init_read_transformations(png_structp png_ptr)
* png_set_alpha_mode (even if the alpha handling mode isn't required
* or isn't changed from the default.)
*/
- png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma);
+ png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
else /* neither are set */
/* Just in case the following prevents any processing - file and screen
@@ -1294,7 +1323,10 @@ png_init_read_transformations(png_structp png_ptr)
* third gamma value other than png_set_background with 'UNIQUE', and,
* prior to 1.5.4
*/
- png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1;
+ png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
+
+ /* We have a gamma value now. */
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
/* Now turn the gamma transformation on or off as appropriate. Notice
* that PNG_GAMMA just refers to the file->screen correction. Alpha
@@ -1304,7 +1336,7 @@ png_init_read_transformations(png_structp png_ptr)
* the code immediately below if the transform can be handled outside the
* row loop.
*/
- if (gamma_correction)
+ if (gamma_correction != 0)
png_ptr->transformations |= PNG_GAMMA;
else
@@ -1313,7 +1345,7 @@ png_init_read_transformations(png_structp png_ptr)
#endif
/* Certain transformations have the effect of preventing other
- * transformations that happen afterward in png_do_read_transformations,
+ * transformations that happen afterward in png_do_read_transformations;
* resolve the interdependencies here. From the code of
* png_do_read_transformations the order is:
*
@@ -1331,19 +1363,19 @@ png_init_read_transformations(png_structp png_ptr)
* 12) PNG_EXPAND_16
* 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
* 14) PNG_INVERT_MONO
- * 15) PNG_SHIFT
- * 16) PNG_PACK
- * 17) PNG_BGR
- * 18) PNG_PACKSWAP
- * 19) PNG_FILLER (includes PNG_ADD_ALPHA)
- * 20) PNG_INVERT_ALPHA
+ * 15) PNG_INVERT_ALPHA
+ * 16) PNG_SHIFT
+ * 17) PNG_PACK
+ * 18) PNG_BGR
+ * 19) PNG_PACKSWAP
+ * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
* 21) PNG_SWAP_ALPHA
* 22) PNG_SWAP_BYTES
* 23) PNG_USER_TRANSFORM [must be last]
*/
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
- !(png_ptr->transformations & PNG_COMPOSE))
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) == 0)
{
/* Stripping the alpha channel happens immediately after the 'expand'
* transformations, before all other transformation, so it cancels out
@@ -1369,16 +1401,23 @@ png_init_read_transformations(png_structp png_ptr)
/* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
* settings will have no effect.
*/
- if (!png_gamma_significant(png_ptr->screen_gamma))
+ if (png_gamma_significant(png_ptr->screen_gamma) == 0)
{
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
}
#endif
-#if defined(PNG_READ_EXPAND_SUPPORTED) && \
- defined(PNG_READ_BACKGROUND_SUPPORTED) && \
- defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ /* Make sure the coefficients for the rgb to gray conversion are set
+ * appropriately.
+ */
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
+ png_colorspace_set_rgb_coefficients(png_ptr);
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
/* Detect gray background and attempt to enable optimization for
* gray --> RGB case.
*
@@ -1394,23 +1433,23 @@ png_init_read_transformations(png_structp png_ptr)
* png_set_background, along with the bit depth, then the code has a record
* of exactly what color space the background is currently in.
*/
- if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
+ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
{
/* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
* the file was grayscale the background value is gray.
*/
- if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
}
- else if (png_ptr->transformations & PNG_COMPOSE)
+ else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
{
/* PNG_COMPOSE: png_set_background was called with need_expand false,
* so the color is in the color space of the output or png_set_alpha_mode
* was called and the color is black. Ignore RGB_TO_GRAY because that
* happens before GRAY_TO_RGB.
*/
- if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
{
if (png_ptr->background.red == png_ptr->background.green &&
png_ptr->background.red == png_ptr->background.blue)
@@ -1420,7 +1459,8 @@ png_init_read_transformations(png_structp png_ptr)
}
}
}
-#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */
+#endif /* READ_EXPAND && READ_BACKGROUND */
+#endif /* READ_GRAY_TO_RGB */
/* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
* can be performed directly on the palette, and some (such as rgb to gray)
@@ -1441,10 +1481,10 @@ png_init_read_transformations(png_structp png_ptr)
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
defined(PNG_READ_EXPAND_16_SUPPORTED)
- if ((png_ptr->transformations & PNG_EXPAND_16) &&
- (png_ptr->transformations & PNG_COMPOSE) &&
- !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
- png_ptr->bit_depth != 16)
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
+ png_ptr->bit_depth != 16)
{
/* TODO: fix this. Because the expand_16 operation is after the compose
* handling the background color must be 8, not 16, bits deep, but the
@@ -1456,22 +1496,22 @@ png_init_read_transformations(png_structp png_ptr)
* NOTE: this discards the low 16 bits of the user supplied background
* color, but until expand_16 works properly there is no choice!
*/
-# define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16))
+# define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
CHOP(png_ptr->background.red);
CHOP(png_ptr->background.green);
CHOP(png_ptr->background.blue);
CHOP(png_ptr->background.gray);
# undef CHOP
}
-#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
+#endif /* READ_BACKGROUND && READ_EXPAND_16 */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
(defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
- if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) &&
- (png_ptr->transformations & PNG_COMPOSE) &&
- !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
- png_ptr->bit_depth == 16)
+ if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
+ png_ptr->bit_depth == 16)
{
/* On the other hand, if a 16-bit file is to be reduced to 8-bits per
* component this will also happen after PNG_COMPOSE and so the background
@@ -1514,25 +1554,24 @@ png_init_read_transformations(png_structp png_ptr)
* file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
* tables.
*/
- if ((png_ptr->transformations & PNG_GAMMA)
- || ((png_ptr->transformations & PNG_RGB_TO_GRAY)
- && (png_gamma_significant(png_ptr->gamma) ||
- png_gamma_significant(png_ptr->screen_gamma)))
- || ((png_ptr->transformations & PNG_COMPOSE)
- && (png_gamma_significant(png_ptr->gamma)
- || png_gamma_significant(png_ptr->screen_gamma)
+ if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
+ ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
+ (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
+ png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
+ ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
+ png_gamma_significant(png_ptr->screen_gamma) != 0
# ifdef PNG_READ_BACKGROUND_SUPPORTED
- || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
- && png_gamma_significant(png_ptr->background_gamma))
+ || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
+ png_gamma_significant(png_ptr->background_gamma) != 0)
# endif
- )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
- && png_gamma_significant(png_ptr->screen_gamma))
- )
+ )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
+ png_gamma_significant(png_ptr->screen_gamma) != 0))
{
png_build_gamma_table(png_ptr, png_ptr->bit_depth);
#ifdef PNG_READ_BACKGROUND_SUPPORTED
- if (png_ptr->transformations & PNG_COMPOSE)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
{
/* Issue a warning about this combination: because RGB_TO_GRAY is
* optimized to do the gamma transform if present yet do_background has
@@ -1540,11 +1579,11 @@ png_init_read_transformations(png_structp png_ptr)
* double-gamma-correction happens. This is true in all versions of
* libpng to date.
*/
- if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
png_warning(png_ptr,
"libpng does not support gamma+background+rgb_to_gray");
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
{
/* We don't get to here unless there is a tRNS chunk with non-opaque
* entries - see the checking code at the start of this function.
@@ -1576,8 +1615,8 @@ png_init_read_transformations(png_structp png_ptr)
break;
case PNG_BACKGROUND_GAMMA_FILE:
- g = png_reciprocal(png_ptr->gamma);
- gs = png_reciprocal2(png_ptr->gamma,
+ g = png_reciprocal(png_ptr->colorspace.gamma);
+ gs = png_reciprocal2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma);
break;
@@ -1592,7 +1631,7 @@ png_init_read_transformations(png_structp png_ptr)
break;
}
- if (png_gamma_significant(gs))
+ if (png_gamma_significant(gs) != 0)
{
back.red = png_gamma_8bit_correct(png_ptr->background.red,
gs);
@@ -1609,7 +1648,7 @@ png_init_read_transformations(png_structp png_ptr)
back.blue = (png_byte)png_ptr->background.blue;
}
- if (png_gamma_significant(g))
+ if (png_gamma_significant(g) != 0)
{
back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
g);
@@ -1685,8 +1724,9 @@ png_init_read_transformations(png_structp png_ptr)
break;
case PNG_BACKGROUND_GAMMA_FILE:
- g = png_reciprocal(png_ptr->gamma);
- gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
+ g = png_reciprocal(png_ptr->colorspace.gamma);
+ gs = png_reciprocal2(png_ptr->colorspace.gamma,
+ png_ptr->screen_gamma);
break;
case PNG_BACKGROUND_GAMMA_UNIQUE:
@@ -1702,11 +1742,11 @@ png_init_read_transformations(png_structp png_ptr)
g_sig = png_gamma_significant(g);
gs_sig = png_gamma_significant(gs);
- if (g_sig)
+ if (g_sig != 0)
png_ptr->background_1.gray = png_gamma_correct(png_ptr,
png_ptr->background.gray, g);
- if (gs_sig)
+ if (gs_sig != 0)
png_ptr->background.gray = png_gamma_correct(png_ptr,
png_ptr->background.gray, gs);
@@ -1715,7 +1755,7 @@ png_init_read_transformations(png_structp png_ptr)
(png_ptr->background.red != png_ptr->background.gray))
{
/* RGB or RGBA with color background */
- if (g_sig)
+ if (g_sig != 0)
{
png_ptr->background_1.red = png_gamma_correct(png_ptr,
png_ptr->background.red, g);
@@ -1727,7 +1767,7 @@ png_init_read_transformations(png_structp png_ptr)
png_ptr->background.blue, g);
}
- if (gs_sig)
+ if (gs_sig != 0)
{
png_ptr->background.red = png_gamma_correct(png_ptr,
png_ptr->background.red, gs);
@@ -1757,7 +1797,7 @@ png_init_read_transformations(png_structp png_ptr)
else
/* Transformation does not include PNG_BACKGROUND */
-#endif /* PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* READ_BACKGROUND */
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
/* RGB_TO_GRAY needs to have non-gamma-corrected values! */
@@ -1770,8 +1810,8 @@ png_init_read_transformations(png_structp png_ptr)
int num_palette = png_ptr->num_palette;
int i;
- /*NOTE: there are other transformations that should probably be in here
- * too.
+ /* NOTE: there are other transformations that should probably be in
+ * here too.
*/
for (i = 0; i < num_palette; i++)
{
@@ -1787,11 +1827,11 @@ png_init_read_transformations(png_structp png_ptr)
#ifdef PNG_READ_BACKGROUND_SUPPORTED
else
#endif
-#endif /* PNG_READ_GAMMA_SUPPORTED */
+#endif /* READ_GAMMA */
#ifdef PNG_READ_BACKGROUND_SUPPORTED
/* No GAMMA transformation (see the hanging else 4 lines above) */
- if ((png_ptr->transformations & PNG_COMPOSE) &&
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
{
int i;
@@ -1826,47 +1866,53 @@ png_init_read_transformations(png_structp png_ptr)
png_ptr->transformations &= ~PNG_COMPOSE;
}
-#endif /* PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* READ_BACKGROUND */
#ifdef PNG_READ_SHIFT_SUPPORTED
- if ((png_ptr->transformations & PNG_SHIFT) &&
+ if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) == 0 &&
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
{
int i;
int istop = png_ptr->num_palette;
int shift = 8 - png_ptr->sig_bit.red;
+ png_ptr->transformations &= ~PNG_SHIFT;
+
/* significant bits can be in the range 1 to 7 for a meaninful result, if
* the number of significant bits is 0 then no shift is done (this is an
* error condition which is silently ignored.)
*/
- if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
- {
- int component = png_ptr->palette[i].red;
+ if (shift > 0 && shift < 8)
+ for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].red;
- component >>= shift;
- png_ptr->palette[i].red = (png_byte)component;
- }
+ component >>= shift;
+ png_ptr->palette[i].red = (png_byte)component;
+ }
shift = 8 - png_ptr->sig_bit.green;
- if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
- {
- int component = png_ptr->palette[i].green;
+ if (shift > 0 && shift < 8)
+ for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].green;
- component >>= shift;
- png_ptr->palette[i].green = (png_byte)component;
- }
+ component >>= shift;
+ png_ptr->palette[i].green = (png_byte)component;
+ }
shift = 8 - png_ptr->sig_bit.blue;
- if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
- {
- int component = png_ptr->palette[i].blue;
+ if (shift > 0 && shift < 8)
+ for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].blue;
- component >>= shift;
- png_ptr->palette[i].blue = (png_byte)component;
- }
+ component >>= shift;
+ png_ptr->palette[i].blue = (png_byte)component;
+ }
}
-#endif /* PNG_READ_SHIFT_SUPPORTED */
+#endif /* READ_SHIFT */
}
/* Modify the info structure to reflect the transformations. The
@@ -1874,12 +1920,12 @@ png_init_read_transformations(png_structp png_ptr)
* assuming the transformations result in valid PNG data.
*/
void /* PRIVATE */
-png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
+png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
{
png_debug(1, "in png_read_transform_info");
#ifdef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND)
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
{
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
@@ -1895,12 +1941,15 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->bit_depth = 8;
info_ptr->num_trans = 0;
+
+ if (png_ptr->palette == NULL)
+ png_error (png_ptr, "Palette is NULL in indexed image");
}
else
{
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
{
- if (png_ptr->transformations & PNG_EXPAND_tRNS)
+ if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
}
if (info_ptr->bit_depth < 8)
@@ -1916,7 +1965,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
/* The following is almost certainly wrong unless the background value is in
* the screen space!
*/
- if (png_ptr->transformations & PNG_COMPOSE)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
info_ptr->background = png_ptr->background;
#endif
@@ -1925,25 +1974,29 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
* however it seems that the code in png_init_read_transformations, which has
* been called before this from png_read_update_info->png_read_start_row
* sometimes does the gamma transform and cancels the flag.
+ *
+ * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
+ * the screen_gamma value. The following probably results in weirdness if
+ * the info_ptr is used by the app after the rows have been read.
*/
- info_ptr->gamma = png_ptr->gamma;
+ info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
#endif
if (info_ptr->bit_depth == 16)
{
# ifdef PNG_READ_16BIT_SUPPORTED
# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
- if (png_ptr->transformations & PNG_SCALE_16_TO_8)
+ if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
info_ptr->bit_depth = 8;
# endif
# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
- if (png_ptr->transformations & PNG_16_TO_8)
+ if ((png_ptr->transformations & PNG_16_TO_8) != 0)
info_ptr->bit_depth = 8;
# endif
# else
- /* No 16 bit support: force chopping 16-bit input down to 8, in this case
+ /* No 16-bit support: force chopping 16-bit input down to 8, in this case
* the app program can chose if both APIs are available by setting the
* correct scaling to use.
*/
@@ -1964,27 +2017,27 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
CONFIGURATION ERROR: you must enable at least one 16 to 8 method
# endif
# endif
-#endif /* !READ_16BIT_SUPPORTED */
+#endif /* !READ_16BIT */
}
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
info_ptr->color_type = (png_byte)(info_ptr->color_type |
PNG_COLOR_MASK_COLOR);
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
info_ptr->color_type = (png_byte)(info_ptr->color_type &
~PNG_COLOR_MASK_COLOR);
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
- if (png_ptr->transformations & PNG_QUANTIZE)
+ if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
{
if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
(info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
- png_ptr->palette_lookup && info_ptr->bit_depth == 8)
+ png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
{
info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
}
@@ -1992,29 +2045,31 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
- info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
+ info_ptr->bit_depth == 8 &&
+ info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
info_ptr->bit_depth = 16;
}
#endif
#ifdef PNG_READ_PACK_SUPPORTED
- if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
+ if ((png_ptr->transformations & PNG_PACK) != 0 &&
+ (info_ptr->bit_depth < 8))
info_ptr->bit_depth = 8;
#endif
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
info_ptr->channels = 1;
- else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
info_ptr->channels = 3;
else
info_ptr->channels = 1;
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_STRIP_ALPHA)
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
{
info_ptr->color_type = (png_byte)(info_ptr->color_type &
~PNG_COLOR_MASK_ALPHA);
@@ -2022,30 +2077,30 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
}
#endif
- if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
info_ptr->channels++;
#ifdef PNG_READ_FILLER_SUPPORTED
/* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
- if ((png_ptr->transformations & PNG_FILLER) &&
- ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
- (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
+ if ((png_ptr->transformations & PNG_FILLER) != 0 &&
+ (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
+ info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
{
info_ptr->channels++;
/* If adding a true alpha channel not just filler */
- if (png_ptr->transformations & PNG_ADD_ALPHA)
+ if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
}
#endif
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
- if (png_ptr->transformations & PNG_USER_TRANSFORM)
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
{
- if (info_ptr->bit_depth < png_ptr->user_transform_depth)
+ if (png_ptr->user_transform_depth != 0)
info_ptr->bit_depth = png_ptr->user_transform_depth;
- if (info_ptr->channels < png_ptr->user_transform_channels)
+ if (png_ptr->user_transform_channels != 0)
info_ptr->channels = png_ptr->user_transform_channels;
}
#endif
@@ -2064,300 +2119,11 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
png_ptr->info_rowbytes = info_ptr->rowbytes;
#ifndef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr)
+ if (png_ptr != NULL)
return;
#endif
}
-/* Transform the row. The order of transformations is significant,
- * and is very touchy. If you add a transformation, take care to
- * decide how it fits in with the other transformations here.
- */
-void /* PRIVATE */
-png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
-{
- png_debug(1, "in png_do_read_transformations");
-
- if (png_ptr->row_buf == NULL)
- {
- /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
- * error is incredibly rare and incredibly easy to debug without this
- * information.
- */
- png_error(png_ptr, "NULL row buffer");
- }
-
- /* The following is debugging; prior to 1.5.4 the code was never compiled in;
- * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
- * PNG_WARN_UNINITIALIZED_ROW removed. In 1.5 the new flag is set only for
- * selected new APIs to ensure that there is no API change.
- */
- if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
- !(png_ptr->flags & PNG_FLAG_ROW_INIT))
- {
- /* Application has failed to call either png_read_start_image() or
- * png_read_update_info() after setting transforms that expand pixels.
- * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
- */
- png_error(png_ptr, "Uninitialized row");
- }
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND)
- {
- if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
- {
- png_do_expand_palette(row_info, png_ptr->row_buf + 1,
- png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
- }
-
- else
- {
- if (png_ptr->num_trans &&
- (png_ptr->transformations & PNG_EXPAND_tRNS))
- png_do_expand(row_info, png_ptr->row_buf + 1,
- &(png_ptr->trans_color));
-
- else
- png_do_expand(row_info, png_ptr->row_buf + 1,
- NULL);
- }
- }
-#endif
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
- !(png_ptr->transformations & PNG_COMPOSE) &&
- (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
- row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- png_do_strip_channel(row_info, png_ptr->row_buf + 1,
- 0 /* at_start == false, because SWAP_ALPHA happens later */);
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- if (png_ptr->transformations & PNG_RGB_TO_GRAY)
- {
- int rgb_error =
- png_do_rgb_to_gray(png_ptr, row_info,
- png_ptr->row_buf + 1);
-
- if (rgb_error)
- {
- png_ptr->rgb_to_gray_status=1;
- if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
- PNG_RGB_TO_GRAY_WARN)
- png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
-
- if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
- PNG_RGB_TO_GRAY_ERR)
- png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
- }
- }
-#endif
-
-/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
- *
- * In most cases, the "simple transparency" should be done prior to doing
- * gray-to-RGB, or you will have to test 3x as many bytes to check if a
- * pixel is transparent. You would also need to make sure that the
- * transparency information is upgraded to RGB.
- *
- * To summarize, the current flow is:
- * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
- * with background "in place" if transparent,
- * convert to RGB if necessary
- * - Gray + alpha -> composite with gray background and remove alpha bytes,
- * convert to RGB if necessary
- *
- * To support RGB backgrounds for gray images we need:
- * - Gray + simple transparency -> convert to RGB + simple transparency,
- * compare 3 or 6 bytes and composite with
- * background "in place" if transparent
- * (3x compare/pixel compared to doing
- * composite with gray bkgrnd)
- * - Gray + alpha -> convert to RGB + alpha, composite with background and
- * remove alpha bytes (3x float
- * operations/pixel compared with composite
- * on gray background)
- *
- * Greg's change will do this. The reason it wasn't done before is for
- * performance, as this increases the per-pixel operations. If we would check
- * in advance if the background was gray or RGB, and position the gray-to-RGB
- * transform appropriately, then it would save a lot of work/time.
- */
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- /* If gray -> RGB, do so now only if background is non-gray; else do later
- * for performance reasons
- */
- if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
- !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
- png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
-#endif
-
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
- if (png_ptr->transformations & PNG_COMPOSE)
- png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
- if ((png_ptr->transformations & PNG_GAMMA) &&
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- /* Because RGB_TO_GRAY does the gamma transform. */
- !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
-#endif
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
- /* Because PNG_COMPOSE does the gamma transform if there is something to
- * do (if there is an alpha channel or transparency.)
- */
- !((png_ptr->transformations & PNG_COMPOSE) &&
- ((png_ptr->num_trans != 0) ||
- (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
-#endif
- /* Because png_init_read_transformations transforms the palette, unless
- * RGB_TO_GRAY will do the transform.
- */
- (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
- png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
- (png_ptr->transformations & PNG_COMPOSE) &&
- (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
- row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- png_do_strip_channel(row_info, png_ptr->row_buf + 1,
- 0 /* at_start == false, because SWAP_ALPHA happens later */);
-#endif
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
- if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
- (row_info->color_type & PNG_COLOR_MASK_ALPHA))
- png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
- if (png_ptr->transformations & PNG_SCALE_16_TO_8)
- png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
- /* There is no harm in doing both of these because only one has any effect,
- * by putting the 'scale' option first if the app asks for scale (either by
- * calling the API or in a TRANSFORM flag) this is what happens.
- */
- if (png_ptr->transformations & PNG_16_TO_8)
- png_do_chop(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
- if (png_ptr->transformations & PNG_QUANTIZE)
- {
- png_do_quantize(row_info, png_ptr->row_buf + 1,
- png_ptr->palette_lookup, png_ptr->quantize_index);
-
- if (row_info->rowbytes == 0)
- png_error(png_ptr, "png_do_quantize returned rowbytes=0");
- }
-#endif /* PNG_READ_QUANTIZE_SUPPORTED */
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
- /* Do the expansion now, after all the arithmetic has been done. Notice
- * that previous transformations can handle the PNG_EXPAND_16 flag if this
- * is efficient (particularly true in the case of gamma correction, where
- * better accuracy results faster!)
- */
- if (png_ptr->transformations & PNG_EXPAND_16)
- png_do_expand_16(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- /*NOTE: moved here in 1.5.4 (from much later in this list.) */
- if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
- (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
- png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_INVERT_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_MONO)
- png_do_invert(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_SHIFT_SUPPORTED
- if (png_ptr->transformations & PNG_SHIFT)
- png_do_unshift(row_info, png_ptr->row_buf + 1,
- &(png_ptr->shift));
-#endif
-
-#ifdef PNG_READ_PACK_SUPPORTED
- if (png_ptr->transformations & PNG_PACK)
- png_do_unpack(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_BGR_SUPPORTED
- if (png_ptr->transformations & PNG_BGR)
- png_do_bgr(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP)
- png_do_packswap(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_FILLER_SUPPORTED
- if (png_ptr->transformations & PNG_FILLER)
- png_do_read_filler(row_info, png_ptr->row_buf + 1,
- (png_uint_32)png_ptr->filler, png_ptr->flags);
-#endif
-
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_ALPHA)
- png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_SWAP_ALPHA)
- png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-#ifdef PNG_READ_SWAP_SUPPORTED
- if (png_ptr->transformations & PNG_SWAP_BYTES)
- png_do_swap(row_info, png_ptr->row_buf + 1);
-#endif
-#endif
-
-#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
- if (png_ptr->transformations & PNG_USER_TRANSFORM)
- {
- if (png_ptr->read_user_transform_fn != NULL)
- (*(png_ptr->read_user_transform_fn)) /* User read transform function */
- (png_ptr, /* png_ptr */
- row_info, /* row_info: */
- /* png_uint_32 width; width of row */
- /* png_size_t rowbytes; number of bytes in row */
- /* png_byte color_type; color type of pixels */
- /* png_byte bit_depth; bit depth of samples */
- /* png_byte channels; number of channels (1-4) */
- /* png_byte pixel_depth; bits per pixel (depth*channels) */
- png_ptr->row_buf + 1); /* start of pixel data for row */
-#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
- if (png_ptr->user_transform_depth)
- row_info->bit_depth = png_ptr->user_transform_depth;
-
- if (png_ptr->user_transform_channels)
- row_info->channels = png_ptr->user_transform_channels;
-#endif
- row_info->pixel_depth = (png_byte)(row_info->bit_depth *
- row_info->channels);
-
- row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
- }
-#endif
-}
-
#ifdef PNG_READ_PACK_SUPPORTED
/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
* without changing the actual values. Thus, if you had a row with
@@ -2365,7 +2131,7 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
* the numbers 0 or 1. If you would rather they contain 0 and 255, use
* png_do_shift() after this.
*/
-void /* PRIVATE */
+static void
png_do_unpack(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_unpack");
@@ -2463,7 +2229,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
* a row of bit depth 8, but only 5 are significant, this will shift
* the values back to 0 through 31.
*/
-void /* PRIVATE */
+static void
png_do_unshift(png_row_infop row_info, png_bytep row,
png_const_color_8p sig_bits)
{
@@ -2480,7 +2246,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
int channels = 0;
int bit_depth = row_info->bit_depth;
- if (color_type & PNG_COLOR_MASK_COLOR)
+ if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
{
shift[channels++] = bit_depth - sig_bits->red;
shift[channels++] = bit_depth - sig_bits->green;
@@ -2492,7 +2258,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
shift[channels++] = bit_depth - sig_bits->gray;
}
- if (color_type & PNG_COLOR_MASK_ALPHA)
+ if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
shift[channels++] = bit_depth - sig_bits->alpha;
}
@@ -2512,7 +2278,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
have_shift = 1;
}
- if (!have_shift)
+ if (have_shift == 0)
return;
}
@@ -2590,7 +2356,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
if (++channel >= channels)
channel = 0;
*bp++ = (png_byte)(value >> 8);
- *bp++ = (png_byte)(value & 0xff);
+ *bp++ = (png_byte)value;
}
break;
}
@@ -2602,7 +2368,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
/* Scale rows of bit depth 16 down to 8 accurately */
-void /* PRIVATE */
+static void
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_scale_16_to_8");
@@ -2615,8 +2381,8 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
while (sp < ep)
{
- /* The input is an array of 16 bit components, these must be scaled to
- * 8 bits each. For a 16 bit value V the required value (from the PNG
+ /* The input is an array of 16-bit components, these must be scaled to
+ * 8 bits each. For a 16-bit value V the required value (from the PNG
* specification) is:
*
* (V * 255) / 65535
@@ -2637,7 +2403,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
*
* The approximate differs from the exact answer only when (vlo-vhi) is
* 128; it then gives a correction of +1 when the exact correction is
- * 0. This gives 128 errors. The exact answer (correct for all 16 bit
+ * 0. This gives 128 errors. The exact answer (correct for all 16-bit
* input values) is:
*
* error = (vlo-vhi+128)*65535 >> 24;
@@ -2660,7 +2426,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-void /* PRIVATE */
+static void
/* Simply discard the low byte. This was the default behavior prior
* to libpng-1.5.4.
*/
@@ -2688,7 +2454,7 @@ png_do_chop(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_read_swap_alpha");
@@ -2785,7 +2551,7 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
png_uint_32 row_width;
@@ -2887,7 +2653,7 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
#ifdef PNG_READ_FILLER_SUPPORTED
/* Add filler channel if we have RGB color */
-void /* PRIVATE */
+static void
png_do_read_filler(png_row_infop row_info, png_bytep row,
png_uint_32 filler, png_uint_32 flags)
{
@@ -2895,9 +2661,9 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
png_uint_32 row_width = row_info->width;
#ifdef PNG_READ_16BIT_SUPPORTED
- png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
+ png_byte hi_filler = (png_byte)(filler>>8);
#endif
- png_byte lo_filler = (png_byte)(filler & 0xff);
+ png_byte lo_filler = (png_byte)filler;
png_debug(1, "in png_do_read_filler");
@@ -2906,7 +2672,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
{
if (row_info->bit_depth == 8)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from G to GX */
png_bytep sp = row + (png_size_t)row_width;
@@ -2941,20 +2707,20 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_16BIT_SUPPORTED
else if (row_info->bit_depth == 16)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from GG to GGXX */
png_bytep sp = row + (png_size_t)row_width * 2;
png_bytep dp = sp + (png_size_t)row_width * 2;
for (i = 1; i < row_width; i++)
{
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
*(--dp) = *(--sp);
*(--dp) = *(--sp);
}
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
row_info->channels = 2;
row_info->pixel_depth = 32;
row_info->rowbytes = row_width * 4;
@@ -2969,8 +2735,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
{
*(--dp) = *(--sp);
*(--dp) = *(--sp);
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
}
row_info->channels = 2;
row_info->pixel_depth = 32;
@@ -2983,7 +2749,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
{
if (row_info->bit_depth == 8)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from RGB to RGBX */
png_bytep sp = row + (png_size_t)row_width * 3;
@@ -3022,15 +2788,15 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_16BIT_SUPPORTED
else if (row_info->bit_depth == 16)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from RRGGBB to RRGGBBXX */
png_bytep sp = row + (png_size_t)row_width * 6;
png_bytep dp = sp + (png_size_t)row_width * 2;
for (i = 1; i < row_width; i++)
{
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
@@ -3038,8 +2804,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
*(--dp) = *(--sp);
*(--dp) = *(--sp);
}
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
row_info->channels = 4;
row_info->pixel_depth = 64;
row_info->rowbytes = row_width * 8;
@@ -3058,8 +2824,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
}
row_info->channels = 4;
@@ -3074,7 +2840,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Expand grayscale files to RGB, with or without alpha */
-void /* PRIVATE */
+static void
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
{
png_uint_32 i;
@@ -3083,7 +2849,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
png_debug(1, "in png_do_gray_to_rgb");
if (row_info->bit_depth >= 8 &&
- !(row_info->color_type & PNG_COLOR_MASK_COLOR))
+ (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{
@@ -3213,16 +2979,16 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
* calculated to make the sum 32768. This will result in different rounding
* to that used above.
*/
-int /* PRIVATE */
-png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
+static int
+png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
{
int rgb_error = 0;
png_debug(1, "in png_do_rgb_to_gray");
- if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
- (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
+ (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
@@ -3233,7 +2999,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
if (row_info->bit_depth == 8)
{
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
/* Notice that gamma to/from 1 are not necessarily inverses (if
* there is an overall gamma correction). Prior to 1.5.5 this code
* checked the linearized values for equality; this doesn't match
@@ -3273,7 +3039,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
*(dp++) = red;
}
- if (have_alpha)
+ if (have_alpha != 0)
*(dp++) = *(sp++);
}
}
@@ -3293,7 +3059,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
if (red != green || red != blue)
{
rgb_error |= 1;
- /*NOTE: this is the historical approach which simply
+ /* NOTE: this is the historical approach which simply
* truncates the results.
*/
*(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
@@ -3302,7 +3068,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
else
*(dp++) = red;
- if (have_alpha)
+ if (have_alpha != 0)
*(dp++) = *(sp++);
}
}
@@ -3310,7 +3076,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
else /* RGB bit_depth == 16 */
{
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
{
png_bytep sp = row;
@@ -3320,16 +3086,17 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
for (i = 0; i < row_width; i++)
{
png_uint_16 red, green, blue, w;
+ png_byte hi,lo;
- red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+ hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));
if (red == green && red == blue)
{
if (png_ptr->gamma_16_table != NULL)
- w = png_ptr->gamma_16_table[(red&0xff)
- >> png_ptr->gamma_shift][red>>8];
+ w = png_ptr->gamma_16_table[(red & 0xff)
+ >> png_ptr->gamma_shift][red >> 8];
else
w = red;
@@ -3337,16 +3104,16 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
else
{
- png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff)
+ png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red & 0xff)
>> png_ptr->gamma_shift][red>>8];
png_uint_16 green_1 =
- png_ptr->gamma_16_to_1[(green&0xff) >>
+ png_ptr->gamma_16_to_1[(green & 0xff) >>
png_ptr->gamma_shift][green>>8];
- png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff)
+ png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue & 0xff)
>> png_ptr->gamma_shift][blue>>8];
png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
+ bc*blue_1 + 16384)>>15);
- w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+ w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >>
png_ptr->gamma_shift][gray16 >> 8];
rgb_error |= 1;
}
@@ -3354,7 +3121,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)((w>>8) & 0xff);
*(dp++) = (png_byte)(w & 0xff);
- if (have_alpha)
+ if (have_alpha != 0)
{
*(dp++) = *(sp++);
*(dp++) = *(sp++);
@@ -3371,24 +3138,25 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
for (i = 0; i < row_width; i++)
{
png_uint_16 red, green, blue, gray16;
+ png_byte hi,lo;
- red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+ hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));
if (red != green || red != blue)
rgb_error |= 1;
- /* From 1.5.5 in the 16 bit case do the accurate conversion even
+ /* From 1.5.5 in the 16-bit case do the accurate conversion even
* in the 'fast' case - this is because this is where the code
- * ends up when handling linear 16 bit data.
+ * ends up when handling linear 16-bit data.
*/
gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
15);
- *(dp++) = (png_byte)((gray16>>8) & 0xff);
+ *(dp++) = (png_byte)((gray16 >> 8) & 0xff);
*(dp++) = (png_byte)(gray16 & 0xff);
- if (have_alpha)
+ if (have_alpha != 0)
{
*(dp++) = *(sp++);
*(dp++) = *(sp++);
@@ -3407,74 +3175,15 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
return rgb_error;
}
#endif
-#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
-
-#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
-/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
- * large of png_color. This lets grayscale images be treated as
- * paletted. Most useful for gamma correction and simplification
- * of code. This API is not used internally.
- */
-void PNGAPI
-png_build_grayscale_palette(int bit_depth, png_colorp palette)
-{
- int num_palette;
- int color_inc;
- int i;
- int v;
-
- png_debug(1, "in png_do_build_grayscale_palette");
- if (palette == NULL)
- return;
-
- switch (bit_depth)
- {
- case 1:
- num_palette = 2;
- color_inc = 0xff;
- break;
-
- case 2:
- num_palette = 4;
- color_inc = 0x55;
- break;
-
- case 4:
- num_palette = 16;
- color_inc = 0x11;
- break;
-
- case 8:
- num_palette = 256;
- color_inc = 1;
- break;
-
- default:
- num_palette = 0;
- color_inc = 0;
- break;
- }
-
- for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
- {
- palette[i].red = (png_byte)v;
- palette[i].green = (png_byte)v;
- palette[i].blue = (png_byte)v;
- }
-}
-#endif
-
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
/* Replace any alpha or transparency with the supplied background color.
* "background" is already in the screen gamma, while "background_1" is
* at a gamma of 1.0. Paletted files have already been taken care of.
*/
-void /* PRIVATE */
-png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+static void
+png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
#ifdef PNG_READ_GAMMA_SUPPORTED
png_const_bytep gamma_table = png_ptr->gamma_table;
@@ -3484,12 +3193,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
int gamma_shift = png_ptr->gamma_shift;
+ int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
#endif
png_bytep sp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
- int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
int shift;
png_debug(1, "in png_do_compose");
@@ -3510,11 +3219,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x01)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 7;
sp++;
@@ -3538,20 +3248,22 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x03)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
else
{
- png_byte p = (png_byte)((*sp >> shift) & 0x03);
- png_byte g = (png_byte)((gamma_table [p | (p << 2) |
- (p << 4) | (p << 6)] >> 6) & 0x03);
- *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *sp |= (png_byte)(g << shift);
+ unsigned int p = (*sp >> shift) & 0x03;
+ unsigned int g = (gamma_table [p | (p << 2) |
+ (p << 4) | (p << 6)] >> 6) & 0x03;
+ unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+ tmp |= g << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 6;
sp++;
@@ -3572,11 +3284,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x03)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 6;
sp++;
@@ -3601,20 +3314,22 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x0f)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
else
{
- png_byte p = (png_byte)((*sp >> shift) & 0x0f);
- png_byte g = (png_byte)((gamma_table[p |
- (p << 4)] >> 4) & 0x0f);
- *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *sp |= (png_byte)(g << shift);
+ unsigned int p = (*sp >> shift) & 0x0f;
+ unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
+ 0x0f;
+ unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
+ tmp |= g << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 4;
sp++;
@@ -3635,11 +3350,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x0f)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 4;
sp++;
@@ -3695,8 +3411,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (v == png_ptr->trans_color.gray)
{
/* Background is already in screen gamma */
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
- *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
+ *(sp + 1) = (png_byte)(png_ptr->background.gray
+ & 0xff);
}
else
@@ -3719,8 +3437,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (v == png_ptr->trans_color.gray)
{
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
- *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
+ *(sp + 1) = (png_byte)(png_ptr->background.gray
+ & 0xff);
}
}
}
@@ -3800,9 +3520,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Background is already in screen gamma */
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -3843,9 +3566,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
{
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
}
@@ -3882,7 +3608,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_to_1[*sp];
png_composite(w, v, a, png_ptr->background_1.gray);
- if (!optimize)
+ if (optimize == 0)
w = gamma_from_1[w];
*sp = w;
}
@@ -3900,7 +3626,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
*sp = (png_byte)png_ptr->background.gray;
else if (a < 0xff)
- png_composite(*sp, *sp, a, png_ptr->background_1.gray);
+ png_composite(*sp, *sp, a, png_ptr->background.gray);
}
}
}
@@ -3928,7 +3654,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
else if (a == 0)
{
/* Background is already in screen gamma */
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
}
@@ -3938,10 +3665,11 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
png_composite_16(v, g, a, png_ptr->background_1.gray);
- if (optimize)
+ if (optimize != 0)
w = v;
else
- w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
+ w = gamma_16_from_1[(v & 0xff) >>
+ gamma_shift][v >> 8];
*sp = (png_byte)((w >> 8) & 0xff);
*(sp + 1) = (png_byte)(w & 0xff);
}
@@ -3958,7 +3686,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (a == 0)
{
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
}
@@ -3967,7 +3696,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
png_uint_16 g, v;
g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
- png_composite_16(v, g, a, png_ptr->background_1.gray);
+ png_composite_16(v, g, a, png_ptr->background.gray);
*sp = (png_byte)((v >> 8) & 0xff);
*(sp + 1) = (png_byte)(v & 0xff);
}
@@ -4011,17 +3740,17 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_to_1[*sp];
png_composite(w, v, a, png_ptr->background_1.red);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*sp = w;
v = gamma_to_1[*(sp + 1)];
png_composite(w, v, a, png_ptr->background_1.green);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*(sp + 1) = w;
v = gamma_to_1[*(sp + 2)];
png_composite(w, v, a, png_ptr->background_1.blue);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*(sp + 2) = w;
}
}
@@ -4088,9 +3817,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Background is already in screen gamma */
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -4100,23 +3832,26 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
png_composite_16(w, v, a, png_ptr->background_1.red);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
+ 8];
*sp = (png_byte)((w >> 8) & 0xff);
*(sp + 1) = (png_byte)(w & 0xff);
v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
png_composite_16(w, v, a, png_ptr->background_1.green);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
+ 8];
*(sp + 2) = (png_byte)((w >> 8) & 0xff);
*(sp + 3) = (png_byte)(w & 0xff);
v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
png_composite_16(w, v, a, png_ptr->background_1.blue);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
+ 8];
*(sp + 4) = (png_byte)((w >> 8) & 0xff);
*(sp + 5) = (png_byte)(w & 0xff);
@@ -4137,9 +3872,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
{
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -4176,7 +3914,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
}
}
}
-#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
+#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
#ifdef PNG_READ_GAMMA_SUPPORTED
/* Gamma correct the image, avoiding the alpha channel. Make sure
@@ -4185,8 +3923,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
* is 16, use gamma_16_table and gamma_shift. Build these with
* build_gamma_table().
*/
-void /* PRIVATE */
-png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+static void
+png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
png_const_bytep gamma_table = png_ptr->gamma_table;
png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
@@ -4386,14 +4124,14 @@ png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
* linear.) Called only with color types that have an alpha channel. Needs the
* from_1 tables.
*/
-void /* PRIVATE */
-png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+static void
+png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
png_uint_32 row_width = row_info->width;
png_debug(1, "in png_do_encode_alpha");
- if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
if (row_info->bit_depth == 8)
{
@@ -4452,7 +4190,7 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Expands a palette row to an RGB or RGBA row depending
* upon whether you supply trans and num_trans.
*/
-void /* PRIVATE */
+static void
png_do_expand_palette(png_row_infop row_info, png_bytep row,
png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
{
@@ -4605,7 +4343,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
/* If the bit depth < 8, it is expanded to 8. Also, if the already
* expanded transparency value is supplied, an alpha channel is built.
*/
-void /* PRIVATE */
+static void
png_do_expand(png_row_infop row_info, png_bytep row,
png_const_color_16p trans_color)
{
@@ -4619,7 +4357,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
{
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{
- png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
+ unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
if (row_info->bit_depth < 8)
{
@@ -4627,7 +4365,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
{
case 1:
{
- gray = (png_uint_16)((gray & 0x01) * 0xff);
+ gray = (gray & 0x01) * 0xff;
sp = row + (png_size_t)((row_width - 1) >> 3);
dp = row + (png_size_t)row_width - 1;
shift = 7 - (int)((row_width + 7) & 0x07);
@@ -4655,7 +4393,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
case 2:
{
- gray = (png_uint_16)((gray & 0x03) * 0x55);
+ gray = (gray & 0x03) * 0x55;
sp = row + (png_size_t)((row_width - 1) >> 2);
dp = row + (png_size_t)row_width - 1;
shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
@@ -4680,7 +4418,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
case 4:
{
- gray = (png_uint_16)((gray & 0x0f) * 0x11);
+ gray = (gray & 0x0f) * 0x11;
sp = row + (png_size_t)((row_width - 1) >> 1);
dp = row + (png_size_t)row_width - 1;
shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
@@ -4721,7 +4459,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
for (i = 0; i < row_width; i++)
{
- if (*sp == gray)
+ if ((*sp & 0xffU) == gray)
*dp-- = 0;
else
@@ -4733,13 +4471,14 @@ png_do_expand(png_row_infop row_info, png_bytep row,
else if (row_info->bit_depth == 16)
{
- png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
- png_byte gray_low = (png_byte)(gray & 0xff);
+ unsigned int gray_high = (gray >> 8) & 0xff;
+ unsigned int gray_low = gray & 0xff;
sp = row + row_info->rowbytes - 1;
dp = row + (row_info->rowbytes << 1) - 1;
for (i = 0; i < row_width; i++)
{
- if (*(sp - 1) == gray_high && *(sp) == gray_low)
+ if ((*(sp - 1) & 0xffU) == gray_high &&
+ (*(sp) & 0xffU) == gray_low)
{
*dp-- = 0;
*dp-- = 0;
@@ -4763,7 +4502,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
row_width);
}
}
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
+ trans_color != NULL)
{
if (row_info->bit_depth == 8)
{
@@ -4835,7 +4575,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
/* If the bit depth is 8 and the color type is not a palette type expand the
* whole row to 16 bits. Has no effect otherwise.
*/
-void /* PRIVATE */
+static void
png_do_expand_16(png_row_infop row_info, png_bytep row)
{
if (row_info->bit_depth == 8 &&
@@ -4863,7 +4603,7 @@ png_do_expand_16(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
-void /* PRIVATE */
+static void
png_do_quantize(png_row_infop row_info, png_bytep row,
png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
{
@@ -4954,70 +4694,304 @@ png_do_quantize(png_row_infop row_info, png_bytep row,
}
}
}
-#endif /* PNG_READ_QUANTIZE_SUPPORTED */
-#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
+#endif /* READ_QUANTIZE */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Undoes intrapixel differencing */
+/* Transform the row. The order of transformations is significant,
+ * and is very touchy. If you add a transformation, take care to
+ * decide how it fits in with the other transformations here.
+ */
void /* PRIVATE */
-png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
+png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
{
- png_debug(1, "in png_do_read_intrapixel");
+ png_debug(1, "in png_do_read_transformations");
- if (
- (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ if (png_ptr->row_buf == NULL)
{
- int bytes_per_pixel;
- png_uint_32 row_width = row_info->width;
+ /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
+ * error is incredibly rare and incredibly easy to debug without this
+ * information.
+ */
+ png_error(png_ptr, "NULL row buffer");
+ }
- if (row_info->bit_depth == 8)
- {
- png_bytep rp;
- png_uint_32 i;
+ /* The following is debugging; prior to 1.5.4 the code was never compiled in;
+ * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
+ * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for
+ * all transformations, however in practice the ROW_INIT always gets done on
+ * demand, if necessary.
+ */
+ if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
+ (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
+ {
+ /* Application has failed to call either png_read_start_image() or
+ * png_read_update_info() after setting transforms that expand pixels.
+ * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
+ */
+ png_error(png_ptr, "Uninitialized row");
+ }
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 3;
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_do_expand_palette(row_info, png_ptr->row_buf + 1,
+ png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
+ }
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 4;
+ else
+ {
+ if (png_ptr->num_trans != 0 &&
+ (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
+ png_do_expand(row_info, png_ptr->row_buf + 1,
+ &(png_ptr->trans_color));
else
- return;
-
- for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
- {
- *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
- *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
- }
+ png_do_expand(row_info, png_ptr->row_buf + 1,
+ NULL);
}
- else if (row_info->bit_depth == 16)
- {
- png_bytep rp;
- png_uint_32 i;
+ }
+#endif
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 6;
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) == 0 &&
+ (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ 0 /* at_start == false, because SWAP_ALPHA happens later */);
+#endif
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 8;
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
+ {
+ int rgb_error =
+ png_do_rgb_to_gray(png_ptr, row_info,
+ png_ptr->row_buf + 1);
- else
- return;
+ if (rgb_error != 0)
+ {
+ png_ptr->rgb_to_gray_status=1;
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
+ PNG_RGB_TO_GRAY_WARN)
+ png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
- for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
- {
- png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
- png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
- png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
- png_uint_32 red = (s0 + s1 + 65536) & 0xffff;
- png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
- *(rp ) = (png_byte)((red >> 8) & 0xff);
- *(rp + 1) = (png_byte)(red & 0xff);
- *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
- *(rp + 5) = (png_byte)(blue & 0xff);
- }
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
+ PNG_RGB_TO_GRAY_ERR)
+ png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
}
}
+#endif
+
+/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
+ *
+ * In most cases, the "simple transparency" should be done prior to doing
+ * gray-to-RGB, or you will have to test 3x as many bytes to check if a
+ * pixel is transparent. You would also need to make sure that the
+ * transparency information is upgraded to RGB.
+ *
+ * To summarize, the current flow is:
+ * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
+ * with background "in place" if transparent,
+ * convert to RGB if necessary
+ * - Gray + alpha -> composite with gray background and remove alpha bytes,
+ * convert to RGB if necessary
+ *
+ * To support RGB backgrounds for gray images we need:
+ * - Gray + simple transparency -> convert to RGB + simple transparency,
+ * compare 3 or 6 bytes and composite with
+ * background "in place" if transparent
+ * (3x compare/pixel compared to doing
+ * composite with gray bkgrnd)
+ * - Gray + alpha -> convert to RGB + alpha, composite with background and
+ * remove alpha bytes (3x float
+ * operations/pixel compared with composite
+ * on gray background)
+ *
+ * Greg's change will do this. The reason it wasn't done before is for
+ * performance, as this increases the per-pixel operations. If we would check
+ * in advance if the background was gray or RGB, and position the gray-to-RGB
+ * transform appropriately, then it would save a lot of work/time.
+ */
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ /* If gray -> RGB, do so now only if background is non-gray; else do later
+ * for performance reasons
+ */
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
+ (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
+ png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
+ png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ /* Because RGB_TO_GRAY does the gamma transform. */
+ (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
+ /* Because PNG_COMPOSE does the gamma transform if there is something to
+ * do (if there is an alpha channel or transparency.)
+ */
+ !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ ((png_ptr->num_trans != 0) ||
+ (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
+#endif
+ /* Because png_init_read_transformations transforms the palette, unless
+ * RGB_TO_GRAY will do the transform.
+ */
+ (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
+ png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
+#endif
+
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ 0 /* at_start == false, because SWAP_ALPHA happens later */);
+#endif
+
+#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
+ if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
+ (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
+ png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
+#endif
+
+#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
+ if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
+ png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
+ /* There is no harm in doing both of these because only one has any effect,
+ * by putting the 'scale' option first if the app asks for scale (either by
+ * calling the API or in a TRANSFORM flag) this is what happens.
+ */
+ if ((png_ptr->transformations & PNG_16_TO_8) != 0)
+ png_do_chop(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_QUANTIZE_SUPPORTED
+ if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
+ {
+ png_do_quantize(row_info, png_ptr->row_buf + 1,
+ png_ptr->palette_lookup, png_ptr->quantize_index);
+
+ if (row_info->rowbytes == 0)
+ png_error(png_ptr, "png_do_quantize returned rowbytes=0");
+ }
+#endif /* READ_QUANTIZE */
+
+#ifdef PNG_READ_EXPAND_16_SUPPORTED
+ /* Do the expansion now, after all the arithmetic has been done. Notice
+ * that previous transformations can handle the PNG_EXPAND_16 flag if this
+ * is efficient (particularly true in the case of gamma correction, where
+ * better accuracy results faster!)
+ */
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
+ png_do_expand_16(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ /* NOTE: moved here in 1.5.4 (from much later in this list.) */
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
+ (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
+ png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_INVERT_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
+ png_do_invert(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
+ png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_SHIFT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
+ png_do_unshift(row_info, png_ptr->row_buf + 1,
+ &(png_ptr->shift));
+#endif
+
+#ifdef PNG_READ_PACK_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACK) != 0)
+ png_do_unpack(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Added at libpng-1.5.10 */
+ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max >= 0)
+ png_do_check_palette_indexes(png_ptr, row_info);
+#endif
+
+#ifdef PNG_READ_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ png_do_bgr(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ png_do_packswap(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_FILLER_SUPPORTED
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
+ png_do_read_filler(row_info, png_ptr->row_buf + 1,
+ (png_uint_32)png_ptr->filler, png_ptr->flags);
+#endif
+
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
+ png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_16BIT_SUPPORTED
+#ifdef PNG_READ_SWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
+ png_do_swap(row_info, png_ptr->row_buf + 1);
+#endif
+#endif
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
+ {
+ if (png_ptr->read_user_transform_fn != NULL)
+ (*(png_ptr->read_user_transform_fn)) /* User read transform function */
+ (png_ptr, /* png_ptr */
+ row_info, /* row_info: */
+ /* png_uint_32 width; width of row */
+ /* png_size_t rowbytes; number of bytes in row */
+ /* png_byte color_type; color type of pixels */
+ /* png_byte bit_depth; bit depth of samples */
+ /* png_byte channels; number of channels (1-4) */
+ /* png_byte pixel_depth; bits per pixel (depth*channels) */
+ png_ptr->row_buf + 1); /* start of pixel data for row */
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
+ if (png_ptr->user_transform_depth != 0)
+ row_info->bit_depth = png_ptr->user_transform_depth;
+
+ if (png_ptr->user_transform_channels != 0)
+ row_info->channels = png_ptr->user_transform_channels;
+#endif
+ row_info->pixel_depth = (png_byte)(row_info->bit_depth *
+ row_info->channels);
+
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
+ }
+#endif
}
-#endif /* PNG_MNG_FEATURES_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED */
+
+#endif /* READ_TRANSFORMS */
+#endif /* READ */
diff --git a/thirdparty/libpng/pngrutil.c b/thirdparty/libpng/pngrutil.c
index d6c0e035..c9747fc2 100644
--- a/thirdparty/libpng/pngrutil.c
+++ b/thirdparty/libpng/pngrutil.c
@@ -1,8 +1,8 @@
/* pngrutil.c - utilities to read a PNG file
*
- * Last changed in libpng 1.5.9 [February 18, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.20 [December 3, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -18,10 +18,8 @@
#ifdef PNG_READ_SUPPORTED
-#define png_strtod(p,a,b) strtod(a,b)
-
png_uint_32 PNGAPI
-png_get_uint_31(png_structp png_ptr, png_const_bytep buf)
+png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
{
png_uint_32 uval = png_get_uint_32(buf);
@@ -40,7 +38,7 @@ png_get_uint_31(png_structp png_ptr, png_const_bytep buf)
#define PNG_FIXED_ERROR (-1)
static png_fixed_point /* PRIVATE */
-png_get_fixed_point(png_structp png_ptr, png_const_bytep buf)
+png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf)
{
png_uint_32 uval = png_get_uint_32(buf);
@@ -91,7 +89,13 @@ png_get_int_32)(png_const_bytep buf)
return uval;
uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */
- return -(png_int_32)uval;
+ if ((uval & 0x80000000) == 0) /* no overflow */
+ return -(png_int_32)uval;
+ /* The following has to be safe; this function only gets called on PNG data
+ * and if we get here that data is invalid. 0 is the most safe value and
+ * if not then an attacker would surely just generate a PNG with 0 instead.
+ */
+ return 0;
}
/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
@@ -100,7 +104,7 @@ png_get_uint_16)(png_const_bytep buf)
{
/* ANSI-C requires an int value to accomodate at least 16 bits so this
* works and allows the compiler not to worry about possible narrowing
- * on 32 bit systems. (Pre-ANSI systems did not make integers smaller
+ * on 32-bit systems. (Pre-ANSI systems did not make integers smaller
* than 16 bits either.)
*/
unsigned int val =
@@ -110,11 +114,11 @@ png_get_uint_16)(png_const_bytep buf)
return (png_uint_16)val;
}
-#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */
+#endif /* READ_INT_FUNCTIONS */
/* Read and check the PNG file signature */
void /* PRIVATE */
-png_read_sig(png_structp png_ptr, png_infop info_ptr)
+png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
{
png_size_t num_checked, num_to_check;
@@ -133,7 +137,7 @@ png_read_sig(png_structp png_ptr, png_infop info_ptr)
png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
png_ptr->sig_bytes = 8;
- if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+ if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
{
if (num_checked < 4 &&
png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
@@ -149,7 +153,7 @@ png_read_sig(png_structp png_ptr, png_infop info_ptr)
* Put the type name into png_ptr->chunk_name, and return the length.
*/
png_uint_32 /* PRIVATE */
-png_read_chunk_header(png_structp png_ptr)
+png_read_chunk_header(png_structrp png_ptr)
{
png_byte buf[8];
png_uint_32 length;
@@ -186,7 +190,7 @@ png_read_chunk_header(png_structp png_ptr)
/* Read data, and (optionally) run it through the CRC. */
void /* PRIVATE */
-png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
+png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length)
{
if (png_ptr == NULL)
return;
@@ -196,40 +200,40 @@ png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
}
/* Optionally skip data and then check the CRC. Depending on whether we
- * are reading a ancillary or critical chunk, and how the program has set
+ * are reading an ancillary or critical chunk, and how the program has set
* things up, we may calculate the CRC on the data and print a message.
* Returns '1' if there was a CRC error, '0' otherwise.
*/
int /* PRIVATE */
-png_crc_finish(png_structp png_ptr, png_uint_32 skip)
+png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
{
- png_size_t i;
- png_size_t istop = png_ptr->zbuf_size;
-
- for (i = (png_size_t)skip; i > istop; i -= istop)
+ /* The size of the local buffer for inflate is a good guess as to a
+ * reasonable size to use for buffering reads from the application.
+ */
+ while (skip > 0)
{
- png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
- }
+ png_uint_32 len;
+ png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];
- if (i)
- {
- png_crc_read(png_ptr, png_ptr->zbuf, i);
+ len = (sizeof tmpbuf);
+ if (len > skip)
+ len = skip;
+ skip -= len;
+
+ png_crc_read(png_ptr, tmpbuf, len);
}
- if (png_crc_error(png_ptr))
+ if (png_crc_error(png_ptr) != 0)
{
- if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name) ?
- !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) :
- (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))
+ if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ?
+ (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0 :
+ (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE) != 0)
{
png_chunk_warning(png_ptr, "CRC error");
}
else
- {
- png_chunk_benign_error(png_ptr, "CRC error");
- return (0);
- }
+ png_chunk_error(png_ptr, "CRC error");
return (1);
}
@@ -241,13 +245,13 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip)
* the data it has read thus far.
*/
int /* PRIVATE */
-png_crc_error(png_structp png_ptr)
+png_crc_error(png_structrp png_ptr)
{
png_byte crc_bytes[4];
png_uint_32 crc;
int need_crc = 1;
- if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name))
+ if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
{
if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
(PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
@@ -256,7 +260,7 @@ png_crc_error(png_structp png_ptr)
else /* critical */
{
- if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+ if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
need_crc = 0;
}
@@ -267,7 +271,7 @@ png_crc_error(png_structp png_ptr)
/* The chunk CRC must be serialized in a single I/O call. */
png_read_data(png_ptr, crc_bytes, 4);
- if (need_crc)
+ if (need_crc != 0)
{
crc = png_get_uint_32(crc_bytes);
return ((int)(crc != png_ptr->crc));
@@ -277,250 +281,552 @@ png_crc_error(png_structp png_ptr)
return (0);
}
-#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
-static png_size_t
-png_inflate(png_structp png_ptr, png_bytep data, png_size_t size,
- png_bytep output, png_size_t output_size)
+#if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
+ defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\
+ defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\
+ defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED)
+/* Manage the read buffer; this simply reallocates the buffer if it is not small
+ * enough (or if it is not allocated). The routine returns a pointer to the
+ * buffer; if an error occurs and 'warn' is set the routine returns NULL, else
+ * it will call png_error (via png_malloc) on failure. (warn == 2 means
+ * 'silent').
+ */
+static png_bytep
+png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
{
- png_size_t count = 0;
-
- /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't
- * even necessarily handle 65536 bytes) because the type uInt is "16 bits or
- * more". Consequently it is necessary to chunk the input to zlib. This
- * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value
- * that can be stored in a uInt.) It is possible to set ZLIB_IO_MAX to a
- * lower value in pngpriv.h and this may sometimes have a performance
- * advantage, because it forces access of the input data to be separated from
- * at least some of the use by some period of time.
- */
- png_ptr->zstream.next_in = data;
- /* avail_in is set below from 'size' */
- png_ptr->zstream.avail_in = 0;
+ png_bytep buffer = png_ptr->read_buffer;
- while (1)
+ if (buffer != NULL && new_size > png_ptr->read_buffer_size)
{
- int ret, avail;
+ png_ptr->read_buffer = NULL;
+ png_ptr->read_buffer = NULL;
+ png_ptr->read_buffer_size = 0;
+ png_free(png_ptr, buffer);
+ buffer = NULL;
+ }
- /* The setting of 'avail_in' used to be outside the loop; by setting it
- * inside it is possible to chunk the input to zlib and simply rely on
- * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o
- * data to be passed through zlib at the unavoidable cost of requiring a
- * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX
- * input bytes.
- */
- if (png_ptr->zstream.avail_in == 0 && size > 0)
+ if (buffer == NULL)
+ {
+ buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size));
+
+ if (buffer != NULL)
{
- if (size <= ZLIB_IO_MAX)
- {
- /* The value is less than ZLIB_IO_MAX so the cast is safe: */
- png_ptr->zstream.avail_in = (uInt)size;
- size = 0;
- }
+ png_ptr->read_buffer = buffer;
+ png_ptr->read_buffer_size = new_size;
+ }
+
+ else if (warn < 2) /* else silent */
+ {
+ if (warn != 0)
+ png_chunk_warning(png_ptr, "insufficient memory to read chunk");
else
- {
- png_ptr->zstream.avail_in = ZLIB_IO_MAX;
- size -= ZLIB_IO_MAX;
- }
+ png_chunk_error(png_ptr, "insufficient memory to read chunk");
}
+ }
- /* Reset the output buffer each time round - we empty it
- * after every inflate call.
- */
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = png_ptr->zbuf_size;
+ return buffer;
+}
+#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */
- ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
- avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+/* png_inflate_claim: claim the zstream for some nefarious purpose that involves
+ * decompression. Returns Z_OK on success, else a zlib error code. It checks
+ * the owner but, in final release builds, just issues a warning if some other
+ * chunk apparently owns the stream. Prior to release it does a png_error.
+ */
+static int
+png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
+{
+ if (png_ptr->zowner != 0)
+ {
+ char msg[64];
- /* First copy/count any new output - but only if we didn't
- * get an error code.
+ PNG_STRING_FROM_CHUNK(msg, png_ptr->zowner);
+ /* So the message that results is "<chunk> using zstream"; this is an
+ * internal error, but is very useful for debugging. i18n requirements
+ * are minimal.
*/
- if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
+ (void)png_safecat(msg, (sizeof msg), 4, " using zstream");
+#if PNG_RELEASE_BUILD
+ png_chunk_warning(png_ptr, msg);
+ png_ptr->zowner = 0;
+#else
+ png_chunk_error(png_ptr, msg);
+#endif
+ }
+
+ /* Implementation note: unlike 'png_deflate_claim' this internal function
+ * does not take the size of the data as an argument. Some efficiency could
+ * be gained by using this when it is known *if* the zlib stream itself does
+ * not record the number; however, this is an illusion: the original writer
+ * of the PNG may have selected a lower window size, and we really must
+ * follow that because, for systems with with limited capabilities, we
+ * would otherwise reject the application's attempts to use a smaller window
+ * size (zlib doesn't have an interface to say "this or lower"!).
+ *
+ * inflateReset2 was added to zlib 1.2.4; before this the window could not be
+ * reset, therefore it is necessary to always allocate the maximum window
+ * size with earlier zlibs just in case later compressed chunks need it.
+ */
+ {
+ int ret; /* zlib return code */
+#if PNG_ZLIB_VERNUM >= 0x1240
+
+# if defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_MAXIMUM_INFLATE_WINDOW)
+ int window_bits;
+
+ if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) ==
+ PNG_OPTION_ON)
{
- png_size_t space = avail; /* > 0, see above */
+ window_bits = 15;
+ png_ptr->zstream_start = 0; /* fixed window size */
+ }
- if (output != 0 && output_size > count)
- {
- png_size_t copy = output_size - count;
+ else
+ {
+ window_bits = 0;
+ png_ptr->zstream_start = 1;
+ }
+# else
+# define window_bits 0
+# endif
+#endif
- if (space < copy)
- copy = space;
+ /* Set this for safety, just in case the previous owner left pointers to
+ * memory allocations.
+ */
+ png_ptr->zstream.next_in = NULL;
+ png_ptr->zstream.avail_in = 0;
+ png_ptr->zstream.next_out = NULL;
+ png_ptr->zstream.avail_out = 0;
- png_memcpy(output + count, png_ptr->zbuf, copy);
- }
- count += space;
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
+ {
+#if PNG_ZLIB_VERNUM < 0x1240
+ ret = inflateReset(&png_ptr->zstream);
+#else
+ ret = inflateReset2(&png_ptr->zstream, window_bits);
+#endif
+ }
+
+ else
+ {
+#if PNG_ZLIB_VERNUM < 0x1240
+ ret = inflateInit(&png_ptr->zstream);
+#else
+ ret = inflateInit2(&png_ptr->zstream, window_bits);
+#endif
+
+ if (ret == Z_OK)
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
}
if (ret == Z_OK)
- continue;
+ png_ptr->zowner = owner;
+
+ else
+ png_zstream_error(png_ptr, ret);
+
+ return ret;
+ }
+
+#ifdef window_bits
+# undef window_bits
+#endif
+}
+
+#if PNG_ZLIB_VERNUM >= 0x1240
+/* Handle the start of the inflate stream if we called inflateInit2(strm,0);
+ * in this case some zlib versions skip validation of the CINFO field and, in
+ * certain circumstances, libpng may end up displaying an invalid image, in
+ * contrast to implementations that call zlib in the normal way (e.g. libpng
+ * 1.5).
+ */
+int /* PRIVATE */
+png_zlib_inflate(png_structrp png_ptr, int flush)
+{
+ if (png_ptr->zstream_start && png_ptr->zstream.avail_in > 0)
+ {
+ if ((*png_ptr->zstream.next_in >> 4) > 7)
+ {
+ png_ptr->zstream.msg = "invalid window size (libpng)";
+ return Z_DATA_ERROR;
+ }
+
+ png_ptr->zstream_start = 0;
+ }
+
+ return inflate(&png_ptr->zstream, flush);
+}
+#endif /* Zlib >= 1.2.4 */
- /* Termination conditions - always reset the zstream, it
- * must be left in inflateInit state.
+#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
+/* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to
+ * allow the caller to do multiple calls if required. If the 'finish' flag is
+ * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must
+ * be returned or there has been a problem, otherwise Z_SYNC_FLUSH is used and
+ * Z_OK or Z_STREAM_END will be returned on success.
+ *
+ * The input and output sizes are updated to the actual amounts of data consumed
+ * or written, not the amount available (as in a z_stream). The data pointers
+ * are not changed, so the next input is (data+input_size) and the next
+ * available output is (output+output_size).
+ */
+static int
+png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish,
+ /* INPUT: */ png_const_bytep input, png_uint_32p input_size_ptr,
+ /* OUTPUT: */ png_bytep output, png_alloc_size_t *output_size_ptr)
+{
+ if (png_ptr->zowner == owner) /* Else not claimed */
+ {
+ int ret;
+ png_alloc_size_t avail_out = *output_size_ptr;
+ png_uint_32 avail_in = *input_size_ptr;
+
+ /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it
+ * can't even necessarily handle 65536 bytes) because the type uInt is
+ * "16 bits or more". Consequently it is necessary to chunk the input to
+ * zlib. This code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the
+ * maximum value that can be stored in a uInt.) It is possible to set
+ * ZLIB_IO_MAX to a lower value in pngpriv.h and this may sometimes have
+ * a performance advantage, because it reduces the amount of data accessed
+ * at each step and that may give the OS more time to page it in.
*/
+ png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
+ /* avail_in and avail_out are set below from 'size' */
png_ptr->zstream.avail_in = 0;
- inflateReset(&png_ptr->zstream);
-
- if (ret == Z_STREAM_END)
- return count; /* NOTE: may be zero. */
+ png_ptr->zstream.avail_out = 0;
- /* Now handle the error codes - the API always returns 0
- * and the error message is dumped into the uncompressed
- * buffer if available.
+ /* Read directly into the output if it is available (this is set to
+ * a local buffer below if output is NULL).
*/
-# ifdef PNG_WARNINGS_SUPPORTED
+ if (output != NULL)
+ png_ptr->zstream.next_out = output;
+
+ do
{
- png_const_charp msg;
+ uInt avail;
+ Byte local_buffer[PNG_INFLATE_BUF_SIZE];
+
+ /* zlib INPUT BUFFER */
+ /* The setting of 'avail_in' used to be outside the loop; by setting it
+ * inside it is possible to chunk the input to zlib and simply rely on
+ * zlib to advance the 'next_in' pointer. This allows arbitrary
+ * amounts of data to be passed through zlib at the unavoidable cost of
+ * requiring a window save (memcpy of up to 32768 output bytes)
+ * every ZLIB_IO_MAX input bytes.
+ */
+ avail_in += png_ptr->zstream.avail_in; /* not consumed last time */
- if (png_ptr->zstream.msg != 0)
- msg = png_ptr->zstream.msg;
+ avail = ZLIB_IO_MAX;
- else switch (ret)
- {
- case Z_BUF_ERROR:
- msg = "Buffer error in compressed datastream";
- break;
+ if (avail_in < avail)
+ avail = (uInt)avail_in; /* safe: < than ZLIB_IO_MAX */
- case Z_DATA_ERROR:
- msg = "Data error in compressed datastream";
- break;
+ avail_in -= avail;
+ png_ptr->zstream.avail_in = avail;
- default:
- msg = "Incomplete compressed datastream";
- break;
+ /* zlib OUTPUT BUFFER */
+ avail_out += png_ptr->zstream.avail_out; /* not written last time */
+
+ avail = ZLIB_IO_MAX; /* maximum zlib can process */
+
+ if (output == NULL)
+ {
+ /* Reset the output buffer each time round if output is NULL and
+ * make available the full buffer, up to 'remaining_space'
+ */
+ png_ptr->zstream.next_out = local_buffer;
+ if ((sizeof local_buffer) < avail)
+ avail = (sizeof local_buffer);
}
- png_chunk_warning(png_ptr, msg);
- }
-# endif
+ if (avail_out < avail)
+ avail = (uInt)avail_out; /* safe: < ZLIB_IO_MAX */
+
+ png_ptr->zstream.avail_out = avail;
+ avail_out -= avail;
+
+ /* zlib inflate call */
+ /* In fact 'avail_out' may be 0 at this point, that happens at the end
+ * of the read when the final LZ end code was not passed at the end of
+ * the previous chunk of input data. Tell zlib if we have reached the
+ * end of the output buffer.
+ */
+ ret = PNG_INFLATE(png_ptr, avail_out > 0 ? Z_NO_FLUSH :
+ (finish ? Z_FINISH : Z_SYNC_FLUSH));
+ } while (ret == Z_OK);
+
+ /* For safety kill the local buffer pointer now */
+ if (output == NULL)
+ png_ptr->zstream.next_out = NULL;
+
+ /* Claw back the 'size' and 'remaining_space' byte counts. */
+ avail_in += png_ptr->zstream.avail_in;
+ avail_out += png_ptr->zstream.avail_out;
- /* 0 means an error - notice that this code simply ignores
- * zero length compressed chunks as a result.
+ /* Update the input and output sizes; the updated values are the amount
+ * consumed or written, effectively the inverse of what zlib uses.
*/
- return 0;
+ if (avail_out > 0)
+ *output_size_ptr -= avail_out;
+
+ if (avail_in > 0)
+ *input_size_ptr -= avail_in;
+
+ /* Ensure png_ptr->zstream.msg is set (even in the success case!) */
+ png_zstream_error(png_ptr, ret);
+ return ret;
+ }
+
+ else
+ {
+ /* This is a bad internal error. The recovery assigns to the zstream msg
+ * pointer, which is not owned by the caller, but this is safe; it's only
+ * used on errors!
+ */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");
+ return Z_STREAM_ERROR;
}
}
/*
- * Decompress trailing data in a chunk. The assumption is that chunkdata
+ * Decompress trailing data in a chunk. The assumption is that read_buffer
* points at an allocated area holding the contents of a chunk with a
* trailing compressed part. What we get back is an allocated area
* holding the original prefix part and an uncompressed version of the
* trailing part (the malloc area passed in is freed).
*/
-void /* PRIVATE */
-png_decompress_chunk(png_structp png_ptr, int comp_type,
- png_size_t chunklength,
- png_size_t prefix_size, png_size_t *newlength)
+static int
+png_decompress_chunk(png_structrp png_ptr,
+ png_uint_32 chunklength, png_uint_32 prefix_size,
+ png_alloc_size_t *newlength /* must be initialized to the maximum! */,
+ int terminate /*add a '\0' to the end of the uncompressed data*/)
{
- /* The caller should guarantee this */
- if (prefix_size > chunklength)
- {
- /* The recovery is to delete the chunk. */
- png_warning(png_ptr, "invalid chunklength");
- prefix_size = 0; /* To delete everything */
- }
+ /* TODO: implement different limits for different types of chunk.
+ *
+ * The caller supplies *newlength set to the maximum length of the
+ * uncompressed data, but this routine allocates space for the prefix and
+ * maybe a '\0' terminator too. We have to assume that 'prefix_size' is
+ * limited only by the maximum chunk size.
+ */
+ png_alloc_size_t limit = PNG_SIZE_MAX;
- else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
+# ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (png_ptr->user_chunk_malloc_max > 0 &&
+ png_ptr->user_chunk_malloc_max < limit)
+ limit = png_ptr->user_chunk_malloc_max;
+# elif PNG_USER_CHUNK_MALLOC_MAX > 0
+ if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+ limit = PNG_USER_CHUNK_MALLOC_MAX;
+# endif
+
+ if (limit >= prefix_size + (terminate != 0))
{
- png_size_t expanded_size = png_inflate(png_ptr,
- (png_bytep)(png_ptr->chunkdata + prefix_size),
- chunklength - prefix_size,
- 0, /* output */
- 0); /* output size */
+ int ret;
- /* Now check the limits on this chunk - if the limit fails the
- * compressed data will be removed, the prefix will remain.
- */
- if (prefix_size >= (~(png_size_t)0) - 1 ||
- expanded_size >= (~(png_size_t)0) - 1 - prefix_size
-#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
- || (png_ptr->user_chunk_malloc_max &&
- (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
-#else
-# ifdef PNG_USER_CHUNK_MALLOC_MAX
- || ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
- prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
-# endif
-#endif
- )
- png_warning(png_ptr, "Exceeded size limit while expanding chunk");
+ limit -= prefix_size + (terminate != 0);
- /* If the size is zero either there was an error and a message
- * has already been output (warning) or the size really is zero
- * and we have nothing to do - the code will exit through the
- * error case below.
- */
- else if (expanded_size > 0)
+ if (limit < *newlength)
+ *newlength = limit;
+
+ /* Now try to claim the stream. */
+ ret = png_inflate_claim(png_ptr, png_ptr->chunk_name);
+
+ if (ret == Z_OK)
{
- /* Success (maybe) - really uncompress the chunk. */
- png_size_t new_size = 0;
- png_charp text = (png_charp)png_malloc_warn(png_ptr,
- prefix_size + expanded_size + 1);
+ png_uint_32 lzsize = chunklength - prefix_size;
- if (text != NULL)
+ ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
+ /* input: */ png_ptr->read_buffer + prefix_size, &lzsize,
+ /* output: */ NULL, newlength);
+
+ if (ret == Z_STREAM_END)
{
- png_memcpy(text, png_ptr->chunkdata, prefix_size);
- new_size = png_inflate(png_ptr,
- (png_bytep)(png_ptr->chunkdata + prefix_size),
- chunklength - prefix_size,
- (png_bytep)(text + prefix_size), expanded_size);
- text[prefix_size + expanded_size] = 0; /* just in case */
-
- if (new_size == expanded_size)
+ /* Use 'inflateReset' here, not 'inflateReset2' because this
+ * preserves the previously decided window size (otherwise it would
+ * be necessary to store the previous window size.) In practice
+ * this doesn't matter anyway, because png_inflate will call inflate
+ * with Z_FINISH in almost all cases, so the window will not be
+ * maintained.
+ */
+ if (inflateReset(&png_ptr->zstream) == Z_OK)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = text;
- *newlength = prefix_size + expanded_size;
- return; /* The success return! */
+ /* Because of the limit checks above we know that the new,
+ * expanded, size will fit in a size_t (let alone an
+ * png_alloc_size_t). Use png_malloc_base here to avoid an
+ * extra OOM message.
+ */
+ png_alloc_size_t new_size = *newlength;
+ png_alloc_size_t buffer_size = prefix_size + new_size +
+ (terminate != 0);
+ png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr,
+ buffer_size));
+
+ if (text != NULL)
+ {
+ ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
+ png_ptr->read_buffer + prefix_size, &lzsize,
+ text + prefix_size, newlength);
+
+ if (ret == Z_STREAM_END)
+ {
+ if (new_size == *newlength)
+ {
+ if (terminate != 0)
+ text[prefix_size + *newlength] = 0;
+
+ if (prefix_size > 0)
+ memcpy(text, png_ptr->read_buffer, prefix_size);
+
+ {
+ png_bytep old_ptr = png_ptr->read_buffer;
+
+ png_ptr->read_buffer = text;
+ png_ptr->read_buffer_size = buffer_size;
+ text = old_ptr; /* freed below */
+ }
+ }
+
+ else
+ {
+ /* The size changed on the second read, there can be no
+ * guarantee that anything is correct at this point.
+ * The 'msg' pointer has been set to "unexpected end of
+ * LZ stream", which is fine, but return an error code
+ * that the caller won't accept.
+ */
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+ }
+ }
+
+ else if (ret == Z_OK)
+ ret = PNG_UNEXPECTED_ZLIB_RETURN; /* for safety */
+
+ /* Free the text pointer (this is the old read_buffer on
+ * success)
+ */
+ png_free(png_ptr, text);
+
+ /* This really is very benign, but it's still an error because
+ * the extra space may otherwise be used as a Trojan Horse.
+ */
+ if (ret == Z_STREAM_END &&
+ chunklength - prefix_size != lzsize)
+ png_chunk_benign_error(png_ptr, "extra compressed data");
+ }
+
+ else
+ {
+ /* Out of memory allocating the buffer */
+ ret = Z_MEM_ERROR;
+ png_zstream_error(png_ptr, Z_MEM_ERROR);
+ }
}
- png_warning(png_ptr, "png_inflate logic error");
- png_free(png_ptr, text);
+ else
+ {
+ /* inflateReset failed, store the error message */
+ png_zstream_error(png_ptr, ret);
+
+ if (ret == Z_STREAM_END)
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+ }
}
- else
- png_warning(png_ptr, "Not enough memory to decompress chunk");
+ else if (ret == Z_OK)
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+
+ /* Release the claimed stream */
+ png_ptr->zowner = 0;
}
+
+ else /* the claim failed */ if (ret == Z_STREAM_END) /* impossible! */
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+
+ return ret;
}
- else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
+ else
{
- PNG_WARNING_PARAMETERS(p)
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, comp_type);
- png_formatted_warning(png_ptr, p, "Unknown compression type @1");
-
- /* The recovery is to simply drop the data. */
+ /* Application/configuration limits exceeded */
+ png_zstream_error(png_ptr, Z_MEM_ERROR);
+ return Z_MEM_ERROR;
}
+}
+#endif /* READ_COMPRESSED_TEXT */
- /* Generic error return - leave the prefix, delete the compressed
- * data, reallocate the chunkdata to remove the potentially large
- * amount of compressed data.
- */
+#ifdef PNG_READ_iCCP_SUPPORTED
+/* Perform a partial read and decompress, producing 'avail_out' bytes and
+ * reading from the current chunk as required.
+ */
+static int
+png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size,
+ png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size,
+ int finish)
+{
+ if (png_ptr->zowner == png_ptr->chunk_name)
{
- png_charp text = (png_charp)png_malloc_warn(png_ptr, prefix_size + 1);
+ int ret;
- if (text != NULL)
+ /* next_in and avail_in must have been initialized by the caller. */
+ png_ptr->zstream.next_out = next_out;
+ png_ptr->zstream.avail_out = 0; /* set in the loop */
+
+ do
{
- if (prefix_size > 0)
- png_memcpy(text, png_ptr->chunkdata, prefix_size);
+ if (png_ptr->zstream.avail_in == 0)
+ {
+ if (read_size > *chunk_bytes)
+ read_size = (uInt)*chunk_bytes;
+ *chunk_bytes -= read_size;
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = text;
+ if (read_size > 0)
+ png_crc_read(png_ptr, read_buffer, read_size);
+
+ png_ptr->zstream.next_in = read_buffer;
+ png_ptr->zstream.avail_in = read_size;
+ }
+
+ if (png_ptr->zstream.avail_out == 0)
+ {
+ uInt avail = ZLIB_IO_MAX;
+ if (avail > *out_size)
+ avail = (uInt)*out_size;
+ *out_size -= avail;
+
+ png_ptr->zstream.avail_out = avail;
+ }
- /* This is an extra zero in the 'uncompressed' part. */
- *(png_ptr->chunkdata + prefix_size) = 0x00;
+ /* Use Z_SYNC_FLUSH when there is no more chunk data to ensure that all
+ * the available output is produced; this allows reading of truncated
+ * streams.
+ */
+ ret = PNG_INFLATE(png_ptr,
+ *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH));
}
- /* Ignore a malloc error here - it is safe. */
+ while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0));
+
+ *out_size += png_ptr->zstream.avail_out;
+ png_ptr->zstream.avail_out = 0; /* Should not be required, but is safe */
+
+ /* Ensure the error message pointer is always set: */
+ png_zstream_error(png_ptr, ret);
+ return ret;
}
- *newlength = prefix_size;
+ else
+ {
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");
+ return Z_STREAM_ERROR;
+ }
}
-#endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */
+#endif
/* Read and check the IDHR chunk */
+
void /* PRIVATE */
-png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[13];
png_uint_32 width, height;
@@ -529,12 +835,12 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_IHDR");
- if (png_ptr->mode & PNG_HAVE_IHDR)
- png_error(png_ptr, "Out of place IHDR");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) != 0)
+ png_chunk_error(png_ptr, "out of place");
/* Check the length */
if (length != 13)
- png_error(png_ptr, "Invalid IHDR chunk");
+ png_chunk_error(png_ptr, "invalid");
png_ptr->mode |= PNG_HAVE_IHDR;
@@ -583,8 +889,7 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
/* Set up other useful info */
- png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
- png_ptr->channels);
+ png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * png_ptr->channels);
png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
png_debug1(3, "channels = %d", png_ptr->channels);
@@ -595,36 +900,43 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Read and check the palette */
void /* PRIVATE */
-png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_color palette[PNG_MAX_PALETTE_LENGTH];
- int num, i;
+ int max_palette_length, num, i;
#ifdef PNG_POINTER_INDEXING_SUPPORTED
png_colorp pal_ptr;
#endif
png_debug(1, "in png_handle_PLTE");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before PLTE");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
+
+ /* Moved to before the 'after IDAT' check below because otherwise duplicate
+ * PLTE chunks are potentially ignored (the spec says there shall not be more
+ * than one PLTE, the error is not treated as benign, so this check trumps
+ * the requirement that PLTE appears before IDAT.)
+ */
+ else if ((png_ptr->mode & PNG_HAVE_PLTE) != 0)
+ png_chunk_error(png_ptr, "duplicate");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid PLTE after IDAT");
+ /* This is benign because the non-benign error happened before, when an
+ * IDAT was encountered in a color-mapped image with no PLTE.
+ */
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- png_error(png_ptr, "Duplicate PLTE chunk");
-
png_ptr->mode |= PNG_HAVE_PLTE;
- if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
- png_warning(png_ptr,
- "Ignoring PLTE chunk in grayscale PNG");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "ignored in grayscale PNG");
return;
}
@@ -638,21 +950,33 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
{
+ png_crc_finish(png_ptr, length);
+
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
- {
- png_warning(png_ptr, "Invalid palette chunk");
- png_crc_finish(png_ptr, length);
- return;
- }
+ png_chunk_benign_error(png_ptr, "invalid");
else
- {
- png_error(png_ptr, "Invalid palette chunk");
- }
+ png_chunk_error(png_ptr, "invalid");
+
+ return;
}
+ /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
num = (int)length / 3;
+ /* If the palette has 256 or fewer entries but is too large for the bit
+ * depth, we don't issue an error, to preserve the behavior of previous
+ * libpng versions. We silently truncate the unused extra palette entries
+ * here.
+ */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ max_palette_length = (1 << png_ptr->bit_depth);
+ else
+ max_palette_length = PNG_MAX_PALETTE_LENGTH;
+
+ if (num > max_palette_length)
+ num = max_palette_length;
+
#ifdef PNG_POINTER_INDEXING_SUPPORTED
for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
{
@@ -685,218 +1009,202 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
#endif
{
- png_crc_finish(png_ptr, 0);
+ png_crc_finish(png_ptr, (int) length - num * 3);
}
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
- else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
+ else if (png_crc_error(png_ptr) != 0) /* Only if we have a CRC error */
{
/* If we don't want to use the data from an ancillary chunk,
* we have two options: an error abort, or a warning and we
* ignore the data in this chunk (which should be OK, since
* it's considered ancillary for a RGB or RGBA image).
+ *
+ * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the
+ * chunk type to determine whether to check the ancillary or the critical
+ * flags.
*/
- if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
+ if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE) == 0)
{
- if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
- {
- png_chunk_benign_error(png_ptr, "CRC error");
- }
+ if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) != 0)
+ return;
else
- {
- png_chunk_warning(png_ptr, "CRC error");
- return;
- }
+ png_chunk_error(png_ptr, "CRC error");
}
/* Otherwise, we (optionally) emit a warning and use the chunk. */
- else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
- {
+ else if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0)
png_chunk_warning(png_ptr, "CRC error");
- }
}
#endif
+ /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its
+ * own copy of the palette. This has the side effect that when png_start_row
+ * is called (this happens after any call to png_read_update_info) the
+ * info_ptr palette gets changed. This is extremely unexpected and
+ * confusing.
+ *
+ * Fix this by not sharing the palette in this way.
+ */
png_set_PLTE(png_ptr, info_ptr, palette, num);
+ /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before
+ * IDAT. Prior to 1.6.0 this was not checked; instead the code merely
+ * checked the apparent validity of a tRNS chunk inserted before PLTE on a
+ * palette PNG. 1.6.0 attempts to rigorously follow the standard and
+ * therefore does a benign error if the erroneous condition is detected *and*
+ * cancels the tRNS if the benign error returns. The alternative is to
+ * amend the standard since it would be rather hypocritical of the standards
+ * maintainers to ignore it.
+ */
#ifdef PNG_READ_tRNS_SUPPORTED
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ if (png_ptr->num_trans > 0 ||
+ (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0))
{
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
- {
- if (png_ptr->num_trans > (png_uint_16)num)
- {
- png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
- png_ptr->num_trans = (png_uint_16)num;
- }
+ /* Cancel this because otherwise it would be used if the transforms
+ * require it. Don't cancel the 'valid' flag because this would prevent
+ * detection of duplicate chunks.
+ */
+ png_ptr->num_trans = 0;
- if (info_ptr->num_trans > (png_uint_16)num)
- {
- png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
- info_ptr->num_trans = (png_uint_16)num;
- }
- }
+ if (info_ptr != NULL)
+ info_ptr->num_trans = 0;
+
+ png_chunk_benign_error(png_ptr, "tRNS must be after");
}
#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
+ png_chunk_benign_error(png_ptr, "hIST must be after");
+#endif
+
+#ifdef PNG_READ_bKGD_SUPPORTED
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
+ png_chunk_benign_error(png_ptr, "bKGD must be after");
+#endif
}
void /* PRIVATE */
-png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_debug(1, "in png_handle_IEND");
- if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
- {
- png_error(png_ptr, "No image in file");
- }
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0 ||
+ (png_ptr->mode & PNG_HAVE_IDAT) == 0)
+ png_chunk_error(png_ptr, "out of place");
png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
- if (length != 0)
- {
- png_warning(png_ptr, "Incorrect IEND chunk length");
- }
-
png_crc_finish(png_ptr, length);
- PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
+ if (length != 0)
+ png_chunk_benign_error(png_ptr, "invalid");
+
+ PNG_UNUSED(info_ptr)
}
#ifdef PNG_READ_gAMA_SUPPORTED
void /* PRIVATE */
-png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_fixed_point igamma;
png_byte buf[4];
png_debug(1, "in png_handle_gAMA");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before gAMA");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Invalid gAMA after IDAT");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place gAMA chunk");
-
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
-#ifdef PNG_READ_sRGB_SUPPORTED
- && !(info_ptr->valid & PNG_INFO_sRGB)
-#endif
- )
- {
- png_warning(png_ptr, "Duplicate gAMA chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (length != 4)
{
- png_warning(png_ptr, "Incorrect gAMA chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 4);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
igamma = png_get_fixed_point(NULL, buf);
- /* Check for zero gamma or an error. */
- if (igamma <= 0)
- {
- png_warning(png_ptr,
- "Ignoring gAMA chunk with out of range gamma");
-
- return;
- }
-
-# ifdef PNG_READ_sRGB_SUPPORTED
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
- {
- if (PNG_OUT_OF_RANGE(igamma, 45500, 500))
- {
- PNG_WARNING_PARAMETERS(p)
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, igamma);
- png_formatted_warning(png_ptr, p,
- "Ignoring incorrect gAMA value @1 when sRGB is also present");
- return;
- }
- }
-# endif /* PNG_READ_sRGB_SUPPORTED */
-
-# ifdef PNG_READ_GAMMA_SUPPORTED
- /* Gamma correction on read is supported. */
- png_ptr->gamma = igamma;
-# endif
- /* And set the 'info' structure members. */
- png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
+ png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma);
+ png_colorspace_sync(png_ptr, info_ptr);
}
#endif
#ifdef PNG_READ_sBIT_SUPPORTED
void /* PRIVATE */
-png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_size_t truelen;
+ unsigned int truelen, i;
+ png_byte sample_depth;
png_byte buf[4];
png_debug(1, "in png_handle_sBIT");
- buf[0] = buf[1] = buf[2] = buf[3] = 0;
-
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sBIT");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Invalid sBIT after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->mode & PNG_HAVE_PLTE)
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) != 0)
{
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place sBIT chunk");
- }
-
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
- {
- png_warning(png_ptr, "Duplicate sBIT chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
truelen = 3;
+ sample_depth = 8;
+ }
else
- truelen = (png_size_t)png_ptr->channels;
+ {
+ truelen = png_ptr->channels;
+ sample_depth = png_ptr->bit_depth;
+ }
if (length != truelen || length > 4)
{
- png_warning(png_ptr, "Incorrect sBIT chunk length");
+ png_chunk_benign_error(png_ptr, "invalid");
png_crc_finish(png_ptr, length);
return;
}
+ buf[0] = buf[1] = buf[2] = buf[3] = sample_depth;
png_crc_read(png_ptr, buf, truelen);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ for (i=0; i<truelen; ++i)
+ {
+ if (buf[i] == 0 || buf[i] > sample_depth)
+ {
+ png_chunk_benign_error(png_ptr, "invalid");
+ return;
+ }
+ }
+
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_ptr->sig_bit.red = buf[0];
png_ptr->sig_bit.green = buf[1];
@@ -919,471 +1227,418 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_cHRM_SUPPORTED
void /* PRIVATE */
-png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[32];
- png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue,
- y_blue;
+ png_xy xy;
png_debug(1, "in png_handle_cHRM");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before cHRM");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Invalid cHRM after IDAT");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place cHRM chunk");
-
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
-# ifdef PNG_READ_sRGB_SUPPORTED
- && !(info_ptr->valid & PNG_INFO_sRGB)
-# endif
- )
- {
- png_warning(png_ptr, "Duplicate cHRM chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (length != 32)
{
- png_warning(png_ptr, "Incorrect cHRM chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 32);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- x_white = png_get_fixed_point(NULL, buf);
- y_white = png_get_fixed_point(NULL, buf + 4);
- x_red = png_get_fixed_point(NULL, buf + 8);
- y_red = png_get_fixed_point(NULL, buf + 12);
- x_green = png_get_fixed_point(NULL, buf + 16);
- y_green = png_get_fixed_point(NULL, buf + 20);
- x_blue = png_get_fixed_point(NULL, buf + 24);
- y_blue = png_get_fixed_point(NULL, buf + 28);
-
- if (x_white == PNG_FIXED_ERROR ||
- y_white == PNG_FIXED_ERROR ||
- x_red == PNG_FIXED_ERROR ||
- y_red == PNG_FIXED_ERROR ||
- x_green == PNG_FIXED_ERROR ||
- y_green == PNG_FIXED_ERROR ||
- x_blue == PNG_FIXED_ERROR ||
- y_blue == PNG_FIXED_ERROR)
- {
- png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities");
+ xy.whitex = png_get_fixed_point(NULL, buf);
+ xy.whitey = png_get_fixed_point(NULL, buf + 4);
+ xy.redx = png_get_fixed_point(NULL, buf + 8);
+ xy.redy = png_get_fixed_point(NULL, buf + 12);
+ xy.greenx = png_get_fixed_point(NULL, buf + 16);
+ xy.greeny = png_get_fixed_point(NULL, buf + 20);
+ xy.bluex = png_get_fixed_point(NULL, buf + 24);
+ xy.bluey = png_get_fixed_point(NULL, buf + 28);
+
+ if (xy.whitex == PNG_FIXED_ERROR ||
+ xy.whitey == PNG_FIXED_ERROR ||
+ xy.redx == PNG_FIXED_ERROR ||
+ xy.redy == PNG_FIXED_ERROR ||
+ xy.greenx == PNG_FIXED_ERROR ||
+ xy.greeny == PNG_FIXED_ERROR ||
+ xy.bluex == PNG_FIXED_ERROR ||
+ xy.bluey == PNG_FIXED_ERROR)
+ {
+ png_chunk_benign_error(png_ptr, "invalid values");
return;
}
-#ifdef PNG_READ_sRGB_SUPPORTED
- if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
- {
- if (PNG_OUT_OF_RANGE(x_white, 31270, 1000) ||
- PNG_OUT_OF_RANGE(y_white, 32900, 1000) ||
- PNG_OUT_OF_RANGE(x_red, 64000, 1000) ||
- PNG_OUT_OF_RANGE(y_red, 33000, 1000) ||
- PNG_OUT_OF_RANGE(x_green, 30000, 1000) ||
- PNG_OUT_OF_RANGE(y_green, 60000, 1000) ||
- PNG_OUT_OF_RANGE(x_blue, 15000, 1000) ||
- PNG_OUT_OF_RANGE(y_blue, 6000, 1000))
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, x_white);
- png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_fixed, y_white);
- png_warning_parameter_signed(p, 3, PNG_NUMBER_FORMAT_fixed, x_red);
- png_warning_parameter_signed(p, 4, PNG_NUMBER_FORMAT_fixed, y_red);
- png_warning_parameter_signed(p, 5, PNG_NUMBER_FORMAT_fixed, x_green);
- png_warning_parameter_signed(p, 6, PNG_NUMBER_FORMAT_fixed, y_green);
- png_warning_parameter_signed(p, 7, PNG_NUMBER_FORMAT_fixed, x_blue);
- png_warning_parameter_signed(p, 8, PNG_NUMBER_FORMAT_fixed, y_blue);
-
- png_formatted_warning(png_ptr, p,
- "Ignoring incorrect cHRM white(@1,@2) r(@3,@4)g(@5,@6)b(@7,@8) "
- "when sRGB is also present");
- }
+ /* If a colorspace error has already been output skip this chunk */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
return;
- }
-#endif /* PNG_READ_sRGB_SUPPORTED */
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- /* Store the _white values as default coefficients for the rgb to gray
- * operation if it is supported. Check if the transform is already set to
- * avoid destroying the transform values.
- */
- if (!png_ptr->rgb_to_gray_coefficients_set)
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0)
{
- /* png_set_background has not been called and we haven't seen an sRGB
- * chunk yet. Find the XYZ of the three end points.
- */
- png_XYZ XYZ;
- png_xy xy;
-
- xy.redx = x_red;
- xy.redy = y_red;
- xy.greenx = x_green;
- xy.greeny = y_green;
- xy.bluex = x_blue;
- xy.bluey = y_blue;
- xy.whitex = x_white;
- xy.whitey = y_white;
-
- if (png_XYZ_from_xy_checked(png_ptr, &XYZ, xy))
- {
- /* The success case, because XYZ_from_xy normalises to a reference
- * white Y of 1.0 we just need to scale the numbers. This should
- * always work just fine. It is an internal error if this overflows.
- */
- {
- png_fixed_point r, g, b;
- if (png_muldiv(&r, XYZ.redY, 32768, PNG_FP_1) &&
- r >= 0 && r <= 32768 &&
- png_muldiv(&g, XYZ.greenY, 32768, PNG_FP_1) &&
- g >= 0 && g <= 32768 &&
- png_muldiv(&b, XYZ.blueY, 32768, PNG_FP_1) &&
- b >= 0 && b <= 32768 &&
- r+g+b <= 32769)
- {
- /* We allow 0 coefficients here. r+g+b may be 32769 if two or
- * all of the coefficients were rounded up. Handle this by
- * reducing the *largest* coefficient by 1; this matches the
- * approach used for the default coefficients in pngrtran.c
- */
- int add = 0;
-
- if (r+g+b > 32768)
- add = -1;
- else if (r+g+b < 32768)
- add = 1;
-
- if (add != 0)
- {
- if (g >= r && g >= b)
- g += add;
- else if (r >= g && r >= b)
- r += add;
- else
- b += add;
- }
-
- /* Check for an internal error. */
- if (r+g+b != 32768)
- png_error(png_ptr,
- "internal error handling cHRM coefficients");
-
- png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r;
- png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
- }
-
- /* This is a png_error at present even though it could be ignored -
- * it should never happen, but it is important that if it does, the
- * bug is fixed.
- */
- else
- png_error(png_ptr, "internal error handling cHRM->XYZ");
- }
- }
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+ png_colorspace_sync(png_ptr, info_ptr);
+ png_chunk_benign_error(png_ptr, "duplicate");
+ return;
}
-#endif
- png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red,
- x_green, y_green, x_blue, y_blue);
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+ (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy,
+ 1/*prefer cHRM values*/);
+ png_colorspace_sync(png_ptr, info_ptr);
}
#endif
#ifdef PNG_READ_sRGB_SUPPORTED
void /* PRIVATE */
-png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- int intent;
- png_byte buf[1];
+ png_byte intent;
png_debug(1, "in png_handle_sRGB");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sRGB");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Invalid sRGB after IDAT");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place sRGB chunk");
-
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
- {
- png_warning(png_ptr, "Duplicate sRGB chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (length != 1)
{
- png_warning(png_ptr, "Incorrect sRGB chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- png_crc_read(png_ptr, buf, 1);
+ png_crc_read(png_ptr, &intent, 1);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- intent = buf[0];
-
- /* Check for bad intent */
- if (intent >= PNG_sRGB_INTENT_LAST)
- {
- png_warning(png_ptr, "Unknown sRGB intent");
+ /* If a colorspace error has already been output skip this chunk */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
return;
- }
-#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
+ /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
+ * this.
+ */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) != 0)
{
- if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500, 500))
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed,
- info_ptr->gamma);
-
- png_formatted_warning(png_ptr, p,
- "Ignoring incorrect gAMA value @1 when sRGB is also present");
- }
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+ png_colorspace_sync(png_ptr, info_ptr);
+ png_chunk_benign_error(png_ptr, "too many profiles");
+ return;
}
-#endif /* PNG_READ_gAMA_SUPPORTED */
-#ifdef PNG_READ_cHRM_SUPPORTED
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
- if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->x_red, 64000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->y_green, 60000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000))
- {
- png_warning(png_ptr,
- "Ignoring incorrect cHRM value when sRGB is also present");
- }
-#endif /* PNG_READ_cHRM_SUPPORTED */
-
- /* This is recorded for use when handling the cHRM chunk above. An sRGB
- * chunk unconditionally overwrites the coefficients for grayscale conversion
- * too.
- */
- png_ptr->is_sRGB = 1;
-
-# ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- /* Don't overwrite user supplied values: */
- if (!png_ptr->rgb_to_gray_coefficients_set)
- {
- /* These numbers come from the sRGB specification (or, since one has to
- * pay much money to get a copy, the wikipedia sRGB page) the
- * chromaticity values quoted have been inverted to get the reverse
- * transformation from RGB to XYZ and the 'Y' coefficients scaled by
- * 32768 (then rounded).
- *
- * sRGB and ITU Rec-709 both truncate the values for the D65 white
- * point to four digits and, even though it actually stores five
- * digits, the PNG spec gives the truncated value.
- *
- * This means that when the chromaticities are converted back to XYZ
- * end points we end up with (6968,23435,2366), which, as described in
- * pngrtran.c, would overflow. If the five digit precision and up is
- * used we get, instead:
- *
- * 6968*R + 23435*G + 2365*B
- *
- * (Notice that this rounds the blue coefficient down, rather than the
- * choice used in pngrtran.c which is to round the green one down.)
- */
- png_ptr->rgb_to_gray_red_coeff = 6968; /* 0.212639005871510 */
- png_ptr->rgb_to_gray_green_coeff = 23434; /* 0.715168678767756 */
- /* png_ptr->rgb_to_gray_blue_coeff = 2366; 0.072192315360734 */
-
- /* The following keeps the cHRM chunk from destroying the
- * coefficients again in the event that it follows the sRGB chunk.
- */
- png_ptr->rgb_to_gray_coefficients_set = 1;
- }
-# endif
-
- png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
+ (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent);
+ png_colorspace_sync(png_ptr, info_ptr);
}
-#endif /* PNG_READ_sRGB_SUPPORTED */
+#endif /* READ_sRGB */
#ifdef PNG_READ_iCCP_SUPPORTED
void /* PRIVATE */
-png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
-/* Note: this does not properly handle chunks that are > 64K under DOS */
+png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+/* Note: this does not properly handle profiles that are > 64K under DOS */
{
- png_byte compression_type;
- png_bytep pC;
- png_charp profile;
- png_uint_32 skip = 0;
- png_uint_32 profile_size;
- png_alloc_size_t profile_length;
- png_size_t slength, prefix_length, data_length;
+ png_const_charp errmsg = NULL; /* error message output, or no error */
+ int finished = 0; /* crc checked */
png_debug(1, "in png_handle_iCCP");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before iCCP");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Invalid iCCP after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place iCCP chunk");
-
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
+ /* Consistent with all the above colorspace handling an obviously *invalid*
+ * chunk is just ignored, so does not invalidate the color space. An
+ * alternative is to set the 'invalid' flags at the start of this routine
+ * and only clear them in they were not set before and all the tests pass.
+ * The minimum 'deflate' stream is assumed to be just the 2 byte header and
+ * 4 byte checksum. The keyword must be at least one character and there is
+ * a terminator (0) byte and the compression method.
+ */
+ if (length < 9)
{
- png_warning(png_ptr, "Duplicate iCCP chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "too short");
return;
}
-#ifdef PNG_MAX_MALLOC_64K
- if (length > (png_uint_32)65535L)
+ /* If a colorspace error has already been output skip this chunk */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
{
- png_warning(png_ptr, "iCCP chunk too large to fit in memory");
- skip = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
+ png_crc_finish(png_ptr, length);
+ return;
}
-#endif
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
-
- if (png_crc_finish(png_ptr, skip))
+ /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
+ * this.
+ */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ uInt read_length, keyword_length;
+ char keyword[81];
- png_ptr->chunkdata[slength] = 0x00;
+ /* Find the keyword; the keyword plus separator and compression method
+ * bytes can be at most 81 characters long.
+ */
+ read_length = 81; /* maximum */
+ if (read_length > length)
+ read_length = (uInt)length;
- for (profile = png_ptr->chunkdata; *profile; profile++)
- /* Empty loop to find end of name */ ;
+ png_crc_read(png_ptr, (png_bytep)keyword, read_length);
+ length -= read_length;
- ++profile;
+ keyword_length = 0;
+ while (keyword_length < 80 && keyword_length < read_length &&
+ keyword[keyword_length] != 0)
+ ++keyword_length;
- /* There should be at least one zero (the compression type byte)
- * following the separator, and we should be on it
- */
- if (profile >= png_ptr->chunkdata + slength - 1)
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- png_warning(png_ptr, "Malformed iCCP chunk");
- return;
- }
+ /* TODO: make the keyword checking common */
+ if (keyword_length >= 1 && keyword_length <= 79)
+ {
+ /* We only understand '0' compression - deflate - so if we get a
+ * different value we can't safely decode the chunk.
+ */
+ if (keyword_length+1 < read_length &&
+ keyword[keyword_length+1] == PNG_COMPRESSION_TYPE_BASE)
+ {
+ read_length -= keyword_length+2;
- /* Compression_type should always be zero */
- compression_type = *profile++;
+ if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK)
+ {
+ Byte profile_header[132];
+ Byte local_buffer[PNG_INFLATE_BUF_SIZE];
+ png_alloc_size_t size = (sizeof profile_header);
- if (compression_type)
- {
- png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
- compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
- wrote nonzero) */
- }
+ png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2);
+ png_ptr->zstream.avail_in = read_length;
+ (void)png_inflate_read(png_ptr, local_buffer,
+ (sizeof local_buffer), &length, profile_header, &size,
+ 0/*finish: don't, because the output is too small*/);
- prefix_length = profile - png_ptr->chunkdata;
- png_decompress_chunk(png_ptr, compression_type,
- slength, prefix_length, &data_length);
+ if (size == 0)
+ {
+ /* We have the ICC profile header; do the basic header checks.
+ */
+ const png_uint_32 profile_length =
+ png_get_uint_32(profile_header);
- profile_length = data_length - prefix_length;
+ if (png_icc_check_length(png_ptr, &png_ptr->colorspace,
+ keyword, profile_length) != 0)
+ {
+ /* The length is apparently ok, so we can check the 132
+ * byte header.
+ */
+ if (png_icc_check_header(png_ptr, &png_ptr->colorspace,
+ keyword, profile_length, profile_header,
+ png_ptr->color_type) != 0)
+ {
+ /* Now read the tag table; a variable size buffer is
+ * needed at this point, allocate one for the whole
+ * profile. The header check has already validated
+ * that none of these stuff will overflow.
+ */
+ const png_uint_32 tag_count = png_get_uint_32(
+ profile_header+128);
+ png_bytep profile = png_read_buffer(png_ptr,
+ profile_length, 2/*silent*/);
+
+ if (profile != NULL)
+ {
+ memcpy(profile, profile_header,
+ (sizeof profile_header));
+
+ size = 12 * tag_count;
+
+ (void)png_inflate_read(png_ptr, local_buffer,
+ (sizeof local_buffer), &length,
+ profile + (sizeof profile_header), &size, 0);
+
+ /* Still expect a buffer error because we expect
+ * there to be some tag data!
+ */
+ if (size == 0)
+ {
+ if (png_icc_check_tag_table(png_ptr,
+ &png_ptr->colorspace, keyword, profile_length,
+ profile) != 0)
+ {
+ /* The profile has been validated for basic
+ * security issues, so read the whole thing in.
+ */
+ size = profile_length - (sizeof profile_header)
+ - 12 * tag_count;
+
+ (void)png_inflate_read(png_ptr, local_buffer,
+ (sizeof local_buffer), &length,
+ profile + (sizeof profile_header) +
+ 12 * tag_count, &size, 1/*finish*/);
+
+ if (length > 0 && !(png_ptr->flags &
+ PNG_FLAG_BENIGN_ERRORS_WARN))
+ errmsg = "extra compressed data";
+
+ /* But otherwise allow extra data: */
+ else if (size == 0)
+ {
+ if (length > 0)
+ {
+ /* This can be handled completely, so
+ * keep going.
+ */
+ png_chunk_warning(png_ptr,
+ "extra compressed data");
+ }
+
+ png_crc_finish(png_ptr, length);
+ finished = 1;
+
+# ifdef PNG_sRGB_SUPPORTED
+ /* Check for a match against sRGB */
+ png_icc_set_sRGB(png_ptr,
+ &png_ptr->colorspace, profile,
+ png_ptr->zstream.adler);
+# endif
+
+ /* Steal the profile for info_ptr. */
+ if (info_ptr != NULL)
+ {
+ png_free_data(png_ptr, info_ptr,
+ PNG_FREE_ICCP, 0);
+
+ info_ptr->iccp_name = png_voidcast(char*,
+ png_malloc_base(png_ptr,
+ keyword_length+1));
+ if (info_ptr->iccp_name != NULL)
+ {
+ memcpy(info_ptr->iccp_name, keyword,
+ keyword_length+1);
+ info_ptr->iccp_proflen =
+ profile_length;
+ info_ptr->iccp_profile = profile;
+ png_ptr->read_buffer = NULL; /*steal*/
+ info_ptr->free_me |= PNG_FREE_ICCP;
+ info_ptr->valid |= PNG_INFO_iCCP;
+ }
+
+ else
+ {
+ png_ptr->colorspace.flags |=
+ PNG_COLORSPACE_INVALID;
+ errmsg = "out of memory";
+ }
+ }
+
+ /* else the profile remains in the read
+ * buffer which gets reused for subsequent
+ * chunks.
+ */
+
+ if (info_ptr != NULL)
+ png_colorspace_sync(png_ptr, info_ptr);
+
+ if (errmsg == NULL)
+ {
+ png_ptr->zowner = 0;
+ return;
+ }
+ }
+
+ else if (size > 0)
+ errmsg = "truncated";
+
+#ifndef __COVERITY__
+ else
+ errmsg = png_ptr->zstream.msg;
+#endif
+ }
- if (prefix_length > data_length || profile_length < 4)
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- png_warning(png_ptr, "Profile size field missing from iCCP chunk");
- return;
- }
+ /* else png_icc_check_tag_table output an error */
+ }
- /* Check the profile_size recorded in the first 32 bits of the ICC profile */
- pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
- profile_size = ((*(pC )) << 24) |
- ((*(pC + 1)) << 16) |
- ((*(pC + 2)) << 8) |
- ((*(pC + 3)) );
+ else /* profile truncated */
+ errmsg = png_ptr->zstream.msg;
+ }
- /* NOTE: the following guarantees that 'profile_length' fits into 32 bits,
- * because profile_size is a 32 bit value.
- */
- if (profile_size < profile_length)
- profile_length = profile_size;
+ else
+ errmsg = "out of memory";
+ }
- /* And the following guarantees that profile_size == profile_length. */
- if (profile_size > profile_length)
- {
- PNG_WARNING_PARAMETERS(p)
+ /* else png_icc_check_header output an error */
+ }
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ /* else png_icc_check_length output an error */
+ }
- png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_u, profile_size);
- png_warning_parameter_unsigned(p, 2, PNG_NUMBER_FORMAT_u, profile_length);
- png_formatted_warning(png_ptr, p,
- "Ignoring iCCP chunk with declared size = @1 and actual length = @2");
- return;
+ else /* profile truncated */
+ errmsg = png_ptr->zstream.msg;
+
+ /* Release the stream */
+ png_ptr->zowner = 0;
+ }
+
+ else /* png_inflate_claim failed */
+ errmsg = png_ptr->zstream.msg;
+ }
+
+ else
+ errmsg = "bad compression method"; /* or missing */
+ }
+
+ else
+ errmsg = "bad keyword";
}
- png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
- compression_type, (png_bytep)png_ptr->chunkdata + prefix_length,
- profile_size);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ else
+ errmsg = "too many profiles";
+
+ /* Failure: the reason is in 'errmsg' */
+ if (finished == 0)
+ png_crc_finish(png_ptr, length);
+
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+ png_colorspace_sync(png_ptr, info_ptr);
+ if (errmsg != NULL) /* else already output */
+ png_chunk_benign_error(png_ptr, errmsg);
}
-#endif /* PNG_READ_iCCP_SUPPORTED */
+#endif /* READ_iCCP */
#ifdef PNG_READ_sPLT_SUPPORTED
void /* PRIVATE */
-png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
/* Note: this does not properly handle chunks that are > 64K under DOS */
{
- png_bytep entry_start;
+ png_bytep entry_start, buffer;
png_sPLT_t new_palette;
png_sPLT_entryp pp;
png_uint_32 data_length;
int entry_size, i;
png_uint_32 skip = 0;
- png_size_t slength;
png_uint_32 dl;
png_size_t max_dl;
png_debug(1, "in png_handle_sPLT");
#ifdef PNG_USER_LIMITS_SUPPORTED
-
if (png_ptr->user_chunk_cache_max != 0)
{
if (png_ptr->user_chunk_cache_max == 1)
@@ -1401,55 +1656,53 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sPLT");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid sPLT after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
#ifdef PNG_MAX_MALLOC_64K
- if (length > (png_uint_32)65535L)
+ if (length > 65535U)
{
- png_warning(png_ptr, "sPLT chunk too large to fit in memory");
- skip = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "too large to fit in memory");
+ return;
}
#endif
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+ buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
+ if (buffer == NULL)
+ {
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
+ return;
+ }
+
/* WARNING: this may break if size_t is less than 32 bits; it is assumed
* that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a
* potential breakage point if the types in pngconf.h aren't exactly right.
*/
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, skip))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, skip) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00;
+ buffer[length] = 0;
- for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
- entry_start++)
+ for (entry_start = buffer; *entry_start; entry_start++)
/* Empty loop to find end of name */ ;
++entry_start;
/* A sample depth should follow the separator, and we should be on it */
- if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
+ if (length < 2U || entry_start > buffer + (length - 2U))
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_warning(png_ptr, "malformed sPLT chunk");
return;
}
@@ -1457,39 +1710,35 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
new_palette.depth = *entry_start++;
entry_size = (new_palette.depth == 8 ? 6 : 10);
/* This must fit in a png_uint_32 because it is derived from the original
- * chunk data length (and use 'length', not 'slength' here for clarity -
- * they are guaranteed to be the same, see the tests above.)
+ * chunk data length.
*/
- data_length = length - (png_uint_32)(entry_start -
- (png_bytep)png_ptr->chunkdata);
+ data_length = length - (png_uint_32)(entry_start - buffer);
/* Integrity-check the data length */
- if (data_length % entry_size)
+ if ((data_length % entry_size) != 0)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_warning(png_ptr, "sPLT chunk has bad length");
return;
}
dl = (png_int_32)(data_length / entry_size);
- max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry);
+ max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry));
if (dl > max_dl)
{
- png_warning(png_ptr, "sPLT chunk too long");
- return;
+ png_warning(png_ptr, "sPLT chunk too long");
+ return;
}
new_palette.nentries = (png_int_32)(data_length / entry_size);
new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
- png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
+ png_ptr, new_palette.nentries * (sizeof (png_sPLT_entry)));
if (new_palette.entries == NULL)
{
- png_warning(png_ptr, "sPLT chunk requires too much memory");
- return;
+ png_warning(png_ptr, "sPLT chunk requires too much memory");
+ return;
}
#ifdef PNG_POINTER_INDEXING_SUPPORTED
@@ -1542,38 +1791,36 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#endif
/* Discard all chunk data except the name and stash that */
- new_palette.name = png_ptr->chunkdata;
+ new_palette.name = (png_charp)buffer;
png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_free(png_ptr, new_palette.entries);
}
-#endif /* PNG_READ_sPLT_SUPPORTED */
+#endif /* READ_sPLT */
#ifdef PNG_READ_tRNS_SUPPORTED
void /* PRIVATE */
-png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
png_debug(1, "in png_handle_tRNS");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before tRNS");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid tRNS after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)
{
- png_warning(png_ptr, "Duplicate tRNS chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
@@ -1583,8 +1830,8 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length != 2)
{
- png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
@@ -1599,12 +1846,12 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length != 6)
{
- png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- png_crc_read(png_ptr, buf, (png_size_t)length);
+ png_crc_read(png_ptr, buf, length);
png_ptr->num_trans = 1;
png_ptr->trans_color.red = png_get_uint_16(buf);
png_ptr->trans_color.green = png_get_uint_16(buf + 2);
@@ -1613,44 +1860,44 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
- if (!(png_ptr->mode & PNG_HAVE_PLTE))
- {
- /* Should be an error, but we can cope with it. */
- png_warning(png_ptr, "Missing PLTE before tRNS");
- }
-
- if (length > (png_uint_32)png_ptr->num_palette ||
- length > PNG_MAX_PALETTE_LENGTH)
+ if ((png_ptr->mode & PNG_HAVE_PLTE) == 0)
{
- png_warning(png_ptr, "Incorrect tRNS chunk length");
+ /* TODO: is this actually an error in the ISO spec? */
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- if (length == 0)
+ if (length > (unsigned int) png_ptr->num_palette ||
+ length > (unsigned int) PNG_MAX_PALETTE_LENGTH ||
+ length == 0)
{
- png_warning(png_ptr, "Zero length tRNS chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- png_crc_read(png_ptr, readbuf, (png_size_t)length);
+ png_crc_read(png_ptr, readbuf, length);
png_ptr->num_trans = (png_uint_16)length;
}
else
{
- png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid with alpha channel");
return;
}
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
{
png_ptr->num_trans = 0;
return;
}
+ /* TODO: this is a horrible side effect in the palette case because the
+ * png_struct ends up with a pointer to the tRNS buffer owned by the
+ * png_info. Fix this.
+ */
png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
&(png_ptr->trans_color));
}
@@ -1658,43 +1905,37 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_bKGD_SUPPORTED
void /* PRIVATE */
-png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_size_t truelen;
+ unsigned int truelen;
png_byte buf[6];
png_color_16 background;
png_debug(1, "in png_handle_bKGD");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before bKGD");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
+ (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0))
{
- png_warning(png_ptr, "Invalid bKGD after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
{
- png_warning(png_ptr, "Missing PLTE before bKGD");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
- {
- png_warning(png_ptr, "Duplicate bKGD chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
truelen = 1;
- else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
truelen = 6;
else
@@ -1702,14 +1943,14 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length != truelen)
{
- png_warning(png_ptr, "Incorrect bKGD chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, truelen);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
/* We convert the index value into RGB components so that we can allow
@@ -1721,11 +1962,11 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
background.index = buf[0];
- if (info_ptr && info_ptr->num_palette)
+ if (info_ptr != NULL && info_ptr->num_palette != 0)
{
if (buf[0] >= info_ptr->num_palette)
{
- png_warning(png_ptr, "Incorrect bKGD chunk index value");
+ png_chunk_benign_error(png_ptr, "invalid index");
return;
}
@@ -1740,7 +1981,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
background.gray = 0;
}
- else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
+ else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* GRAY */
{
background.index = 0;
background.red =
@@ -1764,44 +2005,38 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_hIST_SUPPORTED
void /* PRIVATE */
-png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
unsigned int num, i;
png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
png_debug(1, "in png_handle_hIST");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before hIST");
-
- else if (png_ptr->mode & PNG_HAVE_IDAT)
- {
- png_warning(png_ptr, "Invalid hIST after IDAT");
- png_crc_finish(png_ptr, length);
- return;
- }
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (!(png_ptr->mode & PNG_HAVE_PLTE))
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0)
{
- png_warning(png_ptr, "Missing PLTE before hIST");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
{
- png_warning(png_ptr, "Duplicate hIST chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
num = length / 2 ;
- if (num != (unsigned int)png_ptr->num_palette || num >
- (unsigned int)PNG_MAX_PALETTE_LENGTH)
+ if (num != (unsigned int) png_ptr->num_palette ||
+ num > (unsigned int) PNG_MAX_PALETTE_LENGTH)
{
- png_warning(png_ptr, "Incorrect hIST chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
@@ -1813,7 +2048,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
readbuf[i] = png_get_uint_16(buf);
}
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
png_set_hIST(png_ptr, info_ptr, readbuf);
@@ -1822,7 +2057,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_pHYs_SUPPORTED
void /* PRIVATE */
-png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[9];
png_uint_32 res_x, res_y;
@@ -1830,33 +2065,33 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_pHYs");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before pHYs");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid pHYs after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
- png_warning(png_ptr, "Duplicate pHYs chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (length != 9)
{
- png_warning(png_ptr, "Incorrect pHYs chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 9);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
res_x = png_get_uint_32(buf);
@@ -1868,7 +2103,7 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_oFFs_SUPPORTED
void /* PRIVATE */
-png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[9];
png_int_32 offset_x, offset_y;
@@ -1876,33 +2111,33 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_oFFs");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before oFFs");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid oFFs after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
- png_warning(png_ptr, "Duplicate oFFs chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (length != 9)
{
- png_warning(png_ptr, "Incorrect oFFs chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 9);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
offset_x = png_get_int_32(buf);
@@ -1915,71 +2150,64 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_pCAL_SUPPORTED
/* Read the pCAL chunk (described in the PNG Extensions document) */
void /* PRIVATE */
-png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_int_32 X0, X1;
png_byte type, nparams;
- png_charp buf, units, endptr;
+ png_bytep buffer, buf, units, endptr;
png_charpp params;
- png_size_t slength;
int i;
png_debug(1, "in png_handle_pCAL");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before pCAL");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid pCAL after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) != 0)
{
- png_warning(png_ptr, "Duplicate pCAL chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
length + 1);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
- if (png_ptr->chunkdata == NULL)
+ buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
+
+ if (buffer == NULL)
{
- png_warning(png_ptr, "No memory for pCAL purpose");
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
+ buffer[length] = 0; /* Null terminate the last string */
png_debug(3, "Finding end of pCAL purpose string");
- for (buf = png_ptr->chunkdata; *buf; buf++)
+ for (buf = buffer; *buf; buf++)
/* Empty loop */ ;
- endptr = png_ptr->chunkdata + slength;
+ endptr = buffer + length;
/* We need to have at least 12 bytes after the purpose string
* in order to get the parameter information.
*/
- if (endptr <= buf + 12)
+ if (endptr - buf <= 12)
{
- png_warning(png_ptr, "Invalid pCAL data");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
@@ -1999,15 +2227,13 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
(type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
(type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
{
- png_warning(png_ptr, "Invalid pCAL parameters for equation type");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ png_chunk_benign_error(png_ptr, "invalid parameter count");
return;
}
else if (type >= PNG_EQUATION_LAST)
{
- png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+ png_chunk_benign_error(png_ptr, "unrecognized equation type");
}
for (buf = units; *buf; buf++)
@@ -2015,43 +2241,37 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(3, "Allocating pCAL parameters array");
- params = (png_charpp)png_malloc_warn(png_ptr,
- (png_size_t)(nparams * png_sizeof(png_charp)));
+ params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
+ nparams * (sizeof (png_charp))));
if (params == NULL)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- png_warning(png_ptr, "No memory for pCAL params");
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
/* Get pointers to the start of each parameter string. */
- for (i = 0; i < (int)nparams; i++)
+ for (i = 0; i < nparams; i++)
{
buf++; /* Skip the null string terminator from previous parameter. */
png_debug1(3, "Reading pCAL parameter %d", i);
- for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
+ for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; buf++)
/* Empty loop to move past each parameter string */ ;
/* Make sure we haven't run out of data yet */
if (buf > endptr)
{
- png_warning(png_ptr, "Invalid pCAL data");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_free(png_ptr, params);
+ png_chunk_benign_error(png_ptr, "invalid data");
return;
}
}
- png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
- units, params);
+ png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams,
+ (png_charp)units, params);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_free(png_ptr, params);
}
#endif
@@ -2059,67 +2279,61 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_sCAL_SUPPORTED
/* Read the sCAL chunk */
void /* PRIVATE */
-png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_size_t slength, i;
+ png_bytep buffer;
+ png_size_t i;
int state;
png_debug(1, "in png_handle_sCAL");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sCAL");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid sCAL after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
- png_warning(png_ptr, "Duplicate sCAL chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
/* Need unit type, width, \0, height: minimum 4 bytes */
else if (length < 4)
{
- png_warning(png_ptr, "sCAL chunk too short");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
length + 1);
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
- if (png_ptr->chunkdata == NULL)
+ if (buffer == NULL)
{
- png_warning(png_ptr, "Out of memory while processing sCAL chunk");
+ png_chunk_benign_error(png_ptr, "out of memory");
png_crc_finish(png_ptr, length);
return;
}
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
- png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
+ png_crc_read(png_ptr, buffer, length);
+ buffer[length] = 0; /* Null terminate the last string */
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
/* Validate the unit. */
- if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2)
+ if (buffer[0] != 1 && buffer[0] != 2)
{
- png_warning(png_ptr, "Invalid sCAL ignored: invalid unit");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ png_chunk_benign_error(png_ptr, "invalid unit");
return;
}
@@ -2129,70 +2343,65 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
i = 1;
state = 0;
- if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) ||
- i >= slength || png_ptr->chunkdata[i++] != 0)
- png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format");
+ if (png_check_fp_number((png_const_charp)buffer, length, &state, &i) == 0 ||
+ i >= length || buffer[i++] != 0)
+ png_chunk_benign_error(png_ptr, "bad width format");
- else if (!PNG_FP_IS_POSITIVE(state))
- png_warning(png_ptr, "Invalid sCAL chunk ignored: non-positive width");
+ else if (PNG_FP_IS_POSITIVE(state) == 0)
+ png_chunk_benign_error(png_ptr, "non-positive width");
else
{
png_size_t heighti = i;
state = 0;
- if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) ||
- i != slength)
- png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format");
+ if (png_check_fp_number((png_const_charp)buffer, length,
+ &state, &i) == 0 || i != length)
+ png_chunk_benign_error(png_ptr, "bad height format");
- else if (!PNG_FP_IS_POSITIVE(state))
- png_warning(png_ptr,
- "Invalid sCAL chunk ignored: non-positive height");
+ else if (PNG_FP_IS_POSITIVE(state) == 0)
+ png_chunk_benign_error(png_ptr, "non-positive height");
else
/* This is the (only) success case. */
- png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0],
- png_ptr->chunkdata+1, png_ptr->chunkdata+heighti);
+ png_set_sCAL_s(png_ptr, info_ptr, buffer[0],
+ (png_charp)buffer+1, (png_charp)buffer+heighti);
}
-
- /* Clean up - just free the temporarily allocated buffer. */
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
}
#endif
#ifdef PNG_READ_tIME_SUPPORTED
void /* PRIVATE */
-png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[7];
png_time mod_time;
png_debug(1, "in png_handle_tIME");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Out of place tIME chunk");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) != 0)
{
- png_warning(png_ptr, "Duplicate tIME chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
if (length != 7)
{
- png_warning(png_ptr, "Incorrect tIME chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 7);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
mod_time.second = buf[6];
@@ -2209,14 +2418,13 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_tEXt_SUPPORTED
/* Note: this does not properly handle chunks that are > 64K under DOS */
void /* PRIVATE */
-png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_textp text_ptr;
+ png_text text_info;
+ png_bytep buffer;
png_charp key;
png_charp text;
png_uint_32 skip = 0;
- png_size_t slength;
- int ret;
png_debug(1, "in png_handle_tEXt");
@@ -2231,84 +2439,59 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (--png_ptr->user_chunk_cache_max == 1)
{
- png_warning(png_ptr, "No space in chunk cache for tEXt");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before tEXt");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
#ifdef PNG_MAX_MALLOC_64K
- if (length > (png_uint_32)65535L)
+ if (length > 65535U)
{
- png_warning(png_ptr, "tEXt chunk too large to fit in memory");
- skip = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "too large to fit in memory");
+ return;
}
#endif
- png_free(png_ptr, png_ptr->chunkdata);
-
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
- if (png_ptr->chunkdata == NULL)
+ if (buffer == NULL)
{
- png_warning(png_ptr, "No memory to process text chunk");
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, skip))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, skip) != 0)
return;
- }
-
- key = png_ptr->chunkdata;
- key[slength] = 0x00;
+ key = (png_charp)buffer;
+ key[length] = 0;
for (text = key; *text; text++)
/* Empty loop to find end of key */ ;
- if (text != key + slength)
+ if (text != key + length)
text++;
- text_ptr = (png_textp)png_malloc_warn(png_ptr,
- png_sizeof(png_text));
-
- if (text_ptr == NULL)
- {
- png_warning(png_ptr, "Not enough memory to process text chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
-
- text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
- text_ptr->key = key;
- text_ptr->lang = NULL;
- text_ptr->lang_key = NULL;
- text_ptr->itxt_length = 0;
- text_ptr->text = text;
- text_ptr->text_length = png_strlen(text);
+ text_info.compression = PNG_TEXT_COMPRESSION_NONE;
+ text_info.key = key;
+ text_info.lang = NULL;
+ text_info.lang_key = NULL;
+ text_info.itxt_length = 0;
+ text_info.text = text;
+ text_info.text_length = strlen(text);
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- png_free(png_ptr, text_ptr);
-
- if (ret)
+ if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) != 0)
png_warning(png_ptr, "Insufficient memory to process text chunk");
}
#endif
@@ -2316,13 +2499,11 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_zTXt_SUPPORTED
/* Note: this does not correctly handle chunks that are > 64K under DOS */
void /* PRIVATE */
-png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_textp text_ptr;
- png_charp text;
- int comp_type;
- int ret;
- png_size_t slength, prefix_len, data_len;
+ png_const_charp errmsg = NULL;
+ png_bytep buffer;
+ png_uint_32 keyword_length;
png_debug(1, "in png_handle_zTXt");
@@ -2337,123 +2518,101 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (--png_ptr->user_chunk_cache_max == 1)
{
- png_warning(png_ptr, "No space in chunk cache for zTXt");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before zTXt");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
-#ifdef PNG_MAX_MALLOC_64K
- /* We will no doubt have problems with chunks even half this size, but
- * there is no hard and fast rule to tell us where to stop.
- */
- if (length > (png_uint_32)65535L)
+ buffer = png_read_buffer(png_ptr, length, 2/*silent*/);
+
+ if (buffer == NULL)
{
- png_warning(png_ptr, "zTXt chunk too large to fit in memory");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
-#endif
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ png_crc_read(png_ptr, buffer, length);
- if (png_ptr->chunkdata == NULL)
- {
- png_warning(png_ptr, "Out of memory processing zTXt chunk");
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
-
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ /* TODO: also check that the keyword contents match the spec! */
+ for (keyword_length = 0;
+ keyword_length < length && buffer[keyword_length] != 0;
+ ++keyword_length)
+ /* Empty loop to find end of name */ ;
- png_ptr->chunkdata[slength] = 0x00;
+ if (keyword_length > 79 || keyword_length < 1)
+ errmsg = "bad keyword";
- for (text = png_ptr->chunkdata; *text; text++)
- /* Empty loop */ ;
+ /* zTXt must have some LZ data after the keyword, although it may expand to
+ * zero bytes; we need a '\0' at the end of the keyword, the compression type
+ * then the LZ data:
+ */
+ else if (keyword_length + 3 > length)
+ errmsg = "truncated";
- /* zTXt must have some text after the chunkdataword */
- if (text >= png_ptr->chunkdata + slength - 2)
- {
- png_warning(png_ptr, "Truncated zTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ else if (buffer[keyword_length+1] != PNG_COMPRESSION_TYPE_BASE)
+ errmsg = "unknown compression type";
else
{
- comp_type = *(++text);
-
- if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
- {
- png_warning(png_ptr, "Unknown compression type in zTXt chunk");
- comp_type = PNG_TEXT_COMPRESSION_zTXt;
- }
-
- text++; /* Skip the compression_method byte */
- }
+ png_alloc_size_t uncompressed_length = PNG_SIZE_MAX;
- prefix_len = text - png_ptr->chunkdata;
-
- png_decompress_chunk(png_ptr, comp_type,
- (png_size_t)length, prefix_len, &data_len);
+ /* TODO: at present png_decompress_chunk imposes a single application
+ * level memory limit, this should be split to different values for iCCP
+ * and text chunks.
+ */
+ if (png_decompress_chunk(png_ptr, length, keyword_length+2,
+ &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)
+ {
+ png_text text;
- text_ptr = (png_textp)png_malloc_warn(png_ptr,
- png_sizeof(png_text));
+ /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except
+ * for the extra compression type byte and the fact that it isn't
+ * necessarily '\0' terminated.
+ */
+ buffer = png_ptr->read_buffer;
+ buffer[uncompressed_length+(keyword_length+2)] = 0;
+
+ text.compression = PNG_TEXT_COMPRESSION_zTXt;
+ text.key = (png_charp)buffer;
+ text.text = (png_charp)(buffer + keyword_length+2);
+ text.text_length = uncompressed_length;
+ text.itxt_length = 0;
+ text.lang = NULL;
+ text.lang_key = NULL;
+
+ if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
+ errmsg = "insufficient memory";
+ }
- if (text_ptr == NULL)
- {
- png_warning(png_ptr, "Not enough memory to process zTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
+ else
+ errmsg = png_ptr->zstream.msg;
}
- text_ptr->compression = comp_type;
- text_ptr->key = png_ptr->chunkdata;
- text_ptr->lang = NULL;
- text_ptr->lang_key = NULL;
- text_ptr->itxt_length = 0;
- text_ptr->text = png_ptr->chunkdata + prefix_len;
- text_ptr->text_length = data_len;
-
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_free(png_ptr, text_ptr);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
-
- if (ret)
- png_error(png_ptr, "Insufficient memory to store zTXt chunk");
+ if (errmsg != NULL)
+ png_chunk_benign_error(png_ptr, errmsg);
}
#endif
#ifdef PNG_READ_iTXt_SUPPORTED
/* Note: this does not correctly handle chunks that are > 64K under DOS */
void /* PRIVATE */
-png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_textp text_ptr;
- png_charp key, lang, text, lang_key;
- int comp_flag;
- int comp_type = 0;
- int ret;
- png_size_t slength, prefix_len, data_len;
+ png_const_charp errmsg = NULL;
+ png_bytep buffer;
+ png_uint_32 prefix_length;
png_debug(1, "in png_handle_iTXt");
@@ -2468,279 +2627,393 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (--png_ptr->user_chunk_cache_max == 1)
{
- png_warning(png_ptr, "No space in chunk cache for iTXt");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before iTXt");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
-#ifdef PNG_MAX_MALLOC_64K
- /* We will no doubt have problems with chunks even half this size, but
- * there is no hard and fast rule to tell us where to stop.
- */
- if (length > (png_uint_32)65535L)
- {
- png_warning(png_ptr, "iTXt chunk too large to fit in memory");
- png_crc_finish(png_ptr, length);
- return;
- }
-#endif
-
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
- if (png_ptr->chunkdata == NULL)
+ if (buffer == NULL)
{
- png_warning(png_ptr, "No memory to process iTXt chunk");
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00;
-
- for (lang = png_ptr->chunkdata; *lang; lang++)
+ /* First the keyword. */
+ for (prefix_length=0;
+ prefix_length < length && buffer[prefix_length] != 0;
+ ++prefix_length)
/* Empty loop */ ;
- lang++; /* Skip NUL separator */
+ /* Perform a basic check on the keyword length here. */
+ if (prefix_length > 79 || prefix_length < 1)
+ errmsg = "bad keyword";
- /* iTXt must have a language tag (possibly empty), two compression bytes,
- * translated keyword (possibly empty), and possibly some text after the
- * keyword
+ /* Expect keyword, compression flag, compression type, language, translated
+ * keyword (both may be empty but are 0 terminated) then the text, which may
+ * be empty.
*/
+ else if (prefix_length + 5 > length)
+ errmsg = "truncated";
- if (lang >= png_ptr->chunkdata + slength - 3)
+ else if (buffer[prefix_length+1] == 0 ||
+ (buffer[prefix_length+1] == 1 &&
+ buffer[prefix_length+2] == PNG_COMPRESSION_TYPE_BASE))
{
- png_warning(png_ptr, "Truncated iTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ int compressed = buffer[prefix_length+1] != 0;
+ png_uint_32 language_offset, translated_keyword_offset;
+ png_alloc_size_t uncompressed_length = 0;
- else
- {
- comp_flag = *lang++;
- comp_type = *lang++;
- }
+ /* Now the language tag */
+ prefix_length += 3;
+ language_offset = prefix_length;
- if (comp_type || (comp_flag && comp_flag != PNG_TEXT_COMPRESSION_zTXt))
- {
- png_warning(png_ptr, "Unknown iTXt compression type or method");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ for (; prefix_length < length && buffer[prefix_length] != 0;
+ ++prefix_length)
+ /* Empty loop */ ;
- for (lang_key = lang; *lang_key; lang_key++)
- /* Empty loop */ ;
+ /* WARNING: the length may be invalid here, this is checked below. */
+ translated_keyword_offset = ++prefix_length;
- lang_key++; /* Skip NUL separator */
+ for (; prefix_length < length && buffer[prefix_length] != 0;
+ ++prefix_length)
+ /* Empty loop */ ;
- if (lang_key >= png_ptr->chunkdata + slength)
- {
- png_warning(png_ptr, "Truncated iTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ /* prefix_length should now be at the trailing '\0' of the translated
+ * keyword, but it may already be over the end. None of this arithmetic
+ * can overflow because chunks are at most 2^31 bytes long, but on 16-bit
+ * systems the available allocation may overflow.
+ */
+ ++prefix_length;
- for (text = lang_key; *text; text++)
- /* Empty loop */ ;
+ if (compressed == 0 && prefix_length <= length)
+ uncompressed_length = length - prefix_length;
- text++; /* Skip NUL separator */
+ else if (compressed != 0 && prefix_length < length)
+ {
+ uncompressed_length = PNG_SIZE_MAX;
- if (text >= png_ptr->chunkdata + slength)
- {
- png_warning(png_ptr, "Malformed iTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ /* TODO: at present png_decompress_chunk imposes a single application
+ * level memory limit, this should be split to different values for
+ * iCCP and text chunks.
+ */
+ if (png_decompress_chunk(png_ptr, length, prefix_length,
+ &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)
+ buffer = png_ptr->read_buffer;
- prefix_len = text - png_ptr->chunkdata;
+ else
+ errmsg = png_ptr->zstream.msg;
+ }
- key=png_ptr->chunkdata;
+ else
+ errmsg = "truncated";
- if (comp_flag)
- png_decompress_chunk(png_ptr, comp_type,
- (size_t)length, prefix_len, &data_len);
+ if (errmsg == NULL)
+ {
+ png_text text;
- else
- data_len = png_strlen(png_ptr->chunkdata + prefix_len);
+ buffer[uncompressed_length+prefix_length] = 0;
- text_ptr = (png_textp)png_malloc_warn(png_ptr,
- png_sizeof(png_text));
+ if (compressed == 0)
+ text.compression = PNG_ITXT_COMPRESSION_NONE;
- if (text_ptr == NULL)
- {
- png_warning(png_ptr, "Not enough memory to process iTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ else
+ text.compression = PNG_ITXT_COMPRESSION_zTXt;
- text_ptr->compression = (int)comp_flag + 1;
- text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
- text_ptr->lang = png_ptr->chunkdata + (lang - key);
- text_ptr->itxt_length = data_len;
- text_ptr->text_length = 0;
- text_ptr->key = png_ptr->chunkdata;
- text_ptr->text = png_ptr->chunkdata + prefix_len;
+ text.key = (png_charp)buffer;
+ text.lang = (png_charp)buffer + language_offset;
+ text.lang_key = (png_charp)buffer + translated_keyword_offset;
+ text.text = (png_charp)buffer + prefix_length;
+ text.text_length = 0;
+ text.itxt_length = uncompressed_length;
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+ if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
+ errmsg = "insufficient memory";
+ }
+ }
- png_free(png_ptr, text_ptr);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ else
+ errmsg = "bad compression info";
- if (ret)
- png_error(png_ptr, "Insufficient memory to store iTXt chunk");
+ if (errmsg != NULL)
+ png_chunk_benign_error(png_ptr, errmsg);
}
#endif
-/* This function is called when we haven't found a handler for a
- * chunk. If there isn't a problem with the chunk itself (ie bad
- * chunk name, CRC, or a critical chunk), the chunk is silently ignored
- * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
- * case it will be saved away to be written out later.
- */
-void /* PRIVATE */
-png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
+static int
+png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
{
- png_uint_32 skip = 0;
+ png_alloc_size_t limit = PNG_SIZE_MAX;
- png_debug(1, "in png_handle_unknown");
+ if (png_ptr->unknown_chunk.data != NULL)
+ {
+ png_free(png_ptr, png_ptr->unknown_chunk.data);
+ png_ptr->unknown_chunk.data = NULL;
+ }
-#ifdef PNG_USER_LIMITS_SUPPORTED
- if (png_ptr->user_chunk_cache_max != 0)
+# ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (png_ptr->user_chunk_malloc_max > 0 &&
+ png_ptr->user_chunk_malloc_max < limit)
+ limit = png_ptr->user_chunk_malloc_max;
+
+# elif PNG_USER_CHUNK_MALLOC_MAX > 0
+ if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+ limit = PNG_USER_CHUNK_MALLOC_MAX;
+# endif
+
+ if (length <= limit)
{
- if (png_ptr->user_chunk_cache_max == 1)
- {
- png_crc_finish(png_ptr, length);
- return;
- }
+ PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
+ /* The following is safe because of the PNG_SIZE_MAX init above */
+ png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/;
+ /* 'mode' is a flag array, only the bottom four bits matter here */
+ png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/;
- if (--png_ptr->user_chunk_cache_max == 1)
+ if (length == 0)
+ png_ptr->unknown_chunk.data = NULL;
+
+ else
{
- png_warning(png_ptr, "No space in chunk cache for unknown chunk");
- png_crc_finish(png_ptr, length);
- return;
+ /* Do a 'warn' here - it is handled below. */
+ png_ptr->unknown_chunk.data = png_voidcast(png_bytep,
+ png_malloc_warn(png_ptr, length));
}
}
-#endif
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if (png_ptr->unknown_chunk.data == NULL && length > 0)
{
- if (png_ptr->chunk_name != png_IDAT)
- png_ptr->mode |= PNG_AFTER_IDAT;
+ /* This is benign because we clean up correctly */
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "unknown chunk exceeds memory limits");
+ return 0;
}
- if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
+ else
{
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- if (png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name) !=
- PNG_HANDLE_CHUNK_ALWAYS
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- && png_ptr->read_user_chunk_fn == NULL
-#endif
- )
-#endif
- png_chunk_error(png_ptr, "unknown critical chunk");
+ if (length > 0)
+ png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length);
+ png_crc_finish(png_ptr, 0);
+ return 1;
}
+}
+#endif /* READ_UNKNOWN_CHUNKS */
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
- if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- || (png_ptr->read_user_chunk_fn != NULL)
-#endif
- )
- {
-#ifdef PNG_MAX_MALLOC_64K
- if (length > 65535)
- {
- png_warning(png_ptr, "unknown chunk too large to fit in memory");
- skip = length - 65535;
- length = 65535;
- }
-#endif
-
- /* TODO: this code is very close to the unknown handling in pngpread.c,
- * maybe it can be put into a common utility routine?
- * png_struct::unknown_chunk is just used as a temporary variable, along
- * with the data into which the chunk is read. These can be eliminated.
- */
- PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
- png_ptr->unknown_chunk.size = (png_size_t)length;
+/* Handle an unknown, or known but disabled, chunk */
+void /* PRIVATE */
+png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
+ png_uint_32 length, int keep)
+{
+ int handled = 0; /* the chunk was handled */
- if (length == 0)
- png_ptr->unknown_chunk.data = NULL;
+ png_debug(1, "in png_handle_unknown");
- else
- {
- png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
- png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length);
- }
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+ /* NOTE: this code is based on the code in libpng-1.4.12 except for fixing
+ * the bug which meant that setting a non-default behavior for a specific
+ * chunk would be ignored (the default was always used unless a user
+ * callback was installed).
+ *
+ * 'keep' is the value from the png_chunk_unknown_handling, the setting for
+ * this specific chunk_name, if PNG_HANDLE_AS_UNKNOWN_SUPPORTED, if not it
+ * will always be PNG_HANDLE_CHUNK_AS_DEFAULT and it needs to be set here.
+ * This is just an optimization to avoid multiple calls to the lookup
+ * function.
+ */
+# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name);
+# endif
+# endif
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- if (png_ptr->read_user_chunk_fn != NULL)
+ /* One of the following methods will read the chunk or skip it (at least one
+ * of these is always defined because this is the only way to switch on
+ * PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+ */
+# ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+ /* The user callback takes precedence over the chunk keep value, but the
+ * keep value is still required to validate a save of a critical chunk.
+ */
+ if (png_ptr->read_user_chunk_fn != NULL)
+ {
+ if (png_cache_unknown_chunk(png_ptr, length) != 0)
{
/* Callback to user unknown chunk handler */
- int ret;
-
- ret = (*(png_ptr->read_user_chunk_fn))
- (png_ptr, &png_ptr->unknown_chunk);
-
+ int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr,
+ &png_ptr->unknown_chunk);
+
+ /* ret is:
+ * negative: An error occurred; png_chunk_error will be called.
+ * zero: The chunk was not handled, the chunk will be discarded
+ * unless png_set_keep_unknown_chunks has been used to set
+ * a 'keep' behavior for this particular chunk, in which
+ * case that will be used. A critical chunk will cause an
+ * error at this point unless it is to be saved.
+ * positive: The chunk was handled, libpng will ignore/discard it.
+ */
if (ret < 0)
png_chunk_error(png_ptr, "error in user chunk");
- if (ret == 0)
+ else if (ret == 0)
{
- if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
+ /* If the keep value is 'default' or 'never' override it, but
+ * still error out on critical chunks unless the keep value is
+ * 'always' While this is weird it is the behavior in 1.4.12.
+ * A possible improvement would be to obey the value set for the
+ * chunk, but this would be an API change that would probably
+ * damage some applications.
+ *
+ * The png_app_warning below catches the case that matters, where
+ * the application has not set specific save or ignore for this
+ * chunk or global save or ignore.
+ */
+ if (keep < PNG_HANDLE_CHUNK_IF_SAFE)
{
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- if (png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name) !=
- PNG_HANDLE_CHUNK_ALWAYS)
-#endif
- png_chunk_error(png_ptr, "unknown critical chunk");
+# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE)
+ {
+ png_chunk_warning(png_ptr, "Saving unknown chunk:");
+ png_app_warning(png_ptr,
+ "forcing save of an unhandled chunk;"
+ " please call png_set_keep_unknown_chunks");
+ /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */
+ }
+# endif
+ keep = PNG_HANDLE_CHUNK_IF_SAFE;
}
+ }
- png_set_unknown_chunks(png_ptr, info_ptr,
- &png_ptr->unknown_chunk, 1);
+ else /* chunk was handled */
+ {
+ handled = 1;
+ /* Critical chunks can be safely discarded at this point. */
+ keep = PNG_HANDLE_CHUNK_NEVER;
}
}
else
-#endif
- png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
-
- png_free(png_ptr, png_ptr->unknown_chunk.data);
- png_ptr->unknown_chunk.data = NULL;
+ keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */
}
else
-#endif
- skip = length;
+ /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */
+# endif /* READ_USER_CHUNKS */
- png_crc_finish(png_ptr, skip);
+# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
+ {
+ /* keep is currently just the per-chunk setting, if there was no
+ * setting change it to the global default now (not that this may
+ * still be AS_DEFAULT) then obtain the cache of the chunk if required,
+ * if not simply skip the chunk.
+ */
+ if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT)
+ keep = png_ptr->unknown_default;
-#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
- PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
-#endif
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
+ PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
+ {
+ if (png_cache_unknown_chunk(png_ptr, length) == 0)
+ keep = PNG_HANDLE_CHUNK_NEVER;
+ }
+
+ else
+ png_crc_finish(png_ptr, length);
+ }
+# else
+# ifndef PNG_READ_USER_CHUNKS_SUPPORTED
+# error no method to support READ_UNKNOWN_CHUNKS
+# endif
+
+ {
+ /* If here there is no read callback pointer set and no support is
+ * compiled in to just save the unknown chunks, so simply skip this
+ * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then
+ * the app has erroneously asked for unknown chunk saving when there
+ * is no support.
+ */
+ if (keep > PNG_HANDLE_CHUNK_NEVER)
+ png_app_error(png_ptr, "no unknown chunk support available");
+
+ png_crc_finish(png_ptr, length);
+ }
+# endif
+
+# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+ /* Now store the chunk in the chunk list if appropriate, and if the limits
+ * permit it.
+ */
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
+ PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
+ {
+# ifdef PNG_USER_LIMITS_SUPPORTED
+ switch (png_ptr->user_chunk_cache_max)
+ {
+ case 2:
+ png_ptr->user_chunk_cache_max = 1;
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
+ /* FALL THROUGH */
+ case 1:
+ /* NOTE: prior to 1.6.0 this case resulted in an unknown critical
+ * chunk being skipped, now there will be a hard error below.
+ */
+ break;
+
+ default: /* not at limit */
+ --(png_ptr->user_chunk_cache_max);
+ /* FALL THROUGH */
+ case 0: /* no limit */
+# endif /* USER_LIMITS */
+ /* Here when the limit isn't reached or when limits are compiled
+ * out; store the chunk.
+ */
+ png_set_unknown_chunks(png_ptr, info_ptr,
+ &png_ptr->unknown_chunk, 1);
+ handled = 1;
+# ifdef PNG_USER_LIMITS_SUPPORTED
+ break;
+ }
+# endif
+ }
+# else /* no store support: the chunk must be handled by the user callback */
+ PNG_UNUSED(info_ptr)
+# endif
+
+ /* Regardless of the error handling below the cached data (if any) can be
+ * freed now. Notice that the data is not freed if there is a png_error, but
+ * it will be freed by destroy_read_struct.
+ */
+ if (png_ptr->unknown_chunk.data != NULL)
+ png_free(png_ptr, png_ptr->unknown_chunk.data);
+ png_ptr->unknown_chunk.data = NULL;
+
+#else /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */
+ /* There is no support to read an unknown chunk, so just skip it. */
+ png_crc_finish(png_ptr, length);
+ PNG_UNUSED(info_ptr)
+ PNG_UNUSED(keep)
+#endif /* !READ_UNKNOWN_CHUNKS */
+
+ /* Check for unhandled critical chunks */
+ if (handled == 0 && PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
+ png_chunk_error(png_ptr, "unhandled critical chunk");
}
/* This function is called to verify that a chunk name is valid.
@@ -2756,7 +3029,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
*/
void /* PRIVATE */
-png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name)
+png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name)
{
int i;
@@ -2781,11 +3054,11 @@ png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name)
* 'display' is false only those pixels present in the pass are filled in.
*/
void /* PRIVATE */
-png_combine_row(png_structp png_ptr, png_bytep dp, int display)
+png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
{
unsigned int pixel_depth = png_ptr->transformed_pixel_depth;
png_const_bytep sp = png_ptr->row_buf + 1;
- png_uint_32 row_width = png_ptr->width;
+ png_alloc_size_t row_width = png_ptr->width;
unsigned int pass = png_ptr->pass;
png_bytep end_ptr = 0;
png_byte end_byte = 0;
@@ -2822,26 +3095,28 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1;
end_byte = *end_ptr;
# ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP) /* little-endian byte */
- end_mask = 0xff << end_mask;
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ /* little-endian byte */
+ end_mask = 0xff << end_mask;
- else /* big-endian byte */
+ else /* big-endian byte */
# endif
- end_mask = 0xff >> end_mask;
+ end_mask = 0xff >> end_mask;
/* end_mask is now the bits to *keep* from the destination row */
}
- /* For non-interlaced images this reduces to a png_memcpy(). A png_memcpy()
+ /* For non-interlaced images this reduces to a memcpy(). A memcpy()
* will also happen if interlacing isn't supported or if the application
* does not call png_set_interlace_handling(). In the latter cases the
* caller just gets a sequence of the unexpanded rows from each interlace
* pass.
*/
#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) &&
- pass < 6 && (display == 0 ||
- /* The following copies everything for 'display' on passes 0, 2 and 4. */
- (display == 1 && (pass & 1) != 0)))
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0 &&
+ pass < 6 && (display == 0 ||
+ /* The following copies everything for 'display' on passes 0, 2 and 4. */
+ (display == 1 && (pass & 1) != 0)))
{
/* Narrow images may have no bits in a pass; the caller should handle
* this, but this test is cheap:
@@ -2937,7 +3212,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\
S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) }
-# define B_MASKS(d,s) { B_MASK(1,d,s), S_MASK(3,d,s), S_MASK(5,d,s) }
+# define B_MASKS(d,s) { B_MASK(1,d,s), B_MASK(3,d,s), B_MASK(5,d,s) }
# define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2))
@@ -2973,10 +3248,10 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
*/
# define MASK(pass,depth,display,png)\
((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png))
-#endif /* !PNG_USE_COMPILE_TIME_MASKS */
+#endif /* !USE_COMPILE_TIME_MASKS */
/* Use the appropriate mask to copy the required bits. In some cases
- * the byte mask will be 0 or 0xff, optimize these cases. row_width is
+ * the byte mask will be 0 or 0xff; optimize these cases. row_width is
* the number of pixels, but the code copies bytes, so it is necessary
* to special case the end.
*/
@@ -2984,12 +3259,12 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
png_uint_32 mask;
# ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP)
- mask = MASK(pass, pixel_depth, display, 0);
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ mask = MASK(pass, pixel_depth, display, 0);
- else
+ else
# endif
- mask = MASK(pass, pixel_depth, display, 1);
+ mask = MASK(pass, pixel_depth, display, 1);
for (;;)
{
@@ -3048,7 +3323,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
}
/* Work out the bytes to copy. */
- if (display)
+ if (display != 0)
{
/* When doing the 'block' algorithm the pixel in the pass gets
* replicated to adjacent pixels. This is why the even (0,2,4,6)
@@ -3058,7 +3333,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* But don't allow this number to exceed the actual row width. */
if (bytes_to_copy > row_width)
- bytes_to_copy = row_width;
+ bytes_to_copy = (unsigned int)/*SAFE*/row_width;
}
else /* normal row; Adam7 only ever gives us one pixel to copy. */
@@ -3115,7 +3390,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* This can only be the RGB case, so each copy is exactly one
* pixel and it is not necessary to check for a partial copy.
*/
- for(;;)
+ for (;;)
{
dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2];
@@ -3132,26 +3407,27 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* Check for double byte alignment and, if possible, use a
* 16-bit copy. Don't attempt this for narrow images - ones that
* are less than an interlace panel wide. Don't attempt it for
- * wide bytes_to_copy either - use the png_memcpy there.
+ * wide bytes_to_copy either - use the memcpy there.
*/
- if (bytes_to_copy < 16 /*else use png_memcpy*/ &&
- png_isaligned(dp, png_uint_16) &&
- png_isaligned(sp, png_uint_16) &&
- bytes_to_copy % sizeof (png_uint_16) == 0 &&
- bytes_to_jump % sizeof (png_uint_16) == 0)
+ if (bytes_to_copy < 16 /*else use memcpy*/ &&
+ png_isaligned(dp, png_uint_16) &&
+ png_isaligned(sp, png_uint_16) &&
+ bytes_to_copy % (sizeof (png_uint_16)) == 0 &&
+ bytes_to_jump % (sizeof (png_uint_16)) == 0)
{
/* Everything is aligned for png_uint_16 copies, but try for
* png_uint_32 first.
*/
- if (png_isaligned(dp, png_uint_32) &&
- png_isaligned(sp, png_uint_32) &&
- bytes_to_copy % sizeof (png_uint_32) == 0 &&
- bytes_to_jump % sizeof (png_uint_32) == 0)
+ if (png_isaligned(dp, png_uint_32) != 0 &&
+ png_isaligned(sp, png_uint_32) != 0 &&
+ bytes_to_copy % (sizeof (png_uint_32)) == 0 &&
+ bytes_to_jump % (sizeof (png_uint_32)) == 0)
{
- png_uint_32p dp32 = (png_uint_32p)dp;
- png_const_uint_32p sp32 = (png_const_uint_32p)sp;
- unsigned int skip = (bytes_to_jump-bytes_to_copy) /
- sizeof (png_uint_32);
+ png_uint_32p dp32 = png_aligncast(png_uint_32p,dp);
+ png_const_uint_32p sp32 = png_aligncastconst(
+ png_const_uint_32p, sp);
+ size_t skip = (bytes_to_jump-bytes_to_copy) /
+ (sizeof (png_uint_32));
do
{
@@ -3159,7 +3435,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
do
{
*dp32++ = *sp32++;
- c -= sizeof (png_uint_32);
+ c -= (sizeof (png_uint_32));
}
while (c > 0);
@@ -3189,10 +3465,11 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
*/
else
{
- png_uint_16p dp16 = (png_uint_16p)dp;
- png_const_uint_16p sp16 = (png_const_uint_16p)sp;
- unsigned int skip = (bytes_to_jump-bytes_to_copy) /
- sizeof (png_uint_16);
+ png_uint_16p dp16 = png_aligncast(png_uint_16p, dp);
+ png_const_uint_16p sp16 = png_aligncastconst(
+ png_const_uint_16p, sp);
+ size_t skip = (bytes_to_jump-bytes_to_copy) /
+ (sizeof (png_uint_16));
do
{
@@ -3200,7 +3477,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
do
{
*dp16++ = *sp16++;
- c -= sizeof (png_uint_16);
+ c -= (sizeof (png_uint_16));
}
while (c > 0);
@@ -3222,12 +3499,12 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
return;
}
}
-#endif /* PNG_ALIGN_ code */
+#endif /* ALIGN_TYPE code */
- /* The true default - use a png_memcpy: */
+ /* The true default - use a memcpy: */
for (;;)
{
- png_memcpy(dp, sp, bytes_to_copy);
+ memcpy(dp, sp, bytes_to_copy);
if (row_width <= bytes_to_jump)
return;
@@ -3236,7 +3513,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
dp += bytes_to_jump;
row_width -= bytes_to_jump;
if (bytes_to_copy > row_width)
- bytes_to_copy = row_width;
+ bytes_to_copy = (unsigned int)/*SAFE*/row_width;
}
}
@@ -3246,13 +3523,13 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* Here if pixel_depth < 8 to check 'end_ptr' below. */
}
else
-#endif
+#endif /* READ_INTERLACING */
- /* If here then the switch above wasn't used so just png_memcpy the whole row
+ /* If here then the switch above wasn't used so just memcpy the whole row
* from the temporary row buffer (notice that this overwrites the end of the
* destination row if it is a partial byte.)
*/
- png_memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width));
+ memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width));
/* Restore the overwritten bits from the last byte if necessary. */
if (end_ptr != NULL)
@@ -3289,7 +3566,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
int j;
#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (transformations & PNG_PACKSWAP)
+ if ((transformations & PNG_PACKSWAP) != 0)
{
sshift = (int)((row_info->width + 7) & 0x07);
dshift = (int)((final_width + 7) & 0x07);
@@ -3313,8 +3590,9 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
v = (png_byte)((*sp >> sshift) & 0x01);
for (j = 0; j < jstop; j++)
{
- *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
+ unsigned int tmp = *dp & (0x7f7f >> (7 - dshift));
+ tmp |= v << dshift;
+ *dp = (png_byte)(tmp & 0xff);
if (dshift == s_end)
{
@@ -3348,7 +3626,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
png_uint_32 i;
#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (transformations & PNG_PACKSWAP)
+ if ((transformations & PNG_PACKSWAP) != 0)
{
sshift = (int)(((row_info->width + 3) & 0x03) << 1);
dshift = (int)(((final_width + 3) & 0x03) << 1);
@@ -3375,8 +3653,9 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
v = (png_byte)((*sp >> sshift) & 0x03);
for (j = 0; j < jstop; j++)
{
- *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
+ unsigned int tmp = *dp & (0x3f3f >> (6 - dshift));
+ tmp |= v << dshift;
+ *dp = (png_byte)(tmp & 0xff);
if (dshift == s_end)
{
@@ -3410,7 +3689,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
int jstop = png_pass_inc[pass];
#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (transformations & PNG_PACKSWAP)
+ if ((transformations & PNG_PACKSWAP) != 0)
{
sshift = (int)(((row_info->width + 1) & 0x01) << 2);
dshift = (int)(((final_width + 1) & 0x01) << 2);
@@ -3436,8 +3715,9 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
for (j = 0; j < jstop; j++)
{
- *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
+ unsigned int tmp = *dp & (0xf0f >> (4 - dshift));
+ tmp |= v << dshift;
+ *dp = (png_byte)(tmp & 0xff);
if (dshift == s_end)
{
@@ -3475,14 +3755,14 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
for (i = 0; i < row_info->width; i++)
{
- png_byte v[8];
+ png_byte v[8]; /* SAFE; pixel_depth does not exceed 64 */
int j;
- png_memcpy(v, sp, pixel_bytes);
+ memcpy(v, sp, pixel_bytes);
for (j = 0; j < jstop; j++)
{
- png_memcpy(dp, v, pixel_bytes);
+ memcpy(dp, v, pixel_bytes);
dp -= pixel_bytes;
}
@@ -3499,7 +3779,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
PNG_UNUSED(transformations) /* Silence compiler warning */
#endif
}
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
+#endif /* READ_INTERLACING */
static void
png_read_filter_row_sub(png_row_infop row_info, png_bytep row,
@@ -3585,15 +3865,15 @@ png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row,
p = b - c;
pc = a - c;
-# ifdef PNG_USE_ABS
- pa = abs(p);
- pb = abs(pc);
- pc = abs(p + pc);
-# else
- pa = p < 0 ? -p : p;
- pb = pc < 0 ? -pc : pc;
- pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-# endif
+#ifdef PNG_USE_ABS
+ pa = abs(p);
+ pb = abs(pc);
+ pc = abs(p + pc);
+#else
+ pa = p < 0 ? -p : p;
+ pb = pc < 0 ? -pc : pc;
+ pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
/* Find the best predictor, the least of pa, pb, pc favoring the earlier
* ones in the case of a tie.
@@ -3640,87 +3920,35 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row,
p = b - c;
pc = a - c;
-# ifdef PNG_USE_ABS
- pa = abs(p);
- pb = abs(pc);
- pc = abs(p + pc);
-# else
- pa = p < 0 ? -p : p;
- pb = pc < 0 ? -pc : pc;
- pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-# endif
+#ifdef PNG_USE_ABS
+ pa = abs(p);
+ pb = abs(pc);
+ pc = abs(p + pc);
+#else
+ pa = p < 0 ? -p : p;
+ pb = pc < 0 ? -pc : pc;
+ pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
if (pb < pa) pa = pb, a = b;
if (pc < pa) a = c;
- c = b;
a += *row;
*row++ = (png_byte)a;
}
}
-#ifdef PNG_ARM_NEON
-
-#ifdef __linux__
-#include <stdio.h>
-#include <elf.h>
-#include <asm/hwcap.h>
-
-static int png_have_hwcap(unsigned cap)
-{
- FILE *f = fopen("/proc/self/auxv", "r");
- Elf32_auxv_t aux;
- int have_cap = 0;
-
- if (!f)
- return 0;
-
- while (fread(&aux, sizeof(aux), 1, f) > 0)
- {
- if (aux.a_type == AT_HWCAP &&
- aux.a_un.a_val & cap)
- {
- have_cap = 1;
- break;
- }
- }
-
- fclose(f);
-
- return have_cap;
-}
-#endif /* __linux__ */
-
-static void
-png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
-{
-#ifdef __linux__
- if (!png_have_hwcap(HWCAP_NEON))
- return;
-#endif
-
- pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
-
- if (bpp == 3)
- {
- pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
- pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
- pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
- png_read_filter_row_paeth3_neon;
- }
-
- else if (bpp == 4)
- {
- pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
- pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
- pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
- png_read_filter_row_paeth4_neon;
- }
-}
-#endif /* PNG_ARM_NEON */
-
static void
-png_init_filter_functions(png_structp pp)
+png_init_filter_functions(png_structrp pp)
+ /* This function is called once for every PNG image (except for PNG images
+ * that only use PNG_FILTER_VALUE_NONE for all rows) to set the
+ * implementations required to reverse the filtering of PNG rows. Reversing
+ * the filter is the first transformation performed on the row data. It is
+ * performed in place, therefore an implementation can be selected based on
+ * the image pixel format. If the implementation depends on image width then
+ * take care to ensure that it works correctly if the image is interlaced -
+ * interlacing causes the actual row width to vary.
+ */
{
unsigned int bpp = (pp->pixel_depth + 7) >> 3;
@@ -3734,26 +3962,217 @@ png_init_filter_functions(png_structp pp)
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
png_read_filter_row_paeth_multibyte_pixel;
-#ifdef PNG_ARM_NEON
- png_init_filter_functions_neon(pp, bpp);
+#ifdef PNG_FILTER_OPTIMIZATIONS
+ /* To use this define PNG_FILTER_OPTIMIZATIONS as the name of a function to
+ * call to install hardware optimizations for the above functions; simply
+ * replace whatever elements of the pp->read_filter[] array with a hardware
+ * specific (or, for that matter, generic) optimization.
+ *
+ * To see an example of this examine what configure.ac does when
+ * --enable-arm-neon is specified on the command line.
+ */
+ PNG_FILTER_OPTIMIZATIONS(pp, bpp);
#endif
}
void /* PRIVATE */
-png_read_filter_row(png_structp pp, png_row_infop row_info, png_bytep row,
+png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row,
png_const_bytep prev_row, int filter)
{
- if (pp->read_filter[0] == NULL)
- png_init_filter_functions(pp);
+ /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define
+ * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic
+ * implementations. See png_init_filter_functions above.
+ */
if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST)
+ {
+ if (pp->read_filter[0] == NULL)
+ png_init_filter_functions(pp);
+
pp->read_filter[filter-1](row_info, row, prev_row);
+ }
}
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
void /* PRIVATE */
-png_read_finish_row(png_structp png_ptr)
+png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
+ png_alloc_size_t avail_out)
+{
+ /* Loop reading IDATs and decompressing the result into output[avail_out] */
+ png_ptr->zstream.next_out = output;
+ png_ptr->zstream.avail_out = 0; /* safety: set below */
+
+ if (output == NULL)
+ avail_out = 0;
+
+ do
+ {
+ int ret;
+ png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];
+
+ if (png_ptr->zstream.avail_in == 0)
+ {
+ uInt avail_in;
+ png_bytep buffer;
+
+ while (png_ptr->idat_size == 0)
+ {
+ png_crc_finish(png_ptr, 0);
+
+ png_ptr->idat_size = png_read_chunk_header(png_ptr);
+ /* This is an error even in the 'check' case because the code just
+ * consumed a non-IDAT header.
+ */
+ if (png_ptr->chunk_name != png_IDAT)
+ png_error(png_ptr, "Not enough image data");
+ }
+
+ avail_in = png_ptr->IDAT_read_size;
+
+ if (avail_in > png_ptr->idat_size)
+ avail_in = (uInt)png_ptr->idat_size;
+
+ /* A PNG with a gradually increasing IDAT size will defeat this attempt
+ * to minimize memory usage by causing lots of re-allocs, but
+ * realistically doing IDAT_read_size re-allocs is not likely to be a
+ * big problem.
+ */
+ buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/);
+
+ png_crc_read(png_ptr, buffer, avail_in);
+ png_ptr->idat_size -= avail_in;
+
+ png_ptr->zstream.next_in = buffer;
+ png_ptr->zstream.avail_in = avail_in;
+ }
+
+ /* And set up the output side. */
+ if (output != NULL) /* standard read */
+ {
+ uInt out = ZLIB_IO_MAX;
+
+ if (out > avail_out)
+ out = (uInt)avail_out;
+
+ avail_out -= out;
+ png_ptr->zstream.avail_out = out;
+ }
+
+ else /* after last row, checking for end */
+ {
+ png_ptr->zstream.next_out = tmpbuf;
+ png_ptr->zstream.avail_out = (sizeof tmpbuf);
+ }
+
+ /* Use NO_FLUSH; this gives zlib the maximum opportunity to optimize the
+ * process. If the LZ stream is truncated the sequential reader will
+ * terminally damage the stream, above, by reading the chunk header of the
+ * following chunk (it then exits with png_error).
+ *
+ * TODO: deal more elegantly with truncated IDAT lists.
+ */
+ ret = PNG_INFLATE(png_ptr, Z_NO_FLUSH);
+
+ /* Take the unconsumed output back. */
+ if (output != NULL)
+ avail_out += png_ptr->zstream.avail_out;
+
+ else /* avail_out counts the extra bytes */
+ avail_out += (sizeof tmpbuf) - png_ptr->zstream.avail_out;
+
+ png_ptr->zstream.avail_out = 0;
+
+ if (ret == Z_STREAM_END)
+ {
+ /* Do this for safety; we won't read any more into this row. */
+ png_ptr->zstream.next_out = NULL;
+
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+
+ if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
+ png_chunk_benign_error(png_ptr, "Extra compressed data");
+ break;
+ }
+
+ if (ret != Z_OK)
+ {
+ png_zstream_error(png_ptr, ret);
+
+ if (output != NULL)
+ png_chunk_error(png_ptr, png_ptr->zstream.msg);
+
+ else /* checking */
+ {
+ png_chunk_benign_error(png_ptr, png_ptr->zstream.msg);
+ return;
+ }
+ }
+ } while (avail_out > 0);
+
+ if (avail_out > 0)
+ {
+ /* The stream ended before the image; this is the same as too few IDATs so
+ * should be handled the same way.
+ */
+ if (output != NULL)
+ png_error(png_ptr, "Not enough image data");
+
+ else /* the deflate stream contained extra data */
+ png_chunk_benign_error(png_ptr, "Too much image data");
+ }
+}
+
+void /* PRIVATE */
+png_read_finish_IDAT(png_structrp png_ptr)
+{
+ /* We don't need any more data and the stream should have ended, however the
+ * LZ end code may actually not have been processed. In this case we must
+ * read it otherwise stray unread IDAT data or, more likely, an IDAT chunk
+ * may still remain to be consumed.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
+ {
+ /* The NULL causes png_read_IDAT_data to swallow any remaining bytes in
+ * the compressed stream, but the stream may be damaged too, so even after
+ * this call we may need to terminate the zstream ownership.
+ */
+ png_read_IDAT_data(png_ptr, NULL, 0);
+ png_ptr->zstream.next_out = NULL; /* safety */
+
+ /* Now clear everything out for safety; the following may not have been
+ * done.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
+ {
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+ }
+ }
+
+ /* If the zstream has not been released do it now *and* terminate the reading
+ * of the final IDAT chunk.
+ */
+ if (png_ptr->zowner == png_IDAT)
+ {
+ /* Always do this; the pointers otherwise point into the read buffer. */
+ png_ptr->zstream.next_in = NULL;
+ png_ptr->zstream.avail_in = 0;
+
+ /* Now we no longer own the zstream. */
+ png_ptr->zowner = 0;
+
+ /* The slightly weird semantics of the sequential IDAT reading is that we
+ * are always in or at the end of an IDAT chunk, so we always need to do a
+ * crc_finish here. If idat_size is non-zero we also need to read the
+ * spurious bytes at the end of the chunk now.
+ */
+ (void)png_crc_finish(png_ptr, png_ptr->idat_size);
+ }
+}
+
+void /* PRIVATE */
+png_read_finish_row(png_structrp png_ptr)
{
-#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
@@ -3767,22 +4186,20 @@ png_read_finish_row(png_structp png_ptr)
/* Offset to next interlace block in the y direction */
static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
png_debug(1, "in png_read_finish_row");
png_ptr->row_number++;
if (png_ptr->row_number < png_ptr->num_rows)
return;
-#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
png_ptr->row_number = 0;
/* TO DO: don't do this if prev_row isn't needed (requires
* read-ahead of the next row's filter byte.
*/
- png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
do
{
@@ -3796,7 +4213,7 @@ png_read_finish_row(png_structp png_ptr)
png_pass_start[png_ptr->pass]) /
png_pass_inc[png_ptr->pass];
- if (!(png_ptr->transformations & PNG_INTERLACE))
+ if ((png_ptr->transformations & PNG_INTERLACE) == 0)
{
png_ptr->num_rows = (png_ptr->height +
png_pass_yinc[png_ptr->pass] - 1 -
@@ -3812,80 +4229,15 @@ png_read_finish_row(png_structp png_ptr)
if (png_ptr->pass < 7)
return;
}
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
- {
- char extra;
- int ret;
- png_ptr->zstream.next_out = (Byte *)&extra;
- png_ptr->zstream.avail_out = (uInt)1;
-
- for (;;)
- {
- if (!(png_ptr->zstream.avail_in))
- {
- while (!png_ptr->idat_size)
- {
- png_crc_finish(png_ptr, 0);
- png_ptr->idat_size = png_read_chunk_header(png_ptr);
- if (png_ptr->chunk_name != png_IDAT)
- png_error(png_ptr, "Not enough image data");
- }
-
- png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_in = png_ptr->zbuf;
-
- if (png_ptr->zbuf_size > png_ptr->idat_size)
- png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
-
- png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
- png_ptr->idat_size -= png_ptr->zstream.avail_in;
- }
-
- ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
-
- if (ret == Z_STREAM_END)
- {
- if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
- png_ptr->idat_size)
- png_warning(png_ptr, "Extra compressed data");
-
- png_ptr->mode |= PNG_AFTER_IDAT;
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
- break;
- }
-
- if (ret != Z_OK)
- png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
- "Decompression Error");
-
- if (!(png_ptr->zstream.avail_out))
- {
- png_warning(png_ptr, "Extra compressed data");
- png_ptr->mode |= PNG_AFTER_IDAT;
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
- break;
- }
-
- }
- png_ptr->zstream.avail_out = 0;
- }
-
- if (png_ptr->idat_size || png_ptr->zstream.avail_in)
- png_warning(png_ptr, "Extra compression data");
-
- inflateReset(&png_ptr->zstream);
-
- png_ptr->mode |= PNG_AFTER_IDAT;
+ /* Here after at the end of the last row of the last pass. */
+ png_read_finish_IDAT(png_ptr);
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
void /* PRIVATE */
-png_read_start_row(png_structp png_ptr)
+png_read_start_row(png_structrp png_ptr)
{
-#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
@@ -3899,20 +4251,18 @@ png_read_start_row(png_structp png_ptr)
/* Offset to next interlace block in the y direction */
static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-#endif
int max_pixel_depth;
png_size_t row_bytes;
png_debug(1, "in png_read_start_row");
- png_ptr->zstream.avail_in = 0;
+
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
png_init_read_transformations(png_ptr);
#endif
-#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
- if (!(png_ptr->transformations & PNG_INTERLACE))
+ if ((png_ptr->transformations & PNG_INTERLACE) == 0)
png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
png_pass_ystart[0]) / png_pass_yinc[0];
@@ -3926,7 +4276,6 @@ png_read_start_row(png_structp png_ptr)
}
else
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
{
png_ptr->num_rows = png_ptr->height;
png_ptr->iwidth = png_ptr->width;
@@ -3934,7 +4283,7 @@ png_read_start_row(png_structp png_ptr)
max_pixel_depth = png_ptr->pixel_depth;
- /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of
+ /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpler set of
* calculations to calculate the final pixel depth, then
* png_do_read_transforms actually does the transforms. This means that the
* code which effectively calculates this value is actually repeated in three
@@ -3945,16 +4294,16 @@ png_read_start_row(png_structp png_ptr)
* TODO: fix this.
*/
#ifdef PNG_READ_PACK_SUPPORTED
- if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
+ if ((png_ptr->transformations & PNG_PACK) != 0 && png_ptr->bit_depth < 8)
max_pixel_depth = 8;
#endif
#ifdef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND)
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
max_pixel_depth = 32;
else
@@ -3966,13 +4315,13 @@ png_read_start_row(png_structp png_ptr)
if (max_pixel_depth < 8)
max_pixel_depth = 8;
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
max_pixel_depth *= 2;
}
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
{
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
{
max_pixel_depth *= 4;
max_pixel_depth /= 3;
@@ -3982,25 +4331,25 @@ png_read_start_row(png_structp png_ptr)
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND_16)
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
{
-# ifdef PNG_READ_EXPAND_SUPPORTED
- /* In fact it is an error if it isn't supported, but checking is
- * the safe way.
- */
- if (png_ptr->transformations & PNG_EXPAND)
- {
- if (png_ptr->bit_depth < 16)
- max_pixel_depth *= 2;
- }
- else
-# endif
- png_ptr->transformations &= ~PNG_EXPAND_16;
+# ifdef PNG_READ_EXPAND_SUPPORTED
+ /* In fact it is an error if it isn't supported, but checking is
+ * the safe way.
+ */
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
+ {
+ if (png_ptr->bit_depth < 16)
+ max_pixel_depth *= 2;
+ }
+ else
+# endif
+ png_ptr->transformations &= ~PNG_EXPAND_16;
}
#endif
#ifdef PNG_READ_FILLER_SUPPORTED
- if (png_ptr->transformations & (PNG_FILLER))
+ if ((png_ptr->transformations & (PNG_FILLER)) != 0)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
{
@@ -4024,14 +4373,15 @@ png_read_start_row(png_structp png_ptr)
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
{
if (
#ifdef PNG_READ_EXPAND_SUPPORTED
- (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
+ (png_ptr->num_trans != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) != 0) ||
#endif
#ifdef PNG_READ_FILLER_SUPPORTED
- (png_ptr->transformations & (PNG_FILLER)) ||
+ (png_ptr->transformations & (PNG_FILLER)) != 0 ||
#endif
png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
@@ -4064,7 +4414,7 @@ png_read_start_row(png_structp png_ptr)
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
- if (png_ptr->transformations & PNG_USER_TRANSFORM)
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
{
int user_pixel_depth = png_ptr->user_transform_depth *
png_ptr->user_transform_channels;
@@ -4100,7 +4450,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
png_free(png_ptr, png_ptr->big_row_buf);
png_free(png_ptr, png_ptr->big_prev_row);
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
row_bytes + 48);
@@ -4143,7 +4493,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1))
png_error(png_ptr, "Row has too many bytes to allocate in memory");
- png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
png_debug1(3, "width = %u,", png_ptr->width);
png_debug1(3, "height = %u,", png_ptr->height);
@@ -4153,6 +4503,27 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
png_debug1(3, "irowbytes = %lu",
(unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
+ /* The sequential reader needs a buffer for IDAT, but the progressive reader
+ * does not, so free the read buffer now regardless; the sequential reader
+ * reallocates it on demand.
+ */
+ if (png_ptr->read_buffer != 0)
+ {
+ png_bytep buffer = png_ptr->read_buffer;
+
+ png_ptr->read_buffer_size = 0;
+ png_ptr->read_buffer = NULL;
+ png_free(png_ptr, buffer);
+ }
+
+ /* Finally claim the zstream for the inflate of the IDAT data, use the bits
+ * value from the stream (note that this will result in a fatal error if the
+ * IDAT stream has a bogus deflate header window_bits value, but this should
+ * not be happening any longer!)
+ */
+ if (png_inflate_claim(png_ptr, png_IDAT) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
+
png_ptr->flags |= PNG_FLAG_ROW_INIT;
}
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
diff --git a/thirdparty/libpng/pngset.c b/thirdparty/libpng/pngset.c
index 92db3890..4bd5ab3c 100644
--- a/thirdparty/libpng/pngset.c
+++ b/thirdparty/libpng/pngset.c
@@ -1,8 +1,8 @@
/* pngset.c - storage of image information into info struct
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.21 [January 15, 2016]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -22,50 +22,51 @@
#ifdef PNG_bKGD_SUPPORTED
void PNGAPI
-png_set_bKGD(png_structp png_ptr, png_infop info_ptr,
+png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_color_16p background)
{
png_debug1(1, "in %s storage function", "bKGD");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || background == NULL)
return;
- png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16));
+ info_ptr->background = *background;
info_ptr->valid |= PNG_INFO_bKGD;
}
#endif
#ifdef PNG_cHRM_SUPPORTED
void PNGFAPI
-png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
+png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
png_fixed_point blue_x, png_fixed_point blue_y)
{
+ png_xy xy;
+
png_debug1(1, "in %s storage function", "cHRM fixed");
if (png_ptr == NULL || info_ptr == NULL)
return;
-# ifdef PNG_CHECK_cHRM_SUPPORTED
- if (png_check_cHRM_fixed(png_ptr,
- white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y))
-# endif
- {
- info_ptr->x_white = white_x;
- info_ptr->y_white = white_y;
- info_ptr->x_red = red_x;
- info_ptr->y_red = red_y;
- info_ptr->x_green = green_x;
- info_ptr->y_green = green_y;
- info_ptr->x_blue = blue_x;
- info_ptr->y_blue = blue_y;
- info_ptr->valid |= PNG_INFO_cHRM;
- }
+ xy.redx = red_x;
+ xy.redy = red_y;
+ xy.greenx = green_x;
+ xy.greeny = green_y;
+ xy.bluex = blue_x;
+ xy.bluey = blue_y;
+ xy.whitex = white_x;
+ xy.whitey = white_y;
+
+ if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
+ 2/* override with app values*/) != 0)
+ info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
void PNGFAPI
-png_set_cHRM_XYZ_fixed(png_structp png_ptr, png_infop info_ptr,
+png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
png_fixed_point int_red_X, png_fixed_point int_red_Y,
png_fixed_point int_red_Z, png_fixed_point int_green_X,
png_fixed_point int_green_Y, png_fixed_point int_green_Z,
@@ -73,33 +74,32 @@ png_set_cHRM_XYZ_fixed(png_structp png_ptr, png_infop info_ptr,
png_fixed_point int_blue_Z)
{
png_XYZ XYZ;
- png_xy xy;
png_debug1(1, "in %s storage function", "cHRM XYZ fixed");
if (png_ptr == NULL || info_ptr == NULL)
return;
- XYZ.redX = int_red_X;
- XYZ.redY = int_red_Y;
- XYZ.redZ = int_red_Z;
- XYZ.greenX = int_green_X;
- XYZ.greenY = int_green_Y;
- XYZ.greenZ = int_green_Z;
- XYZ.blueX = int_blue_X;
- XYZ.blueY = int_blue_Y;
- XYZ.blueZ = int_blue_Z;
-
- if (png_xy_from_XYZ(&xy, XYZ))
- png_error(png_ptr, "XYZ values out of representable range");
-
- png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy,
- xy.greenx, xy.greeny, xy.bluex, xy.bluey);
+ XYZ.red_X = int_red_X;
+ XYZ.red_Y = int_red_Y;
+ XYZ.red_Z = int_red_Z;
+ XYZ.green_X = int_green_X;
+ XYZ.green_Y = int_green_Y;
+ XYZ.green_Z = int_green_Z;
+ XYZ.blue_X = int_blue_X;
+ XYZ.blue_Y = int_blue_Y;
+ XYZ.blue_Z = int_blue_Z;
+
+ if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
+ &XYZ, 2) != 0)
+ info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
+png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
double white_x, double white_y, double red_x, double red_y,
double green_x, double green_y, double blue_x, double blue_y)
{
@@ -115,7 +115,7 @@ png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
}
void PNGAPI
-png_set_cHRM_XYZ(png_structp png_ptr, png_infop info_ptr, double red_X,
+png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
double blue_X, double blue_Y, double blue_Z)
{
@@ -123,48 +123,34 @@ png_set_cHRM_XYZ(png_structp png_ptr, png_infop info_ptr, double red_X,
png_fixed(png_ptr, red_X, "cHRM Red X"),
png_fixed(png_ptr, red_Y, "cHRM Red Y"),
png_fixed(png_ptr, red_Z, "cHRM Red Z"),
- png_fixed(png_ptr, green_X, "cHRM Red X"),
- png_fixed(png_ptr, green_Y, "cHRM Red Y"),
- png_fixed(png_ptr, green_Z, "cHRM Red Z"),
- png_fixed(png_ptr, blue_X, "cHRM Red X"),
- png_fixed(png_ptr, blue_Y, "cHRM Red Y"),
- png_fixed(png_ptr, blue_Z, "cHRM Red Z"));
+ png_fixed(png_ptr, green_X, "cHRM Green X"),
+ png_fixed(png_ptr, green_Y, "cHRM Green Y"),
+ png_fixed(png_ptr, green_Z, "cHRM Green Z"),
+ png_fixed(png_ptr, blue_X, "cHRM Blue X"),
+ png_fixed(png_ptr, blue_Y, "cHRM Blue Y"),
+ png_fixed(png_ptr, blue_Z, "cHRM Blue Z"));
}
-# endif /* PNG_FLOATING_POINT_SUPPORTED */
+# endif /* FLOATING_POINT */
-#endif /* PNG_cHRM_SUPPORTED */
+#endif /* cHRM */
#ifdef PNG_gAMA_SUPPORTED
void PNGFAPI
-png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
- file_gamma)
+png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_fixed_point file_gamma)
{
png_debug1(1, "in %s storage function", "gAMA");
if (png_ptr == NULL || info_ptr == NULL)
return;
- /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
- * occur. Since the fixed point representation is assymetrical it is
- * possible for 1/gamma to overflow the limit of 21474 and this means the
- * gamma value must be at least 5/100000 and hence at most 20000.0. For
- * safety the limits here are a little narrower. The values are 0.00016 to
- * 6250.0, which are truly ridiculous gammma values (and will produce
- * displays that are all black or all white.)
- */
- if (file_gamma < 16 || file_gamma > 625000000)
- png_warning(png_ptr, "Out of range gamma value ignored");
-
- else
- {
- info_ptr->gamma = file_gamma;
- info_ptr->valid |= PNG_INFO_gAMA;
- }
+ png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
+png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
{
png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
"png_set_gAMA"));
@@ -174,7 +160,8 @@ png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
#ifdef PNG_hIST_SUPPORTED
void PNGAPI
-png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist)
+png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_const_uint_16p hist)
{
int i;
@@ -197,26 +184,27 @@ png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist)
/* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
* version 1.2.1
*/
- png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr,
- PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16));
+ info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr,
+ PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16))));
- if (png_ptr->hist == NULL)
+ if (info_ptr->hist == NULL)
{
png_warning(png_ptr, "Insufficient memory for hIST chunk data");
+
return;
}
+ info_ptr->free_me |= PNG_FREE_HIST;
+
for (i = 0; i < info_ptr->num_palette; i++)
- png_ptr->hist[i] = hist[i];
+ info_ptr->hist[i] = hist[i];
- info_ptr->hist = png_ptr->hist;
info_ptr->valid |= PNG_INFO_hIST;
- info_ptr->free_me |= PNG_FREE_HIST;
}
#endif
void PNGAPI
-png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
+png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_type, int compression_type,
int filter_type)
@@ -241,32 +229,23 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
info_ptr->channels = 1;
- else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
info_ptr->channels = 3;
else
info_ptr->channels = 1;
- if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
info_ptr->channels++;
info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
- /* Check for potential overflow */
- if (width >
- (PNG_UINT_32_MAX >> 3) /* 8-byte RRGGBBAA pixels */
- - 48 /* bigrowbuf hack */
- - 1 /* filter byte */
- - 7*8 /* rounding of width to multiple of 8 pixels */
- - 8) /* extra max_pixel_depth pad */
- info_ptr->rowbytes = 0;
- else
- info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
+ info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
}
#ifdef PNG_oFFs_SUPPORTED
void PNGAPI
-png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
+png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
png_int_32 offset_x, png_int_32 offset_y, int unit_type)
{
png_debug1(1, "in %s storage function", "oFFs");
@@ -283,7 +262,7 @@ png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_pCAL_SUPPORTED
void PNGAPI
-png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
+png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
int nparams, png_const_charp units, png_charpp params)
{
@@ -292,10 +271,11 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
png_debug1(1, "in %s storage function", "pCAL");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
+ || (nparams > 0 && params == NULL))
return;
- length = png_strlen(purpose) + 1;
+ length = strlen(purpose) + 1;
png_debug1(3, "allocating purpose for info (%lu bytes)",
(unsigned long)length);
@@ -305,20 +285,28 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
if (type < 0 || type > 3)
png_error(png_ptr, "Invalid pCAL equation type");
+ if (nparams < 0 || nparams > 255)
+ png_error(png_ptr, "Invalid pCAL parameter count");
+
/* Validate params[nparams] */
for (i=0; i<nparams; ++i)
- if (!png_check_fp_string(params[i], png_strlen(params[i])))
+ {
+ if (params[i] == NULL ||
+ !png_check_fp_string(params[i], strlen(params[i])))
png_error(png_ptr, "Invalid format for pCAL parameter");
+ }
- info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
+ info_ptr->pcal_purpose = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, length));
if (info_ptr->pcal_purpose == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL purpose");
+
return;
}
- png_memcpy(info_ptr->pcal_purpose, purpose, length);
+ memcpy(info_ptr->pcal_purpose, purpose, length);
png_debug(3, "storing X0, X1, type, and nparams in info");
info_ptr->pcal_X0 = X0;
@@ -326,34 +314,37 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
info_ptr->pcal_type = (png_byte)type;
info_ptr->pcal_nparams = (png_byte)nparams;
- length = png_strlen(units) + 1;
+ length = strlen(units) + 1;
png_debug1(3, "allocating units for info (%lu bytes)",
(unsigned long)length);
- info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
+ info_ptr->pcal_units = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, length));
if (info_ptr->pcal_units == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL units");
+
return;
}
- png_memcpy(info_ptr->pcal_units, units, length);
+ memcpy(info_ptr->pcal_units, units, length);
- info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,
- (png_size_t)((nparams + 1) * png_sizeof(png_charp)));
+ info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
+ (png_size_t)((nparams + 1) * (sizeof (png_charp)))));
if (info_ptr->pcal_params == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL params");
+
return;
}
- png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp));
+ memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp)));
for (i = 0; i < nparams; i++)
{
- length = png_strlen(params[i]) + 1;
+ length = strlen(params[i]) + 1;
png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
(unsigned long)length);
@@ -362,10 +353,11 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
if (info_ptr->pcal_params[i] == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL parameter");
+
return;
}
- png_memcpy(info_ptr->pcal_params[i], params[i], length);
+ memcpy(info_ptr->pcal_params[i], params[i], length);
}
info_ptr->valid |= PNG_INFO_pCAL;
@@ -375,7 +367,7 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_sCAL_SUPPORTED
void PNGAPI
-png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
+png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
int unit, png_const_charp swidth, png_const_charp sheight)
{
png_size_t lengthw = 0, lengthh = 0;
@@ -391,11 +383,11 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
if (unit != 1 && unit != 2)
png_error(png_ptr, "Invalid sCAL unit");
- if (swidth == NULL || (lengthw = png_strlen(swidth)) == 0 ||
+ if (swidth == NULL || (lengthw = strlen(swidth)) == 0 ||
swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
png_error(png_ptr, "Invalid sCAL width");
- if (sheight == NULL || (lengthh = png_strlen(sheight)) == 0 ||
+ if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
png_error(png_ptr, "Invalid sCAL height");
@@ -405,21 +397,24 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw);
- info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw);
+ info_ptr->scal_s_width = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, lengthw));
if (info_ptr->scal_s_width == NULL)
{
png_warning(png_ptr, "Memory allocation failed while processing sCAL");
+
return;
}
- png_memcpy(info_ptr->scal_s_width, swidth, lengthw);
+ memcpy(info_ptr->scal_s_width, swidth, lengthw);
++lengthh;
png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh);
- info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh);
+ info_ptr->scal_s_height = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, lengthh));
if (info_ptr->scal_s_height == NULL)
{
@@ -427,10 +422,11 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
info_ptr->scal_s_width = NULL;
png_warning(png_ptr, "Memory allocation failed while processing sCAL");
+
return;
}
- png_memcpy(info_ptr->scal_s_height, sheight, lengthh);
+ memcpy(info_ptr->scal_s_height, sheight, lengthh);
info_ptr->valid |= PNG_INFO_sCAL;
info_ptr->free_me |= PNG_FREE_SCAL;
@@ -438,8 +434,8 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
- double height)
+png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
+ double width, double height)
{
png_debug1(1, "in %s storage function", "sCAL");
@@ -456,9 +452,9 @@ png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
char swidth[PNG_sCAL_MAX_DIGITS+1];
char sheight[PNG_sCAL_MAX_DIGITS+1];
- png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width,
+ png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
PNG_sCAL_PRECISION);
- png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height,
+ png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
PNG_sCAL_PRECISION);
png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
@@ -468,7 +464,7 @@ png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
# ifdef PNG_FIXED_POINT_SUPPORTED
void PNGAPI
-png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
+png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
png_fixed_point width, png_fixed_point height)
{
png_debug1(1, "in %s storage function", "sCAL");
@@ -486,8 +482,8 @@ png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
char swidth[PNG_sCAL_MAX_DIGITS+1];
char sheight[PNG_sCAL_MAX_DIGITS+1];
- png_ascii_from_fixed(png_ptr, swidth, sizeof swidth, width);
- png_ascii_from_fixed(png_ptr, sheight, sizeof sheight, height);
+ png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width);
+ png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height);
png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
}
@@ -497,7 +493,7 @@ png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
#ifdef PNG_pHYs_SUPPORTED
void PNGAPI
-png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
+png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{
png_debug1(1, "in %s storage function", "pHYs");
@@ -513,16 +509,21 @@ png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
#endif
void PNGAPI
-png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
+png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
png_const_colorp palette, int num_palette)
{
+ png_uint_32 max_palette_length;
+
png_debug1(1, "in %s storage function", "PLTE");
if (png_ptr == NULL || info_ptr == NULL)
return;
- if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
+ max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
+ (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
+
+ if (num_palette < 0 || num_palette > (int) max_palette_length)
{
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
png_error(png_ptr, "Invalid palette length");
@@ -530,24 +531,39 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
else
{
png_warning(png_ptr, "Invalid palette length");
+
return;
}
}
+ if ((num_palette > 0 && palette == NULL) ||
+ (num_palette == 0
+# ifdef PNG_MNG_FEATURES_SUPPORTED
+ && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
+# endif
+ ))
+ {
+ png_error(png_ptr, "Invalid palette");
+ }
+
/* It may not actually be necessary to set png_ptr->palette here;
* we do it for backward compatibility with the way the png_handle_tRNS
* function used to do the allocation.
+ *
+ * 1.6.0: the above statement appears to be incorrect; something has to set
+ * the palette inside png_struct on read.
*/
png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
/* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
- * of num_palette entries, in case of an invalid PNG file that has
- * too-large sample values.
+ * of num_palette entries, in case of an invalid PNG file or incorrect
+ * call to png_set_PLTE() with too-large sample values.
*/
- png_ptr->palette = (png_colorp)png_calloc(png_ptr,
- PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
+ png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
+ PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
- png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
+ if (num_palette > 0)
+ memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
info_ptr->palette = png_ptr->palette;
info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
@@ -558,34 +574,34 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_sBIT_SUPPORTED
void PNGAPI
-png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
+png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_color_8p sig_bit)
{
png_debug1(1, "in %s storage function", "sBIT");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
return;
- png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
+ info_ptr->sig_bit = *sig_bit;
info_ptr->valid |= PNG_INFO_sBIT;
}
#endif
#ifdef PNG_sRGB_SUPPORTED
void PNGAPI
-png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int srgb_intent)
+png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
{
png_debug1(1, "in %s storage function", "sRGB");
if (png_ptr == NULL || info_ptr == NULL)
return;
- info_ptr->srgb_intent = (png_byte)srgb_intent;
- info_ptr->valid |= PNG_INFO_sRGB;
+ (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
void PNGAPI
-png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
+png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
int srgb_intent)
{
png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
@@ -593,28 +609,22 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
if (png_ptr == NULL || info_ptr == NULL)
return;
- png_set_sRGB(png_ptr, info_ptr, srgb_intent);
-
-# ifdef PNG_gAMA_SUPPORTED
- png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
-# endif
+ if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
+ srgb_intent) != 0)
+ {
+ /* This causes the gAMA and cHRM to be written too */
+ info_ptr->colorspace.flags |=
+ PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+ }
-# ifdef PNG_cHRM_SUPPORTED
- png_set_cHRM_fixed(png_ptr, info_ptr,
- /* color x y */
- /* white */ 31270, 32900,
- /* red */ 64000, 33000,
- /* green */ 30000, 60000,
- /* blue */ 15000, 6000
- );
-# endif /* cHRM */
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
#endif /* sRGB */
#ifdef PNG_iCCP_SUPPORTED
void PNGAPI
-png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
+png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_charp name, int compression_type,
png_const_bytep profile, png_uint_32 proflen)
{
@@ -627,37 +637,60 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
return;
- length = png_strlen(name)+1;
- new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);
+ if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+ png_app_error(png_ptr, "Invalid iCCP compression method");
+
+ /* Set the colorspace first because this validates the profile; do not
+ * override previously set app cHRM or gAMA here (because likely as not the
+ * application knows better than libpng what the correct values are.) Pass
+ * the info_ptr color_type field to png_colorspace_set_ICC because in the
+ * write case it has not yet been stored in png_ptr.
+ */
+ {
+ int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
+ proflen, profile, info_ptr->color_type);
+
+ png_colorspace_sync_info(png_ptr, info_ptr);
+
+ /* Don't do any of the copying if the profile was bad, or inconsistent. */
+ if (result == 0)
+ return;
+
+ /* But do write the gAMA and cHRM chunks from the profile. */
+ info_ptr->colorspace.flags |=
+ PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+ }
+
+ length = strlen(name)+1;
+ new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
if (new_iccp_name == NULL)
{
- png_warning(png_ptr, "Insufficient memory to process iCCP chunk");
+ png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");
+
return;
}
- png_memcpy(new_iccp_name, name, length);
- new_iccp_profile = (png_bytep)png_malloc_warn(png_ptr, proflen);
+ memcpy(new_iccp_name, name, length);
+ new_iccp_profile = png_voidcast(png_bytep,
+ png_malloc_warn(png_ptr, proflen));
if (new_iccp_profile == NULL)
{
- png_free (png_ptr, new_iccp_name);
- png_warning(png_ptr,
+ png_free(png_ptr, new_iccp_name);
+ png_benign_error(png_ptr,
"Insufficient memory to process iCCP profile");
+
return;
}
- png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);
+ memcpy(new_iccp_profile, profile, proflen);
png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
info_ptr->iccp_proflen = proflen;
info_ptr->iccp_name = new_iccp_name;
info_ptr->iccp_profile = new_iccp_profile;
- /* Compression is always zero but is here so the API and info structure
- * does not have to change if we introduce multiple compression types
- */
- info_ptr->iccp_compression = (png_byte)compression_type;
info_ptr->free_me |= PNG_FREE_ICCP;
info_ptr->valid |= PNG_INFO_iCCP;
}
@@ -665,73 +698,82 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_TEXT_SUPPORTED
void PNGAPI
-png_set_text(png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr,
- int num_text)
+png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_const_textp text_ptr, int num_text)
{
int ret;
ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
- if (ret)
+ if (ret != 0)
png_error(png_ptr, "Insufficient memory to store text");
}
int /* PRIVATE */
-png_set_text_2(png_structp png_ptr, png_infop info_ptr,
+png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_textp text_ptr, int num_text)
{
int i;
- png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" :
+ png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U :
(unsigned long)png_ptr->chunk_name);
- if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
+ if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
return(0);
/* Make sure we have enough space in the "text" array in info_struct
- * to hold all of the incoming text_ptr objects.
+ * to hold all of the incoming text_ptr objects. This compare can't overflow
+ * because max_text >= num_text (anyway, subtract of two positive integers
+ * can't overflow in any case.)
*/
- if (info_ptr->num_text + num_text > info_ptr->max_text)
+ if (num_text > info_ptr->max_text - info_ptr->num_text)
{
- if (info_ptr->text != NULL)
- {
- png_textp old_text;
- int old_max;
+ int old_num_text = info_ptr->num_text;
+ int max_text;
+ png_textp new_text = NULL;
- old_max = info_ptr->max_text;
- info_ptr->max_text = info_ptr->num_text + num_text + 8;
- old_text = info_ptr->text;
- info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
- (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
+ /* Calculate an appropriate max_text, checking for overflow. */
+ max_text = old_num_text;
+ if (num_text <= INT_MAX - max_text)
+ {
+ max_text += num_text;
- if (info_ptr->text == NULL)
- {
- png_free(png_ptr, old_text);
- return(1);
- }
+ /* Round up to a multiple of 8 */
+ if (max_text < INT_MAX-8)
+ max_text = (max_text + 8) & ~0x7;
- png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
- png_sizeof(png_text)));
- png_free(png_ptr, old_text);
+ else
+ max_text = INT_MAX;
+
+ /* Now allocate a new array and copy the old members in; this does all
+ * the overflow checks.
+ */
+ new_text = png_voidcast(png_textp,png_realloc_array(png_ptr,
+ info_ptr->text, old_num_text, max_text-old_num_text,
+ sizeof *new_text));
}
- else
+ if (new_text == NULL)
{
- info_ptr->max_text = num_text + 8;
- info_ptr->num_text = 0;
- info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
- (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
- if (info_ptr->text == NULL)
- return(1);
- info_ptr->free_me |= PNG_FREE_TEXT;
+ png_chunk_report(png_ptr, "too many text chunks",
+ PNG_CHUNK_WRITE_ERROR);
+
+ return 1;
}
- png_debug1(3, "allocated %d entries for info_ptr->text",
- info_ptr->max_text);
+ png_free(png_ptr, info_ptr->text);
+
+ info_ptr->text = new_text;
+ info_ptr->free_me |= PNG_FREE_TEXT;
+ info_ptr->max_text = max_text;
+ /* num_text is adjusted below as the entries are copied in */
+
+ png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
}
+
for (i = 0; i < num_text; i++)
{
- png_size_t text_length, key_len;
- png_size_t lang_len, lang_key_len;
+ size_t text_length, key_len;
+ size_t lang_len, lang_key_len;
png_textp textp = &(info_ptr->text[info_ptr->num_text]);
if (text_ptr[i].key == NULL)
@@ -740,11 +782,12 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
{
- png_warning(png_ptr, "text compression mode is out of range");
+ png_chunk_report(png_ptr, "text compression mode is out of range",
+ PNG_CHUNK_WRITE_ERROR);
continue;
}
- key_len = png_strlen(text_ptr[i].key);
+ key_len = strlen(text_ptr[i].key);
if (text_ptr[i].compression <= 0)
{
@@ -758,20 +801,21 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
/* Set iTXt data */
if (text_ptr[i].lang != NULL)
- lang_len = png_strlen(text_ptr[i].lang);
+ lang_len = strlen(text_ptr[i].lang);
else
lang_len = 0;
if (text_ptr[i].lang_key != NULL)
- lang_key_len = png_strlen(text_ptr[i].lang_key);
+ lang_key_len = strlen(text_ptr[i].lang_key);
else
lang_key_len = 0;
}
-# else /* PNG_iTXt_SUPPORTED */
+# else /* iTXt */
{
- png_warning(png_ptr, "iTXt chunk not supported");
+ png_chunk_report(png_ptr, "iTXt chunk not supported",
+ PNG_CHUNK_WRITE_ERROR);
continue;
}
# endif
@@ -790,32 +834,36 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
else
{
- text_length = png_strlen(text_ptr[i].text);
+ text_length = strlen(text_ptr[i].text);
textp->compression = text_ptr[i].compression;
}
- textp->key = (png_charp)png_malloc_warn(png_ptr,
- (png_size_t)
- (key_len + text_length + lang_len + lang_key_len + 4));
+ textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr,
+ key_len + text_length + lang_len + lang_key_len + 4));
if (textp->key == NULL)
- return(1);
+ {
+ png_chunk_report(png_ptr, "text chunk: out of memory",
+ PNG_CHUNK_WRITE_ERROR);
+
+ return 1;
+ }
png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
(unsigned long)(png_uint_32)
(key_len + lang_len + lang_key_len + text_length + 4),
textp->key);
- png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
+ memcpy(textp->key, text_ptr[i].key, key_len);
*(textp->key + key_len) = '\0';
if (text_ptr[i].compression > 0)
{
textp->lang = textp->key + key_len + 1;
- png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
+ memcpy(textp->lang, text_ptr[i].lang, lang_len);
*(textp->lang + lang_len) = '\0';
textp->lang_key = textp->lang + lang_len + 1;
- png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
+ memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
*(textp->lang_key + lang_key_len) = '\0';
textp->text = textp->lang_key + lang_key_len + 1;
}
@@ -827,9 +875,8 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
textp->text = textp->key + key_len + 1;
}
- if (text_length)
- png_memcpy(textp->text, text_ptr[i].text,
- (png_size_t)(text_length));
+ if (text_length != 0)
+ memcpy(textp->text, text_ptr[i].text, text_length);
*(textp->text + text_length) = '\0';
@@ -850,18 +897,20 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
info_ptr->num_text++;
png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
}
+
return(0);
}
#endif
#ifdef PNG_tIME_SUPPORTED
void PNGAPI
-png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)
+png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_const_timep mod_time)
{
png_debug1(1, "in %s storage function", "tIME");
- if (png_ptr == NULL || info_ptr == NULL ||
- (png_ptr->mode & PNG_WROTE_tIME))
+ if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
+ (png_ptr->mode & PNG_WROTE_tIME) != 0)
return;
if (mod_time->month == 0 || mod_time->month > 12 ||
@@ -870,22 +919,24 @@ png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)
mod_time->second > 60)
{
png_warning(png_ptr, "Ignoring invalid time value");
+
return;
}
- png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
+ info_ptr->mod_time = *mod_time;
info_ptr->valid |= PNG_INFO_tIME;
}
#endif
#ifdef PNG_tRNS_SUPPORTED
void PNGAPI
-png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
+png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
{
png_debug1(1, "in %s storage function", "tRNS");
if (png_ptr == NULL || info_ptr == NULL)
+
return;
if (trans_alpha != NULL)
@@ -893,33 +944,41 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
/* It may not actually be necessary to set png_ptr->trans_alpha here;
* we do it for backward compatibility with the way the png_handle_tRNS
* function used to do the allocation.
+ *
+ * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
+ * relies on png_set_tRNS storing the information in png_struct
+ * (otherwise it won't be there for the code in pngrtran.c).
*/
png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
/* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
- png_ptr->trans_alpha = info_ptr->trans_alpha =
- (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH);
+ png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
+ png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
- png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
+ memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
}
if (trans_color != NULL)
{
- int sample_max = (1 << info_ptr->bit_depth);
-
- if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
- (int)trans_color->gray > sample_max) ||
- (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
- ((int)trans_color->red > sample_max ||
- (int)trans_color->green > sample_max ||
- (int)trans_color->blue > sample_max)))
- png_warning(png_ptr,
- "tRNS chunk has out-of-range samples for bit_depth");
+#ifdef PNG_WARNINGS_SUPPORTED
+ if (info_ptr->bit_depth < 16)
+ {
+ int sample_max = (1 << info_ptr->bit_depth) - 1;
+
+ if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
+ trans_color->gray > sample_max) ||
+ (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
+ (trans_color->red > sample_max ||
+ trans_color->green > sample_max ||
+ trans_color->blue > sample_max)))
+ png_warning(png_ptr,
+ "tRNS chunk has out-of-range samples for bit_depth");
+ }
+#endif
- png_memcpy(&(info_ptr->trans_color), trans_color,
- png_sizeof(png_color_16));
+ info_ptr->trans_color = *trans_color;
if (num_trans == 0)
num_trans = 1;
@@ -937,8 +996,8 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_sPLT_SUPPORTED
void PNGAPI
-png_set_sPLT(png_structp png_ptr,
- png_infop info_ptr, png_const_sPLT_tp entries, int nentries)
+png_set_sPLT(png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
/*
* entries - array of png_sPLT_t structures
* to be added to the list of palettes
@@ -949,220 +1008,462 @@ png_set_sPLT(png_structp png_ptr,
*/
{
png_sPLT_tp np;
- int i;
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
return;
- np = (png_sPLT_tp)png_malloc_warn(png_ptr,
- (info_ptr->splt_palettes_num + nentries) *
- (png_size_t)png_sizeof(png_sPLT_t));
+ /* Use the internal realloc function, which checks for all the possible
+ * overflows. Notice that the parameters are (int) and (size_t)
+ */
+ np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
+ info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
+ sizeof *np));
if (np == NULL)
{
- png_warning(png_ptr, "No memory for sPLT palettes");
+ /* Out of memory or too many chunks */
+ png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
+
return;
}
- png_memcpy(np, info_ptr->splt_palettes,
- info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
-
png_free(png_ptr, info_ptr->splt_palettes);
- info_ptr->splt_palettes=NULL;
+ info_ptr->splt_palettes = np;
+ info_ptr->free_me |= PNG_FREE_SPLT;
+
+ np += info_ptr->splt_palettes_num;
- for (i = 0; i < nentries; i++)
+ do
{
- png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
- png_const_sPLT_tp from = entries + i;
png_size_t length;
- length = png_strlen(from->name) + 1;
- to->name = (png_charp)png_malloc_warn(png_ptr, length);
-
- if (to->name == NULL)
+ /* Skip invalid input entries */
+ if (entries->name == NULL || entries->entries == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing sPLT chunk");
+ /* png_handle_sPLT doesn't do this, so this is an app error */
+ png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
+ /* Just skip the invalid entry */
continue;
}
- png_memcpy(to->name, from->name, length);
- to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
- from->nentries * png_sizeof(png_sPLT_entry));
+ np->depth = entries->depth;
+
+ /* In the event of out-of-memory just return - there's no point keeping
+ * on trying to add sPLT chunks.
+ */
+ length = strlen(entries->name) + 1;
+ np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length));
+
+ if (np->name == NULL)
+ break;
+
+ memcpy(np->name, entries->name, length);
+
+ /* IMPORTANT: we have memory now that won't get freed if something else
+ * goes wrong; this code must free it. png_malloc_array produces no
+ * warnings; use a png_chunk_report (below) if there is an error.
+ */
+ np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr,
+ entries->nentries, sizeof (png_sPLT_entry)));
- if (to->entries == NULL)
+ if (np->entries == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing sPLT chunk");
- png_free(png_ptr, to->name);
- to->name = NULL;
- continue;
+ png_free(png_ptr, np->name);
+ np->name = NULL;
+ break;
}
- png_memcpy(to->entries, from->entries,
- from->nentries * png_sizeof(png_sPLT_entry));
+ np->nentries = entries->nentries;
+ /* This multiply can't overflow because png_malloc_array has already
+ * checked it when doing the allocation.
+ */
+ memcpy(np->entries, entries->entries,
+ entries->nentries * sizeof (png_sPLT_entry));
+
+ /* Note that 'continue' skips the advance of the out pointer and out
+ * count, so an invalid entry is not added.
+ */
+ info_ptr->valid |= PNG_INFO_sPLT;
+ ++(info_ptr->splt_palettes_num);
+ ++np;
+ }
+ while (++entries, --nentries);
+
+ if (nentries > 0)
+ png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
+}
+#endif /* sPLT */
- to->nentries = from->nentries;
- to->depth = from->depth;
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+static png_byte
+check_location(png_const_structrp png_ptr, int location)
+{
+ location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
+
+ /* New in 1.6.0; copy the location and check it. This is an API
+ * change; previously the app had to use the
+ * png_set_unknown_chunk_location API below for each chunk.
+ */
+ if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ /* Write struct, so unknown chunks come from the app */
+ png_app_warning(png_ptr,
+ "png_set_unknown_chunks now expects a valid location");
+ /* Use the old behavior */
+ location = (png_byte)(png_ptr->mode &
+ (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
}
- info_ptr->splt_palettes = np;
- info_ptr->splt_palettes_num += nentries;
- info_ptr->valid |= PNG_INFO_sPLT;
- info_ptr->free_me |= PNG_FREE_SPLT;
+ /* This need not be an internal error - if the app calls
+ * png_set_unknown_chunks on a read pointer it must get the location right.
+ */
+ if (location == 0)
+ png_error(png_ptr, "invalid location in png_set_unknown_chunks");
+
+ /* Now reduce the location to the top-most set bit by removing each least
+ * significant bit in turn.
+ */
+ while (location != (location & -location))
+ location &= ~(location & -location);
+
+ /* The cast is safe because 'location' is a bit mask and only the low four
+ * bits are significant.
+ */
+ return (png_byte)location;
}
-#endif /* PNG_sPLT_SUPPORTED */
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
void PNGAPI
-png_set_unknown_chunks(png_structp png_ptr,
- png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
+png_set_unknown_chunks(png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
{
png_unknown_chunkp np;
- int i;
- if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
+ if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
+ unknowns == NULL)
return;
- np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
- (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) *
- png_sizeof(png_unknown_chunk));
+ /* Check for the failure cases where support has been disabled at compile
+ * time. This code is hardly ever compiled - it's here because
+ * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
+ * code) but may be meaningless if the read or write handling of unknown
+ * chunks is not compiled in.
+ */
+# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
+ defined(PNG_READ_SUPPORTED)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+ png_app_error(png_ptr, "no unknown chunk support on read");
+
+ return;
+ }
+# endif
+# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
+ defined(PNG_WRITE_SUPPORTED)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ png_app_error(png_ptr, "no unknown chunk support on write");
+
+ return;
+ }
+# endif
+
+ /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
+ * unknown critical chunks could be lost with just a warning resulting in
+ * undefined behavior. Now png_chunk_report is used to provide behavior
+ * appropriate to read or write.
+ */
+ np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
+ info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
+ sizeof *np));
if (np == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing unknown chunk");
+ png_chunk_report(png_ptr, "too many unknown chunks",
+ PNG_CHUNK_WRITE_ERROR);
+
return;
}
- png_memcpy(np, info_ptr->unknown_chunks,
- (png_size_t)info_ptr->unknown_chunks_num *
- png_sizeof(png_unknown_chunk));
-
png_free(png_ptr, info_ptr->unknown_chunks);
- info_ptr->unknown_chunks = NULL;
-
- for (i = 0; i < num_unknowns; i++)
- {
- png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
- png_const_unknown_chunkp from = unknowns + i;
+ info_ptr->unknown_chunks = np; /* safe because it is initialized */
+ info_ptr->free_me |= PNG_FREE_UNKN;
- png_memcpy(to->name, from->name, png_sizeof(from->name));
- to->name[png_sizeof(to->name)-1] = '\0';
- to->size = from->size;
+ np += info_ptr->unknown_chunks_num;
- /* Note our location in the read or write sequence */
- to->location = (png_byte)(png_ptr->mode & 0xff);
+ /* Increment unknown_chunks_num each time round the loop to protect the
+ * just-allocated chunk data.
+ */
+ for (; num_unknowns > 0; --num_unknowns, ++unknowns)
+ {
+ memcpy(np->name, unknowns->name, (sizeof np->name));
+ np->name[(sizeof np->name)-1] = '\0';
+ np->location = check_location(png_ptr, unknowns->location);
- if (from->size == 0)
- to->data=NULL;
+ if (unknowns->size == 0)
+ {
+ np->data = NULL;
+ np->size = 0;
+ }
else
{
- to->data = (png_bytep)png_malloc_warn(png_ptr,
- (png_size_t)from->size);
+ np->data = png_voidcast(png_bytep,
+ png_malloc_base(png_ptr, unknowns->size));
- if (to->data == NULL)
+ if (np->data == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing unknown chunk");
- to->size = 0;
+ png_chunk_report(png_ptr, "unknown chunk: out of memory",
+ PNG_CHUNK_WRITE_ERROR);
+ /* But just skip storing the unknown chunk */
+ continue;
}
- else
- png_memcpy(to->data, from->data, from->size);
+ memcpy(np->data, unknowns->data, unknowns->size);
+ np->size = unknowns->size;
}
- }
- info_ptr->unknown_chunks = np;
- info_ptr->unknown_chunks_num += num_unknowns;
- info_ptr->free_me |= PNG_FREE_UNKN;
+ /* These increments are skipped on out-of-memory for the data - the
+ * unknown chunk entry gets overwritten if the png_chunk_report returns.
+ * This is correct in the read case (the chunk is just dropped.)
+ */
+ ++np;
+ ++(info_ptr->unknown_chunks_num);
+ }
}
void PNGAPI
-png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
+png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
int chunk, int location)
{
- if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
- info_ptr->unknown_chunks_num)
- info_ptr->unknown_chunks[chunk].location = (png_byte)location;
-}
-#endif
+ /* This API is pretty pointless in 1.6.0 because the location can be set
+ * before the call to png_set_unknown_chunks.
+ *
+ * TODO: add a png_app_warning in 1.7
+ */
+ if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
+ chunk < info_ptr->unknown_chunks_num)
+ {
+ if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
+ {
+ png_app_error(png_ptr, "invalid unknown chunk location");
+ /* Fake out the pre 1.6.0 behavior: */
+ if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */
+ location = PNG_AFTER_IDAT;
+ else
+ location = PNG_HAVE_IHDR; /* also undocumented */
+ }
+
+ info_ptr->unknown_chunks[chunk].location =
+ check_location(png_ptr, location);
+ }
+}
+#endif /* STORE_UNKNOWN_CHUNKS */
#ifdef PNG_MNG_FEATURES_SUPPORTED
png_uint_32 PNGAPI
-png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
+png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
{
png_debug(1, "in png_permit_mng_features");
if (png_ptr == NULL)
- return (png_uint_32)0;
+ return 0;
- png_ptr->mng_features_permitted =
- (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
+ png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
- return (png_uint_32)png_ptr->mng_features_permitted;
+ return png_ptr->mng_features_permitted;
}
#endif
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+static unsigned int
+add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
+{
+ unsigned int i;
+
+ /* Utility function: update the 'keep' state of a chunk if it is already in
+ * the list, otherwise add it to the list.
+ */
+ for (i=0; i<count; ++i, list += 5)
+ {
+ if (memcmp(list, add, 4) == 0)
+ {
+ list[4] = (png_byte)keep;
+
+ return count;
+ }
+ }
+
+ if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
+ {
+ ++count;
+ memcpy(list, add, 4);
+ list[4] = (png_byte)keep;
+ }
+
+ return count;
+}
+
void PNGAPI
-png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_const_bytep
- chunk_list, int num_chunks)
+png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
+ png_const_bytep chunk_list, int num_chunks_in)
{
- png_bytep new_list, p;
- int i, old_num_chunks;
+ png_bytep new_list;
+ unsigned int num_chunks, old_num_chunks;
+
if (png_ptr == NULL)
return;
- if (num_chunks == 0)
+ if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
{
- if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
- png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+ png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
- else
- png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+ return;
+ }
- if (keep == PNG_HANDLE_CHUNK_ALWAYS)
- png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+ if (num_chunks_in <= 0)
+ {
+ png_ptr->unknown_default = keep;
- else
- png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+ /* '0' means just set the flags, so stop here */
+ if (num_chunks_in == 0)
+ return;
+ }
- return;
+ if (num_chunks_in < 0)
+ {
+ /* Ignore all unknown chunks and all chunks recognized by
+ * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
+ */
+ static PNG_CONST png_byte chunks_to_ignore[] = {
+ 98, 75, 71, 68, '\0', /* bKGD */
+ 99, 72, 82, 77, '\0', /* cHRM */
+ 103, 65, 77, 65, '\0', /* gAMA */
+ 104, 73, 83, 84, '\0', /* hIST */
+ 105, 67, 67, 80, '\0', /* iCCP */
+ 105, 84, 88, 116, '\0', /* iTXt */
+ 111, 70, 70, 115, '\0', /* oFFs */
+ 112, 67, 65, 76, '\0', /* pCAL */
+ 112, 72, 89, 115, '\0', /* pHYs */
+ 115, 66, 73, 84, '\0', /* sBIT */
+ 115, 67, 65, 76, '\0', /* sCAL */
+ 115, 80, 76, 84, '\0', /* sPLT */
+ 115, 84, 69, 82, '\0', /* sTER */
+ 115, 82, 71, 66, '\0', /* sRGB */
+ 116, 69, 88, 116, '\0', /* tEXt */
+ 116, 73, 77, 69, '\0', /* tIME */
+ 122, 84, 88, 116, '\0' /* zTXt */
+ };
+
+ chunk_list = chunks_to_ignore;
+ num_chunks = (unsigned int)/*SAFE*/(sizeof chunks_to_ignore)/5U;
}
- if (chunk_list == NULL)
- return;
+ else /* num_chunks_in > 0 */
+ {
+ if (chunk_list == NULL)
+ {
+ /* Prior to 1.6.0 this was silently ignored, now it is an app_error
+ * which can be switched off.
+ */
+ png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
+
+ return;
+ }
+
+ num_chunks = num_chunks_in;
+ }
old_num_chunks = png_ptr->num_chunk_list;
- new_list=(png_bytep)png_malloc(png_ptr,
- (png_size_t)(5*(num_chunks + old_num_chunks)));
+ if (png_ptr->chunk_list == NULL)
+ old_num_chunks = 0;
- if (png_ptr->chunk_list != NULL)
+ /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
+ */
+ if (num_chunks + old_num_chunks > UINT_MAX/5)
{
- png_memcpy(new_list, png_ptr->chunk_list,
- (png_size_t)(5*old_num_chunks));
- png_free(png_ptr, png_ptr->chunk_list);
- png_ptr->chunk_list=NULL;
+ png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
+
+ return;
}
- png_memcpy(new_list + 5*old_num_chunks, chunk_list,
- (png_size_t)(5*num_chunks));
+ /* If these chunks are being reset to the default then no more memory is
+ * required because add_one_chunk above doesn't extend the list if the 'keep'
+ * parameter is the default.
+ */
+ if (keep != 0)
+ {
+ new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
+ 5 * (num_chunks + old_num_chunks)));
+
+ if (old_num_chunks > 0)
+ memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
+ }
- for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
- *p=(png_byte)keep;
+ else if (old_num_chunks > 0)
+ new_list = png_ptr->chunk_list;
+
+ else
+ new_list = NULL;
+
+ /* Add the new chunks together with each one's handling code. If the chunk
+ * already exists the code is updated, otherwise the chunk is added to the
+ * end. (In libpng 1.6.0 order no longer matters because this code enforces
+ * the earlier convention that the last setting is the one that is used.)
+ */
+ if (new_list != NULL)
+ {
+ png_const_bytep inlist;
+ png_bytep outlist;
+ unsigned int i;
+
+ for (i=0; i<num_chunks; ++i)
+ {
+ old_num_chunks = add_one_chunk(new_list, old_num_chunks,
+ chunk_list+5*i, keep);
+ }
+
+ /* Now remove any spurious 'default' entries. */
+ num_chunks = 0;
+ for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5)
+ {
+ if (inlist[4])
+ {
+ if (outlist != inlist)
+ memcpy(outlist, inlist, 5);
+ outlist += 5;
+ ++num_chunks;
+ }
+ }
+
+ /* This means the application has removed all the specialized handling. */
+ if (num_chunks == 0)
+ {
+ if (png_ptr->chunk_list != new_list)
+ png_free(png_ptr, new_list);
+
+ new_list = NULL;
+ }
+ }
+
+ else
+ num_chunks = 0;
- png_ptr->num_chunk_list = old_num_chunks + num_chunks;
- png_ptr->chunk_list = new_list;
- png_ptr->free_me |= PNG_FREE_LIST;
+ png_ptr->num_chunk_list = num_chunks;
+
+ if (png_ptr->chunk_list != new_list)
+ {
+ if (png_ptr->chunk_list != NULL)
+ png_free(png_ptr, png_ptr->chunk_list);
+
+ png_ptr->chunk_list = new_list;
+ }
}
#endif
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
void PNGAPI
-png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
+png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
png_user_chunk_ptr read_user_chunk_fn)
{
png_debug(1, "in png_set_read_user_chunk_fn");
@@ -1177,69 +1478,102 @@ png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
-png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
+png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_bytepp row_pointers)
{
png_debug1(1, "in %s storage function", "rows");
if (png_ptr == NULL || info_ptr == NULL)
return;
- if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
+ if (info_ptr->row_pointers != NULL &&
+ (info_ptr->row_pointers != row_pointers))
png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
info_ptr->row_pointers = row_pointers;
- if (row_pointers)
+ if (row_pointers != NULL)
info_ptr->valid |= PNG_INFO_IDAT;
}
#endif
void PNGAPI
-png_set_compression_buffer_size(png_structp png_ptr, png_size_t size)
+png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
{
if (png_ptr == NULL)
return;
- png_free(png_ptr, png_ptr->zbuf);
+ if (size == 0 || size > PNG_UINT_31_MAX)
+ png_error(png_ptr, "invalid compression buffer size");
- if (size > ZLIB_IO_MAX)
- {
- png_warning(png_ptr, "Attempt to set buffer size beyond max ignored");
- png_ptr->zbuf_size = ZLIB_IO_MAX;
- size = ZLIB_IO_MAX; /* must fit */
- }
+# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+ png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
+ return;
+ }
+# endif
- else
- png_ptr->zbuf_size = (uInt)size;
+# ifdef PNG_WRITE_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ if (png_ptr->zowner != 0)
+ {
+ png_warning(png_ptr,
+ "Compression buffer size cannot be changed because it is in use");
+
+ return;
+ }
- png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
+#ifndef __COVERITY__
+ /* Some compilers complain that this is always false. However, it
+ * can be true when integer overflow happens.
+ */
+ if (size > ZLIB_IO_MAX)
+ {
+ png_warning(png_ptr,
+ "Compression buffer size limited to system maximum");
+ size = ZLIB_IO_MAX; /* must fit */
+ }
+#endif
- /* The following ensures a relatively safe failure if this gets called while
- * the buffer is actually in use.
- */
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = 0;
- png_ptr->zstream.avail_in = 0;
+ if (size < 6)
+ {
+ /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
+ * if this is permitted.
+ */
+ png_warning(png_ptr,
+ "Compression buffer size cannot be reduced below 6");
+
+ return;
+ }
+
+ if (png_ptr->zbuffer_size != size)
+ {
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
+ png_ptr->zbuffer_size = (uInt)size;
+ }
+ }
+# endif
}
void PNGAPI
-png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
+png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
{
- if (png_ptr && info_ptr)
+ if (png_ptr != NULL && info_ptr != NULL)
info_ptr->valid &= ~mask;
}
-
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* This function was added to libpng 1.2.6 */
void PNGAPI
-png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
+png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
png_uint_32 user_height_max)
{
/* Images with dimensions larger than these limits will be
* rejected by png_set_IHDR(). To accept any PNG datastream
- * regardless of dimensions, set both limits to 0x7ffffffL.
+ * regardless of dimensions, set both limits to 0x7fffffff.
*/
if (png_ptr == NULL)
return;
@@ -1250,35 +1584,148 @@ png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
/* This function was added to libpng 1.4.0 */
void PNGAPI
-png_set_chunk_cache_max (png_structp png_ptr,
- png_uint_32 user_chunk_cache_max)
+png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
{
- if (png_ptr)
- png_ptr->user_chunk_cache_max = user_chunk_cache_max;
+ if (png_ptr != NULL)
+ png_ptr->user_chunk_cache_max = user_chunk_cache_max;
}
/* This function was added to libpng 1.4.1 */
void PNGAPI
-png_set_chunk_malloc_max (png_structp png_ptr,
+png_set_chunk_malloc_max (png_structrp png_ptr,
png_alloc_size_t user_chunk_malloc_max)
{
- if (png_ptr)
+ if (png_ptr != NULL)
png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
}
-#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
+#endif /* ?SET_USER_LIMITS */
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
-png_set_benign_errors(png_structp png_ptr, int allowed)
+png_set_benign_errors(png_structrp png_ptr, int allowed)
{
png_debug(1, "in png_set_benign_errors");
- if (allowed)
- png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
+ /* If allowed is 1, png_benign_error() is treated as a warning.
+ *
+ * If allowed is 0, png_benign_error() is treated as an error (which
+ * is the default behavior if png_set_benign_errors() is not called).
+ */
+
+ if (allowed != 0)
+ png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
+ PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
+
+ else
+ png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
+ PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
+}
+#endif /* BENIGN_ERRORS */
+
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Whether to report invalid palette index; added at libng-1.5.10.
+ * It is possible for an indexed (color-type==3) PNG file to contain
+ * pixels with invalid (out-of-range) indexes if the PLTE chunk has
+ * fewer entries than the image's bit-depth would allow. We recover
+ * from this gracefully by filling any incomplete palette with zeros
+ * (opaque black). By default, when this occurs libpng will issue
+ * a benign error. This API can be used to override that behavior.
+ */
+void PNGAPI
+png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
+{
+ png_debug(1, "in png_set_check_for_invalid_index");
+
+ if (allowed > 0)
+ png_ptr->num_palette_max = 0;
else
- png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
+ png_ptr->num_palette_max = -1;
+}
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
+ defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
+ *
+ * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
+ * trailing '\0'). If this routine returns 0 then there was no keyword, or a
+ * valid one could not be generated, and the caller must png_error.
+ */
+png_uint_32 /* PRIVATE */
+png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
+{
+ png_const_charp orig_key = key;
+ png_uint_32 key_len = 0;
+ int bad_character = 0;
+ int space = 1;
+
+ png_debug(1, "in png_check_keyword");
+
+ if (key == NULL)
+ {
+ *new_key = 0;
+ return 0;
+ }
+
+ while (*key && key_len < 79)
+ {
+ png_byte ch = (png_byte)*key++;
+
+ if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
+ *new_key++ = ch, ++key_len, space = 0;
+
+ else if (space == 0)
+ {
+ /* A space or an invalid character when one wasn't seen immediately
+ * before; output just a space.
+ */
+ *new_key++ = 32, ++key_len, space = 1;
+
+ /* If the character was not a space then it is invalid. */
+ if (ch != 32)
+ bad_character = ch;
+ }
+
+ else if (bad_character == 0)
+ bad_character = ch; /* just skip it, record the first error */
+ }
+
+ if (key_len > 0 && space != 0) /* trailing space */
+ {
+ --key_len, --new_key;
+ if (bad_character == 0)
+ bad_character = 32;
+ }
+
+ /* Terminate the keyword */
+ *new_key = 0;
+
+ if (key_len == 0)
+ return 0;
+
+#ifdef PNG_WARNINGS_SUPPORTED
+ /* Try to only output one warning per keyword: */
+ if (*key != 0) /* keyword too long */
+ png_warning(png_ptr, "keyword truncated");
+
+ else if (bad_character != 0)
+ {
+ PNG_WARNING_PARAMETERS(p)
+
+ png_warning_parameter(p, 1, orig_key);
+ png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
+
+ png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
+ }
+#endif /* WARNINGS */
+
+ return key_len;
}
-#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* TEXT || pCAL || iCCP || sPLT */
+#endif /* READ || WRITE */
diff --git a/thirdparty/libpng/pngstruct.h b/thirdparty/libpng/pngstruct.h
index 860b8bff..c1f35ede 100644
--- a/thirdparty/libpng/pngstruct.h
+++ b/thirdparty/libpng/pngstruct.h
@@ -1,12 +1,11 @@
/* pngstruct.h - header file for PNG reference library
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.18 [July 23, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.9 [February 18, 2012]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -24,13 +23,130 @@
* in this structure and is required for decompressing the LZ compressed
* data in PNG files.
*/
+#ifndef ZLIB_CONST
+ /* We must ensure that zlib uses 'const' in declarations. */
+# define ZLIB_CONST
+#endif
#include "zlib.h"
+#ifdef const
+ /* zlib.h sometimes #defines const to nothing, undo this. */
+# undef const
+#endif
+
+/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
+ * with older builds.
+ */
+#if ZLIB_VERNUM < 0x1260
+# define PNGZ_MSG_CAST(s) png_constcast(char*,s)
+# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b)
+#else
+# define PNGZ_MSG_CAST(s) (s)
+# define PNGZ_INPUT_CAST(b) (b)
+#endif
+
+/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib
+ * can handle at once. This type need be no larger than 16 bits (so maximum of
+ * 65535), this define allows us to discover how big it is, but limited by the
+ * maximuum for png_size_t. The value can be overriden in a library build
+ * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably
+ * lower value (e.g. 255 works). A lower value may help memory usage (slightly)
+ * and may even improve performance on some systems (and degrade it on others.)
+ */
+#ifndef ZLIB_IO_MAX
+# define ZLIB_IO_MAX ((uInt)-1)
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+/* The type of a compression buffer list used by the write code. */
+typedef struct png_compression_buffer
+{
+ struct png_compression_buffer *next;
+ png_byte output[1]; /* actually zbuf_size */
+} png_compression_buffer, *png_compression_bufferp;
+
+#define PNG_COMPRESSION_BUFFER_SIZE(pp)\
+ (offsetof(png_compression_buffer, output) + (pp)->zbuffer_size)
+#endif
+
+/* Colorspace support; structures used in png_struct, png_info and in internal
+ * functions to hold and communicate information about the color space.
+ *
+ * PNG_COLORSPACE_SUPPORTED is only required if the application will perform
+ * colorspace corrections, otherwise all the colorspace information can be
+ * skipped and the size of libpng can be reduced (significantly) by compiling
+ * out the colorspace support.
+ */
+#ifdef PNG_COLORSPACE_SUPPORTED
+/* The chromaticities of the red, green and blue colorants and the chromaticity
+ * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
+ */
+typedef struct png_xy
+{
+ png_fixed_point redx, redy;
+ png_fixed_point greenx, greeny;
+ png_fixed_point bluex, bluey;
+ png_fixed_point whitex, whitey;
+} png_xy;
+
+/* The same data as above but encoded as CIE XYZ values. When this data comes
+ * from chromaticities the sum of the Y values is assumed to be 1.0
+ */
+typedef struct png_XYZ
+{
+ png_fixed_point red_X, red_Y, red_Z;
+ png_fixed_point green_X, green_Y, green_Z;
+ png_fixed_point blue_X, blue_Y, blue_Z;
+} png_XYZ;
+#endif /* COLORSPACE */
+
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+/* A colorspace is all the above plus, potentially, profile information;
+ * however at present libpng does not use the profile internally so it is only
+ * stored in the png_info struct (if iCCP is supported.) The rendering intent
+ * is retained here and is checked.
+ *
+ * The file gamma encoding information is also stored here and gamma correction
+ * is done by libpng, whereas color correction must currently be done by the
+ * application.
+ */
+typedef struct png_colorspace
+{
+#ifdef PNG_GAMMA_SUPPORTED
+ png_fixed_point gamma; /* File gamma */
+#endif
+
+#ifdef PNG_COLORSPACE_SUPPORTED
+ png_xy end_points_xy; /* End points as chromaticities */
+ png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */
+ png_uint_16 rendering_intent; /* Rendering intent of a profile */
+#endif
+
+ /* Flags are always defined to simplify the code. */
+ png_uint_16 flags; /* As defined below */
+} png_colorspace, * PNG_RESTRICT png_colorspacerp;
+
+typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
+
+/* General flags for the 'flags' field */
+#define PNG_COLORSPACE_HAVE_GAMMA 0x0001
+#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002
+#define PNG_COLORSPACE_HAVE_INTENT 0x0004
+#define PNG_COLORSPACE_FROM_gAMA 0x0008
+#define PNG_COLORSPACE_FROM_cHRM 0x0010
+#define PNG_COLORSPACE_FROM_sRGB 0x0020
+#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040
+#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */
+#define PNG_COLORSPACE_INVALID 0x8000
+#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags))
+#endif /* COLORSPACE || GAMMA */
struct png_struct_def
{
#ifdef PNG_SETJMP_SUPPORTED
- jmp_buf longjmp_buffer; /* used in png_error */
+ jmp_buf jmp_buf_local; /* New name in 1.6.0 for jmp_buf in png_struct */
png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */
+ jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */
+ size_t jmp_buf_size; /* size of the above, if allocated */
#endif
png_error_ptr error_fn; /* function for printing errors and aborting */
#ifdef PNG_WARNINGS_SUPPORTED
@@ -63,22 +179,12 @@ struct png_struct_def
png_uint_32 flags; /* flags indicating various things to libpng */
png_uint_32 transformations; /* which transformations to perform */
- z_stream zstream; /* pointer to decompression structure (below) */
- png_bytep zbuf; /* buffer for zlib */
- uInt zbuf_size; /* size of zbuf (typically 65536) */
-#ifdef PNG_WRITE_SUPPORTED
-
-/* Added in 1.5.4: state to keep track of whether the zstream has been
- * initialized and if so whether it is for IDAT or some other chunk.
- */
-#define PNG_ZLIB_UNINITIALIZED 0
-#define PNG_ZLIB_FOR_IDAT 1
-#define PNG_ZLIB_FOR_TEXT 2 /* anything other than IDAT */
-#define PNG_ZLIB_USE_MASK 3 /* bottom two bits */
-#define PNG_ZLIB_IN_USE 4 /* a flag value */
+ png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */
+ z_stream zstream; /* decompression structure */
- png_uint_32 zlib_state; /* State of zlib initialization */
-/* End of material added at libpng 1.5.4 */
+#ifdef PNG_WRITE_SUPPORTED
+ png_compression_bufferp zbuffer_list; /* Created on demand during write */
+ uInt zbuffer_size; /* size of the actual buffer */
int zlib_level; /* holds zlib compression level */
int zlib_method; /* holds zlib compression method */
@@ -87,8 +193,7 @@ struct png_struct_def
int zlib_strategy; /* holds zlib compression strategy */
#endif
/* Added at libpng 1.5.4 */
-#if defined(PNG_WRITE_COMPRESSED_TEXT_SUPPORTED) || \
- defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED)
+#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
int zlib_text_level; /* holds zlib compression level */
int zlib_text_method; /* holds zlib compression method */
int zlib_text_window_bits; /* holds zlib compression window bits */
@@ -96,6 +201,14 @@ struct png_struct_def
int zlib_text_strategy; /* holds zlib compression strategy */
#endif
/* End of material added at libpng 1.5.4 */
+/* Added at libpng 1.6.0 */
+#ifdef PNG_WRITE_SUPPORTED
+ int zlib_set_level; /* Actual values set into the zstream on write */
+ int zlib_set_method;
+ int zlib_set_window_bits;
+ int zlib_set_mem_level;
+ int zlib_set_strategy;
+#endif
png_uint_32 width; /* width of image in pixels */
png_uint_32 height; /* height of image in pixels */
@@ -106,21 +219,31 @@ struct png_struct_def
png_uint_32 row_number; /* current row in interlace pass */
png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */
png_bytep prev_row; /* buffer to save previous (unfiltered) row.
- * This is a pointer into big_prev_row
+ * While reading this is a pointer into
+ * big_prev_row; while writing it is separately
+ * allocated if needed.
*/
png_bytep row_buf; /* buffer to save current (unfiltered) row.
- * This is a pointer into big_row_buf
+ * While reading, this is a pointer into
+ * big_row_buf; while writing it is separately
+ * allocated.
*/
- png_bytep sub_row; /* buffer to save "sub" row when filtering */
- png_bytep up_row; /* buffer to save "up" row when filtering */
- png_bytep avg_row; /* buffer to save "avg" row when filtering */
- png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+ png_bytep try_row; /* buffer to save trial row when filtering */
+ png_bytep tst_row; /* buffer to save best trial row when filtering */
+#endif
png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */
png_uint_32 idat_size; /* current IDAT size for read */
png_uint_32 crc; /* current chunk CRC value */
png_colorp palette; /* palette from the input file */
png_uint_16 num_palette; /* number of color entries in palette */
+
+/* Added at libpng-1.5.10 */
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ int num_palette_max; /* maximum palette index found in IDAT */
+#endif
+
png_uint_16 num_trans; /* number of transparency values */
png_byte compression; /* file compression type (always 0) */
png_byte filter; /* file filter type (always 0) */
@@ -132,15 +255,17 @@ struct png_struct_def
png_byte usr_bit_depth; /* bit depth of users row: write only */
png_byte pixel_depth; /* number of bits per pixel */
png_byte channels; /* number of channels in file */
+#ifdef PNG_WRITE_SUPPORTED
png_byte usr_channels; /* channels at start of write: write only */
+#endif
png_byte sig_bytes; /* magic bytes read/written from start of file */
png_byte maximum_pixel_depth;
/* pixel depth used for the row buffers */
png_byte transformed_pixel_depth;
/* pixel depth after read/write transforms */
- png_byte io_chunk_string[5];
- /* string name of chunk */
-
+#if PNG_ZLIB_VERNUM >= 0x1240
+ png_byte zstream_start; /* at start of an input zlib stream */
+#endif /* Zlib >= 1.2.4 */
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
png_uint_16 filler; /* filler bytes for pixel expansion */
#endif
@@ -153,7 +278,7 @@ struct png_struct_def
#ifdef PNG_READ_GAMMA_SUPPORTED
png_color_16 background_1; /* background normalized to gamma 1.0 */
#endif
-#endif /* PNG_bKGD_SUPPORTED */
+#endif /* bKGD */
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_flush_ptr output_flush_fn; /* Function for flushing output */
@@ -163,7 +288,6 @@ struct png_struct_def
#ifdef PNG_READ_GAMMA_SUPPORTED
int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */
- png_fixed_point gamma; /* file gamma value */
png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */
png_bytep gamma_table; /* gamma table for 8-bit depth files */
@@ -211,14 +335,7 @@ struct png_struct_def
int process_mode; /* what push library is currently doing */
int cur_palette; /* current push library palette index */
-# ifdef PNG_TEXT_SUPPORTED
- png_size_t current_text_size; /* current size of text input data */
- png_size_t current_text_left; /* how much text left to read in input */
- png_charp current_text; /* current text chunk buffer */
- png_charp current_text_ptr; /* current location in current_text */
-# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */
-
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PROGRESSIVE_READ */
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
/* For the Borland special 64K segment handler */
@@ -234,23 +351,17 @@ struct png_struct_def
png_bytep quantize_index; /* index translation for palette files */
#endif
-#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED)
- png_uint_16p hist; /* histogram */
-#endif
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- png_byte heuristic_method; /* heuristic for row filter selection */
- png_byte num_prev_filters; /* number of weights for previous rows */
- png_bytep prev_filters; /* filter type(s) of previous row(s) */
- png_uint_16p filter_weights; /* weight(s) for previous line(s) */
- png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */
- png_uint_16p filter_costs; /* relative filter calculation cost */
- png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */
+/* Options */
+#ifdef PNG_SET_OPTION_SUPPORTED
+ png_byte options; /* On/off state (up to 4 options) */
#endif
+#if PNG_LIBPNG_VER < 10700
+/* To do: remove this from libpng-1.7 */
#ifdef PNG_TIME_RFC1123_SUPPORTED
char time_buffer[29]; /* String to hold RFC 1123 time text */
#endif
+#endif
/* New members added in libpng-1.0.6 */
@@ -258,17 +369,16 @@ struct png_struct_def
#ifdef PNG_USER_CHUNKS_SUPPORTED
png_voidp user_chunk_ptr;
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
#endif
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- int num_chunk_list;
- png_bytep chunk_list;
#endif
-#ifdef PNG_READ_sRGB_SUPPORTED
- /* Added in 1.5.5 to record an sRGB chunk in the png. */
- png_byte is_sRGB;
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ int unknown_default; /* As PNG_HANDLE_* */
+ unsigned int num_chunk_list; /* Number of entries in the list */
+ png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name
+ * followed by a PNG_HANDLE_* byte */
#endif
/* New members added in libpng-1.0.3 */
@@ -333,16 +443,24 @@ struct png_struct_def
#endif
/* New member added in libpng-1.0.25 and 1.2.17 */
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
- /* Storage for unknown chunk that the library doesn't recognize. */
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+ /* Temporary storage for unknown chunk that the library doesn't recognize,
+ * used while reading the chunk.
+ */
png_unknown_chunk unknown_chunk;
#endif
/* New member added in libpng-1.2.26 */
png_size_t old_big_row_buf_size;
+#ifdef PNG_READ_SUPPORTED
/* New member added in libpng-1.2.30 */
- png_charp chunkdata; /* buffer for reading chunk data */
+ png_bytep read_buffer; /* buffer for reading chunk data */
+ png_alloc_size_t read_buffer_size; /* current size of the buffer */
+#endif
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ uInt IDAT_read_size; /* limit on read buffer size for IDAT */
+#endif
#ifdef PNG_IO_STATE_SUPPORTED
/* New member added in libpng-1.4.0 */
@@ -352,7 +470,14 @@ struct png_struct_def
/* New member added in libpng-1.5.6 */
png_bytep big_prev_row;
+/* New member added in libpng-1.5.7 */
void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
png_bytep row, png_const_bytep prev_row);
+
+#ifdef PNG_READ_SUPPORTED
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+ png_colorspace colorspace;
+#endif
+#endif
};
#endif /* PNGSTRUCT_H */
diff --git a/thirdparty/libpng/pngtrans.c b/thirdparty/libpng/pngtrans.c
index 6a6908dc..7f8cc455 100644
--- a/thirdparty/libpng/pngtrans.c
+++ b/thirdparty/libpng/pngtrans.c
@@ -1,8 +1,8 @@
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.18 [July 23, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -18,7 +18,7 @@
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* Turn on BGR-to-RGB mapping */
void PNGAPI
-png_set_bgr(png_structp png_ptr)
+png_set_bgr(png_structrp png_ptr)
{
png_debug(1, "in png_set_bgr");
@@ -30,9 +30,9 @@ png_set_bgr(png_structp png_ptr)
#endif
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-/* Turn on 16 bit byte swapping */
+/* Turn on 16-bit byte swapping */
void PNGAPI
-png_set_swap(png_structp png_ptr)
+png_set_swap(png_structrp png_ptr)
{
png_debug(1, "in png_set_swap");
@@ -47,7 +47,7 @@ png_set_swap(png_structp png_ptr)
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
/* Turn on pixel packing */
void PNGAPI
-png_set_packing(png_structp png_ptr)
+png_set_packing(png_structrp png_ptr)
{
png_debug(1, "in png_set_packing");
@@ -57,7 +57,9 @@ png_set_packing(png_structp png_ptr)
if (png_ptr->bit_depth < 8)
{
png_ptr->transformations |= PNG_PACK;
- png_ptr->usr_bit_depth = 8;
+# ifdef PNG_WRITE_SUPPORTED
+ png_ptr->usr_bit_depth = 8;
+# endif
}
}
#endif
@@ -65,7 +67,7 @@ png_set_packing(png_structp png_ptr)
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* Turn on packed pixel swapping */
void PNGAPI
-png_set_packswap(png_structp png_ptr)
+png_set_packswap(png_structrp png_ptr)
{
png_debug(1, "in png_set_packswap");
@@ -79,7 +81,7 @@ png_set_packswap(png_structp png_ptr)
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
void PNGAPI
-png_set_shift(png_structp png_ptr, png_const_color_8p true_bits)
+png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
{
png_debug(1, "in png_set_shift");
@@ -94,11 +96,11 @@ png_set_shift(png_structp png_ptr, png_const_color_8p true_bits)
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
defined(PNG_WRITE_INTERLACING_SUPPORTED)
int PNGAPI
-png_set_interlace_handling(png_structp png_ptr)
+png_set_interlace_handling(png_structrp png_ptr)
{
png_debug(1, "in png_set_interlace handling");
- if (png_ptr && png_ptr->interlaced)
+ if (png_ptr != 0 && png_ptr->interlaced != 0)
{
png_ptr->transformations |= PNG_INTERLACE;
return (7);
@@ -115,44 +117,91 @@ png_set_interlace_handling(png_structp png_ptr)
* that don't like bytes as parameters.
*/
void PNGAPI
-png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
+png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_filler");
if (png_ptr == NULL)
return;
+ /* In libpng 1.6 it is possible to determine whether this is a read or write
+ * operation and therefore to do more checking here for a valid call.
+ */
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+# ifdef PNG_READ_FILLER_SUPPORTED
+ /* On read png_set_filler is always valid, regardless of the base PNG
+ * format, because other transformations can give a format where the
+ * filler code can execute (basically an 8 or 16-bit component RGB or G
+ * format.)
+ *
+ * NOTE: usr_channels is not used by the read code! (This has led to
+ * confusion in the past.) The filler is only used in the read code.
+ */
+ png_ptr->filler = (png_uint_16)filler;
+# else
+ png_app_error(png_ptr, "png_set_filler not supported on read");
+ PNG_UNUSED(filler) /* not used in the write case */
+ return;
+# endif
+ }
+
+ else /* write */
+ {
+# ifdef PNG_WRITE_FILLER_SUPPORTED
+ /* On write the usr_channels parameter must be set correctly at the
+ * start to record the number of channels in the app-supplied data.
+ */
+ switch (png_ptr->color_type)
+ {
+ case PNG_COLOR_TYPE_RGB:
+ png_ptr->usr_channels = 4;
+ break;
+
+ case PNG_COLOR_TYPE_GRAY:
+ if (png_ptr->bit_depth >= 8)
+ {
+ png_ptr->usr_channels = 2;
+ break;
+ }
+
+ else
+ {
+ /* There simply isn't any code in libpng to strip out bits
+ * from bytes when the components are less than a byte in
+ * size!
+ */
+ png_app_error(png_ptr,
+ "png_set_filler is invalid for low bit depth gray output");
+ return;
+ }
+
+ default:
+ png_app_error(png_ptr,
+ "png_set_filler: inappropriate color type");
+ return;
+ }
+# else
+ png_app_error(png_ptr, "png_set_filler not supported on write");
+ return;
+# endif
+ }
+
+ /* Here on success - libpng supports the operation, set the transformation
+ * and the flag to say where the filler channel is.
+ */
png_ptr->transformations |= PNG_FILLER;
- png_ptr->filler = (png_uint_16)filler;
if (filler_loc == PNG_FILLER_AFTER)
png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
else
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
-
- /* This should probably go in the "do_read_filler" routine.
- * I attempted to do that in libpng-1.0.1a but that caused problems
- * so I restored it in libpng-1.0.2a
- */
-
- if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
- {
- png_ptr->usr_channels = 4;
- }
-
- /* Also I added this in libpng-1.0.2a (what happens when we expand
- * a less-than-8-bit grayscale to GA?) */
-
- if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
- {
- png_ptr->usr_channels = 2;
- }
}
/* Added to libpng-1.2.7 */
void PNGAPI
-png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
+png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_add_alpha");
@@ -160,7 +209,9 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
return;
png_set_filler(png_ptr, filler, filler_loc);
- png_ptr->transformations |= PNG_ADD_ALPHA;
+ /* The above may fail to do anything. */
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
+ png_ptr->transformations |= PNG_ADD_ALPHA;
}
#endif
@@ -168,7 +219,7 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
void PNGAPI
-png_set_swap_alpha(png_structp png_ptr)
+png_set_swap_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_swap_alpha");
@@ -182,7 +233,7 @@ png_set_swap_alpha(png_structp png_ptr)
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
void PNGAPI
-png_set_invert_alpha(png_structp png_ptr)
+png_set_invert_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_invert_alpha");
@@ -195,7 +246,7 @@ png_set_invert_alpha(png_structp png_ptr)
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
void PNGAPI
-png_set_invert_mono(png_structp png_ptr)
+png_set_invert_mono(png_structrp png_ptr)
{
png_debug(1, "in png_set_invert_mono");
@@ -262,7 +313,7 @@ png_do_invert(png_row_infop row_info, png_bytep row)
#ifdef PNG_16BIT_SUPPORTED
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-/* Swaps byte order on 16 bit depth images */
+/* Swaps byte order on 16-bit depth images */
void /* PRIVATE */
png_do_swap(png_row_infop row_info, png_bytep row)
{
@@ -276,9 +327,16 @@ png_do_swap(png_row_infop row_info, png_bytep row)
for (i = 0; i < istop; i++, rp += 2)
{
+#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
+ /* Feature added to libpng-1.6.11 for testing purposes, not
+ * enabled by default.
+ */
+ *(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
+#else
png_byte t = *rp;
*rp = *(rp + 1);
*(rp + 1) = t;
+#endif
}
}
}
@@ -420,7 +478,7 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
*rp = table[*rp];
}
}
-#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
+#endif /* PACKSWAP || WRITE_PACKSWAP */
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
@@ -452,7 +510,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
if (row_info->bit_depth == 8)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channel and, for sp, the filler */
sp += 2, ++dp;
@@ -466,7 +524,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
else if (row_info->bit_depth == 16)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channel and, for sp, the filler */
sp += 4, dp += 2;
@@ -492,7 +550,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
if (row_info->bit_depth == 8)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channels and, for sp, the filler */
sp += 4, dp += 3;
@@ -506,7 +564,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
else if (row_info->bit_depth == 16)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channels and, for sp, the filler */
sp += 8, dp += 6;
@@ -547,7 +605,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_bgr");
- if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
+ if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_uint_32 row_width = row_info->width;
if (row_info->bit_depth == 8)
@@ -617,19 +675,133 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
#endif
}
}
-#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
+#endif /* READ_BGR || WRITE_BGR */
+
+#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
+ defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
+/* Added at libpng-1.5.10 */
+void /* PRIVATE */
+png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
+{
+ if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
+ png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
+ {
+ /* Calculations moved outside switch in an attempt to stop different
+ * compiler warnings. 'padding' is in *bits* within the last byte, it is
+ * an 'int' because pixel_depth becomes an 'int' in the expression below,
+ * and this calculation is used because it avoids warnings that other
+ * forms produced on either GCC or MSVC.
+ */
+ int padding = (-row_info->pixel_depth * row_info->width) & 7;
+ png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
+
+ switch (row_info->bit_depth)
+ {
+ case 1:
+ {
+ /* in this case, all bytes must be 0 so we don't need
+ * to unpack the pixels except for the rightmost one.
+ */
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ if ((*rp >> padding) != 0)
+ png_ptr->num_palette_max = 1;
+ padding = 0;
+ }
+
+ break;
+ }
+
+ case 2:
+ {
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ int i = ((*rp >> padding) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 2) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 4) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 6) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ padding = 0;
+ }
+
+ break;
+ }
+
+ case 4:
+ {
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ int i = ((*rp >> padding) & 0x0f);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 4) & 0x0f);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ padding = 0;
+ }
+
+ break;
+ }
+
+ case 8:
+ {
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ if (*rp > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = (int) *rp;
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+}
+#endif /* CHECK_FOR_INVALID_INDEX */
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
void PNGAPI
-png_set_user_transform_info(png_structp png_ptr, png_voidp
+png_set_user_transform_info(png_structrp png_ptr, png_voidp
user_transform_ptr, int user_transform_depth, int user_transform_channels)
{
png_debug(1, "in png_set_user_transform_info");
if (png_ptr == NULL)
return;
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
+ {
+ png_app_error(png_ptr,
+ "info change after png_start_read_image or png_read_update_info");
+ return;
+ }
+#endif
+
png_ptr->user_transform_ptr = user_transform_ptr;
png_ptr->user_transform_depth = (png_byte)user_transform_depth;
png_ptr->user_transform_channels = (png_byte)user_transform_channels;
@@ -643,20 +815,20 @@ png_set_user_transform_info(png_structp png_ptr, png_voidp
*/
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
png_voidp PNGAPI
-png_get_user_transform_ptr(png_const_structp png_ptr)
+png_get_user_transform_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
- return ((png_voidp)png_ptr->user_transform_ptr);
+ return png_ptr->user_transform_ptr;
}
#endif
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
png_uint_32 PNGAPI
-png_get_current_row_number(png_const_structp png_ptr)
+png_get_current_row_number(png_const_structrp png_ptr)
{
- /* See the comments in png.h - this is the sub-image row when reading and
+ /* See the comments in png.h - this is the sub-image row when reading an
* interlaced image.
*/
if (png_ptr != NULL)
@@ -666,13 +838,12 @@ png_get_current_row_number(png_const_structp png_ptr)
}
png_byte PNGAPI
-png_get_current_pass_number(png_const_structp png_ptr)
+png_get_current_pass_number(png_const_structrp png_ptr)
{
if (png_ptr != NULL)
return png_ptr->pass;
return 8; /* invalid */
}
-#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
-#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
- PNG_WRITE_USER_TRANSFORM_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* USER_TRANSFORM_INFO */
+#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
+#endif /* READ || WRITE */
diff --git a/thirdparty/libpng/pngwio.c b/thirdparty/libpng/pngwio.c
index 95ffb342..586c03b7 100644
--- a/thirdparty/libpng/pngwio.c
+++ b/thirdparty/libpng/pngwio.c
@@ -1,8 +1,8 @@
/* pngwio.c - functions for data output
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -26,15 +26,16 @@
* writes to a file pointer. Note that this routine sometimes gets called
* with very small lengths, so you should implement some kind of simple
* buffering if you are using unbuffered writes. This should never be asked
- * to write more than 64K on a 16 bit machine.
+ * to write more than 64K on a 16-bit machine.
*/
void /* PRIVATE */
-png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length)
+png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length)
{
/* NOTE: write_data_fn must not change the buffer! */
if (png_ptr->write_data_fn != NULL )
- (*(png_ptr->write_data_fn))(png_ptr, (png_bytep)data, length);
+ (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data),
+ length);
else
png_error(png_ptr, "Call to NULL write function");
@@ -46,7 +47,6 @@ png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length)
* write_data function and use it at run time with png_set_write_fn(), rather
* than changing the library.
*/
-#ifndef USE_FAR_KEYWORD
void PNGCBAPI
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
@@ -60,64 +60,6 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
if (check != length)
png_error(png_ptr, "Write Error");
}
-#else
-/* This is the model-independent version. Since the standard I/O library
- * can't handle far buffers in the medium and small models, we have to copy
- * the data.
- */
-
-#define NEAR_BUF_SIZE 1024
-#define MIN(a,b) (a <= b ? a : b)
-
-void PNGCBAPI
-png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
-{
- png_uint_32 check;
- png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
- png_FILE_p io_ptr;
-
- if (png_ptr == NULL)
- return;
-
- /* Check if data really is near. If so, use usual code. */
- near_data = (png_byte *)CVT_PTR_NOCHECK(data);
- io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
-
- if ((png_bytep)near_data == data)
- {
- check = fwrite(near_data, 1, length, io_ptr);
- }
-
- else
- {
- png_byte buf[NEAR_BUF_SIZE];
- png_size_t written, remaining, err;
- check = 0;
- remaining = length;
-
- do
- {
- written = MIN(NEAR_BUF_SIZE, remaining);
- png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
- err = fwrite(buf, 1, written, io_ptr);
-
- if (err != written)
- break;
-
- else
- check += err;
-
- data += written;
- remaining -= written;
- }
- while (remaining != 0);
- }
-
- if (check != length)
- png_error(png_ptr, "Write Error");
-}
-
-#endif
#endif
/* This function is called to output any data pending writing (normally
@@ -126,7 +68,7 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
*/
#ifdef PNG_WRITE_FLUSH_SUPPORTED
void /* PRIVATE */
-png_flush(png_structp png_ptr)
+png_flush(png_structrp png_ptr)
{
if (png_ptr->output_flush_fn != NULL)
(*(png_ptr->output_flush_fn))(png_ptr);
@@ -141,7 +83,7 @@ png_default_flush(png_structp png_ptr)
if (png_ptr == NULL)
return;
- io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
+ io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr));
fflush(io_ptr);
}
# endif
@@ -177,7 +119,7 @@ png_default_flush(png_structp png_ptr)
* *FILE structure.
*/
void PNGAPI
-png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
+png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
{
if (png_ptr == NULL)
@@ -207,8 +149,11 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
# else
png_ptr->output_flush_fn = output_flush_fn;
# endif
-#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+#else
+ PNG_UNUSED(output_flush_fn)
+#endif /* WRITE_FLUSH */
+#ifdef PNG_READ_SUPPORTED
/* It is an error to read while writing a png file */
if (png_ptr->read_data_fn != NULL)
{
@@ -218,37 +163,6 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
"Can't set both read_data_fn and write_data_fn in the"
" same structure");
}
-}
-
-#ifdef USE_FAR_KEYWORD
-# ifdef _MSC_VER
-void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
-{
- void *near_ptr;
- void FAR *far_ptr;
- FP_OFF(near_ptr) = FP_OFF(ptr);
- far_ptr = (void FAR *)near_ptr;
-
- if (check != 0)
- if (FP_SEG(ptr) != FP_SEG(far_ptr))
- png_error(png_ptr, "segment lost in conversion");
-
- return(near_ptr);
-}
-# else
-void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
-{
- void *near_ptr;
- void FAR *far_ptr;
- near_ptr = (void FAR *)ptr;
- far_ptr = (void FAR *)near_ptr;
-
- if (check != 0)
- if (far_ptr != ptr)
- png_error(png_ptr, "segment lost in conversion");
-
- return(near_ptr);
-}
-# endif
#endif
-#endif /* PNG_WRITE_SUPPORTED */
+}
+#endif /* WRITE */
diff --git a/thirdparty/libpng/pngwrite.c b/thirdparty/libpng/pngwrite.c
index 6d3fd4c3..f843796b 100644
--- a/thirdparty/libpng/pngwrite.c
+++ b/thirdparty/libpng/pngwrite.c
@@ -1,8 +1,8 @@
/* pngwrite.c - general routines to write a PNG file
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.19 [November 12, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -12,9 +12,65 @@
*/
#include "pngpriv.h"
+#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+# include <errno.h>
+#endif
#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+/* Write out all the unknown chunks for the current given location */
+static void
+write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
+ unsigned int where)
+{
+ if (info_ptr->unknown_chunks_num != 0)
+ {
+ png_const_unknown_chunkp up;
+
+ png_debug(5, "writing extra chunks");
+
+ for (up = info_ptr->unknown_chunks;
+ up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+ ++up)
+ if ((up->location & where) != 0)
+ {
+ /* If per-chunk unknown chunk handling is enabled use it, otherwise
+ * just write the chunks the application has set.
+ */
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ int keep = png_handle_as_unknown(png_ptr, up->name);
+
+ /* NOTE: this code is radically different from the read side in the
+ * matter of handling an ancillary unknown chunk. In the read side
+ * the default behavior is to discard it, in the code below the default
+ * behavior is to write it. Critical chunks are, however, only
+ * written if explicitly listed or if the default is set to write all
+ * unknown chunks.
+ *
+ * The default handling is also slightly weird - it is not possible to
+ * stop the writing of all unsafe-to-copy chunks!
+ *
+ * TODO: REVIEW: this would seem to be a bug.
+ */
+ if (keep != PNG_HANDLE_CHUNK_NEVER &&
+ ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ ||
+ keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_AS_DEFAULT &&
+ png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
+#endif
+ {
+ /* TODO: review, what is wrong with a zero length unknown chunk? */
+ if (up->size == 0)
+ png_warning(png_ptr, "Writing zero-length unknown chunk");
+
+ png_write_chunk(png_ptr, up->name, up->data, up->size);
+ }
+ }
+ }
+}
+#endif /* WRITE_UNKNOWN_CHUNKS */
+
/* Writes all the PNG information. This is the suggested way to use the
* library. If you have a new chunk to add, make a function to write it,
* and put it in the correct location here. If you want the chunk written
@@ -25,101 +81,115 @@
* them in png_write_end(), and compressing them.
*/
void PNGAPI
-png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
+png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
{
png_debug(1, "in png_write_info_before_PLTE");
if (png_ptr == NULL || info_ptr == NULL)
return;
- if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
+ if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
{
- /* Write PNG signature */
- png_write_sig(png_ptr);
+ /* Write PNG signature */
+ png_write_sig(png_ptr);
#ifdef PNG_MNG_FEATURES_SUPPORTED
- if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \
- (png_ptr->mng_features_permitted))
- {
- png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
- png_ptr->mng_features_permitted = 0;
- }
+ if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \
+ png_ptr->mng_features_permitted != 0)
+ {
+ png_warning(png_ptr,
+ "MNG features are not allowed in a PNG datastream");
+ png_ptr->mng_features_permitted = 0;
+ }
#endif
- /* Write IHDR information. */
- png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
- info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
- info_ptr->filter_type,
+ /* Write IHDR information. */
+ png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
+ info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
+ info_ptr->filter_type,
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
- info_ptr->interlace_type);
+ info_ptr->interlace_type
#else
- 0);
-#endif
- /* The rest of these check to see if the valid field has the appropriate
- * flag set, and if it does, writes the chunk.
- */
-#ifdef PNG_WRITE_gAMA_SUPPORTED
- if (info_ptr->valid & PNG_INFO_gAMA)
- png_write_gAMA_fixed(png_ptr, info_ptr->gamma);
-#endif
-#ifdef PNG_WRITE_sRGB_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sRGB)
- png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
+ 0
+#endif
+ );
+
+ /* The rest of these check to see if the valid field has the appropriate
+ * flag set, and if it does, writes the chunk.
+ *
+ * 1.6.0: COLORSPACE support controls the writing of these chunks too, and
+ * the chunks will be written if the WRITE routine is there and
+ * information * is available in the COLORSPACE. (See
+ * png_colorspace_sync_info in png.c for where the valid flags get set.)
+ *
+ * Under certain circumstances the colorspace can be invalidated without
+ * syncing the info_struct 'valid' flags; this happens if libpng detects
+ * an error and calls png_error while the color space is being set, yet
+ * the application continues writing the PNG. So check the 'invalid'
+ * flag here too.
+ */
+#ifdef PNG_GAMMA_SUPPORTED
+# ifdef PNG_WRITE_gAMA_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 &&
+ (info_ptr->valid & PNG_INFO_gAMA) != 0)
+ png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
+# endif
#endif
-#ifdef PNG_WRITE_iCCP_SUPPORTED
- if (info_ptr->valid & PNG_INFO_iCCP)
- png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
- (png_charp)info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
-#endif
+#ifdef PNG_COLORSPACE_SUPPORTED
+ /* Write only one of sRGB or an ICC profile. If a profile was supplied
+ * and it matches one of the known sRGB ones issue a warning.
+ */
+# ifdef PNG_WRITE_iCCP_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->valid & PNG_INFO_iCCP) != 0)
+ {
+# ifdef PNG_WRITE_sRGB_SUPPORTED
+ if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
+ png_app_warning(png_ptr,
+ "profile matches sRGB but writing iCCP instead");
+# endif
+
+ png_write_iCCP(png_ptr, info_ptr->iccp_name,
+ info_ptr->iccp_profile);
+ }
+# ifdef PNG_WRITE_sRGB_SUPPORTED
+ else
+# endif
+# endif
+
+# ifdef PNG_WRITE_sRGB_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->valid & PNG_INFO_sRGB) != 0)
+ png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
+# endif /* WRITE_sRGB */
+#endif /* COLORSPACE */
+
#ifdef PNG_WRITE_sBIT_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sBIT)
- png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
+ if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
+ png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
#endif
-#ifdef PNG_WRITE_cHRM_SUPPORTED
- if (info_ptr->valid & PNG_INFO_cHRM)
- png_write_cHRM_fixed(png_ptr,
- info_ptr->x_white, info_ptr->y_white,
- info_ptr->x_red, info_ptr->y_red,
- info_ptr->x_green, info_ptr->y_green,
- info_ptr->x_blue, info_ptr->y_blue);
+
+#ifdef PNG_COLORSPACE_SUPPORTED
+# ifdef PNG_WRITE_cHRM_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 &&
+ (info_ptr->valid & PNG_INFO_cHRM) != 0)
+ png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
+# endif
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
- if (info_ptr->unknown_chunks_num)
- {
- png_unknown_chunk *up;
-
- png_debug(5, "writing extra chunks");
-
- for (up = info_ptr->unknown_chunks;
- up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
- up++)
- {
- int keep = png_handle_as_unknown(png_ptr, up->name);
-
- if (keep != PNG_HANDLE_CHUNK_NEVER &&
- up->location &&
- !(up->location & PNG_HAVE_PLTE) &&
- !(up->location & PNG_HAVE_IDAT) &&
- !(up->location & PNG_AFTER_IDAT) &&
- ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
- (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
- {
- if (up->size == 0)
- png_warning(png_ptr, "Writing zero-length unknown chunk");
-
- png_write_chunk(png_ptr, up->name, up->data, up->size);
- }
- }
- }
+ write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
#endif
+
png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
}
}
void PNGAPI
-png_write_info(png_structp png_ptr, png_infop info_ptr)
+png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
{
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
int i;
@@ -132,7 +202,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
png_write_info_before_PLTE(png_ptr, info_ptr);
- if (info_ptr->valid & PNG_INFO_PLTE)
+ if ((info_ptr->valid & PNG_INFO_PLTE) != 0)
png_write_PLTE(png_ptr, info_ptr->palette,
(png_uint_32)info_ptr->num_palette);
@@ -140,15 +210,20 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
png_error(png_ptr, "Valid palette required for paletted images");
#ifdef PNG_WRITE_tRNS_SUPPORTED
- if (info_ptr->valid & PNG_INFO_tRNS)
+ if ((info_ptr->valid & PNG_INFO_tRNS) !=0)
{
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel (in tRNS) */
- if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
- int j;
- for (j = 0; j<(int)info_ptr->num_trans; j++)
+ int j, jend;
+
+ jend = info_ptr->num_trans;
+ if (jend > PNG_MAX_PALETTE_LENGTH)
+ jend = PNG_MAX_PALETTE_LENGTH;
+
+ for (j = 0; j<jend; ++j)
info_ptr->trans_alpha[j] =
(png_byte)(255 - info_ptr->trans_alpha[j]);
}
@@ -158,42 +233,42 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
}
#endif
#ifdef PNG_WRITE_bKGD_SUPPORTED
- if (info_ptr->valid & PNG_INFO_bKGD)
+ if ((info_ptr->valid & PNG_INFO_bKGD) != 0)
png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
#endif
#ifdef PNG_WRITE_hIST_SUPPORTED
- if (info_ptr->valid & PNG_INFO_hIST)
+ if ((info_ptr->valid & PNG_INFO_hIST) != 0)
png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
#endif
#ifdef PNG_WRITE_oFFs_SUPPORTED
- if (info_ptr->valid & PNG_INFO_oFFs)
+ if ((info_ptr->valid & PNG_INFO_oFFs) != 0)
png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
info_ptr->offset_unit_type);
#endif
#ifdef PNG_WRITE_pCAL_SUPPORTED
- if (info_ptr->valid & PNG_INFO_pCAL)
+ if ((info_ptr->valid & PNG_INFO_pCAL) != 0)
png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
info_ptr->pcal_units, info_ptr->pcal_params);
#endif
#ifdef PNG_WRITE_sCAL_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sCAL)
+ if ((info_ptr->valid & PNG_INFO_sCAL) != 0)
png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
info_ptr->scal_s_width, info_ptr->scal_s_height);
#endif /* sCAL */
#ifdef PNG_WRITE_pHYs_SUPPORTED
- if (info_ptr->valid & PNG_INFO_pHYs)
+ if ((info_ptr->valid & PNG_INFO_pHYs) != 0)
png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
#endif /* pHYs */
#ifdef PNG_WRITE_tIME_SUPPORTED
- if (info_ptr->valid & PNG_INFO_tIME)
+ if ((info_ptr->valid & PNG_INFO_tIME) != 0)
{
png_write_tIME(png_ptr, &(info_ptr->mod_time));
png_ptr->mode |= PNG_WROTE_tIME;
@@ -201,7 +276,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#endif /* tIME */
#ifdef PNG_WRITE_sPLT_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sPLT)
+ if ((info_ptr->valid & PNG_INFO_sPLT) != 0)
for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
#endif /* sPLT */
@@ -223,11 +298,14 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->text[i].lang,
info_ptr->text[i].lang_key,
info_ptr->text[i].text);
+ /* Mark this chunk as written */
+ if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ else
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
- png_warning(png_ptr, "Unable to write international text");
+ png_warning(png_ptr, "Unable to write international text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
/* If we want a compressed text chunk */
@@ -236,13 +314,12 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_WRITE_zTXt_SUPPORTED
/* Write compressed chunk */
png_write_zTXt(png_ptr, info_ptr->text[i].key,
- info_ptr->text[i].text, 0,
- info_ptr->text[i].compression);
+ info_ptr->text[i].text, info_ptr->text[i].compression);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
png_warning(png_ptr, "Unable to write compressed text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
}
else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
@@ -263,29 +340,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#endif /* tEXt */
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
- if (info_ptr->unknown_chunks_num)
- {
- png_unknown_chunk *up;
-
- png_debug(5, "writing extra chunks");
-
- for (up = info_ptr->unknown_chunks;
- up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
- up++)
- {
- int keep = png_handle_as_unknown(png_ptr, up->name);
- if (keep != PNG_HANDLE_CHUNK_NEVER &&
- up->location &&
- (up->location & PNG_HAVE_PLTE) &&
- !(up->location & PNG_HAVE_IDAT) &&
- !(up->location & PNG_AFTER_IDAT) &&
- ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
- (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
- {
- png_write_chunk(png_ptr, up->name, up->data, up->size);
- }
- }
- }
+ write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
#endif
}
@@ -295,16 +350,21 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
* comments, I suggest writing them here, and compressing them.
*/
void PNGAPI
-png_write_end(png_structp png_ptr, png_infop info_ptr)
+png_write_end(png_structrp png_ptr, png_inforp info_ptr)
{
png_debug(1, "in png_write_end");
if (png_ptr == NULL)
return;
- if (!(png_ptr->mode & PNG_HAVE_IDAT))
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
png_error(png_ptr, "No IDATs written into file");
+#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ if (png_ptr->num_palette_max > png_ptr->num_palette)
+ png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
+#endif
+
/* See if user wants us to write information chunks */
if (info_ptr != NULL)
{
@@ -313,8 +373,8 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
#endif
#ifdef PNG_WRITE_tIME_SUPPORTED
/* Check to see if user has supplied a time chunk */
- if ((info_ptr->valid & PNG_INFO_tIME) &&
- !(png_ptr->mode & PNG_WROTE_tIME))
+ if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
+ (png_ptr->mode & PNG_WROTE_tIME) == 0)
png_write_tIME(png_ptr, &(info_ptr->mod_time));
#endif
@@ -335,11 +395,14 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
info_ptr->text[i].lang,
info_ptr->text[i].lang_key,
info_ptr->text[i].text);
+ /* Mark this chunk as written */
+ if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ else
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
png_warning(png_ptr, "Unable to write international text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
@@ -347,13 +410,12 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_WRITE_zTXt_SUPPORTED
/* Write compressed chunk */
png_write_zTXt(png_ptr, info_ptr->text[i].key,
- info_ptr->text[i].text, 0,
- info_ptr->text[i].compression);
+ info_ptr->text[i].text, info_ptr->text[i].compression);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
png_warning(png_ptr, "Unable to write compressed text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
}
else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
@@ -362,37 +424,16 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
/* Write uncompressed chunk */
png_write_tEXt(png_ptr, info_ptr->text[i].key,
info_ptr->text[i].text, 0);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
#else
png_warning(png_ptr, "Unable to write uncompressed text");
#endif
-
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
}
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
- if (info_ptr->unknown_chunks_num)
- {
- png_unknown_chunk *up;
-
- png_debug(5, "writing extra chunks");
-
- for (up = info_ptr->unknown_chunks;
- up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
- up++)
- {
- int keep = png_handle_as_unknown(png_ptr, up->name);
- if (keep != PNG_HANDLE_CHUNK_NEVER &&
- up->location &&
- (up->location & PNG_AFTER_IDAT) &&
- ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
- (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
- {
- png_write_chunk(png_ptr, up->name, up->data, up->size);
- }
- }
- }
+ write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
#endif
}
@@ -400,6 +441,7 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
/* Write end of PNG file */
png_write_IEND(png_ptr);
+
/* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
* and restored again in libpng-1.2.30, may cause some applications that
* do not set png_ptr->output_flush_fn to crash. If your application
@@ -415,9 +457,8 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
}
#ifdef PNG_CONVERT_tIME_SUPPORTED
-/* "tm" structure is not supported on WindowsCE */
void PNGAPI
-png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm FAR * ttime)
+png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime)
{
png_debug(1, "in png_convert_from_struct_tm");
@@ -446,104 +487,75 @@ PNG_FUNCTION(png_structp,PNGAPI
png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
{
-#ifdef PNG_USER_MEM_SUPPORTED
- return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
- warn_fn, NULL, NULL, NULL));
+#ifndef PNG_USER_MEM_SUPPORTED
+ png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, NULL, NULL, NULL);
+#else
+ return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
+ warn_fn, NULL, NULL, NULL);
}
/* Alternate initialize png_ptr structure, and allocate any memory needed */
-static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */
-
PNG_FUNCTION(png_structp,PNGAPI
png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
{
-#endif /* PNG_USER_MEM_SUPPORTED */
- volatile int png_cleanup_needed = 0;
-#ifdef PNG_SETJMP_SUPPORTED
- volatile
-#endif
- png_structp png_ptr;
-#ifdef PNG_SETJMP_SUPPORTED
-#ifdef USE_FAR_KEYWORD
- jmp_buf tmp_jmpbuf;
-#endif
-#endif
-
- png_debug(1, "in png_create_write_struct");
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
- (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
-#else
- png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
-#endif /* PNG_USER_MEM_SUPPORTED */
- if (png_ptr == NULL)
- return (NULL);
+ png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
+#endif /* USER_MEM */
+ if (png_ptr != NULL)
+ {
+ /* Set the zlib control values to defaults; they can be overridden by the
+ * application after the struct has been created.
+ */
+ png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
- /* Added at libpng-1.2.6 */
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
- png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
- png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
+ /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
+ * pngwutil.c defaults it according to whether or not filters will be
+ * used, and ignores this setting.
+ */
+ png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
+ png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION;
+ png_ptr->zlib_mem_level = 8;
+ png_ptr->zlib_window_bits = 15;
+ png_ptr->zlib_method = 8;
+
+#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
+ png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
+ png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
+ png_ptr->zlib_text_mem_level = 8;
+ png_ptr->zlib_text_window_bits = 15;
+ png_ptr->zlib_text_method = 8;
+#endif /* WRITE_COMPRESSED_TEXT */
+
+ /* This is a highly dubious configuration option; by default it is off,
+ * but it may be appropriate for private builds that are testing
+ * extensions not conformant to the current specification, or of
+ * applications that must not fail to write at all costs!
+ */
+#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
+ /* In stable builds only warn if an application error can be completely
+ * handled.
+ */
+ png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
#endif
-#ifdef PNG_SETJMP_SUPPORTED
-/* Applications that neglect to set up their own setjmp() and then
- * encounter a png_error() will longjmp here. Since the jmpbuf is
- * then meaningless we abort instead of returning.
- */
-#ifdef USE_FAR_KEYWORD
- if (setjmp(tmp_jmpbuf))
-#else
- if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */
-#endif
-#ifdef USE_FAR_KEYWORD
- png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf));
-#endif
- PNG_ABORT();
+ /* App warnings are warnings in release (or release candidate) builds but
+ * are errors during development.
+ */
+#if PNG_RELEASE_BUILD
+ png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
#endif
-#ifdef PNG_USER_MEM_SUPPORTED
- png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
-#endif /* PNG_USER_MEM_SUPPORTED */
- png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
-
- if (!png_user_version_check(png_ptr, user_png_ver))
- png_cleanup_needed = 1;
-
- /* Initialize zbuf - compression buffer */
- png_ptr->zbuf_size = PNG_ZBUF_SIZE;
-
- if (!png_cleanup_needed)
- {
- png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr,
- png_ptr->zbuf_size);
- if (png_ptr->zbuf == NULL)
- png_cleanup_needed = 1;
- }
-
- if (png_cleanup_needed)
- {
- /* Clean up PNG structure and deallocate any memory. */
- png_free(png_ptr, png_ptr->zbuf);
- png_ptr->zbuf = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)png_ptr,
- (png_free_ptr)free_fn, (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)png_ptr);
-#endif
- return (NULL);
+ /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
+ * do it itself) avoiding setting the default function if it is not
+ * required.
+ */
+ png_set_write_fn(png_ptr, NULL, NULL, NULL);
}
- png_set_write_fn(png_ptr, NULL, NULL, NULL);
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- png_reset_filter_heuristics(png_ptr);
-#endif
-
- return (png_ptr);
+ return png_ptr;
}
@@ -553,7 +565,7 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
* "write" the image seven times.
*/
void PNGAPI
-png_write_rows(png_structp png_ptr, png_bytepp row,
+png_write_rows(png_structrp png_ptr, png_bytepp row,
png_uint_32 num_rows)
{
png_uint_32 i; /* row counter */
@@ -575,7 +587,7 @@ png_write_rows(png_structp png_ptr, png_bytepp row,
* if you are writing an interlaced image.
*/
void PNGAPI
-png_write_image(png_structp png_ptr, png_bytepp image)
+png_write_image(png_structrp png_ptr, png_bytepp image)
{
png_uint_32 i; /* row index */
int pass, num_pass; /* pass variables */
@@ -605,9 +617,74 @@ png_write_image(png_structp png_ptr, png_bytepp image)
}
}
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Performs intrapixel differencing */
+static void
+png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_write_intrapixel");
+
+ if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
+ {
+ int bytes_per_pixel;
+ png_uint_32 row_width = row_info->width;
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 3;
+
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 4;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ *(rp) = (png_byte)(*rp - *(rp + 1));
+ *(rp + 2) = (png_byte)(*(rp + 2) - *(rp + 1));
+ }
+ }
+
+#ifdef PNG_WRITE_16BIT_SUPPORTED
+ else if (row_info->bit_depth == 16)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 6;
+
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 8;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
+ png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
+ png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
+ png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
+ png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
+ *(rp ) = (png_byte)(red >> 8);
+ *(rp + 1) = (png_byte)red;
+ *(rp + 4) = (png_byte)(blue >> 8);
+ *(rp + 5) = (png_byte)blue;
+ }
+ }
+#endif /* WRITE_16BIT */
+ }
+}
+#endif /* MNG_FEATURES */
+
/* Called by user to write a row of image data */
void PNGAPI
-png_write_row(png_structp png_ptr, png_const_bytep row)
+png_write_row(png_structrp png_ptr, png_const_bytep row)
{
/* 1.5.6: moved from png_struct to be a local structure: */
png_row_info row_info;
@@ -622,44 +699,44 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
if (png_ptr->row_number == 0 && png_ptr->pass == 0)
{
/* Make sure we wrote the header info */
- if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
+ if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
png_error(png_ptr,
"png_write_info was never called before png_write_row");
/* Check for transforms that have been set but were defined out */
#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
- if (png_ptr->transformations & PNG_INVERT_MONO)
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
- if (png_ptr->transformations & PNG_FILLER)
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
png_warning(png_ptr,
"PNG_WRITE_PACKSWAP_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
- if (png_ptr->transformations & PNG_PACK)
+ if ((png_ptr->transformations & PNG_PACK) != 0)
png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
- if (png_ptr->transformations & PNG_SHIFT)
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
- if (png_ptr->transformations & PNG_BGR)
+ if ((png_ptr->transformations & PNG_BGR) != 0)
png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_SWAP_BYTES)
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined");
#endif
@@ -668,12 +745,13 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced and not interested in row, return */
- if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
switch (png_ptr->pass)
{
case 0:
- if (png_ptr->row_number & 0x07)
+ if ((png_ptr->row_number & 0x07) != 0)
{
png_write_finish_row(png_ptr);
return;
@@ -681,7 +759,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 1:
- if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
+ if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5)
{
png_write_finish_row(png_ptr);
return;
@@ -697,7 +775,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 3:
- if ((png_ptr->row_number & 0x03) || png_ptr->width < 3)
+ if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3)
{
png_write_finish_row(png_ptr);
return;
@@ -713,7 +791,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 5:
- if ((png_ptr->row_number & 0x01) || png_ptr->width < 2)
+ if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2)
{
png_write_finish_row(png_ptr);
return;
@@ -721,7 +799,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 6:
- if (!(png_ptr->row_number & 0x01))
+ if ((png_ptr->row_number & 0x01) == 0)
{
png_write_finish_row(png_ptr);
return;
@@ -750,16 +828,16 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes);
/* Copy user's row into buffer, leaving room for filter byte. */
- png_memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
+ memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Handle interlacing */
if (png_ptr->interlaced && png_ptr->pass < 6 &&
- (png_ptr->transformations & PNG_INTERLACE))
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
/* This should always get caught above, but still ... */
- if (!(row_info.width))
+ if (row_info.width == 0)
{
png_write_finish_row(png_ptr);
return;
@@ -769,7 +847,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
/* Handle other transformations */
- if (png_ptr->transformations)
+ if (png_ptr->transformations != 0)
png_do_write_transformations(png_ptr, &row_info);
#endif
@@ -777,7 +855,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
* which is also the output depth.
*/
if (row_info.pixel_depth != png_ptr->pixel_depth ||
- row_info.pixel_depth != png_ptr->transformed_pixel_depth)
+ row_info.pixel_depth != png_ptr->transformed_pixel_depth)
png_error(png_ptr, "internal write transform logic error");
#ifdef PNG_MNG_FEATURES_SUPPORTED
@@ -790,7 +868,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
* 4. The filter_method is 64 and
* 5. The color_type is RGB or RGBA
*/
- if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
{
/* Intrapixel differencing */
@@ -798,6 +876,14 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
}
#endif
+/* Added at libpng-1.5.10 */
+#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Check for out-of-range palette index */
+ if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max >= 0)
+ png_do_check_palette_indexes(png_ptr, &row_info);
+#endif
+
/* Find a filter if necessary, filter the row and write it out. */
png_write_find_filter(png_ptr, &row_info);
@@ -808,7 +894,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_FLUSH_SUPPORTED
/* Set the automatic flush interval or 0 to turn flushing off */
void PNGAPI
-png_set_flush(png_structp png_ptr, int nrows)
+png_set_flush(png_structrp png_ptr, int nrows)
{
png_debug(1, "in png_set_flush");
@@ -820,10 +906,8 @@ png_set_flush(png_structp png_ptr, int nrows)
/* Flush the current output buffers now */
void PNGAPI
-png_write_flush(png_structp png_ptr)
+png_write_flush(png_structrp png_ptr)
{
- int wrote_IDAT;
-
png_debug(1, "in png_write_flush");
if (png_ptr == NULL)
@@ -833,182 +917,76 @@ png_write_flush(png_structp png_ptr)
if (png_ptr->row_number >= png_ptr->num_rows)
return;
- do
- {
- int ret;
-
- /* Compress the data */
- ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
- wrote_IDAT = 0;
-
- /* Check for compression errors */
- if (ret != Z_OK)
- {
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
-
- else
- png_error(png_ptr, "zlib error");
- }
-
- if (!(png_ptr->zstream.avail_out))
- {
- /* Write the IDAT and reset the zlib output buffer */
- png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
- wrote_IDAT = 1;
- }
- } while (wrote_IDAT == 1);
-
- /* If there is any data left to be output, write it into a new IDAT */
- if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
- {
- /* Write the IDAT and reset the zlib output buffer */
- png_write_IDAT(png_ptr, png_ptr->zbuf,
- png_ptr->zbuf_size - png_ptr->zstream.avail_out);
- }
+ png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
png_ptr->flush_rows = 0;
png_flush(png_ptr);
}
-#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+#endif /* WRITE_FLUSH */
-/* Free all memory used by the write */
-void PNGAPI
-png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
-{
- png_structp png_ptr = NULL;
- png_infop info_ptr = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_free_ptr free_fn = NULL;
- png_voidp mem_ptr = NULL;
-#endif
-
- png_debug(1, "in png_destroy_write_struct");
-
- if (png_ptr_ptr != NULL)
- png_ptr = *png_ptr_ptr;
-
-#ifdef PNG_USER_MEM_SUPPORTED
- if (png_ptr != NULL)
- {
- free_fn = png_ptr->free_fn;
- mem_ptr = png_ptr->mem_ptr;
- }
-#endif
-
- if (info_ptr_ptr != NULL)
- info_ptr = *info_ptr_ptr;
-
- if (info_ptr != NULL)
- {
- if (png_ptr != NULL)
- {
- png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- if (png_ptr->num_chunk_list)
- {
- png_free(png_ptr, png_ptr->chunk_list);
- png_ptr->num_chunk_list = 0;
- }
-#endif
- }
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)info_ptr);
-#endif
- *info_ptr_ptr = NULL;
- }
-
- if (png_ptr != NULL)
- {
- png_write_destroy(png_ptr);
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)png_ptr);
-#endif
- *png_ptr_ptr = NULL;
- }
-}
-
-
-/* Free any memory used in png_ptr struct (old method) */
-void /* PRIVATE */
-png_write_destroy(png_structp png_ptr)
+/* Free any memory used in png_ptr struct without freeing the struct itself. */
+static void
+png_write_destroy(png_structrp png_ptr)
{
-#ifdef PNG_SETJMP_SUPPORTED
- jmp_buf tmp_jmp; /* Save jump buffer */
-#endif
- png_error_ptr error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_error_ptr warning_fn;
-#endif
- png_voidp error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_free_ptr free_fn;
-#endif
-
png_debug(1, "in png_write_destroy");
/* Free any memory zlib uses */
- if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED)
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
deflateEnd(&png_ptr->zstream);
/* Free our memory. png_free checks NULL for us. */
- png_free(png_ptr, png_ptr->zbuf);
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
png_free(png_ptr, png_ptr->row_buf);
+ png_ptr->row_buf = NULL;
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_free(png_ptr, png_ptr->prev_row);
- png_free(png_ptr, png_ptr->sub_row);
- png_free(png_ptr, png_ptr->up_row);
- png_free(png_ptr, png_ptr->avg_row);
- png_free(png_ptr, png_ptr->paeth_row);
+ png_free(png_ptr, png_ptr->try_row);
+ png_free(png_ptr, png_ptr->tst_row);
+ png_ptr->prev_row = NULL;
+ png_ptr->try_row = NULL;
+ png_ptr->tst_row = NULL;
#endif
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- /* Use this to save a little code space, it doesn't free the filter_costs */
- png_reset_filter_heuristics(png_ptr);
- png_free(png_ptr, png_ptr->filter_costs);
- png_free(png_ptr, png_ptr->inv_filter_costs);
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ png_free(png_ptr, png_ptr->chunk_list);
+ png_ptr->chunk_list = NULL;
#endif
-#ifdef PNG_SETJMP_SUPPORTED
- /* Reset structure */
- png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
-#endif
+ /* The error handling and memory handling information is left intact at this
+ * point: the jmp_buf may still have to be freed. See png_destroy_png_struct
+ * for how this happens.
+ */
+}
- error_fn = png_ptr->error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- warning_fn = png_ptr->warning_fn;
-#endif
- error_ptr = png_ptr->error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- free_fn = png_ptr->free_fn;
-#endif
+/* Free all memory used by the write.
+ * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
+ * *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free
+ * the passed in info_structs but it would quietly fail to free any of the data
+ * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it
+ * has no png_ptr.)
+ */
+void PNGAPI
+png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
+{
+ png_debug(1, "in png_destroy_write_struct");
- png_memset(png_ptr, 0, png_sizeof(png_struct));
+ if (png_ptr_ptr != NULL)
+ {
+ png_structrp png_ptr = *png_ptr_ptr;
- png_ptr->error_fn = error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_ptr->warning_fn = warning_fn;
-#endif
- png_ptr->error_ptr = error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_ptr->free_fn = free_fn;
-#endif
+ if (png_ptr != NULL) /* added in libpng 1.6.0 */
+ {
+ png_destroy_info_struct(png_ptr, info_ptr_ptr);
-#ifdef PNG_SETJMP_SUPPORTED
- png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf));
-#endif
+ *png_ptr_ptr = NULL;
+ png_write_destroy(png_ptr);
+ png_destroy_png_struct(png_ptr);
+ }
+ }
}
/* Allow the application to select one or more row filters to use. */
void PNGAPI
-png_set_filter(png_structp png_ptr, int method, int filters)
+png_set_filter(png_structrp png_ptr, int method, int filters)
{
png_debug(1, "in png_set_filter");
@@ -1016,7 +994,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
return;
#ifdef PNG_MNG_FEATURES_SUPPORTED
- if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(method == PNG_INTRAPIXEL_DIFFERENCING))
method = PNG_FILTER_TYPE_BASE;
@@ -1028,8 +1006,9 @@ png_set_filter(png_structp png_ptr, int method, int filters)
#ifdef PNG_WRITE_FILTER_SUPPORTED
case 5:
case 6:
- case 7: png_warning(png_ptr, "Unknown row filter for method 0");
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+ case 7: png_app_error(png_ptr, "Unknown row filter for method 0");
+ /* FALL THROUGH */
+#endif /* WRITE_FILTER */
case PNG_FILTER_VALUE_NONE:
png_ptr->do_filter = PNG_FILTER_NONE; break;
@@ -1050,367 +1029,152 @@ png_set_filter(png_structp png_ptr, int method, int filters)
png_ptr->do_filter = (png_byte)filters; break;
#else
default:
- png_warning(png_ptr, "Unknown row filter for method 0");
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+ png_app_error(png_ptr, "Unknown row filter for method 0");
+#endif /* WRITE_FILTER */
}
+#ifdef PNG_WRITE_FILTER_SUPPORTED
/* If we have allocated the row_buf, this means we have already started
* with the image and we should have allocated all of the filter buffers
* that have been selected. If prev_row isn't already allocated, then
* it is too late to start using the filters that need it, since we
* will be missing the data in the previous row. If an application
* wants to start and stop using particular filters during compression,
- * it should start out with all of the filters, and then add and
- * remove them after the start of compression.
+ * it should start out with all of the filters, and then remove them
+ * or add them back after the start of compression.
+ *
+ * NOTE: this is a nasty constraint on the code, because it means that the
+ * prev_row buffer must be maintained even if there are currently no
+ * 'prev_row' requiring filters active.
*/
if (png_ptr->row_buf != NULL)
{
-#ifdef PNG_WRITE_FILTER_SUPPORTED
- if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
- {
- png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
- (png_ptr->rowbytes + 1));
- png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
- }
+ int num_filters;
+ png_alloc_size_t buf_size;
- if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL)
- {
- if (png_ptr->prev_row == NULL)
- {
- png_warning(png_ptr, "Can't add Up filter after starting");
- png_ptr->do_filter = (png_byte)(png_ptr->do_filter &
- ~PNG_FILTER_UP);
- }
-
- else
- {
- png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
- (png_ptr->rowbytes + 1));
- png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
- }
- }
-
- if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
- {
- if (png_ptr->prev_row == NULL)
- {
- png_warning(png_ptr, "Can't add Average filter after starting");
- png_ptr->do_filter = (png_byte)(png_ptr->do_filter &
- ~PNG_FILTER_AVG);
- }
+ /* Repeat the checks in png_write_start_row; 1 pixel high or wide
+ * images cannot benefit from certain filters. If this isn't done here
+ * the check below will fire on 1 pixel high images.
+ */
+ if (png_ptr->height == 1)
+ filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
- else
- {
- png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
- (png_ptr->rowbytes + 1));
- png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
- }
- }
+ if (png_ptr->width == 1)
+ filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
- if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
- png_ptr->paeth_row == NULL)
+ if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0
+ && png_ptr->prev_row == NULL)
{
- if (png_ptr->prev_row == NULL)
- {
- png_warning(png_ptr, "Can't add Paeth filter after starting");
- png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH);
- }
-
- else
- {
- png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
- (png_ptr->rowbytes + 1));
- png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
- }
+ /* This is the error case, however it is benign - the previous row
+ * is not available so the filter can't be used. Just warn here.
+ */
+ png_app_warning(png_ptr,
+ "png_set_filter: UP/AVG/PAETH cannot be added after start");
+ filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
}
- if (png_ptr->do_filter == PNG_NO_FILTERS)
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
- png_ptr->do_filter = PNG_FILTER_NONE;
- }
- }
- else
- png_error(png_ptr, "Unknown custom filter method");
-}
-
-/* This allows us to influence the way in which libpng chooses the "best"
- * filter for the current scanline. While the "minimum-sum-of-absolute-
- * differences metric is relatively fast and effective, there is some
- * question as to whether it can be improved upon by trying to keep the
- * filtered data going to zlib more consistent, hopefully resulting in
- * better compression.
- */
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */
-/* Convenience reset API. */
-static void
-png_reset_filter_heuristics(png_structp png_ptr)
-{
- /* Clear out any old values in the 'weights' - this must be done because if
- * the app calls set_filter_heuristics multiple times with different
- * 'num_weights' values we would otherwise potentially have wrong sized
- * arrays.
- */
- png_ptr->num_prev_filters = 0;
- png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
- if (png_ptr->prev_filters != NULL)
- {
- png_bytep old = png_ptr->prev_filters;
- png_ptr->prev_filters = NULL;
- png_free(png_ptr, old);
- }
- if (png_ptr->filter_weights != NULL)
- {
- png_uint_16p old = png_ptr->filter_weights;
- png_ptr->filter_weights = NULL;
- png_free(png_ptr, old);
- }
-
- if (png_ptr->inv_filter_weights != NULL)
- {
- png_uint_16p old = png_ptr->inv_filter_weights;
- png_ptr->inv_filter_weights = NULL;
- png_free(png_ptr, old);
- }
+ num_filters = 0;
- /* Leave the filter_costs - this array is fixed size. */
-}
+ if (filters & PNG_FILTER_SUB)
+ num_filters++;
-static int
-png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
- int num_weights)
-{
- if (png_ptr == NULL)
- return 0;
-
- /* Clear out the arrays */
- png_reset_filter_heuristics(png_ptr);
+ if (filters & PNG_FILTER_UP)
+ num_filters++;
- /* Check arguments; the 'reset' function makes the correct settings for the
- * unweighted case, but we must handle the weight case by initializing the
- * arrays for the caller.
- */
- if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int i;
+ if (filters & PNG_FILTER_AVG)
+ num_filters++;
- if (num_weights > 0)
- {
- png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_byte) * num_weights));
+ if (filters & PNG_FILTER_PAETH)
+ num_filters++;
- /* To make sure that the weighting starts out fairly */
- for (i = 0; i < num_weights; i++)
- {
- png_ptr->prev_filters[i] = 255;
- }
-
- png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
+ /* Allocate needed row buffers if they have not already been
+ * allocated.
+ */
+ buf_size = PNG_ROWBYTES(png_ptr->usr_channels * png_ptr->usr_bit_depth,
+ png_ptr->width) + 1;
- png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
+ if (png_ptr->try_row == NULL)
+ png_ptr->try_row = png_voidcast(png_bytep,
+ png_malloc(png_ptr, buf_size));
- for (i = 0; i < num_weights; i++)
+ if (num_filters > 1)
{
- png_ptr->inv_filter_weights[i] =
- png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
+ if (png_ptr->tst_row == NULL)
+ png_ptr->tst_row = png_voidcast(png_bytep,
+ png_malloc(png_ptr, buf_size));
}
-
- /* Safe to set this now */
- png_ptr->num_prev_filters = (png_byte)num_weights;
- }
-
- /* If, in the future, there are other filter methods, this would
- * need to be based on png_ptr->filter.
- */
- if (png_ptr->filter_costs == NULL)
- {
- png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
-
- png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
- }
-
- for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
- {
- png_ptr->inv_filter_costs[i] =
- png_ptr->filter_costs[i] = PNG_COST_FACTOR;
}
-
- /* All the arrays are inited, safe to set this: */
- png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED;
-
- /* Return the 'ok' code. */
- return 1;
- }
- else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT ||
- heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
- {
- return 1;
+ png_ptr->do_filter = (png_byte)filters;
+#endif
}
else
- {
- png_warning(png_ptr, "Unknown filter heuristic method");
- return 0;
- }
+ png_error(png_ptr, "Unknown custom filter method");
}
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
/* Provide floating and fixed point APIs */
#ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
+png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
int num_weights, png_const_doublep filter_weights,
png_const_doublep filter_costs)
{
- png_debug(1, "in png_set_filter_heuristics");
-
- /* The internal API allocates all the arrays and ensures that the elements of
- * those arrays are set to the default value.
- */
- if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
- return;
-
- /* If using the weighted method copy in the weights. */
- if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int i;
- for (i = 0; i < num_weights; i++)
- {
- if (filter_weights[i] <= 0.0)
- {
- png_ptr->inv_filter_weights[i] =
- png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
- }
-
- else
- {
- png_ptr->inv_filter_weights[i] =
- (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5);
-
- png_ptr->filter_weights[i] =
- (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5);
- }
- }
-
- /* Here is where we set the relative costs of the different filters. We
- * should take the desired compression level into account when setting
- * the costs, so that Paeth, for instance, has a high relative cost at low
- * compression levels, while it has a lower relative cost at higher
- * compression settings. The filter types are in order of increasing
- * relative cost, so it would be possible to do this with an algorithm.
- */
- for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0)
- {
- png_ptr->inv_filter_costs[i] =
- (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5);
-
- png_ptr->filter_costs[i] =
- (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5);
- }
- }
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(heuristic_method)
+ PNG_UNUSED(num_weights)
+ PNG_UNUSED(filter_weights)
+ PNG_UNUSED(filter_costs)
}
#endif /* FLOATING_POINT */
#ifdef PNG_FIXED_POINT_SUPPORTED
void PNGAPI
-png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method,
+png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
int num_weights, png_const_fixed_point_p filter_weights,
png_const_fixed_point_p filter_costs)
{
- png_debug(1, "in png_set_filter_heuristics_fixed");
-
- /* The internal API allocates all the arrays and ensures that the elements of
- * those arrays are set to the default value.
- */
- if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
- return;
-
- /* If using the weighted method copy in the weights. */
- if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int i;
- for (i = 0; i < num_weights; i++)
- {
- if (filter_weights[i] <= 0)
- {
- png_ptr->inv_filter_weights[i] =
- png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
- }
-
- else
- {
- png_ptr->inv_filter_weights[i] = (png_uint_16)
- ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1);
-
- png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR*
- PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]);
- }
- }
-
- /* Here is where we set the relative costs of the different filters. We
- * should take the desired compression level into account when setting
- * the costs, so that Paeth, for instance, has a high relative cost at low
- * compression levels, while it has a lower relative cost at higher
- * compression settings. The filter types are in order of increasing
- * relative cost, so it would be possible to do this with an algorithm.
- */
- for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
- if (filter_costs[i] >= PNG_FP_1)
- {
- png_uint_32 tmp;
-
- /* Use a 32 bit unsigned temporary here because otherwise the
- * intermediate value will be a 32 bit *signed* integer (ANSI rules)
- * and this will get the wrong answer on division.
- */
- tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2);
- tmp /= filter_costs[i];
-
- png_ptr->inv_filter_costs[i] = (png_uint_16)tmp;
-
- tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF;
- tmp /= PNG_FP_1;
-
- png_ptr->filter_costs[i] = (png_uint_16)tmp;
- }
- }
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(heuristic_method)
+ PNG_UNUSED(num_weights)
+ PNG_UNUSED(filter_weights)
+ PNG_UNUSED(filter_costs)
}
#endif /* FIXED_POINT */
-#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+#endif /* WRITE_WEIGHTED_FILTER */
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
void PNGAPI
-png_set_compression_level(png_structp png_ptr, int level)
+png_set_compression_level(png_structrp png_ptr, int level)
{
png_debug(1, "in png_set_compression_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
png_ptr->zlib_level = level;
}
void PNGAPI
-png_set_compression_mem_level(png_structp png_ptr, int mem_level)
+png_set_compression_mem_level(png_structrp png_ptr, int mem_level)
{
png_debug(1, "in png_set_compression_mem_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
png_ptr->zlib_mem_level = mem_level;
}
void PNGAPI
-png_set_compression_strategy(png_structp png_ptr, int strategy)
+png_set_compression_strategy(png_structrp png_ptr, int strategy)
{
png_debug(1, "in png_set_compression_strategy");
if (png_ptr == NULL)
return;
+ /* The flag setting here prevents the libpng dynamic selection of strategy.
+ */
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
png_ptr->zlib_strategy = strategy;
}
@@ -1419,80 +1183,82 @@ png_set_compression_strategy(png_structp png_ptr, int strategy)
* smaller value of window_bits if it can do so safely.
*/
void PNGAPI
-png_set_compression_window_bits(png_structp png_ptr, int window_bits)
+png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
{
if (png_ptr == NULL)
return;
+ /* Prior to 1.6.0 this would warn but then set the window_bits value. This
+ * meant that negative window bits values could be selected that would cause
+ * libpng to write a non-standard PNG file with raw deflate or gzip
+ * compressed IDAT or ancillary chunks. Such files can be read and there is
+ * no warning on read, so this seems like a very bad idea.
+ */
if (window_bits > 15)
+ {
png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
+ window_bits = 15;
+ }
else if (window_bits < 8)
+ {
png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
+ window_bits = 8;
+ }
-#ifndef WBITS_8_OK
- /* Avoid libpng bug with 256-byte windows */
- if (window_bits == 8)
- {
- png_warning(png_ptr, "Compression window is being reset to 512");
- window_bits = 9;
- }
-
-#endif
- png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
png_ptr->zlib_window_bits = window_bits;
}
void PNGAPI
-png_set_compression_method(png_structp png_ptr, int method)
+png_set_compression_method(png_structrp png_ptr, int method)
{
png_debug(1, "in png_set_compression_method");
if (png_ptr == NULL)
return;
+ /* This would produce an invalid PNG file if it worked, but it doesn't and
+ * deflate will fault it, so it is harmless to just warn here.
+ */
if (method != 8)
png_warning(png_ptr, "Only compression method 8 is supported by PNG");
- png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
png_ptr->zlib_method = method;
}
+#endif /* WRITE_CUSTOMIZE_COMPRESSION */
/* The following were added to libpng-1.5.4 */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
void PNGAPI
-png_set_text_compression_level(png_structp png_ptr, int level)
+png_set_text_compression_level(png_structrp png_ptr, int level)
{
png_debug(1, "in png_set_text_compression_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_LEVEL;
png_ptr->zlib_text_level = level;
}
void PNGAPI
-png_set_text_compression_mem_level(png_structp png_ptr, int mem_level)
+png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level)
{
png_debug(1, "in png_set_text_compression_mem_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL;
png_ptr->zlib_text_mem_level = mem_level;
}
void PNGAPI
-png_set_text_compression_strategy(png_structp png_ptr, int strategy)
+png_set_text_compression_strategy(png_structrp png_ptr, int strategy)
{
png_debug(1, "in png_set_text_compression_strategy");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_STRATEGY;
png_ptr->zlib_text_strategy = strategy;
}
@@ -1500,32 +1266,28 @@ png_set_text_compression_strategy(png_structp png_ptr, int strategy)
* smaller value of window_bits if it can do so safely.
*/
void PNGAPI
-png_set_text_compression_window_bits(png_structp png_ptr, int window_bits)
+png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits)
{
if (png_ptr == NULL)
return;
if (window_bits > 15)
+ {
png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
+ window_bits = 15;
+ }
else if (window_bits < 8)
+ {
png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
+ window_bits = 8;
+ }
-#ifndef WBITS_8_OK
- /* Avoid libpng bug with 256-byte windows */
- if (window_bits == 8)
- {
- png_warning(png_ptr, "Text compression window is being reset to 512");
- window_bits = 9;
- }
-
-#endif
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS;
png_ptr->zlib_text_window_bits = window_bits;
}
void PNGAPI
-png_set_text_compression_method(png_structp png_ptr, int method)
+png_set_text_compression_method(png_structrp png_ptr, int method)
{
png_debug(1, "in png_set_text_compression_method");
@@ -1535,14 +1297,13 @@ png_set_text_compression_method(png_structp png_ptr, int method)
if (method != 8)
png_warning(png_ptr, "Only compression method 8 is supported by PNG");
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_METHOD;
png_ptr->zlib_text_method = method;
}
-#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
+#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
/* end of API added to libpng-1.5.4 */
void PNGAPI
-png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
+png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
{
if (png_ptr == NULL)
return;
@@ -1552,7 +1313,7 @@ png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
void PNGAPI
-png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
write_user_transform_fn)
{
png_debug(1, "in png_set_write_user_transform_fn");
@@ -1568,88 +1329,902 @@ png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
-png_write_png(png_structp png_ptr, png_infop info_ptr,
+png_write_png(png_structrp png_ptr, png_inforp info_ptr,
int transforms, voidp params)
{
if (png_ptr == NULL || info_ptr == NULL)
return;
+ if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
+ {
+ png_app_error(png_ptr, "no rows for png_write_image to write");
+ return;
+ }
+
/* Write the file header information. */
png_write_info(png_ptr, info_ptr);
/* ------ these transformations don't touch the info structure ------- */
-#ifdef PNG_WRITE_INVERT_SUPPORTED
/* Invert monochrome pixels */
- if (transforms & PNG_TRANSFORM_INVERT_MONO)
+ if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
+#ifdef PNG_WRITE_INVERT_SUPPORTED
png_set_invert_mono(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
#endif
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
/* Shift the pixels up to a legal bit depth and fill in
* as appropriate to correctly scale the image.
*/
- if ((transforms & PNG_TRANSFORM_SHIFT)
- && (info_ptr->valid & PNG_INFO_sBIT))
- png_set_shift(png_ptr, &info_ptr->sig_bit);
+ if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+ if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
+ png_set_shift(png_ptr, &info_ptr->sig_bit);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
#endif
-#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes */
- if (transforms & PNG_TRANSFORM_PACKING)
- png_set_packing(png_ptr);
+ if ((transforms & PNG_TRANSFORM_PACKING) != 0)
+#ifdef PNG_WRITE_PACK_SUPPORTED
+ png_set_packing(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
#endif
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
/* Swap location of alpha bytes from ARGB to RGBA */
- if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+ if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
png_set_swap_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
#endif
+ /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
+ * RGB, note that the code expects the input color type to be G or RGB; no
+ * alpha channel.
+ */
+ if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER|
+ PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0)
+ {
#ifdef PNG_WRITE_FILLER_SUPPORTED
- /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */
- if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
- png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+ if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0)
+ {
+ if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
+ png_app_error(png_ptr,
+ "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
- else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
- png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+ /* Continue if ignored - this is the pre-1.6.10 behavior */
+ png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+ }
+
+ else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
+ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
#endif
+ }
-#ifdef PNG_WRITE_BGR_SUPPORTED
/* Flip BGR pixels to RGB */
- if (transforms & PNG_TRANSFORM_BGR)
+ if ((transforms & PNG_TRANSFORM_BGR) != 0)
+#ifdef PNG_WRITE_BGR_SUPPORTED
png_set_bgr(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
#endif
-#ifdef PNG_WRITE_SWAP_SUPPORTED
/* Swap bytes of 16-bit files to most significant byte first */
- if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+ if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
+#ifdef PNG_WRITE_SWAP_SUPPORTED
png_set_swap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
#endif
+ /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */
+ if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
- /* Swap bits of 1, 2, 4 bit packed pixel formats */
- if (transforms & PNG_TRANSFORM_PACKSWAP)
png_set_packswap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
#endif
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel from opacity to transparency */
- if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+ if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
png_set_invert_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
#endif
/* ----------------------- end of transformations ------------------- */
/* Write the bits */
- if (info_ptr->valid & PNG_INFO_IDAT)
- png_write_image(png_ptr, info_ptr->row_pointers);
+ png_write_image(png_ptr, info_ptr->row_pointers);
/* It is REQUIRED to call this to finish writing the rest of the file */
png_write_end(png_ptr, info_ptr);
- PNG_UNUSED(transforms) /* Quiet compiler warnings */
PNG_UNUSED(params)
}
#endif
-#endif /* PNG_WRITE_SUPPORTED */
+
+
+#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
+# ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
+/* Initialize the write structure - general purpose utility. */
+static int
+png_image_write_init(png_imagep image)
+{
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
+ png_safe_error, png_safe_warning);
+
+ if (png_ptr != NULL)
+ {
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+
+ if (info_ptr != NULL)
+ {
+ png_controlp control = png_voidcast(png_controlp,
+ png_malloc_warn(png_ptr, (sizeof *control)));
+
+ if (control != NULL)
+ {
+ memset(control, 0, (sizeof *control));
+
+ control->png_ptr = png_ptr;
+ control->info_ptr = info_ptr;
+ control->for_write = 1;
+
+ image->opaque = control;
+ return 1;
+ }
+
+ /* Error clean up */
+ png_destroy_info_struct(png_ptr, &info_ptr);
+ }
+
+ png_destroy_write_struct(&png_ptr, NULL);
+ }
+
+ return png_image_error(image, "png_image_write_: out of memory");
+}
+
+/* Arguments to png_image_write_main: */
+typedef struct
+{
+ /* Arguments: */
+ png_imagep image;
+ png_const_voidp buffer;
+ png_int_32 row_stride;
+ png_const_voidp colormap;
+ int convert_to_8bit;
+ /* Local variables: */
+ png_const_voidp first_row;
+ ptrdiff_t row_bytes;
+ png_voidp local_row;
+} png_image_write_control;
+
+/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
+ * do any necessary byte swapping. The component order is defined by the
+ * png_image format value.
+ */
+static int
+png_write_image_16bit(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+
+ png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
+ display->first_row);
+ png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
+ png_uint_16p row_end;
+ const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+ int aindex = 0;
+ png_uint_32 y = image->height;
+
+ if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ aindex = -1;
+ ++input_row; /* To point to the first component */
+ ++output_row;
+ }
+ else
+ aindex = channels;
+# else
+ aindex = channels;
+# endif
+ }
+
+ else
+ png_error(png_ptr, "png_write_image: internal call error");
+
+ /* Work out the output row end and count over this, note that the increment
+ * above to 'row' means that row_end can actually be beyond the end of the
+ * row; this is correct.
+ */
+ row_end = output_row + image->width * (channels+1);
+
+ while (y-- > 0)
+ {
+ png_const_uint_16p in_ptr = input_row;
+ png_uint_16p out_ptr = output_row;
+
+ while (out_ptr < row_end)
+ {
+ const png_uint_16 alpha = in_ptr[aindex];
+ png_uint_32 reciprocal = 0;
+ int c;
+
+ out_ptr[aindex] = alpha;
+
+ /* Calculate a reciprocal. The correct calculation is simply
+ * component/alpha*65535 << 15. (I.e. 15 bits of precision); this
+ * allows correct rounding by adding .5 before the shift. 'reciprocal'
+ * is only initialized when required.
+ */
+ if (alpha > 0 && alpha < 65535)
+ reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
+
+ c = channels;
+ do /* always at least one channel */
+ {
+ png_uint_16 component = *in_ptr++;
+
+ /* The following gives 65535 for an alpha of 0, which is fine,
+ * otherwise if 0/0 is represented as some other value there is more
+ * likely to be a discontinuity which will probably damage
+ * compression when moving from a fully transparent area to a
+ * nearly transparent one. (The assumption here is that opaque
+ * areas tend not to be 0 intensity.)
+ */
+ if (component >= alpha)
+ component = 65535;
+
+ /* component<alpha, so component/alpha is less than one and
+ * component*reciprocal is less than 2^31.
+ */
+ else if (component > 0 && alpha < 65535)
+ {
+ png_uint_32 calc = component * reciprocal;
+ calc += 16384; /* round to nearest */
+ component = (png_uint_16)(calc >> 15);
+ }
+
+ *out_ptr++ = component;
+ }
+ while (--c > 0);
+
+ /* Skip to next component (skip the intervening alpha channel) */
+ ++in_ptr;
+ ++out_ptr;
+ }
+
+ png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
+ input_row += display->row_bytes/(sizeof (png_uint_16));
+ }
+
+ return 1;
+}
+
+/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
+ * is present it must be removed from the components, the components are then
+ * written in sRGB encoding. No components are added or removed.
+ *
+ * Calculate an alpha reciprocal to reverse pre-multiplication. As above the
+ * calculation can be done to 15 bits of accuracy; however, the output needs to
+ * be scaled in the range 0..255*65535, so include that scaling here.
+ */
+# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
+
+static png_byte
+png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
+ png_uint_32 reciprocal/*from the above macro*/)
+{
+ /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
+ * is represented as some other value there is more likely to be a
+ * discontinuity which will probably damage compression when moving from a
+ * fully transparent area to a nearly transparent one. (The assumption here
+ * is that opaque areas tend not to be 0 intensity.)
+ *
+ * There is a rounding problem here; if alpha is less than 128 it will end up
+ * as 0 when scaled to 8 bits. To avoid introducing spurious colors into the
+ * output change for this too.
+ */
+ if (component >= alpha || alpha < 128)
+ return 255;
+
+ /* component<alpha, so component/alpha is less than one and
+ * component*reciprocal is less than 2^31.
+ */
+ else if (component > 0)
+ {
+ /* The test is that alpha/257 (rounded) is less than 255, the first value
+ * that becomes 255 is 65407.
+ * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
+ * be exact!) [Could also test reciprocal != 0]
+ */
+ if (alpha < 65407)
+ {
+ component *= reciprocal;
+ component += 64; /* round to nearest */
+ component >>= 7;
+ }
+
+ else
+ component *= 255;
+
+ /* Convert the component to sRGB. */
+ return (png_byte)PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ else
+ return 0;
+}
+
+static int
+png_write_image_8bit(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+
+ png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
+ display->first_row);
+ png_bytep output_row = png_voidcast(png_bytep, display->local_row);
+ png_uint_32 y = image->height;
+ const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+
+ if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ png_bytep row_end;
+ int aindex;
+
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ aindex = -1;
+ ++input_row; /* To point to the first component */
+ ++output_row;
+ }
+
+ else
+# endif
+ aindex = channels;
+
+ /* Use row_end in place of a loop counter: */
+ row_end = output_row + image->width * (channels+1);
+
+ while (y-- > 0)
+ {
+ png_const_uint_16p in_ptr = input_row;
+ png_bytep out_ptr = output_row;
+
+ while (out_ptr < row_end)
+ {
+ png_uint_16 alpha = in_ptr[aindex];
+ png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
+ png_uint_32 reciprocal = 0;
+ int c;
+
+ /* Scale and write the alpha channel. */
+ out_ptr[aindex] = alphabyte;
+
+ if (alphabyte > 0 && alphabyte < 255)
+ reciprocal = UNP_RECIPROCAL(alpha);
+
+ c = channels;
+ do /* always at least one channel */
+ *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
+ while (--c > 0);
+
+ /* Skip to next component (skip the intervening alpha channel) */
+ ++in_ptr;
+ ++out_ptr;
+ } /* while out_ptr < row_end */
+
+ png_write_row(png_ptr, png_voidcast(png_const_bytep,
+ display->local_row));
+ input_row += display->row_bytes/(sizeof (png_uint_16));
+ } /* while y */
+ }
+
+ else
+ {
+ /* No alpha channel, so the row_end really is the end of the row and it
+ * is sufficient to loop over the components one by one.
+ */
+ png_bytep row_end = output_row + image->width * channels;
+
+ while (y-- > 0)
+ {
+ png_const_uint_16p in_ptr = input_row;
+ png_bytep out_ptr = output_row;
+
+ while (out_ptr < row_end)
+ {
+ png_uint_32 component = *in_ptr++;
+
+ component *= 255;
+ *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ png_write_row(png_ptr, output_row);
+ input_row += display->row_bytes/(sizeof (png_uint_16));
+ }
+ }
+
+ return 1;
+}
+
+static void
+png_image_set_PLTE(png_image_write_control *display)
+{
+ const png_imagep image = display->image;
+ const void *cmap = display->colormap;
+ const int entries = image->colormap_entries > 256 ? 256 :
+ (int)image->colormap_entries;
+
+ /* NOTE: the caller must check for cmap != NULL and entries != 0 */
+ const png_uint_32 format = image->format;
+ const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
+
+# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
+ defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
+ const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ (format & PNG_FORMAT_FLAG_ALPHA) != 0;
+# else
+# define afirst 0
+# endif
+
+# ifdef PNG_FORMAT_BGR_SUPPORTED
+ const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+# else
+# define bgr 0
+# endif
+
+ int i, num_trans;
+ png_color palette[256];
+ png_byte tRNS[256];
+
+ memset(tRNS, 255, (sizeof tRNS));
+ memset(palette, 0, (sizeof palette));
+
+ for (i=num_trans=0; i<entries; ++i)
+ {
+ /* This gets automatically converted to sRGB with reversal of the
+ * pre-multiplication if the color-map has an alpha channel.
+ */
+ if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
+ {
+ png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
+
+ entry += i * channels;
+
+ if ((channels & 1) != 0) /* no alpha */
+ {
+ if (channels >= 3) /* RGB */
+ {
+ palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
+ entry[(2 ^ bgr)]);
+ palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
+ entry[1]);
+ palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
+ entry[bgr]);
+ }
+
+ else /* Gray */
+ palette[i].blue = palette[i].red = palette[i].green =
+ (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
+ }
+
+ else /* alpha */
+ {
+ png_uint_16 alpha = entry[afirst ? 0 : channels-1];
+ png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
+ png_uint_32 reciprocal = 0;
+
+ /* Calculate a reciprocal, as in the png_write_image_8bit code above
+ * this is designed to produce a value scaled to 255*65535 when
+ * divided by 128 (i.e. asr 7).
+ */
+ if (alphabyte > 0 && alphabyte < 255)
+ reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
+
+ tRNS[i] = alphabyte;
+ if (alphabyte < 255)
+ num_trans = i+1;
+
+ if (channels >= 3) /* RGB */
+ {
+ palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
+ alpha, reciprocal);
+ palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
+ reciprocal);
+ palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
+ reciprocal);
+ }
+
+ else /* gray */
+ palette[i].blue = palette[i].red = palette[i].green =
+ png_unpremultiply(entry[afirst], alpha, reciprocal);
+ }
+ }
+
+ else /* Color-map has sRGB values */
+ {
+ png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
+
+ entry += i * channels;
+
+ switch (channels)
+ {
+ case 4:
+ tRNS[i] = entry[afirst ? 0 : 3];
+ if (tRNS[i] < 255)
+ num_trans = i+1;
+ /* FALL THROUGH */
+ case 3:
+ palette[i].blue = entry[afirst + (2 ^ bgr)];
+ palette[i].green = entry[afirst + 1];
+ palette[i].red = entry[afirst + bgr];
+ break;
+
+ case 2:
+ tRNS[i] = entry[1 ^ afirst];
+ if (tRNS[i] < 255)
+ num_trans = i+1;
+ /* FALL THROUGH */
+ case 1:
+ palette[i].blue = palette[i].red = palette[i].green =
+ entry[afirst];
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+# ifdef afirst
+# undef afirst
+# endif
+# ifdef bgr
+# undef bgr
+# endif
+
+ png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
+ entries);
+
+ if (num_trans > 0)
+ png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
+ num_trans, NULL);
+
+ image->colormap_entries = entries;
+}
+
+static int
+png_image_write_main(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_inforp info_ptr = image->opaque->info_ptr;
+ png_uint_32 format = image->format;
+
+ /* The following four ints are actually booleans */
+ int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
+ int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
+ int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
+ int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
+
+# ifdef PNG_BENIGN_ERRORS_SUPPORTED
+ /* Make sure we error out on any bad situation */
+ png_set_benign_errors(png_ptr, 0/*error*/);
+# endif
+
+ /* Default the 'row_stride' parameter if required. */
+ if (display->row_stride == 0)
+ display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+
+ /* Set the required transforms then write the rows in the correct order. */
+ if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
+ {
+ if (display->colormap != NULL && image->colormap_entries > 0)
+ {
+ png_uint_32 entries = image->colormap_entries;
+
+ png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
+ entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
+ PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_image_set_PLTE(display);
+ }
+
+ else
+ png_error(image->opaque->png_ptr,
+ "no color-map for color-mapped image");
+ }
+
+ else
+ png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
+ write_16bit ? 16 : 8,
+ ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
+ ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ /* Counter-intuitively the data transformations must be called *after*
+ * png_write_info, not before as in the read code, but the 'set' functions
+ * must still be called before. Just set the color space information, never
+ * write an interlaced image.
+ */
+
+ if (write_16bit != 0)
+ {
+ /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
+ png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
+
+ if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
+ png_set_cHRM_fixed(png_ptr, info_ptr,
+ /* color x y */
+ /* white */ 31270, 32900,
+ /* red */ 64000, 33000,
+ /* green */ 30000, 60000,
+ /* blue */ 15000, 6000
+ );
+ }
+
+ else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
+ png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
+
+ /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
+ * space must still be gamma encoded.
+ */
+ else
+ png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
+
+ /* Write the file header. */
+ png_write_info(png_ptr, info_ptr);
+
+ /* Now set up the data transformations (*after* the header is written),
+ * remove the handled transformations from the 'format' flags for checking.
+ *
+ * First check for a little endian system if writing 16-bit files.
+ */
+ if (write_16bit != 0)
+ {
+ PNG_CONST png_uint_16 le = 0x0001;
+
+ if ((*(png_const_bytep) & le) != 0)
+ png_set_swap(png_ptr);
+ }
+
+# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_BGR) != 0)
+ {
+ if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0)
+ png_set_bgr(png_ptr);
+ format &= ~PNG_FORMAT_FLAG_BGR;
+ }
+# endif
+
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ png_set_swap_alpha(png_ptr);
+ format &= ~PNG_FORMAT_FLAG_AFIRST;
+ }
+# endif
+
+ /* If there are 16 or fewer color-map entries we wrote a lower bit depth
+ * above, but the application data is still byte packed.
+ */
+ if (colormap != 0 && image->colormap_entries <= 16)
+ png_set_packing(png_ptr);
+
+ /* That should have handled all (both) the transforms. */
+ if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
+ PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
+ png_error(png_ptr, "png_write_image: unsupported transformation");
+
+ {
+ png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
+ ptrdiff_t row_bytes = display->row_stride;
+
+ if (linear != 0)
+ row_bytes *= (sizeof (png_uint_16));
+
+ if (row_bytes < 0)
+ row += (image->height-1) * (-row_bytes);
+
+ display->first_row = row;
+ display->row_bytes = row_bytes;
+ }
+
+ /* Apply 'fast' options if the flag is set. */
+ if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
+ {
+ png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
+ /* NOTE: determined by experiment using pngstest, this reflects some
+ * balance between the time to write the image once and the time to read
+ * it about 50 times. The speed-up in pngstest was about 10-20% of the
+ * total (user) time on a heavily loaded system.
+ */
+# ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
+ png_set_compression_level(png_ptr, 3);
+# endif
+ }
+
+ /* Check for the cases that currently require a pre-transform on the row
+ * before it is written. This only applies when the input is 16-bit and
+ * either there is an alpha channel or it is converted to 8-bit.
+ */
+ if ((linear != 0 && alpha != 0 ) ||
+ (colormap == 0 && display->convert_to_8bit != 0))
+ {
+ png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
+ png_get_rowbytes(png_ptr, info_ptr)));
+ int result;
+
+ display->local_row = row;
+ if (write_16bit != 0)
+ result = png_safe_execute(image, png_write_image_16bit, display);
+ else
+ result = png_safe_execute(image, png_write_image_8bit, display);
+ display->local_row = NULL;
+
+ png_free(png_ptr, row);
+
+ /* Skip the 'write_end' on error: */
+ if (result == 0)
+ return 0;
+ }
+
+ /* Otherwise this is the case where the input is in a format currently
+ * supported by the rest of the libpng write code; call it directly.
+ */
+ else
+ {
+ png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
+ ptrdiff_t row_bytes = display->row_bytes;
+ png_uint_32 y = image->height;
+
+ while (y-- > 0)
+ {
+ png_write_row(png_ptr, row);
+ row += row_bytes;
+ }
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ return 1;
+}
+
+int PNGAPI
+png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
+ const void *buffer, png_int_32 row_stride, const void *colormap)
+{
+ /* Write the image to the given (FILE*). */
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file != NULL)
+ {
+ if (png_image_write_init(image) != 0)
+ {
+ png_image_write_control display;
+ int result;
+
+ /* This is slightly evil, but png_init_io doesn't do anything other
+ * than this and we haven't changed the standard IO functions so
+ * this saves a 'safe' function.
+ */
+ image->opaque->png_ptr->io_ptr = file;
+
+ memset(&display, 0, (sizeof display));
+ display.image = image;
+ display.buffer = buffer;
+ display.row_stride = row_stride;
+ display.colormap = colormap;
+ display.convert_to_8bit = convert_to_8bit;
+
+ result = png_safe_execute(image, png_image_write_main, &display);
+ png_image_free(image);
+ return result;
+ }
+
+ else
+ return 0;
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_write_to_stdio: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
+
+ else
+ return 0;
+}
+
+int PNGAPI
+png_image_write_to_file(png_imagep image, const char *file_name,
+ int convert_to_8bit, const void *buffer, png_int_32 row_stride,
+ const void *colormap)
+{
+ /* Write the image to the named file. */
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file_name != NULL)
+ {
+ FILE *fp = fopen(file_name, "wb");
+
+ if (fp != NULL)
+ {
+ if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
+ row_stride, colormap) != 0)
+ {
+ int error; /* from fflush/fclose */
+
+ /* Make sure the file is flushed correctly. */
+ if (fflush(fp) == 0 && ferror(fp) == 0)
+ {
+ if (fclose(fp) == 0)
+ return 1;
+
+ error = errno; /* from fclose */
+ }
+
+ else
+ {
+ error = errno; /* from fflush or ferror */
+ (void)fclose(fp);
+ }
+
+ (void)remove(file_name);
+ /* The image has already been cleaned up; this is just used to
+ * set the error (because the original write succeeded).
+ */
+ return png_image_error(image, strerror(error));
+ }
+
+ else
+ {
+ /* Clean up: just the opened file. */
+ (void)fclose(fp);
+ (void)remove(file_name);
+ return 0;
+ }
+ }
+
+ else
+ return png_image_error(image, strerror(errno));
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_write_to_file: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
+
+ else
+ return 0;
+}
+# endif /* STDIO */
+#endif /* SIMPLIFIED_WRITE */
+#endif /* WRITE */
diff --git a/thirdparty/libpng/pngwtran.c b/thirdparty/libpng/pngwtran.c
index 96608efc..038a2ef5 100644
--- a/thirdparty/libpng/pngwtran.c
+++ b/thirdparty/libpng/pngwtran.c
@@ -1,8 +1,8 @@
/* pngwtran.c - transforms the data in a row for PNG writers
*
- * Last changed in libpng 1.5.6 [November 3, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.18 [July 23, 2015]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -14,90 +14,14 @@
#include "pngpriv.h"
#ifdef PNG_WRITE_SUPPORTED
-
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
-/* Transform the data according to the user's wishes. The order of
- * transformations is significant.
- */
-void /* PRIVATE */
-png_do_write_transformations(png_structp png_ptr, png_row_infop row_info)
-{
- png_debug(1, "in png_do_write_transformations");
-
- if (png_ptr == NULL)
- return;
-
-#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
- if (png_ptr->transformations & PNG_USER_TRANSFORM)
- if (png_ptr->write_user_transform_fn != NULL)
- (*(png_ptr->write_user_transform_fn)) /* User write transform
- function */
- (png_ptr, /* png_ptr */
- row_info, /* row_info: */
- /* png_uint_32 width; width of row */
- /* png_size_t rowbytes; number of bytes in row */
- /* png_byte color_type; color type of pixels */
- /* png_byte bit_depth; bit depth of samples */
- /* png_byte channels; number of channels (1-4) */
- /* png_byte pixel_depth; bits per pixel (depth*channels) */
- png_ptr->row_buf + 1); /* start of pixel data for row */
-#endif
-
-#ifdef PNG_WRITE_FILLER_SUPPORTED
- if (png_ptr->transformations & PNG_FILLER)
- png_do_strip_channel(row_info, png_ptr->row_buf + 1,
- !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
-#endif
-
-#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP)
- png_do_packswap(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_PACK_SUPPORTED
- if (png_ptr->transformations & PNG_PACK)
- png_do_pack(row_info, png_ptr->row_buf + 1,
- (png_uint_32)png_ptr->bit_depth);
-#endif
-
-#ifdef PNG_WRITE_SWAP_SUPPORTED
- if (png_ptr->transformations & PNG_SWAP_BYTES)
- png_do_swap(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
- if (png_ptr->transformations & PNG_SHIFT)
- png_do_shift(row_info, png_ptr->row_buf + 1,
- &(png_ptr->shift));
-#endif
-
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_SWAP_ALPHA)
- png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_ALPHA)
- png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_BGR_SUPPORTED
- if (png_ptr->transformations & PNG_BGR)
- png_do_bgr(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_INVERT_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_MONO)
- png_do_invert(row_info, png_ptr->row_buf + 1);
-#endif
-}
#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
* row_info bit depth should be 8 (one pixel per byte). The channels
* should be 1 (this only happens on grayscale and paletted images).
*/
-void /* PRIVATE */
+static void
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
{
png_debug(1, "in png_do_pack");
@@ -147,7 +71,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
case 2:
{
png_bytep sp, dp;
- int shift, v;
+ unsigned int shift;
+ int v;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
@@ -186,7 +111,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
case 4:
{
png_bytep sp, dp;
- int shift, v;
+ unsigned int shift;
+ int v;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
@@ -242,7 +168,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
* would pass 3 as bit_depth, and this routine would translate the
* data to 0 to 15.
*/
-void /* PRIVATE */
+static void
png_do_shift(png_row_infop row_info, png_bytep row,
png_const_color_8p bit_depth)
{
@@ -253,7 +179,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
int shift_start[4], shift_dec[4];
int channels = 0;
- if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+ if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
shift_start[channels] = row_info->bit_depth - bit_depth->red;
shift_dec[channels] = bit_depth->red;
@@ -275,7 +201,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
channels++;
}
- if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
shift_dec[channels] = bit_depth->alpha;
@@ -287,7 +213,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
{
png_bytep bp = row;
png_size_t i;
- png_byte mask;
+ unsigned int mask;
png_size_t row_bytes = row_info->rowbytes;
if (bit_depth->gray == 1 && row_info->bit_depth == 2)
@@ -301,20 +227,22 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (i = 0; i < row_bytes; i++, bp++)
{
- png_uint_16 v;
int j;
+ unsigned int v, out;
v = *bp;
- *bp = 0;
+ out = 0;
for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
{
if (j > 0)
- *bp |= (png_byte)((v << j) & 0xff);
+ out |= v << j;
else
- *bp |= (png_byte)((v >> (-j)) & mask);
+ out |= (v >> (-j)) & mask;
}
+
+ *bp = (png_byte)(out & 0xff);
}
}
@@ -327,21 +255,23 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (i = 0; i < istop; i++, bp++)
{
- png_uint_16 v;
+ const unsigned int c = i%channels;
int j;
- int c = (int)(i%channels);
+ unsigned int v, out;
v = *bp;
- *bp = 0;
+ out = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{
if (j > 0)
- *bp |= (png_byte)((v << j) & 0xff);
+ out |= v << j;
else
- *bp |= (png_byte)((v >> (-j)) & 0xff);
+ out |= v >> (-j);
}
+
+ *bp = (png_byte)(out & 0xff);
}
}
@@ -353,22 +283,22 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (bp = row, i = 0; i < istop; i++)
{
- int c = (int)(i%channels);
- png_uint_16 value, v;
+ const unsigned int c = i%channels;
int j;
+ unsigned int value, v;
- v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
+ v = png_get_uint_16(bp);
value = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{
if (j > 0)
- value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
+ value |= v << j;
else
- value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
+ value |= v >> (-j);
}
- *bp++ = (png_byte)(value >> 8);
+ *bp++ = (png_byte)((value >> 8) & 0xff);
*bp++ = (png_byte)(value & 0xff);
}
}
@@ -377,7 +307,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_swap_alpha");
@@ -425,7 +355,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save[1];
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
@@ -464,14 +394,14 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save[1];
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
}
}
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_invert_alpha");
@@ -494,7 +424,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = *(sp++);
*/
sp+=3; dp = sp;
- *(dp++) = (png_byte)(255 - *(sp++));
+ *dp = (png_byte)(255 - *(sp++));
}
}
@@ -518,10 +448,10 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*/
sp+=6; dp = sp;
*(dp++) = (png_byte)(255 - *(sp++));
- *(dp++) = (png_byte)(255 - *(sp++));
+ *dp = (png_byte)(255 - *(sp++));
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
@@ -556,78 +486,91 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*/
sp+=2; dp = sp;
*(dp++) = (png_byte)(255 - *(sp++));
- *(dp++) = (png_byte)(255 - *(sp++));
+ *dp = (png_byte)(255 - *(sp++));
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
}
}
#endif
-#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Undoes intrapixel differencing */
+/* Transform the data according to the user's wishes. The order of
+ * transformations is significant.
+ */
void /* PRIVATE */
-png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
+png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
{
- png_debug(1, "in png_do_write_intrapixel");
+ png_debug(1, "in png_do_write_transformations");
- if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
- {
- int bytes_per_pixel;
- png_uint_32 row_width = row_info->width;
- if (row_info->bit_depth == 8)
- {
- png_bytep rp;
- png_uint_32 i;
+ if (png_ptr == NULL)
+ return;
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 3;
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
+ if (png_ptr->write_user_transform_fn != NULL)
+ (*(png_ptr->write_user_transform_fn)) /* User write transform
+ function */
+ (png_ptr, /* png_ptr */
+ row_info, /* row_info: */
+ /* png_uint_32 width; width of row */
+ /* png_size_t rowbytes; number of bytes in row */
+ /* png_byte color_type; color type of pixels */
+ /* png_byte bit_depth; bit depth of samples */
+ /* png_byte channels; number of channels (1-4) */
+ /* png_byte pixel_depth; bits per pixel (depth*channels) */
+ png_ptr->row_buf + 1); /* start of pixel data for row */
+#endif
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 4;
+#ifdef PNG_WRITE_FILLER_SUPPORTED
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
+#endif
- else
- return;
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ png_do_packswap(row_info, png_ptr->row_buf + 1);
+#endif
- for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
- {
- *(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff);
- *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff);
- }
- }
+#ifdef PNG_WRITE_PACK_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACK) != 0)
+ png_do_pack(row_info, png_ptr->row_buf + 1,
+ (png_uint_32)png_ptr->bit_depth);
+#endif
-#ifdef PNG_WRITE_16BIT_SUPPORTED
- else if (row_info->bit_depth == 16)
- {
- png_bytep rp;
- png_uint_32 i;
+#ifdef PNG_WRITE_SWAP_SUPPORTED
+# ifdef PNG_16BIT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
+ png_do_swap(row_info, png_ptr->row_buf + 1);
+# endif
+#endif
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 6;
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
+ png_do_shift(row_info, png_ptr->row_buf + 1,
+ &(png_ptr->shift));
+#endif
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 8;
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
+ png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
+#endif
- else
- return;
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
+ png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
+#endif
- for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
- {
- png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
- png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
- png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
- png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
- png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
- *(rp ) = (png_byte)((red >> 8) & 0xff);
- *(rp + 1) = (png_byte)(red & 0xff);
- *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
- *(rp + 5) = (png_byte)(blue & 0xff);
- }
- }
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
- }
+#ifdef PNG_WRITE_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ png_do_bgr(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_WRITE_INVERT_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
+ png_do_invert(row_info, png_ptr->row_buf + 1);
+#endif
}
-#endif /* PNG_MNG_FEATURES_SUPPORTED */
-#endif /* PNG_WRITE_SUPPORTED */
+#endif /* WRITE_TRANSFORMS */
+#endif /* WRITE */
diff --git a/thirdparty/libpng/pngwutil.c b/thirdparty/libpng/pngwutil.c
index da18e950..8cf4c2bb 100644
--- a/thirdparty/libpng/pngwutil.c
+++ b/thirdparty/libpng/pngwutil.c
@@ -1,8 +1,8 @@
/* pngwutil.c - utilities to write a PNG file
*
- * Last changed in libpng 1.5.6 [November 3, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.21 [January 15, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -23,29 +23,12 @@
void PNGAPI
png_save_uint_32(png_bytep buf, png_uint_32 i)
{
- buf[0] = (png_byte)((i >> 24) & 0xff);
- buf[1] = (png_byte)((i >> 16) & 0xff);
- buf[2] = (png_byte)((i >> 8) & 0xff);
- buf[3] = (png_byte)(i & 0xff);
+ buf[0] = (png_byte)(i >> 24);
+ buf[1] = (png_byte)(i >> 16);
+ buf[2] = (png_byte)(i >> 8);
+ buf[3] = (png_byte)(i );
}
-#ifdef PNG_SAVE_INT_32_SUPPORTED
-/* The png_save_int_32 function assumes integers are stored in two's
- * complement format. If this isn't the case, then this routine needs to
- * be modified to write data in two's complement format. Note that,
- * the following works correctly even if png_int_32 has more than 32 bits
- * (compare the more complex code required on read for sign extention.)
- */
-void PNGAPI
-png_save_int_32(png_bytep buf, png_int_32 i)
-{
- buf[0] = (png_byte)((i >> 24) & 0xff);
- buf[1] = (png_byte)((i >> 16) & 0xff);
- buf[2] = (png_byte)((i >> 8) & 0xff);
- buf[3] = (png_byte)(i & 0xff);
-}
-#endif
-
/* Place a 16-bit number into a buffer in PNG byte order.
* The parameter is declared unsigned int, not png_uint_16,
* just to avoid potential problems on pre-ANSI C compilers.
@@ -53,8 +36,8 @@ png_save_int_32(png_bytep buf, png_int_32 i)
void PNGAPI
png_save_uint_16(png_bytep buf, unsigned int i)
{
- buf[0] = (png_byte)((i >> 8) & 0xff);
- buf[1] = (png_byte)(i & 0xff);
+ buf[0] = (png_byte)(i >> 8);
+ buf[1] = (png_byte)(i );
}
#endif
@@ -65,7 +48,7 @@ png_save_uint_16(png_bytep buf, unsigned int i)
* bytes have already been written.
*/
void PNGAPI
-png_write_sig(png_structp png_ptr)
+png_write_sig(png_structrp png_ptr)
{
png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
@@ -87,7 +70,7 @@ png_write_sig(png_structp png_ptr)
* passing in png_write_chunk_data().
*/
static void
-png_write_chunk_header(png_structp png_ptr, png_uint_32 chunk_name,
+png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
png_uint_32 length)
{
png_byte buf[8];
@@ -129,7 +112,7 @@ png_write_chunk_header(png_structp png_ptr, png_uint_32 chunk_name,
}
void PNGAPI
-png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_string,
+png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
png_uint_32 length)
{
png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
@@ -141,7 +124,7 @@ png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_string,
* given to png_write_chunk_header().
*/
void PNGAPI
-png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
+png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
png_size_t length)
{
/* Write the data, and run the CRC over it */
@@ -153,7 +136,7 @@ png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
png_write_data(png_ptr, data, length);
/* Update the CRC after writing the data,
- * in case that the user I/O routine alters it.
+ * in case the user I/O routine alters it.
*/
png_calculate_crc(png_ptr, data, length);
}
@@ -161,7 +144,7 @@ png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
/* Finish a chunk started with png_write_chunk_header(). */
void PNGAPI
-png_write_chunk_end(png_structp png_ptr)
+png_write_chunk_end(png_structrp png_ptr)
{
png_byte buf[4];
@@ -190,15 +173,15 @@ png_write_chunk_end(png_structp png_ptr)
* functions instead.
*/
static void
-png_write_complete_chunk(png_structp png_ptr, png_uint_32 chunk_name,
+png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
png_const_bytep data, png_size_t length)
{
if (png_ptr == NULL)
return;
- /* On 64 bit architectures 'length' may not fit in a png_uint_32. */
- if (length > PNG_UINT_32_MAX)
- png_error(png_ptr, "length exceeds PNG maxima");
+ /* On 64-bit architectures 'length' may not fit in a png_uint_32. */
+ if (length > PNG_UINT_31_MAX)
+ png_error(png_ptr, "length exceeds PNG maximum");
png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
png_write_chunk_data(png_ptr, data, length);
@@ -207,473 +190,487 @@ png_write_complete_chunk(png_structp png_ptr, png_uint_32 chunk_name,
/* This is the API that calls the internal function above. */
void PNGAPI
-png_write_chunk(png_structp png_ptr, png_const_bytep chunk_string,
+png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
png_const_bytep data, png_size_t length)
{
png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
length);
}
-/* Initialize the compressor for the appropriate type of compression. */
-static void
-png_zlib_claim(png_structp png_ptr, png_uint_32 state)
+/* This is used below to find the size of an image to pass to png_deflate_claim,
+ * so it only needs to be accurate if the size is less than 16384 bytes (the
+ * point at which a lower LZ window size can be used.)
+ */
+static png_alloc_size_t
+png_image_size(png_structrp png_ptr)
{
- if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE))
+ /* Only return sizes up to the maximum of a png_uint_32; do this by limiting
+ * the width and height used to 15 bits.
+ */
+ png_uint_32 h = png_ptr->height;
+
+ if (png_ptr->rowbytes < 32768 && h < 32768)
{
- /* If already initialized for 'state' do not re-init. */
- if (png_ptr->zlib_state != state)
+ if (png_ptr->interlaced != 0)
{
- int ret = Z_OK;
- png_const_charp who = "-";
-
- /* If actually initialized for another state do a deflateEnd. */
- if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED)
- {
- ret = deflateEnd(&png_ptr->zstream);
- who = "end";
- png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
- }
+ /* Interlacing makes the image larger because of the replication of
+ * both the filter byte and the padding to a byte boundary.
+ */
+ png_uint_32 w = png_ptr->width;
+ unsigned int pd = png_ptr->pixel_depth;
+ png_alloc_size_t cb_base;
+ int pass;
- /* zlib itself detects an incomplete state on deflateEnd */
- if (ret == Z_OK) switch (state)
+ for (cb_base=0, pass=0; pass<=6; ++pass)
{
-# ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
- case PNG_ZLIB_FOR_TEXT:
- ret = deflateInit2(&png_ptr->zstream,
- png_ptr->zlib_text_level, png_ptr->zlib_text_method,
- png_ptr->zlib_text_window_bits,
- png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy);
- who = "text";
- break;
-# endif
+ png_uint_32 pw = PNG_PASS_COLS(w, pass);
- case PNG_ZLIB_FOR_IDAT:
- ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
- png_ptr->zlib_method, png_ptr->zlib_window_bits,
- png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
- who = "IDAT";
- break;
-
- default:
- png_error(png_ptr, "invalid zlib state");
+ if (pw > 0)
+ cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
}
- if (ret == Z_OK)
- png_ptr->zlib_state = state;
-
- else /* an error in deflateEnd or deflateInit2 */
- {
- size_t pos = 0;
- char msg[64];
-
- pos = png_safecat(msg, sizeof msg, pos,
- "zlib failed to initialize compressor (");
- pos = png_safecat(msg, sizeof msg, pos, who);
-
- switch (ret)
- {
- case Z_VERSION_ERROR:
- pos = png_safecat(msg, sizeof msg, pos, ") version error");
- break;
-
- case Z_STREAM_ERROR:
- pos = png_safecat(msg, sizeof msg, pos, ") stream error");
- break;
-
- case Z_MEM_ERROR:
- pos = png_safecat(msg, sizeof msg, pos, ") memory error");
- break;
-
- default:
- pos = png_safecat(msg, sizeof msg, pos, ") unknown error");
- break;
- }
-
- png_error(png_ptr, msg);
- }
+ return cb_base;
}
- /* Here on success, claim the zstream: */
- png_ptr->zlib_state |= PNG_ZLIB_IN_USE;
+ else
+ return (png_ptr->rowbytes+1) * h;
}
else
- png_error(png_ptr, "zstream already in use (internal error)");
+ return 0xffffffffU;
}
-/* The opposite: release the stream. It is also reset, this API will warn on
- * error but will not fail.
- */
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ /* This is the code to hack the first two bytes of the deflate stream (the
+ * deflate header) to correct the windowBits value to match the actual data
+ * size. Note that the second argument is the *uncompressed* size but the
+ * first argument is the *compressed* data (and it must be deflate
+ * compressed.)
+ */
static void
-png_zlib_release(png_structp png_ptr)
+optimize_cmf(png_bytep data, png_alloc_size_t data_size)
{
- if (png_ptr->zlib_state & PNG_ZLIB_IN_USE)
+ /* Optimize the CMF field in the zlib stream. The resultant zlib stream is
+ * still compliant to the stream specification.
+ */
+ if (data_size <= 16384) /* else windowBits must be 15 */
{
- int ret = deflateReset(&png_ptr->zstream);
-
- png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE;
+ unsigned int z_cmf = data[0]; /* zlib compression method and flags */
- if (ret != Z_OK)
+ if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
{
- png_const_charp err;
- PNG_WARNING_PARAMETERS(p)
+ unsigned int z_cinfo;
+ unsigned int half_z_window_size;
+
+ z_cinfo = z_cmf >> 4;
+ half_z_window_size = 1U << (z_cinfo + 7);
- switch (ret)
+ if (data_size <= half_z_window_size) /* else no change */
{
- case Z_VERSION_ERROR:
- err = "version";
- break;
+ unsigned int tmp;
- case Z_STREAM_ERROR:
- err = "stream";
- break;
+ do
+ {
+ half_z_window_size >>= 1;
+ --z_cinfo;
+ }
+ while (z_cinfo > 0 && data_size <= half_z_window_size);
- case Z_MEM_ERROR:
- err = "memory";
- break;
+ z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
- default:
- err = "unknown";
- break;
+ data[0] = (png_byte)z_cmf;
+ tmp = data[1] & 0xe0;
+ tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
+ data[1] = (png_byte)tmp;
}
-
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret);
- png_warning_parameter(p, 2, err);
-
- if (png_ptr->zstream.msg)
- err = png_ptr->zstream.msg;
- else
- err = "[no zlib message]";
-
- png_warning_parameter(p, 3, err);
-
- png_formatted_warning(png_ptr, p,
- "zlib failed to reset compressor: @1(@2): @3");
}
}
-
- else
- png_warning(png_ptr, "zstream not in use (internal error)");
}
+#endif /* WRITE_OPTIMIZE_CMF */
-#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
-/* This pair of functions encapsulates the operation of (a) compressing a
- * text string, and (b) issuing it later as a series of chunk data writes.
- * The compression_state structure is shared context for these functions
- * set up by the caller in order to make the whole mess thread-safe.
- */
-
-typedef struct
-{
- png_const_bytep input; /* The uncompressed input data */
- png_size_t input_len; /* Its length */
- int num_output_ptr; /* Number of output pointers used */
- int max_output_ptr; /* Size of output_ptr */
- png_bytep *output_ptr; /* Array of pointers to output */
-} compression_state;
-
-/* Compress given text into storage in the png_ptr structure */
-static int /* PRIVATE */
-png_text_compress(png_structp png_ptr,
- png_const_charp text, png_size_t text_len, int compression,
- compression_state *comp)
+/* Initialize the compressor for the appropriate type of compression. */
+static int
+png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
+ png_alloc_size_t data_size)
{
- int ret;
+ if (png_ptr->zowner != 0)
+ {
+#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
+ char msg[64];
+
+ PNG_STRING_FROM_CHUNK(msg, owner);
+ msg[4] = ':';
+ msg[5] = ' ';
+ PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner);
+ /* So the message that results is "<chunk> using zstream"; this is an
+ * internal error, but is very useful for debugging. i18n requirements
+ * are minimal.
+ */
+ (void)png_safecat(msg, (sizeof msg), 10, " using zstream");
+#endif
+#if PNG_RELEASE_BUILD
+ png_warning(png_ptr, msg);
- comp->num_output_ptr = 0;
- comp->max_output_ptr = 0;
- comp->output_ptr = NULL;
- comp->input = NULL;
- comp->input_len = text_len;
+ /* Attempt sane error recovery */
+ if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */
+ {
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT");
+ return Z_STREAM_ERROR;
+ }
- /* We may just want to pass the text right through */
- if (compression == PNG_TEXT_COMPRESSION_NONE)
- {
- comp->input = (png_const_bytep)text;
- return((int)text_len);
+ png_ptr->zowner = 0;
+#else
+ png_error(png_ptr, msg);
+#endif
}
- if (compression >= PNG_TEXT_COMPRESSION_LAST)
{
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d,
- compression);
- png_formatted_warning(png_ptr, p, "Unknown compression type @1");
- }
+ int level = png_ptr->zlib_level;
+ int method = png_ptr->zlib_method;
+ int windowBits = png_ptr->zlib_window_bits;
+ int memLevel = png_ptr->zlib_mem_level;
+ int strategy; /* set below */
+ int ret; /* zlib return code */
- /* We can't write the chunk until we find out how much data we have,
- * which means we need to run the compressor first and save the
- * output. This shouldn't be a problem, as the vast majority of
- * comments should be reasonable, but we will set up an array of
- * malloc'd pointers to be sure.
- *
- * If we knew the application was well behaved, we could simplify this
- * greatly by assuming we can always malloc an output buffer large
- * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
- * and malloc this directly. The only time this would be a bad idea is
- * if we can't malloc more than 64K and we have 64K of random input
- * data, or if the input string is incredibly large (although this
- * wouldn't cause a failure, just a slowdown due to swapping).
- */
- png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT);
+ if (owner == png_IDAT)
+ {
+ if ((png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) != 0)
+ strategy = png_ptr->zlib_strategy;
- /* Set up the compression buffers */
- /* TODO: the following cast hides a potential overflow problem. */
- png_ptr->zstream.avail_in = (uInt)text_len;
+ else if (png_ptr->do_filter != PNG_FILTER_NONE)
+ strategy = PNG_Z_DEFAULT_STRATEGY;
- /* NOTE: assume zlib doesn't overwrite the input */
- png_ptr->zstream.next_in = (Bytef *)text;
- png_ptr->zstream.avail_out = png_ptr->zbuf_size;
- png_ptr->zstream.next_out = png_ptr->zbuf;
+ else
+ strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY;
+ }
- /* This is the same compression loop as in png_write_row() */
- do
- {
- /* Compress the data */
- ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
+ else
+ {
+#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
+ level = png_ptr->zlib_text_level;
+ method = png_ptr->zlib_text_method;
+ windowBits = png_ptr->zlib_text_window_bits;
+ memLevel = png_ptr->zlib_text_mem_level;
+ strategy = png_ptr->zlib_text_strategy;
+#else
+ /* If customization is not supported the values all come from the
+ * IDAT values except for the strategy, which is fixed to the
+ * default. (This is the pre-1.6.0 behavior too, although it was
+ * implemented in a very different way.)
+ */
+ strategy = Z_DEFAULT_STRATEGY;
+#endif
+ }
- if (ret != Z_OK)
+ /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
+ * happening just pass 32768 as the data_size parameter. Notice that zlib
+ * requires an extra 262 bytes in the window in addition to the data to be
+ * able to see the whole of the data, so if data_size+262 takes us to the
+ * next windowBits size we need to fix up the value later. (Because even
+ * though deflate needs the extra window, inflate does not!)
+ */
+ if (data_size <= 16384)
{
- /* Error */
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
+ /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
+ * work round a Microsoft Visual C misbehavior which, contrary to C-90,
+ * widens the result of the following shift to 64-bits if (and,
+ * apparently, only if) it is used in a test.
+ */
+ unsigned int half_window_size = 1U << (windowBits-1);
- else
- png_error(png_ptr, "zlib error");
+ while (data_size + 262 <= half_window_size)
+ {
+ half_window_size >>= 1;
+ --windowBits;
+ }
}
- /* Check to see if we need more room */
- if (!(png_ptr->zstream.avail_out))
+ /* Check against the previous initialized values, if any. */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0 &&
+ (png_ptr->zlib_set_level != level ||
+ png_ptr->zlib_set_method != method ||
+ png_ptr->zlib_set_window_bits != windowBits ||
+ png_ptr->zlib_set_mem_level != memLevel ||
+ png_ptr->zlib_set_strategy != strategy))
{
- /* Make sure the output array has room */
- if (comp->num_output_ptr >= comp->max_output_ptr)
- {
- int old_max;
+ if (deflateEnd(&png_ptr->zstream) != Z_OK)
+ png_warning(png_ptr, "deflateEnd failed (ignored)");
- old_max = comp->max_output_ptr;
- comp->max_output_ptr = comp->num_output_ptr + 4;
- if (comp->output_ptr != NULL)
- {
- png_bytepp old_ptr;
+ png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
+ }
- old_ptr = comp->output_ptr;
+ /* For safety clear out the input and output pointers (currently zlib
+ * doesn't use them on Init, but it might in the future).
+ */
+ png_ptr->zstream.next_in = NULL;
+ png_ptr->zstream.avail_in = 0;
+ png_ptr->zstream.next_out = NULL;
+ png_ptr->zstream.avail_out = 0;
- comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)
- (comp->max_output_ptr * png_sizeof(png_charpp)));
+ /* Now initialize if required, setting the new parameters, otherwise just
+ * to a simple reset to the previous parameters.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
+ ret = deflateReset(&png_ptr->zstream);
- png_memcpy(comp->output_ptr, old_ptr, old_max
- * png_sizeof(png_charp));
+ else
+ {
+ ret = deflateInit2(&png_ptr->zstream, level, method, windowBits,
+ memLevel, strategy);
- png_free(png_ptr, old_ptr);
- }
- else
- comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)
- (comp->max_output_ptr * png_sizeof(png_charp)));
- }
+ if (ret == Z_OK)
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
+ }
- /* Save the data */
- comp->output_ptr[comp->num_output_ptr] =
- (png_bytep)png_malloc(png_ptr,
- (png_alloc_size_t)png_ptr->zbuf_size);
+ /* The return code is from either deflateReset or deflateInit2; they have
+ * pretty much the same set of error codes.
+ */
+ if (ret == Z_OK)
+ png_ptr->zowner = owner;
- png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
- png_ptr->zbuf_size);
+ else
+ png_zstream_error(png_ptr, ret);
- comp->num_output_ptr++;
+ return ret;
+ }
+}
- /* and reset the buffer */
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_out = png_ptr->zbuf;
- }
- /* Continue until we don't have any more to compress */
- } while (png_ptr->zstream.avail_in);
+/* Clean up (or trim) a linked list of compression buffers. */
+void /* PRIVATE */
+png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
+{
+ png_compression_bufferp list = *listp;
- /* Finish the compression */
- do
+ if (list != NULL)
{
- /* Tell zlib we are finished */
- ret = deflate(&png_ptr->zstream, Z_FINISH);
+ *listp = NULL;
- if (ret == Z_OK)
+ do
{
- /* Check to see if we need more room */
- if (!(png_ptr->zstream.avail_out))
- {
- /* Check to make sure our output array has room */
- if (comp->num_output_ptr >= comp->max_output_ptr)
- {
- int old_max;
+ png_compression_bufferp next = list->next;
- old_max = comp->max_output_ptr;
- comp->max_output_ptr = comp->num_output_ptr + 4;
- if (comp->output_ptr != NULL)
- {
- png_bytepp old_ptr;
+ png_free(png_ptr, list);
+ list = next;
+ }
+ while (list != NULL);
+ }
+}
- old_ptr = comp->output_ptr;
+#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
+/* This pair of functions encapsulates the operation of (a) compressing a
+ * text string, and (b) issuing it later as a series of chunk data writes.
+ * The compression_state structure is shared context for these functions
+ * set up by the caller to allow access to the relevant local variables.
+ *
+ * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
+ * temporary buffers. From 1.6.0 it is retained in png_struct so that it will
+ * be correctly freed in the event of a write error (previous implementations
+ * just leaked memory.)
+ */
+typedef struct
+{
+ png_const_bytep input; /* The uncompressed input data */
+ png_alloc_size_t input_len; /* Its length */
+ png_uint_32 output_len; /* Final compressed length */
+ png_byte output[1024]; /* First block of output */
+} compression_state;
- /* This could be optimized to realloc() */
- comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)(comp->max_output_ptr *
- png_sizeof(png_charp)));
+static void
+png_text_compress_init(compression_state *comp, png_const_bytep input,
+ png_alloc_size_t input_len)
+{
+ comp->input = input;
+ comp->input_len = input_len;
+ comp->output_len = 0;
+}
- png_memcpy(comp->output_ptr, old_ptr,
- old_max * png_sizeof(png_charp));
+/* Compress the data in the compression state input */
+static int
+png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
+ compression_state *comp, png_uint_32 prefix_len)
+{
+ int ret;
- png_free(png_ptr, old_ptr);
- }
+ /* To find the length of the output it is necessary to first compress the
+ * input. The result is buffered rather than using the two-pass algorithm
+ * that is used on the inflate side; deflate is assumed to be slower and a
+ * PNG writer is assumed to have more memory available than a PNG reader.
+ *
+ * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
+ * upper limit on the output size, but it is always bigger than the input
+ * size so it is likely to be more efficient to use this linked-list
+ * approach.
+ */
+ ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
- else
- comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)(comp->max_output_ptr *
- png_sizeof(png_charp)));
- }
+ if (ret != Z_OK)
+ return ret;
- /* Save the data */
- comp->output_ptr[comp->num_output_ptr] =
- (png_bytep)png_malloc(png_ptr,
- (png_alloc_size_t)png_ptr->zbuf_size);
+ /* Set up the compression buffers, we need a loop here to avoid overflowing a
+ * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited
+ * by the output buffer size, so there is no need to check that. Since this
+ * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
+ * in size.
+ */
+ {
+ png_compression_bufferp *end = &png_ptr->zbuffer_list;
+ png_alloc_size_t input_len = comp->input_len; /* may be zero! */
+ png_uint_32 output_len;
- png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
- png_ptr->zbuf_size);
+ /* zlib updates these for us: */
+ png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input);
+ png_ptr->zstream.avail_in = 0; /* Set below */
+ png_ptr->zstream.next_out = comp->output;
+ png_ptr->zstream.avail_out = (sizeof comp->output);
- comp->num_output_ptr++;
+ output_len = png_ptr->zstream.avail_out;
- /* and reset the buffer pointers */
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_out = png_ptr->zbuf;
- }
- }
- else if (ret != Z_STREAM_END)
+ do
{
- /* We got an error */
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
+ uInt avail_in = ZLIB_IO_MAX;
- else
- png_error(png_ptr, "zlib error");
- }
- } while (ret != Z_STREAM_END);
-
- /* Text length is number of buffers plus last buffer */
- text_len = png_ptr->zbuf_size * comp->num_output_ptr;
+ if (avail_in > input_len)
+ avail_in = (uInt)input_len;
- if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
- text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
+ input_len -= avail_in;
- return((int)text_len);
-}
+ png_ptr->zstream.avail_in = avail_in;
-/* Ship the compressed text out via chunk writes */
-static void /* PRIVATE */
-png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
-{
- int i;
+ if (png_ptr->zstream.avail_out == 0)
+ {
+ png_compression_buffer *next;
- /* Handle the no-compression case */
- if (comp->input)
- {
- png_write_chunk_data(png_ptr, comp->input, comp->input_len);
+ /* Chunk data is limited to 2^31 bytes in length, so the prefix
+ * length must be counted here.
+ */
+ if (output_len + prefix_len > PNG_UINT_31_MAX)
+ {
+ ret = Z_MEM_ERROR;
+ break;
+ }
- return;
- }
+ /* Need a new (malloc'ed) buffer, but there may be one present
+ * already.
+ */
+ next = *end;
+ if (next == NULL)
+ {
+ next = png_voidcast(png_compression_bufferp, png_malloc_base
+ (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
- /* The zbuf_size test is because the code below doesn't work if zbuf_size is
- * '1'; simply skip it to avoid memory overwrite.
- */
- if (comp->input_len >= 2 && comp->input_len < 16384 && png_ptr->zbuf_size > 1)
- {
- unsigned int z_cmf; /* zlib compression method and flags */
+ if (next == NULL)
+ {
+ ret = Z_MEM_ERROR;
+ break;
+ }
- /* Optimize the CMF field in the zlib stream. This hack of the zlib
- * stream is compliant to the stream specification.
- */
+ /* Link in this buffer (so that it will be freed later) */
+ next->next = NULL;
+ *end = next;
+ }
- if (comp->num_output_ptr)
- z_cmf = comp->output_ptr[0][0];
- else
- z_cmf = png_ptr->zbuf[0];
+ png_ptr->zstream.next_out = next->output;
+ png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
+ output_len += png_ptr->zstream.avail_out;
- if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
- {
- unsigned int z_cinfo;
- unsigned int half_z_window_size;
- png_size_t uncompressed_text_size = comp->input_len;
+ /* Move 'end' to the next buffer pointer. */
+ end = &next->next;
+ }
- z_cinfo = z_cmf >> 4;
- half_z_window_size = 1 << (z_cinfo + 7);
+ /* Compress the data */
+ ret = deflate(&png_ptr->zstream,
+ input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
- while (uncompressed_text_size <= half_z_window_size &&
- half_z_window_size >= 256)
- {
- z_cinfo--;
- half_z_window_size >>= 1;
- }
+ /* Claw back input data that was not consumed (because avail_in is
+ * reset above every time round the loop).
+ */
+ input_len += png_ptr->zstream.avail_in;
+ png_ptr->zstream.avail_in = 0; /* safety */
+ }
+ while (ret == Z_OK);
- z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
+ /* There may be some space left in the last output buffer. This needs to
+ * be subtracted from output_len.
+ */
+ output_len -= png_ptr->zstream.avail_out;
+ png_ptr->zstream.avail_out = 0; /* safety */
+ comp->output_len = output_len;
- if (comp->num_output_ptr)
- {
+ /* Now double check the output length, put in a custom message if it is
+ * too long. Otherwise ensure the z_stream::msg pointer is set to
+ * something.
+ */
+ if (output_len + prefix_len >= PNG_UINT_31_MAX)
+ {
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long");
+ ret = Z_MEM_ERROR;
+ }
- if (comp->output_ptr[0][0] != z_cmf)
- {
- int tmp;
+ else
+ png_zstream_error(png_ptr, ret);
- comp->output_ptr[0][0] = (png_byte)z_cmf;
- tmp = comp->output_ptr[0][1] & 0xe0;
- tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
- comp->output_ptr[0][1] = (png_byte)tmp;
- }
- }
- else
- {
- int tmp;
+ /* Reset zlib for another zTXt/iTXt or image data */
+ png_ptr->zowner = 0;
- png_ptr->zbuf[0] = (png_byte)z_cmf;
- tmp = png_ptr->zbuf[1] & 0xe0;
- tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
- png_ptr->zbuf[1] = (png_byte)tmp;
- }
+ /* The only success case is Z_STREAM_END, input_len must be 0; if not this
+ * is an internal error.
+ */
+ if (ret == Z_STREAM_END && input_len == 0)
+ {
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ /* Fix up the deflate header, if required */
+ optimize_cmf(comp->output, comp->input_len);
+#endif
+ /* But Z_OK is returned, not Z_STREAM_END; this allows the claim
+ * function above to return Z_STREAM_END on an error (though it never
+ * does in the current versions of zlib.)
+ */
+ return Z_OK;
}
else
- png_error(png_ptr,
- "Invalid zlib compression method or flags in non-IDAT chunk");
+ return ret;
}
-#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
+}
- /* Write saved output buffers, if any */
- for (i = 0; i < comp->num_output_ptr; i++)
+/* Ship the compressed text out via chunk writes */
+static void
+png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
+{
+ png_uint_32 output_len = comp->output_len;
+ png_const_bytep output = comp->output;
+ png_uint_32 avail = (sizeof comp->output);
+ png_compression_buffer *next = png_ptr->zbuffer_list;
+
+ for (;;)
{
- png_write_chunk_data(png_ptr, comp->output_ptr[i],
- (png_size_t)png_ptr->zbuf_size);
+ if (avail > output_len)
+ avail = output_len;
- png_free(png_ptr, comp->output_ptr[i]);
- }
+ png_write_chunk_data(png_ptr, output, avail);
- if (comp->max_output_ptr != 0)
- png_free(png_ptr, comp->output_ptr);
+ output_len -= avail;
- /* Write anything left in zbuf */
- if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
- png_write_chunk_data(png_ptr, png_ptr->zbuf,
- (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
+ if (output_len == 0 || next == NULL)
+ break;
- /* Reset zlib for another zTXt/iTXt or image data */
- png_zlib_release(png_ptr);
+ avail = png_ptr->zbuffer_size;
+ output = next->output;
+ next = next->next;
+ }
+
+ /* This is an internal error; 'next' must have been NULL! */
+ if (output_len > 0)
+ png_error(png_ptr, "error writing ancillary chunked compressed data");
}
-#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
+#endif /* WRITE_COMPRESSED_TEXT */
/* Write the IHDR chunk, and update the png_struct with the necessary
* information. Note that the rest of this code depends upon this
* information being correct.
*/
void /* PRIVATE */
-png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
+png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
int bit_depth, int color_type, int compression_type, int filter_type,
int interlace_type)
{
@@ -767,8 +764,8 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
*/
if (
#ifdef PNG_MNG_FEATURES_SUPPORTED
- !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
- ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
+ !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
+ ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
(color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
(filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
@@ -790,7 +787,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
interlace_type=PNG_INTERLACE_NONE;
#endif
- /* Save the relevent information */
+ /* Save the relevant information */
png_ptr->bit_depth = (png_byte)bit_depth;
png_ptr->color_type = (png_byte)color_type;
png_ptr->interlaced = (png_byte)interlace_type;
@@ -820,12 +817,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
/* Write the chunk */
png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
- /* Initialize zlib with PNG info */
- png_ptr->zstream.zalloc = png_zalloc;
- png_ptr->zstream.zfree = png_zfree;
- png_ptr->zstream.opaque = (voidpf)png_ptr;
-
- if (!(png_ptr->do_filter))
+ if ((png_ptr->do_filter) == PNG_NO_FILTERS)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
png_ptr->bit_depth < 8)
@@ -835,55 +827,6 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
png_ptr->do_filter = PNG_ALL_FILTERS;
}
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
- {
- if (png_ptr->do_filter != PNG_FILTER_NONE)
- png_ptr->zlib_strategy = Z_FILTERED;
-
- else
- png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
- }
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
- png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
- png_ptr->zlib_mem_level = 8;
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
- png_ptr->zlib_window_bits = 15;
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
- png_ptr->zlib_method = 8;
-
-#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
-#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY))
- png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL))
- png_ptr->zlib_text_level = png_ptr->zlib_level;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL))
- png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS))
- png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD))
- png_ptr->zlib_text_method = png_ptr->zlib_method;
-#else
- png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
- png_ptr->zlib_text_level = png_ptr->zlib_level;
- png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
- png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
- png_ptr->zlib_text_method = png_ptr->zlib_method;
-#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
-#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
-
- /* Record that the compressor has not yet been initialized. */
- png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
-
png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
}
@@ -892,20 +835,23 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
* structure.
*/
void /* PRIVATE */
-png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
+png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
png_uint_32 num_pal)
{
- png_uint_32 i;
+ png_uint_32 max_palette_length, i;
png_const_colorp pal_ptr;
png_byte buf[3];
png_debug(1, "in png_write_PLTE");
+ max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
+ (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
+
if ((
#ifdef PNG_MNG_FEATURES_SUPPORTED
- !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
+ (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 &&
#endif
- num_pal == 0) || num_pal > 256)
+ num_pal == 0) || num_pal > max_palette_length)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
@@ -919,7 +865,7 @@ png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
}
}
- if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
png_warning(png_ptr,
"Ignoring request to write a PLTE chunk in grayscale PNG");
@@ -960,94 +906,165 @@ png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
png_ptr->mode |= PNG_HAVE_PLTE;
}
-/* Write an IDAT chunk */
+/* This is similar to png_text_compress, above, except that it does not require
+ * all of the data at once and, instead of buffering the compressed result,
+ * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out
+ * because it calls the write interface. As a result it does its own error
+ * reporting and does not return an error code. In the event of error it will
+ * just call png_error. The input data length may exceed 32-bits. The 'flush'
+ * parameter is exactly the same as that to deflate, with the following
+ * meanings:
+ *
+ * Z_NO_FLUSH: normal incremental output of compressed data
+ * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
+ * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
+ *
+ * The routine manages the acquire and release of the png_ptr->zstream by
+ * checking and (at the end) clearing png_ptr->zowner; it does some sanity
+ * checks on the 'mode' flags while doing this.
+ */
void /* PRIVATE */
-png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
+png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
+ png_alloc_size_t input_len, int flush)
{
- png_debug(1, "in png_write_IDAT");
+ if (png_ptr->zowner != png_IDAT)
+ {
+ /* First time. Ensure we have a temporary buffer for compression and
+ * trim the buffer list if it has more than one entry to free memory.
+ * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
+ * created at this point, but the check here is quick and safe.
+ */
+ if (png_ptr->zbuffer_list == NULL)
+ {
+ png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp,
+ png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
+ png_ptr->zbuffer_list->next = NULL;
+ }
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
- if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
- png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ else
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next);
+
+ /* It is a terminal error if we can't claim the zstream. */
+ if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
+
+ /* The output state is maintained in png_ptr->zstream, so it must be
+ * initialized here after the claim.
+ */
+ png_ptr->zstream.next_out = png_ptr->zbuffer_list->output;
+ png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
+ }
+
+ /* Now loop reading and writing until all the input is consumed or an error
+ * terminates the operation. The _out values are maintained across calls to
+ * this function, but the input must be reset each time.
+ */
+ png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
+ png_ptr->zstream.avail_in = 0; /* set below */
+ for (;;)
{
- /* Optimize the CMF field in the zlib stream. This hack of the zlib
- * stream is compliant to the stream specification.
+ int ret;
+
+ /* INPUT: from the row data */
+ uInt avail = ZLIB_IO_MAX;
+
+ if (avail > input_len)
+ avail = (uInt)input_len; /* safe because of the check */
+
+ png_ptr->zstream.avail_in = avail;
+ input_len -= avail;
+
+ ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush);
+
+ /* Include as-yet unconsumed input */
+ input_len += png_ptr->zstream.avail_in;
+ png_ptr->zstream.avail_in = 0;
+
+ /* OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note
+ * that these two zstream fields are preserved across the calls, therefore
+ * there is no need to set these up on entry to the loop.
*/
- unsigned int z_cmf = data[0]; /* zlib compression method and flags */
+ if (png_ptr->zstream.avail_out == 0)
+ {
+ png_bytep data = png_ptr->zbuffer_list->output;
+ uInt size = png_ptr->zbuffer_size;
- if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
+ /* Write an IDAT containing the data then reset the buffer. The
+ * first IDAT may need deflate header optimization.
+ */
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
+ png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ optimize_cmf(data, png_image_size(png_ptr));
+#endif
+
+ png_write_complete_chunk(png_ptr, png_IDAT, data, size);
+ png_ptr->mode |= PNG_HAVE_IDAT;
+
+ png_ptr->zstream.next_out = data;
+ png_ptr->zstream.avail_out = size;
+
+ /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
+ * the same flush parameter until it has finished output, for NO_FLUSH
+ * it doesn't matter.
+ */
+ if (ret == Z_OK && flush != Z_NO_FLUSH)
+ continue;
+ }
+
+ /* The order of these checks doesn't matter much; it just affects which
+ * possible error might be detected if multiple things go wrong at once.
+ */
+ if (ret == Z_OK) /* most likely return code! */
{
- /* Avoid memory underflows and multiplication overflows.
- *
- * The conditions below are practically always satisfied;
- * however, they still must be checked.
+ /* If all the input has been consumed then just return. If Z_FINISH
+ * was used as the flush parameter something has gone wrong if we get
+ * here.
*/
- if (length >= 2 &&
- png_ptr->height < 16384 && png_ptr->width < 16384)
+ if (input_len == 0)
{
- /* Compute the maximum possible length of the datastream */
+ if (flush == Z_FINISH)
+ png_error(png_ptr, "Z_OK on Z_FINISH with output space");
- /* Number of pixels, plus for each row a filter byte
- * and possibly a padding byte, so increase the maximum
- * size to account for these.
- */
- unsigned int z_cinfo;
- unsigned int half_z_window_size;
- png_uint_32 uncompressed_idat_size = png_ptr->height *
- ((png_ptr->width *
- png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
-
- /* If it's interlaced, each block of 8 rows is sent as up to
- * 14 rows, i.e., 6 additional rows, each with a filter byte
- * and possibly a padding byte
- */
- if (png_ptr->interlaced)
- uncompressed_idat_size += ((png_ptr->height + 7)/8) *
- (png_ptr->bit_depth < 8 ? 12 : 6);
+ return;
+ }
+ }
- z_cinfo = z_cmf >> 4;
- half_z_window_size = 1 << (z_cinfo + 7);
+ else if (ret == Z_STREAM_END && flush == Z_FINISH)
+ {
+ /* This is the end of the IDAT data; any pending output must be
+ * flushed. For small PNG files we may still be at the beginning.
+ */
+ png_bytep data = png_ptr->zbuffer_list->output;
+ uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out;
- while (uncompressed_idat_size <= half_z_window_size &&
- half_z_window_size >= 256)
- {
- z_cinfo--;
- half_z_window_size >>= 1;
- }
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
+ png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ optimize_cmf(data, png_image_size(png_ptr));
+#endif
- z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
+ png_write_complete_chunk(png_ptr, png_IDAT, data, size);
+ png_ptr->zstream.avail_out = 0;
+ png_ptr->zstream.next_out = NULL;
+ png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
- if (data[0] != z_cmf)
- {
- int tmp;
- data[0] = (png_byte)z_cmf;
- tmp = data[1] & 0xe0;
- tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
- data[1] = (png_byte)tmp;
- }
- }
+ png_ptr->zowner = 0; /* Release the stream */
+ return;
}
else
- png_error(png_ptr,
- "Invalid zlib compression method or flags in IDAT");
+ {
+ /* This is an error condition. */
+ png_zstream_error(png_ptr, ret);
+ png_error(png_ptr, png_ptr->zstream.msg);
+ }
}
-#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
-
- png_write_complete_chunk(png_ptr, png_IDAT, data, length);
- png_ptr->mode |= PNG_HAVE_IDAT;
-
- /* Prior to 1.5.4 this code was replicated in every caller (except at the
- * end, where it isn't technically necessary). Since this function has
- * flushed the data we can safely reset the zlib output buffer here.
- */
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
}
/* Write an IEND chunk */
void /* PRIVATE */
-png_write_IEND(png_structp png_ptr)
+png_write_IEND(png_structrp png_ptr)
{
png_debug(1, "in png_write_IEND");
@@ -1058,7 +1075,7 @@ png_write_IEND(png_structp png_ptr)
#ifdef PNG_WRITE_gAMA_SUPPORTED
/* Write a gAMA chunk */
void /* PRIVATE */
-png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
+png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
{
png_byte buf[4];
@@ -1073,7 +1090,7 @@ png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
#ifdef PNG_WRITE_sRGB_SUPPORTED
/* Write a sRGB chunk */
void /* PRIVATE */
-png_write_sRGB(png_structp png_ptr, int srgb_intent)
+png_write_sRGB(png_structrp png_ptr, int srgb_intent)
{
png_byte buf[1];
@@ -1091,95 +1108,72 @@ png_write_sRGB(png_structp png_ptr, int srgb_intent)
#ifdef PNG_WRITE_iCCP_SUPPORTED
/* Write an iCCP chunk */
void /* PRIVATE */
-png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
- png_const_charp profile, int profile_len)
+png_write_iCCP(png_structrp png_ptr, png_const_charp name,
+ png_const_bytep profile)
{
- png_size_t name_len;
- png_charp new_name;
+ png_uint_32 name_len;
+ png_uint_32 profile_len;
+ png_byte new_name[81]; /* 1 byte for the compression byte */
compression_state comp;
- int embedded_profile_len = 0;
+ png_uint_32 temp;
png_debug(1, "in png_write_iCCP");
- comp.num_output_ptr = 0;
- comp.max_output_ptr = 0;
- comp.output_ptr = NULL;
- comp.input = NULL;
- comp.input_len = 0;
-
- if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0)
- return;
-
- if (compression_type != PNG_COMPRESSION_TYPE_BASE)
- png_warning(png_ptr, "Unknown compression type in iCCP chunk");
-
+ /* These are all internal problems: the profile should have been checked
+ * before when it was stored.
+ */
if (profile == NULL)
- profile_len = 0;
+ png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */
- if (profile_len > 3)
- embedded_profile_len =
- ((*( (png_const_bytep)profile ))<<24) |
- ((*( (png_const_bytep)profile + 1))<<16) |
- ((*( (png_const_bytep)profile + 2))<< 8) |
- ((*( (png_const_bytep)profile + 3)) );
+ profile_len = png_get_uint_32(profile);
- if (embedded_profile_len < 0)
- {
- png_warning(png_ptr,
- "Embedded profile length in iCCP chunk is negative");
+ if (profile_len < 132)
+ png_error(png_ptr, "ICC profile too short");
- png_free(png_ptr, new_name);
- return;
- }
+ temp = (png_uint_32) (*(profile+8));
+ if (temp > 3 && (profile_len & 0x03))
+ png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
- if (profile_len < embedded_profile_len)
{
- png_warning(png_ptr,
- "Embedded profile length too large in iCCP chunk");
+ png_uint_32 embedded_profile_len = png_get_uint_32(profile);
- png_free(png_ptr, new_name);
- return;
+ if (profile_len != embedded_profile_len)
+ png_error(png_ptr, "Profile length does not match profile");
}
- if (profile_len > embedded_profile_len)
- {
- png_warning(png_ptr,
- "Truncating profile to actual length in iCCP chunk");
+ name_len = png_check_keyword(png_ptr, name, new_name);
- profile_len = embedded_profile_len;
- }
+ if (name_len == 0)
+ png_error(png_ptr, "iCCP: invalid keyword");
- if (profile_len)
- profile_len = png_text_compress(png_ptr, profile,
- (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
+ new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
/* Make sure we include the NULL after the name and the compression type */
- png_write_chunk_header(png_ptr, png_iCCP,
- (png_uint_32)(name_len + profile_len + 2));
+ ++name_len;
- new_name[name_len + 1] = 0x00;
+ png_text_compress_init(&comp, profile, profile_len);
- png_write_chunk_data(png_ptr, (png_bytep)new_name,
- (png_size_t)(name_len + 2));
+ /* Allow for keyword terminator and compression byte */
+ if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
- if (profile_len)
- {
- comp.input_len = profile_len;
- png_write_compressed_data_out(png_ptr, &comp);
- }
+ png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
+
+ png_write_chunk_data(png_ptr, new_name, name_len);
+
+ png_write_compressed_data_out(png_ptr, &comp);
png_write_chunk_end(png_ptr);
- png_free(png_ptr, new_name);
}
#endif
#ifdef PNG_WRITE_sPLT_SUPPORTED
/* Write a sPLT chunk */
void /* PRIVATE */
-png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
+png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
{
- png_size_t name_len;
- png_charp new_name;
+ png_uint_32 name_len;
+ png_byte new_name[80];
png_byte entrybuf[10];
png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
png_size_t palette_size = entry_size * spalette->nentries;
@@ -1190,8 +1184,10 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_debug(1, "in png_write_sPLT");
- if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
- return;
+ name_len = png_check_keyword(png_ptr, spalette->name, new_name);
+
+ if (name_len == 0)
+ png_error(png_ptr, "sPLT: invalid keyword");
/* Make sure we include the NULL after the name */
png_write_chunk_header(png_ptr, png_sPLT,
@@ -1224,7 +1220,7 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_save_uint_16(entrybuf + 8, ep->frequency);
}
- png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+ png_write_chunk_data(png_ptr, entrybuf, entry_size);
}
#else
ep=spalette->entries;
@@ -1248,19 +1244,18 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_save_uint_16(entrybuf + 8, ep[i].frequency);
}
- png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+ png_write_chunk_data(png_ptr, entrybuf, entry_size);
}
#endif
png_write_chunk_end(png_ptr);
- png_free(png_ptr, new_name);
}
#endif
#ifdef PNG_WRITE_sBIT_SUPPORTED
/* Write the sBIT chunk */
void /* PRIVATE */
-png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
+png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
{
png_byte buf[4];
png_size_t size;
@@ -1268,7 +1263,7 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
png_debug(1, "in png_write_sBIT");
/* Make sure we don't depend upon the order of PNG_COLOR_8 */
- if (color_type & PNG_COLOR_MASK_COLOR)
+ if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_byte maxbits;
@@ -1301,7 +1296,7 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
size = 1;
}
- if (color_type & PNG_COLOR_MASK_ALPHA)
+ if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
{
@@ -1319,42 +1314,33 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
#ifdef PNG_WRITE_cHRM_SUPPORTED
/* Write the cHRM chunk */
void /* PRIVATE */
-png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
- png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
- png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
- png_fixed_point blue_y)
+png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
{
png_byte buf[32];
png_debug(1, "in png_write_cHRM");
/* Each value is saved in 1/100,000ths */
-#ifdef PNG_CHECK_cHRM_SUPPORTED
- if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
- green_x, green_y, blue_x, blue_y))
-#endif
- {
- png_save_uint_32(buf, (png_uint_32)white_x);
- png_save_uint_32(buf + 4, (png_uint_32)white_y);
+ png_save_int_32(buf, xy->whitex);
+ png_save_int_32(buf + 4, xy->whitey);
- png_save_uint_32(buf + 8, (png_uint_32)red_x);
- png_save_uint_32(buf + 12, (png_uint_32)red_y);
+ png_save_int_32(buf + 8, xy->redx);
+ png_save_int_32(buf + 12, xy->redy);
- png_save_uint_32(buf + 16, (png_uint_32)green_x);
- png_save_uint_32(buf + 20, (png_uint_32)green_y);
+ png_save_int_32(buf + 16, xy->greenx);
+ png_save_int_32(buf + 20, xy->greeny);
- png_save_uint_32(buf + 24, (png_uint_32)blue_x);
- png_save_uint_32(buf + 28, (png_uint_32)blue_y);
+ png_save_int_32(buf + 24, xy->bluex);
+ png_save_int_32(buf + 28, xy->bluey);
- png_write_complete_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
- }
+ png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
}
#endif
#ifdef PNG_WRITE_tRNS_SUPPORTED
/* Write the tRNS chunk */
void /* PRIVATE */
-png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
+png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
png_const_color_16p tran, int num_trans, int color_type)
{
png_byte buf[6];
@@ -1365,20 +1351,22 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
{
if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
{
- png_warning(png_ptr, "Invalid number of transparent colors specified");
+ png_app_warning(png_ptr,
+ "Invalid number of transparent colors specified");
return;
}
/* Write the chunk out as it is */
- png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans);
+ png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
+ (png_size_t)num_trans);
}
else if (color_type == PNG_COLOR_TYPE_GRAY)
{
- /* One 16 bit value */
+ /* One 16-bit value */
if (tran->gray >= (1 << png_ptr->bit_depth))
{
- png_warning(png_ptr,
+ png_app_warning(png_ptr,
"Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
return;
@@ -1390,17 +1378,17 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
else if (color_type == PNG_COLOR_TYPE_RGB)
{
- /* Three 16 bit values */
+ /* Three 16-bit values */
png_save_uint_16(buf, tran->red);
png_save_uint_16(buf + 2, tran->green);
png_save_uint_16(buf + 4, tran->blue);
#ifdef PNG_WRITE_16BIT_SUPPORTED
- if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+ if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
#else
- if (buf[0] | buf[2] | buf[4])
+ if ((buf[0] | buf[2] | buf[4]) != 0)
#endif
{
- png_warning(png_ptr,
+ png_app_warning(png_ptr,
"Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
return;
}
@@ -1410,7 +1398,7 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
else
{
- png_warning(png_ptr, "Can't write tRNS with an alpha channel");
+ png_app_warning(png_ptr, "Can't write tRNS with an alpha channel");
}
}
#endif
@@ -1418,7 +1406,7 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
#ifdef PNG_WRITE_bKGD_SUPPORTED
/* Write the background chunk */
void /* PRIVATE */
-png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
+png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
{
png_byte buf[6];
@@ -1428,8 +1416,8 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
{
if (
#ifdef PNG_MNG_FEATURES_SUPPORTED
- (png_ptr->num_palette ||
- (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
+ (png_ptr->num_palette != 0 ||
+ (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
#endif
back->index >= png_ptr->num_palette)
{
@@ -1441,15 +1429,15 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
}
- else if (color_type & PNG_COLOR_MASK_COLOR)
+ else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_save_uint_16(buf, back->red);
png_save_uint_16(buf + 2, back->green);
png_save_uint_16(buf + 4, back->blue);
#ifdef PNG_WRITE_16BIT_SUPPORTED
- if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+ if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
#else
- if (buf[0] | buf[2] | buf[4])
+ if ((buf[0] | buf[2] | buf[4]) != 0)
#endif
{
png_warning(png_ptr,
@@ -1480,7 +1468,7 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
#ifdef PNG_WRITE_hIST_SUPPORTED
/* Write the histogram */
void /* PRIVATE */
-png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
+png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
{
int i;
png_byte buf[3];
@@ -1508,234 +1496,93 @@ png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
}
#endif
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
- defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
- * and if invalid, correct the keyword rather than discarding the entire
- * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
- * length, forbids leading or trailing whitespace, multiple internal spaces,
- * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
- *
- * The new_key is allocated to hold the corrected keyword and must be freed
- * by the calling routine. This avoids problems with trying to write to
- * static keywords without having to have duplicate copies of the strings.
- */
-png_size_t /* PRIVATE */
-png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key)
-{
- png_size_t key_len;
- png_const_charp ikp;
- png_charp kp, dp;
- int kflag;
- int kwarn=0;
-
- png_debug(1, "in png_check_keyword");
-
- *new_key = NULL;
-
- if (key == NULL || (key_len = png_strlen(key)) == 0)
- {
- png_warning(png_ptr, "zero length keyword");
- return ((png_size_t)0);
- }
-
- png_debug1(2, "Keyword to be checked is '%s'", key);
-
- *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
-
- if (*new_key == NULL)
- {
- png_warning(png_ptr, "Out of memory while procesing keyword");
- return ((png_size_t)0);
- }
-
- /* Replace non-printing characters with a blank and print a warning */
- for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++)
- {
- if ((png_byte)*ikp < 0x20 ||
- ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1))
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x,
- (png_byte)*ikp);
- png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1");
- *dp = ' ';
- }
-
- else
- {
- *dp = *ikp;
- }
- }
- *dp = '\0';
-
- /* Remove any trailing white space. */
- kp = *new_key + key_len - 1;
- if (*kp == ' ')
- {
- png_warning(png_ptr, "trailing spaces removed from keyword");
-
- while (*kp == ' ')
- {
- *(kp--) = '\0';
- key_len--;
- }
- }
-
- /* Remove any leading white space. */
- kp = *new_key;
- if (*kp == ' ')
- {
- png_warning(png_ptr, "leading spaces removed from keyword");
-
- while (*kp == ' ')
- {
- kp++;
- key_len--;
- }
- }
-
- png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
-
- /* Remove multiple internal spaces. */
- for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
- {
- if (*kp == ' ' && kflag == 0)
- {
- *(dp++) = *kp;
- kflag = 1;
- }
-
- else if (*kp == ' ')
- {
- key_len--;
- kwarn = 1;
- }
-
- else
- {
- *(dp++) = *kp;
- kflag = 0;
- }
- }
- *dp = '\0';
- if (kwarn)
- png_warning(png_ptr, "extra interior spaces removed from keyword");
-
- if (key_len == 0)
- {
- png_free(png_ptr, *new_key);
- png_warning(png_ptr, "Zero length keyword");
- }
-
- if (key_len > 79)
- {
- png_warning(png_ptr, "keyword length must be 1 - 79 characters");
- (*new_key)[79] = '\0';
- key_len = 79;
- }
-
- return (key_len);
-}
-#endif
-
#ifdef PNG_WRITE_tEXt_SUPPORTED
/* Write a tEXt chunk */
void /* PRIVATE */
-png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
+png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
png_size_t text_len)
{
- png_size_t key_len;
- png_charp new_key;
+ png_uint_32 key_len;
+ png_byte new_key[80];
png_debug(1, "in png_write_tEXt");
- if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
- return;
+ key_len = png_check_keyword(png_ptr, key, new_key);
+
+ if (key_len == 0)
+ png_error(png_ptr, "tEXt: invalid keyword");
if (text == NULL || *text == '\0')
text_len = 0;
else
- text_len = png_strlen(text);
+ text_len = strlen(text);
+
+ if (text_len > PNG_UINT_31_MAX - (key_len+1))
+ png_error(png_ptr, "tEXt: text too long");
/* Make sure we include the 0 after the key */
png_write_chunk_header(png_ptr, png_tEXt,
- (png_uint_32)(key_len + text_len + 1));
+ (png_uint_32)/*checked above*/(key_len + text_len + 1));
/*
* We leave it to the application to meet PNG-1.0 requirements on the
* contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
* any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
* The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
*/
- png_write_chunk_data(png_ptr, (png_bytep)new_key,
- (png_size_t)(key_len + 1));
+ png_write_chunk_data(png_ptr, new_key, key_len + 1);
- if (text_len)
- png_write_chunk_data(png_ptr, (png_const_bytep)text,
- (png_size_t)text_len);
+ if (text_len != 0)
+ png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
png_write_chunk_end(png_ptr);
- png_free(png_ptr, new_key);
}
#endif
#ifdef PNG_WRITE_zTXt_SUPPORTED
/* Write a compressed text chunk */
void /* PRIVATE */
-png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
- png_size_t text_len, int compression)
+png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
+ int compression)
{
- png_size_t key_len;
- png_byte buf;
- png_charp new_key;
+ png_uint_32 key_len;
+ png_byte new_key[81];
compression_state comp;
png_debug(1, "in png_write_zTXt");
- comp.num_output_ptr = 0;
- comp.max_output_ptr = 0;
- comp.output_ptr = NULL;
- comp.input = NULL;
- comp.input_len = 0;
-
- if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
+ if (compression == PNG_TEXT_COMPRESSION_NONE)
{
- png_free(png_ptr, new_key);
+ png_write_tEXt(png_ptr, key, text, 0);
return;
}
- if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
- {
- png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
- png_free(png_ptr, new_key);
- return;
- }
+ if (compression != PNG_TEXT_COMPRESSION_zTXt)
+ png_error(png_ptr, "zTXt: invalid compression type");
- text_len = png_strlen(text);
+ key_len = png_check_keyword(png_ptr, key, new_key);
- /* Compute the compressed data; do it now for the length */
- text_len = png_text_compress(png_ptr, text, text_len, compression,
- &comp);
+ if (key_len == 0)
+ png_error(png_ptr, "zTXt: invalid keyword");
- /* Write start of chunk */
- png_write_chunk_header(png_ptr, png_zTXt,
- (png_uint_32)(key_len+text_len + 2));
+ /* Add the compression method and 1 for the keyword separator. */
+ new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
+ ++key_len;
- /* Write key */
- png_write_chunk_data(png_ptr, (png_bytep)new_key,
- (png_size_t)(key_len + 1));
+ /* Compute the compressed data; do it now for the length */
+ png_text_compress_init(&comp, (png_const_bytep)text,
+ text == NULL ? 0 : strlen(text));
- png_free(png_ptr, new_key);
+ if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
- buf = (png_byte)compression;
+ /* Write start of chunk */
+ png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
- /* Write compression */
- png_write_chunk_data(png_ptr, &buf, (png_size_t)1);
+ /* Write key */
+ png_write_chunk_data(png_ptr, new_key, key_len);
/* Write the compressed data */
- comp.input_len = text_len;
png_write_compressed_data_out(png_ptr, &comp);
/* Close the chunk */
@@ -1746,100 +1593,107 @@ png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
#ifdef PNG_WRITE_iTXt_SUPPORTED
/* Write an iTXt chunk */
void /* PRIVATE */
-png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
+png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
png_const_charp lang, png_const_charp lang_key, png_const_charp text)
{
- png_size_t lang_len, key_len, lang_key_len, text_len;
- png_charp new_lang;
- png_charp new_key = NULL;
- png_byte cbuf[2];
+ png_uint_32 key_len, prefix_len;
+ png_size_t lang_len, lang_key_len;
+ png_byte new_key[82];
compression_state comp;
png_debug(1, "in png_write_iTXt");
- comp.num_output_ptr = 0;
- comp.max_output_ptr = 0;
- comp.output_ptr = NULL;
- comp.input = NULL;
+ key_len = png_check_keyword(png_ptr, key, new_key);
- if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
- return;
+ if (key_len == 0)
+ png_error(png_ptr, "iTXt: invalid keyword");
- if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0)
+ /* Set the compression flag */
+ switch (compression)
{
- png_warning(png_ptr, "Empty language field in iTXt chunk");
- new_lang = NULL;
- lang_len = 0;
- }
+ case PNG_ITXT_COMPRESSION_NONE:
+ case PNG_TEXT_COMPRESSION_NONE:
+ compression = new_key[++key_len] = 0; /* no compression */
+ break;
- if (lang_key == NULL)
- lang_key_len = 0;
+ case PNG_TEXT_COMPRESSION_zTXt:
+ case PNG_ITXT_COMPRESSION_zTXt:
+ compression = new_key[++key_len] = 1; /* compressed */
+ break;
- else
- lang_key_len = png_strlen(lang_key);
+ default:
+ png_error(png_ptr, "iTXt: invalid compression");
+ }
- if (text == NULL)
- text_len = 0;
+ new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
+ ++key_len; /* for the keywod separator */
+ /* We leave it to the application to meet PNG-1.0 requirements on the
+ * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
+ * any non-Latin-1 characters except for NEWLINE. ISO PNG, however,
+ * specifies that the text is UTF-8 and this really doesn't require any
+ * checking.
+ *
+ * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
+ *
+ * TODO: validate the language tag correctly (see the spec.)
+ */
+ if (lang == NULL) lang = ""; /* empty language is valid */
+ lang_len = strlen(lang)+1;
+ if (lang_key == NULL) lang_key = ""; /* may be empty */
+ lang_key_len = strlen(lang_key)+1;
+ if (text == NULL) text = ""; /* may be empty */
+
+ prefix_len = key_len;
+ if (lang_len > PNG_UINT_31_MAX-prefix_len)
+ prefix_len = PNG_UINT_31_MAX;
else
- text_len = png_strlen(text);
-
- /* Compute the compressed data; do it now for the length */
- text_len = png_text_compress(png_ptr, text, text_len, compression - 2,
- &comp);
+ prefix_len = (png_uint_32)(prefix_len + lang_len);
+ if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
+ prefix_len = PNG_UINT_31_MAX;
+ else
+ prefix_len = (png_uint_32)(prefix_len + lang_key_len);
- /* Make sure we include the compression flag, the compression byte,
- * and the NULs after the key, lang, and lang_key parts
- */
+ png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
- png_write_chunk_header(png_ptr, png_iTXt, (png_uint_32)(
- 5 /* comp byte, comp flag, terminators for key, lang and lang_key */
- + key_len
- + lang_len
- + lang_key_len
- + text_len));
+ if (compression != 0)
+ {
+ if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
+ }
- /* We leave it to the application to meet PNG-1.0 requirements on the
- * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
- * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
- * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
- */
- png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1));
+ else
+ {
+ if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
+ png_error(png_ptr, "iTXt: uncompressed text too long");
- /* Set the compression flag */
- if (compression == PNG_ITXT_COMPRESSION_NONE ||
- compression == PNG_TEXT_COMPRESSION_NONE)
- cbuf[0] = 0;
+ /* So the string will fit in a chunk: */
+ comp.output_len = (png_uint_32)/*SAFE*/comp.input_len;
+ }
- else /* compression == PNG_ITXT_COMPRESSION_zTXt */
- cbuf[0] = 1;
+ png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
- /* Set the compression method */
- cbuf[1] = 0;
+ png_write_chunk_data(png_ptr, new_key, key_len);
- png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
+ png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
- cbuf[0] = 0;
- png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf),
- (png_size_t)(lang_len + 1));
+ png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
- png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf),
- (png_size_t)(lang_key_len + 1));
+ if (compression != 0)
+ png_write_compressed_data_out(png_ptr, &comp);
- png_write_compressed_data_out(png_ptr, &comp);
+ else
+ png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len);
png_write_chunk_end(png_ptr);
-
- png_free(png_ptr, new_key);
- png_free(png_ptr, new_lang);
}
#endif
#ifdef PNG_WRITE_oFFs_SUPPORTED
/* Write the oFFs chunk */
void /* PRIVATE */
-png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
+png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
int unit_type)
{
png_byte buf[9];
@@ -1859,36 +1713,43 @@ png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
#ifdef PNG_WRITE_pCAL_SUPPORTED
/* Write the pCAL chunk (described in the PNG extensions document) */
void /* PRIVATE */
-png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
+png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
png_int_32 X1, int type, int nparams, png_const_charp units,
png_charpp params)
{
- png_size_t purpose_len, units_len, total_len;
+ png_uint_32 purpose_len;
+ png_size_t units_len, total_len;
png_size_tp params_len;
png_byte buf[10];
- png_charp new_purpose;
+ png_byte new_purpose[80];
int i;
png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
if (type >= PNG_EQUATION_LAST)
- png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+ png_error(png_ptr, "Unrecognized equation type for pCAL chunk");
+
+ purpose_len = png_check_keyword(png_ptr, purpose, new_purpose);
+
+ if (purpose_len == 0)
+ png_error(png_ptr, "pCAL: invalid keyword");
+
+ ++purpose_len; /* terminator */
- purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
- units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
+ units_len = strlen(units) + (nparams == 0 ? 0 : 1);
png_debug1(3, "pCAL units length = %d", (int)units_len);
total_len = purpose_len + units_len + 10;
params_len = (png_size_tp)png_malloc(png_ptr,
- (png_alloc_size_t)(nparams * png_sizeof(png_size_t)));
+ (png_alloc_size_t)(nparams * (sizeof (png_size_t))));
/* Find the length of each parameter, making sure we don't count the
* null terminator for the last parameter.
*/
for (i = 0; i < nparams; i++)
{
- params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
+ params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
png_debug2(3, "pCAL parameter %d length = %lu", i,
(unsigned long)params_len[i]);
total_len += params_len[i];
@@ -1896,7 +1757,7 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
png_debug1(3, "pCAL total length = %d", (int)total_len);
png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
- png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, purpose_len);
+ png_write_chunk_data(png_ptr, new_purpose, purpose_len);
png_save_int_32(buf, X0);
png_save_int_32(buf + 4, X1);
buf[8] = (png_byte)type;
@@ -1904,8 +1765,6 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
png_write_chunk_data(png_ptr, buf, (png_size_t)10);
png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
- png_free(png_ptr, new_purpose);
-
for (i = 0; i < nparams; i++)
{
png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
@@ -1919,7 +1778,7 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
#ifdef PNG_WRITE_sCAL_SUPPORTED
/* Write the sCAL chunk */
void /* PRIVATE */
-png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
+png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
png_const_charp height)
{
png_byte buf[64];
@@ -1927,8 +1786,8 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
png_debug(1, "in png_write_sCAL_s");
- wlen = png_strlen(width);
- hlen = png_strlen(height);
+ wlen = strlen(width);
+ hlen = strlen(height);
total_len = wlen + hlen + 2;
if (total_len > 64)
@@ -1938,8 +1797,8 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
}
buf[0] = (png_byte)unit;
- png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */
- png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */
+ memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */
+ memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */
png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
@@ -1949,7 +1808,7 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
#ifdef PNG_WRITE_pHYs_SUPPORTED
/* Write the pHYs chunk */
void /* PRIVATE */
-png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
+png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
png_uint_32 y_pixels_per_unit,
int unit_type)
{
@@ -1973,7 +1832,7 @@ png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
* or png_convert_from_time_t(), or fill in the structure yourself.
*/
void /* PRIVATE */
-png_write_tIME(png_structp png_ptr, png_const_timep mod_time)
+png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
{
png_byte buf[7];
@@ -2000,7 +1859,7 @@ png_write_tIME(png_structp png_ptr, png_const_timep mod_time)
/* Initializes the row writing capability of libpng */
void /* PRIVATE */
-png_write_start_row(png_structp png_ptr)
+png_write_start_row(png_structrp png_ptr)
{
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
@@ -2021,6 +1880,10 @@ png_write_start_row(png_structp png_ptr)
png_alloc_size_t buf_size;
int usr_pixel_depth;
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+ png_byte filters;
+#endif
+
png_debug(1, "in png_write_start_row");
usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
@@ -2031,56 +1894,61 @@ png_write_start_row(png_structp png_ptr)
png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
/* Set up row buffer */
- png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
+ png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
#ifdef PNG_WRITE_FILTER_SUPPORTED
- /* Set up filtering buffer, if using this filter */
- if (png_ptr->do_filter & PNG_FILTER_SUB)
- {
- png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
+ filters = png_ptr->do_filter;
- png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
- }
+ if (png_ptr->height == 1)
+ filters &= 0xff & ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
+
+ if (png_ptr->width == 1)
+ filters &= 0xff & ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
+
+ if (filters == 0)
+ filters = PNG_FILTER_NONE;
- /* We only need to keep the previous row if we are using one of these. */
- if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
+ png_ptr->do_filter = filters;
+
+ if (((filters & (PNG_FILTER_SUB | PNG_FILTER_UP | PNG_FILTER_AVG |
+ PNG_FILTER_PAETH)) != 0) && png_ptr->try_row == NULL)
{
- /* Set up previous row buffer */
- png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
+ int num_filters = 0;
- if (png_ptr->do_filter & PNG_FILTER_UP)
- {
- png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
- png_ptr->rowbytes + 1);
+ png_ptr->try_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
- png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
- }
+ if (filters & PNG_FILTER_SUB)
+ num_filters++;
- if (png_ptr->do_filter & PNG_FILTER_AVG)
- {
- png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
- png_ptr->rowbytes + 1);
+ if (filters & PNG_FILTER_UP)
+ num_filters++;
- png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
- }
+ if (filters & PNG_FILTER_AVG)
+ num_filters++;
- if (png_ptr->do_filter & PNG_FILTER_PAETH)
- {
- png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
- png_ptr->rowbytes + 1);
+ if (filters & PNG_FILTER_PAETH)
+ num_filters++;
- png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
- }
+ if (num_filters > 1)
+ png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr,
+ buf_size));
}
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+
+ /* We only need to keep the previous row if we are using one of the following
+ * filters.
+ */
+ if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0)
+ png_ptr->prev_row = png_voidcast(png_bytep,
+ png_calloc(png_ptr, buf_size));
+#endif /* WRITE_FILTER */
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced, we need to set up width and height of pass */
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
- if (!(png_ptr->transformations & PNG_INTERLACE))
+ if ((png_ptr->transformations & PNG_INTERLACE) == 0)
{
png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
png_pass_ystart[0]) / png_pass_yinc[0];
@@ -2102,15 +1970,11 @@ png_write_start_row(png_structp png_ptr)
png_ptr->num_rows = png_ptr->height;
png_ptr->usr_width = png_ptr->width;
}
-
- png_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT);
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_out = png_ptr->zbuf;
}
/* Internal use only. Called when finished processing a row of data. */
void /* PRIVATE */
-png_write_finish_row(png_structp png_ptr)
+png_write_finish_row(png_structrp png_ptr)
{
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
@@ -2128,8 +1992,6 @@ png_write_finish_row(png_structp png_ptr)
static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
- int ret;
-
png_debug(1, "in png_write_finish_row");
/* Next row */
@@ -2141,10 +2003,10 @@ png_write_finish_row(png_structp png_ptr)
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced, go to next pass */
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
png_ptr->row_number = 0;
- if (png_ptr->transformations & PNG_INTERLACE)
+ if ((png_ptr->transformations & PNG_INTERLACE) != 0)
{
png_ptr->pass++;
}
@@ -2169,7 +2031,7 @@ png_write_finish_row(png_structp png_ptr)
png_pass_ystart[png_ptr->pass]) /
png_pass_yinc[png_ptr->pass];
- if (png_ptr->transformations & PNG_INTERLACE)
+ if ((png_ptr->transformations & PNG_INTERLACE) != 0)
break;
} while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
@@ -2180,7 +2042,7 @@ png_write_finish_row(png_structp png_ptr)
if (png_ptr->pass < 7)
{
if (png_ptr->prev_row != NULL)
- png_memset(png_ptr->prev_row, 0,
+ memset(png_ptr->prev_row, 0,
(png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
png_ptr->usr_bit_depth, png_ptr->width)) + 1);
@@ -2191,42 +2053,7 @@ png_write_finish_row(png_structp png_ptr)
/* If we get here, we've just written the last row, so we need
to flush the compressor */
- do
- {
- /* Tell the compressor we are done */
- ret = deflate(&png_ptr->zstream, Z_FINISH);
-
- /* Check for an error */
- if (ret == Z_OK)
- {
- /* Check to see if we need more room */
- if (!(png_ptr->zstream.avail_out))
- {
- png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- }
- }
-
- else if (ret != Z_STREAM_END)
- {
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
-
- else
- png_error(png_ptr, "zlib error");
- }
- } while (ret != Z_STREAM_END);
-
- /* Write any extra space */
- if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
- {
- png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
- png_ptr->zstream.avail_out);
- }
-
- png_zlib_release(png_ptr);
- png_ptr->zstream.data_type = Z_BINARY;
+ png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
}
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
@@ -2260,7 +2087,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
{
png_bytep sp;
png_bytep dp;
- int shift;
+ unsigned int shift;
int d;
int value;
png_uint_32 i;
@@ -2298,7 +2125,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
{
png_bytep sp;
png_bytep dp;
- int shift;
+ unsigned int shift;
int d;
int value;
png_uint_32 i;
@@ -2335,7 +2162,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
{
png_bytep sp;
png_bytep dp;
- int shift;
+ unsigned int shift;
int d;
int value;
png_uint_32 i;
@@ -2390,7 +2217,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
/* Move the pixel */
if (dp != sp)
- png_memcpy(dp, sp, pixel_bytes);
+ memcpy(dp, sp, pixel_bytes);
/* Next pixel */
dp += pixel_bytes;
@@ -2410,49 +2237,181 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
}
#endif
+
/* This filters the row, chooses which filter to use, if it has not already
* been specified by the application, and then writes the row out with the
* chosen filter.
*/
-static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
+static void /* PRIVATE */
+png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
png_size_t row_bytes);
-#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
-#define PNG_HISHIFT 10
-#define PNG_LOMASK ((png_uint_32)0xffffL)
-#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+static png_size_t /* PRIVATE */
+png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp,
+ const png_size_t row_bytes, const png_size_t lmins)
+{
+ png_bytep rp, dp, lp;
+ png_size_t i;
+ png_size_t sum = 0;
+ int v;
+
+ png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
+
+ for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
+ i++, rp++, dp++)
+ {
+ v = *dp = *rp;
+ sum += (v < 128) ? v : 256 - v;
+ }
+
+ for (lp = png_ptr->row_buf + 1; i < row_bytes;
+ i++, rp++, lp++, dp++)
+ {
+ v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+ sum += (v < 128) ? v : 256 - v;
+
+ if (sum > lmins) /* We are already worse, don't continue. */
+ break;
+ }
+
+ return (sum);
+}
+
+static png_size_t /* PRIVATE */
+png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes,
+ const png_size_t lmins)
+{
+ png_bytep rp, dp, pp;
+ png_size_t i;
+ png_size_t sum = 0;
+ int v;
+
+ png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
+
+ for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
+ pp = png_ptr->prev_row + 1; i < row_bytes;
+ i++, rp++, pp++, dp++)
+ {
+ v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
+ sum += (v < 128) ? v : 256 - v;
+
+ if (sum > lmins) /* We are already worse, don't continue. */
+ break;
+ }
+
+ return (sum);
+}
+
+static png_size_t /* PRIVATE */
+png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
+ const png_size_t row_bytes, const png_size_t lmins)
+{
+ png_bytep rp, dp, pp, lp;
+ png_uint_32 i;
+ png_size_t sum = 0;
+ int v;
+
+ png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
+
+ for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
+ pp = png_ptr->prev_row + 1; i < bpp; i++)
+ {
+ v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+ }
+
+ for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
+ {
+ v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
+ & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+
+ if (sum > lmins) /* We are already worse, don't continue. */
+ break;
+ }
+
+ return (sum);
+}
+
+static png_size_t /* PRIVATE */
+png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
+ const png_size_t row_bytes, const png_size_t lmins)
+{
+ png_bytep rp, dp, pp, cp, lp;
+ png_size_t i;
+ png_size_t sum = 0;
+ int v;
+
+ png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
+
+ for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
+ pp = png_ptr->prev_row + 1; i < bpp; i++)
+ {
+ v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+ }
+
+ for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
+ i++)
+ {
+ int a, b, c, pa, pb, pc, p;
+
+ b = *pp++;
+ c = *cp++;
+ a = *lp++;
+
+ p = b - c;
+ pc = a - c;
+
+#ifdef PNG_USE_ABS
+ pa = abs(p);
+ pb = abs(pc);
+ pc = abs(p + pc);
+#else
+ pa = p < 0 ? -p : p;
+ pb = pc < 0 ? -pc : pc;
+ pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+ p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+
+ v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+
+ if (sum > lmins) /* We are already worse, don't continue. */
+ break;
+ }
+
+ return (sum);
+}
+#endif /* WRITE_FILTER */
+
void /* PRIVATE */
-png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
+png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
{
- png_bytep best_row;
-#ifdef PNG_WRITE_FILTER_SUPPORTED
- png_bytep prev_row, row_buf;
- png_uint_32 mins, bpp;
+#ifndef PNG_WRITE_FILTER_SUPPORTED
+ png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1);
+#else
png_byte filter_to_do = png_ptr->do_filter;
+ png_bytep row_buf;
+ png_bytep best_row;
+ png_uint_32 bpp;
+ png_size_t mins;
png_size_t row_bytes = row_info->rowbytes;
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- int num_p_filters = png_ptr->num_prev_filters;
-#endif
png_debug(1, "in png_write_find_filter");
-#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
- {
- /* These will never be selected so we need not test them. */
- filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
- }
-#endif
-
/* Find out how many bytes offset each pixel is */
bpp = (row_info->pixel_depth + 7) >> 3;
- prev_row = png_ptr->prev_row;
-#endif
- best_row = png_ptr->row_buf;
-#ifdef PNG_WRITE_FILTER_SUPPORTED
- row_buf = best_row;
- mins = PNG_MAXSUM;
+ row_buf = png_ptr->row_buf;
+ mins = PNG_SIZE_MAX - 256/* so we can detect potential overflow of the
+ running sum */;
/* The prediction method we use is to find which method provides the
* smallest value when summing the absolute values of the distances
@@ -2482,57 +2441,37 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
/* We don't need to test the 'no filter' case if this is the only filter
* that has been chosen, as it doesn't actually do anything to the data.
*/
- if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE)
+ best_row = png_ptr->row_buf;
+
+
+ if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE)
{
png_bytep rp;
- png_uint_32 sum = 0;
+ png_size_t sum = 0;
png_size_t i;
int v;
- for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
+ if (PNG_SIZE_MAX/128 <= row_bytes)
{
- v = *rp;
- sum += (v < 128) ? v : 256 - v;
- }
+ for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
+ {
+ /* Check for overflow */
+ if (sum > PNG_SIZE_MAX/128 - 256)
+ break;
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ v = *rp;
+ sum += (v < 128) ? v : 256 - v;
+ }
+ }
+ else /* Overflow is not possible */
{
- png_uint_32 sumhi, sumlo;
- int j;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
-
- /* Reduce the sum if we match any of the previous rows */
- for (j = 0; j < num_p_filters; j++)
+ for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
{
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
- {
- sumlo = (sumlo * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
+ v = *rp;
+ sum += (v < 128) ? v : 256 - v;
}
-
- /* Factor in the cost of this filter (this is here for completeness,
- * but it makes no sense to have a "cost" for the NONE filter, as
- * it has the minimum possible computational cost - none).
- */
- sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
- PNG_COST_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
- PNG_COST_SHIFT;
-
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
}
-#endif
+
mins = sum;
}
@@ -2540,620 +2479,125 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
if (filter_to_do == PNG_FILTER_SUB)
/* It's the only filter so no testing is needed */
{
- png_bytep rp, lp, dp;
- png_size_t i;
-
- for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
- i++, rp++, dp++)
- {
- *dp = *rp;
- }
-
- for (lp = row_buf + 1; i < row_bytes;
- i++, rp++, lp++, dp++)
- {
- *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
- }
-
- best_row = png_ptr->sub_row;
+ (void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins);
+ best_row = png_ptr->try_row;
}
- else if (filter_to_do & PNG_FILTER_SUB)
+ else if ((filter_to_do & PNG_FILTER_SUB) != 0)
{
- png_bytep rp, dp, lp;
- png_uint_32 sum = 0, lmins = mins;
- png_size_t i;
- int v;
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- /* We temporarily increase the "minimum sum" by the factor we
- * would reduce the sum of this filter, so that we can do the
- * early exit comparison without scaling the sum each time.
- */
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 lmhi, lmlo;
- lmlo = lmins & PNG_LOMASK;
- lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
- {
- lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
- PNG_COST_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
- PNG_COST_SHIFT;
-
- if (lmhi > PNG_HIMASK)
- lmins = PNG_MAXSUM;
-
- else
- lmins = (lmhi << PNG_HISHIFT) + lmlo;
- }
-#endif
-
- for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
- i++, rp++, dp++)
- {
- v = *dp = *rp;
+ png_size_t sum;
+ png_size_t lmins = mins;
- sum += (v < 128) ? v : 256 - v;
- }
-
- for (lp = row_buf + 1; i < row_bytes;
- i++, rp++, lp++, dp++)
- {
- v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
-
- sum += (v < 128) ? v : 256 - v;
-
- if (sum > lmins) /* We are already worse, don't continue. */
- break;
- }
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 sumhi, sumlo;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
- {
- sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
- PNG_COST_SHIFT;
-
- sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
- PNG_COST_SHIFT;
-
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
- }
-#endif
+ sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins);
if (sum < mins)
{
mins = sum;
- best_row = png_ptr->sub_row;
+ best_row = png_ptr->try_row;
+ if (png_ptr->tst_row != NULL)
+ {
+ png_ptr->try_row = png_ptr->tst_row;
+ png_ptr->tst_row = best_row;
+ }
}
}
/* Up filter */
if (filter_to_do == PNG_FILTER_UP)
{
- png_bytep rp, dp, pp;
- png_size_t i;
-
- for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
- pp = prev_row + 1; i < row_bytes;
- i++, rp++, pp++, dp++)
- {
- *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
- }
-
- best_row = png_ptr->up_row;
+ (void) png_setup_up_row(png_ptr, row_bytes, mins);
+ best_row = png_ptr->try_row;
}
- else if (filter_to_do & PNG_FILTER_UP)
+ else if ((filter_to_do & PNG_FILTER_UP) != 0)
{
- png_bytep rp, dp, pp;
- png_uint_32 sum = 0, lmins = mins;
- png_size_t i;
- int v;
-
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 lmhi, lmlo;
- lmlo = lmins & PNG_LOMASK;
- lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
- {
- lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
- PNG_COST_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
- PNG_COST_SHIFT;
-
- if (lmhi > PNG_HIMASK)
- lmins = PNG_MAXSUM;
-
- else
- lmins = (lmhi << PNG_HISHIFT) + lmlo;
- }
-#endif
-
- for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
- pp = prev_row + 1; i < row_bytes; i++)
- {
- v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
-
- sum += (v < 128) ? v : 256 - v;
-
- if (sum > lmins) /* We are already worse, don't continue. */
- break;
- }
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 sumhi, sumlo;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
- {
- sumlo = (sumlo * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
- PNG_COST_SHIFT;
+ png_size_t sum;
+ png_size_t lmins = mins;
- sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
- PNG_COST_SHIFT;
-
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
- }
-#endif
+ sum = png_setup_up_row(png_ptr, row_bytes, lmins);
if (sum < mins)
{
mins = sum;
- best_row = png_ptr->up_row;
+ best_row = png_ptr->try_row;
+ if (png_ptr->tst_row != NULL)
+ {
+ png_ptr->try_row = png_ptr->tst_row;
+ png_ptr->tst_row = best_row;
+ }
}
}
/* Avg filter */
if (filter_to_do == PNG_FILTER_AVG)
{
- png_bytep rp, dp, pp, lp;
- png_uint_32 i;
-
- for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
- pp = prev_row + 1; i < bpp; i++)
- {
- *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
- }
-
- for (lp = row_buf + 1; i < row_bytes; i++)
- {
- *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
- & 0xff);
- }
- best_row = png_ptr->avg_row;
+ (void) png_setup_avg_row(png_ptr, bpp, row_bytes, mins);
+ best_row = png_ptr->try_row;
}
- else if (filter_to_do & PNG_FILTER_AVG)
+ else if ((filter_to_do & PNG_FILTER_AVG) != 0)
{
- png_bytep rp, dp, pp, lp;
- png_uint_32 sum = 0, lmins = mins;
- png_size_t i;
- int v;
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 lmhi, lmlo;
- lmlo = lmins & PNG_LOMASK;
- lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
- {
- lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
- PNG_COST_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
- PNG_COST_SHIFT;
-
- if (lmhi > PNG_HIMASK)
- lmins = PNG_MAXSUM;
-
- else
- lmins = (lmhi << PNG_HISHIFT) + lmlo;
- }
-#endif
-
- for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
- pp = prev_row + 1; i < bpp; i++)
- {
- v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
-
- sum += (v < 128) ? v : 256 - v;
- }
-
- for (lp = row_buf + 1; i < row_bytes; i++)
- {
- v = *dp++ =
- (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
-
- sum += (v < 128) ? v : 256 - v;
-
- if (sum > lmins) /* We are already worse, don't continue. */
- break;
- }
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 sumhi, sumlo;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
- {
- sumlo = (sumlo * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
- PNG_COST_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
- PNG_COST_SHIFT;
+ png_size_t sum;
+ png_size_t lmins = mins;
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
- }
-#endif
+ sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins);
if (sum < mins)
{
mins = sum;
- best_row = png_ptr->avg_row;
+ best_row = png_ptr->try_row;
+ if (png_ptr->tst_row != NULL)
+ {
+ png_ptr->try_row = png_ptr->tst_row;
+ png_ptr->tst_row = best_row;
+ }
}
}
/* Paeth filter */
- if (filter_to_do == PNG_FILTER_PAETH)
+ if ((filter_to_do == PNG_FILTER_PAETH) != 0)
{
- png_bytep rp, dp, pp, cp, lp;
- png_size_t i;
-
- for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
- pp = prev_row + 1; i < bpp; i++)
- {
- *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
- }
-
- for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
- {
- int a, b, c, pa, pb, pc, p;
-
- b = *pp++;
- c = *cp++;
- a = *lp++;
-
- p = b - c;
- pc = a - c;
-
-#ifdef PNG_USE_ABS
- pa = abs(p);
- pb = abs(pc);
- pc = abs(p + pc);
-#else
- pa = p < 0 ? -p : p;
- pb = pc < 0 ? -pc : pc;
- pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-#endif
-
- p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
-
- *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
- }
- best_row = png_ptr->paeth_row;
+ (void) png_setup_paeth_row(png_ptr, bpp, row_bytes, mins);
+ best_row = png_ptr->try_row;
}
- else if (filter_to_do & PNG_FILTER_PAETH)
+ else if ((filter_to_do & PNG_FILTER_PAETH) != 0)
{
- png_bytep rp, dp, pp, cp, lp;
- png_uint_32 sum = 0, lmins = mins;
- png_size_t i;
- int v;
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
- {
- int j;
- png_uint_32 lmhi, lmlo;
- lmlo = lmins & PNG_LOMASK;
- lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
- {
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
- {
- lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
- }
-
- lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
- PNG_COST_SHIFT;
-
- lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
- PNG_COST_SHIFT;
-
- if (lmhi > PNG_HIMASK)
- lmins = PNG_MAXSUM;
-
- else
- lmins = (lmhi << PNG_HISHIFT) + lmlo;
- }
-#endif
-
- for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
- pp = prev_row + 1; i < bpp; i++)
- {
- v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
-
- sum += (v < 128) ? v : 256 - v;
- }
-
- for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
- {
- int a, b, c, pa, pb, pc, p;
-
- b = *pp++;
- c = *cp++;
- a = *lp++;
-
-#ifndef PNG_SLOW_PAETH
- p = b - c;
- pc = a - c;
-#ifdef PNG_USE_ABS
- pa = abs(p);
- pb = abs(pc);
- pc = abs(p + pc);
-#else
- pa = p < 0 ? -p : p;
- pb = pc < 0 ? -pc : pc;
- pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-#endif
- p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
-#else /* PNG_SLOW_PAETH */
- p = a + b - c;
- pa = abs(p - a);
- pb = abs(p - b);
- pc = abs(p - c);
-
- if (pa <= pb && pa <= pc)
- p = a;
+ png_size_t sum;
+ png_size_t lmins = mins;
- else if (pb <= pc)
- p = b;
+ sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins);
- else
- p = c;
-#endif /* PNG_SLOW_PAETH */
-
- v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
-
- sum += (v < 128) ? v : 256 - v;
-
- if (sum > lmins) /* We are already worse, don't continue. */
- break;
- }
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ if (sum < mins)
{
- int j;
- png_uint_32 sumhi, sumlo;
- sumlo = sum & PNG_LOMASK;
- sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
-
- for (j = 0; j < num_p_filters; j++)
+ best_row = png_ptr->try_row;
+ if (png_ptr->tst_row != NULL)
{
- if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
- {
- sumlo = (sumlo * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_weights[j]) >>
- PNG_WEIGHT_SHIFT;
- }
+ png_ptr->try_row = png_ptr->tst_row;
+ png_ptr->tst_row = best_row;
}
-
- sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
- PNG_COST_SHIFT;
-
- sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
- PNG_COST_SHIFT;
-
- if (sumhi > PNG_HIMASK)
- sum = PNG_MAXSUM;
-
- else
- sum = (sumhi << PNG_HISHIFT) + sumlo;
- }
-#endif
-
- if (sum < mins)
- {
- best_row = png_ptr->paeth_row;
}
}
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
/* Do the actual writing of the filtered row data from the chosen filter. */
png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- /* Save the type of filter we picked this time for future calculations */
- if (png_ptr->num_prev_filters > 0)
- {
- int j;
-
- for (j = 1; j < num_p_filters; j++)
- {
- png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
- }
-
- png_ptr->prev_filters[j] = best_row[0];
- }
-#endif
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+#endif /* WRITE_FILTER */
}
/* Do the actual writing of a previously filtered row. */
static void
-png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
- png_size_t avail/*includes filter byte*/)
+png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
+ png_size_t full_row_length/*includes filter byte*/)
{
png_debug(1, "in png_write_filtered_row");
png_debug1(2, "filter = %d", filtered_row[0]);
- /* Set up the zlib input buffer */
-
- png_ptr->zstream.next_in = filtered_row;
- png_ptr->zstream.avail_in = 0;
- /* Repeat until we have compressed all the data */
- do
- {
- int ret; /* Return of zlib */
-
- /* Record the number of bytes available - zlib supports at least 65535
- * bytes at one step, depending on the size of the zlib type 'uInt', the
- * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h).
- * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e.
- * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a
- * uInt. ZLIB_IO_MAX can be safely reduced to cause zlib to be called
- * with smaller chunks of data.
- */
- if (png_ptr->zstream.avail_in == 0)
- {
- if (avail > ZLIB_IO_MAX)
- {
- png_ptr->zstream.avail_in = ZLIB_IO_MAX;
- avail -= ZLIB_IO_MAX;
- }
-
- else
- {
- /* So this will fit in the available uInt space: */
- png_ptr->zstream.avail_in = (uInt)avail;
- avail = 0;
- }
- }
-
- /* Compress the data */
- ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
-
- /* Check for compression errors */
- if (ret != Z_OK)
- {
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
-
- else
- png_error(png_ptr, "zlib error");
- }
- /* See if it is time to write another IDAT */
- if (!(png_ptr->zstream.avail_out))
- {
- /* Write the IDAT and reset the zlib output buffer */
- png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
- }
- /* Repeat until all data has been compressed */
- } while (avail > 0 || png_ptr->zstream.avail_in > 0);
+ png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
+#ifdef PNG_WRITE_FILTER_SUPPORTED
/* Swap the current and previous rows */
if (png_ptr->prev_row != NULL)
{
@@ -3163,6 +2607,7 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
png_ptr->prev_row = png_ptr->row_buf;
png_ptr->row_buf = tptr;
}
+#endif /* WRITE_FILTER */
/* Finish row - updates counters and flushes zlib if last row */
png_write_finish_row(png_ptr);
@@ -3175,6 +2620,6 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
{
png_write_flush(png_ptr);
}
-#endif
+#endif /* WRITE_FLUSH */
}
-#endif /* PNG_WRITE_SUPPORTED */
+#endif /* WRITE */
diff --git a/thirdparty/md5/md5.h b/thirdparty/md5/md5.h
index 5b3bc285..ef50033e 100644
--- a/thirdparty/md5/md5.h
+++ b/thirdparty/md5/md5.h
@@ -24,6 +24,10 @@
#undef HIGHFIRST
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* On machines where "long" is 64 bits, we need to declare
uint32 as something guaranteed to be 32 bits. */
@@ -45,8 +49,8 @@ extern void MD5Transform(uint32 * , uint32 *);
*/
typedef struct MD5Context MD5_CTX;
-/* Define CHECK_HARDWARE_PROPERTIES to have main.c verify
- byte order and uint32 settings. */
-#define CHECK_HARDWARE_PROPERTIES
+#ifdef __cplusplus
+}
+#endif
#endif /* !MD5_H */
diff --git a/thirdparty/mingw/sal/sal.h b/thirdparty/mingw/sal/sal.h
deleted file mode 100644
index 99871197..00000000
--- a/thirdparty/mingw/sal/sal.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is part of the mingw-w64 runtime package.
- * No warranty is given; refer to the file DISCLAIMER.PD within this package.
- */
-
-#ifndef SAL_HXX
-#define SAL_HXX
-
-#ifdef __GNUC__
-# define __inner_checkReturn __attribute__((warn_unused_result))
-#elif defined(_MSC_VER)
-# define __inner_checkReturn __declspec("SAL_checkReturn")
-#else
-# define __inner_checkReturn
-#endif
-
-#define __checkReturn __inner_checkReturn
-
-#define _In_
-#define _In_opt_
-#define _Out_
-
-#define _Struct_size_bytes_(size)
-
-#endif
-
diff --git a/thirdparty/mingw/wrl/wrl/client.h b/thirdparty/mingw/wrl/wrl/client.h
new file mode 100644
index 00000000..60890d69
--- /dev/null
+++ b/thirdparty/mingw/wrl/wrl/client.h
@@ -0,0 +1,112 @@
+/**************************************************************************
+ *
+ * Copyright 2014-2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#pragma once
+
+
+#include <assert.h>
+
+#include <windows.h>
+
+
+namespace Microsoft {
+namespace WRL {
+
+/**
+ * See
+ * - https://msdn.microsoft.com/en-us/library/br244983.aspx
+ * - https://msdn.microsoft.com/en-us/magazine/dn904668.aspx
+ */
+template< typename T >
+class ComPtr
+{
+private:
+ T *p;
+
+public:
+ ComPtr(void) :
+ p(nullptr)
+ {
+ }
+
+ ComPtr(T *_p) :
+ p(_p)
+ {
+ }
+
+ ~ComPtr() {
+ T *temp = p;
+ p = nullptr;
+ if (temp) {
+ temp->Release();
+ }
+ }
+
+ T **
+ GetAddressOf(void) {
+ assert(p == nullptr);
+ return &p;
+ }
+
+ T *
+ Get(void) const {
+ return p;
+ }
+
+ struct no_ref_count : public T
+ {
+ private:
+ ULONG STDMETHODCALLTYPE AddRef(void);
+ ULONG STDMETHODCALLTYPE Release(void);
+ };
+
+ // Methods
+ no_ref_count *
+ operator -> () const {
+ assert(p != nullptr);
+ return static_cast< no_ref_count *>(p);
+ }
+
+ ComPtr &
+ operator = (T *q) {
+ if (p != q) {
+ T *temp = p;
+ p = q;
+ if (temp) {
+ temp->Release();
+ }
+ if (q) {
+ q->AddRef();
+ }
+ }
+ return *this;
+ }
+
+ ComPtr(const ComPtr &) = delete;
+ ComPtr & operator= (const ComPtr &) = delete;
+};
+
+} // namespace WRL
+} // namespace Microsoft
diff --git a/thirdparty/msinttypes/.gitignore b/thirdparty/msinttypes/.gitignore
deleted file mode 100644
index 24600083..00000000
--- a/thirdparty/msinttypes/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-!Makefile
diff --git a/thirdparty/msinttypes/LICENSE b/thirdparty/msinttypes/LICENSE
deleted file mode 100644
index 41d3ab6a..00000000
--- a/thirdparty/msinttypes/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2006-2013 Alexander Chemeris
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the product nor the names of its contributors may
- be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/thirdparty/msinttypes/Makefile b/thirdparty/msinttypes/Makefile
deleted file mode 100644
index ab18b4dd..00000000
--- a/thirdparty/msinttypes/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-update: \
- inttypes.h \
- stdint.h
-
-%.h: FORCE
- wget -N http://msinttypes.googlecode.com/svn/trunk/$@
-
-.PHONY: update
-
-FORCE:
diff --git a/thirdparty/msinttypes/inttypes.h b/thirdparty/msinttypes/inttypes.h
deleted file mode 100644
index ac7e32b6..00000000
--- a/thirdparty/msinttypes/inttypes.h
+++ /dev/null
@@ -1,306 +0,0 @@
-// ISO C9x compliant inttypes.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006-2013 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the product nor the names of its contributors may
-// be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_INTTYPES_H_ // [
-#define _MSC_INTTYPES_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#include "stdint.h"
-
-// 7.8 Format conversion of integer types
-
-typedef struct {
- intmax_t quot;
- intmax_t rem;
-} imaxdiv_t;
-
-// 7.8.1 Macros for format specifiers
-
-#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
-
-// The fprintf macros for signed integers are:
-#define PRId8 "d"
-#define PRIi8 "i"
-#define PRIdLEAST8 "d"
-#define PRIiLEAST8 "i"
-#define PRIdFAST8 "d"
-#define PRIiFAST8 "i"
-
-#define PRId16 "hd"
-#define PRIi16 "hi"
-#define PRIdLEAST16 "hd"
-#define PRIiLEAST16 "hi"
-#define PRIdFAST16 "hd"
-#define PRIiFAST16 "hi"
-
-#define PRId32 "I32d"
-#define PRIi32 "I32i"
-#define PRIdLEAST32 "I32d"
-#define PRIiLEAST32 "I32i"
-#define PRIdFAST32 "I32d"
-#define PRIiFAST32 "I32i"
-
-#define PRId64 "I64d"
-#define PRIi64 "I64i"
-#define PRIdLEAST64 "I64d"
-#define PRIiLEAST64 "I64i"
-#define PRIdFAST64 "I64d"
-#define PRIiFAST64 "I64i"
-
-#define PRIdMAX "I64d"
-#define PRIiMAX "I64i"
-
-#define PRIdPTR "Id"
-#define PRIiPTR "Ii"
-
-// The fprintf macros for unsigned integers are:
-#define PRIo8 "o"
-#define PRIu8 "u"
-#define PRIx8 "x"
-#define PRIX8 "X"
-#define PRIoLEAST8 "o"
-#define PRIuLEAST8 "u"
-#define PRIxLEAST8 "x"
-#define PRIXLEAST8 "X"
-#define PRIoFAST8 "o"
-#define PRIuFAST8 "u"
-#define PRIxFAST8 "x"
-#define PRIXFAST8 "X"
-
-#define PRIo16 "ho"
-#define PRIu16 "hu"
-#define PRIx16 "hx"
-#define PRIX16 "hX"
-#define PRIoLEAST16 "ho"
-#define PRIuLEAST16 "hu"
-#define PRIxLEAST16 "hx"
-#define PRIXLEAST16 "hX"
-#define PRIoFAST16 "ho"
-#define PRIuFAST16 "hu"
-#define PRIxFAST16 "hx"
-#define PRIXFAST16 "hX"
-
-#define PRIo32 "I32o"
-#define PRIu32 "I32u"
-#define PRIx32 "I32x"
-#define PRIX32 "I32X"
-#define PRIoLEAST32 "I32o"
-#define PRIuLEAST32 "I32u"
-#define PRIxLEAST32 "I32x"
-#define PRIXLEAST32 "I32X"
-#define PRIoFAST32 "I32o"
-#define PRIuFAST32 "I32u"
-#define PRIxFAST32 "I32x"
-#define PRIXFAST32 "I32X"
-
-#define PRIo64 "I64o"
-#define PRIu64 "I64u"
-#define PRIx64 "I64x"
-#define PRIX64 "I64X"
-#define PRIoLEAST64 "I64o"
-#define PRIuLEAST64 "I64u"
-#define PRIxLEAST64 "I64x"
-#define PRIXLEAST64 "I64X"
-#define PRIoFAST64 "I64o"
-#define PRIuFAST64 "I64u"
-#define PRIxFAST64 "I64x"
-#define PRIXFAST64 "I64X"
-
-#define PRIoMAX "I64o"
-#define PRIuMAX "I64u"
-#define PRIxMAX "I64x"
-#define PRIXMAX "I64X"
-
-#define PRIoPTR "Io"
-#define PRIuPTR "Iu"
-#define PRIxPTR "Ix"
-#define PRIXPTR "IX"
-
-// The fscanf macros for signed integers are:
-#define SCNd8 "d"
-#define SCNi8 "i"
-#define SCNdLEAST8 "d"
-#define SCNiLEAST8 "i"
-#define SCNdFAST8 "d"
-#define SCNiFAST8 "i"
-
-#define SCNd16 "hd"
-#define SCNi16 "hi"
-#define SCNdLEAST16 "hd"
-#define SCNiLEAST16 "hi"
-#define SCNdFAST16 "hd"
-#define SCNiFAST16 "hi"
-
-#define SCNd32 "ld"
-#define SCNi32 "li"
-#define SCNdLEAST32 "ld"
-#define SCNiLEAST32 "li"
-#define SCNdFAST32 "ld"
-#define SCNiFAST32 "li"
-
-#define SCNd64 "I64d"
-#define SCNi64 "I64i"
-#define SCNdLEAST64 "I64d"
-#define SCNiLEAST64 "I64i"
-#define SCNdFAST64 "I64d"
-#define SCNiFAST64 "I64i"
-
-#define SCNdMAX "I64d"
-#define SCNiMAX "I64i"
-
-#ifdef _WIN64 // [
-# define SCNdPTR "I64d"
-# define SCNiPTR "I64i"
-#else // _WIN64 ][
-# define SCNdPTR "ld"
-# define SCNiPTR "li"
-#endif // _WIN64 ]
-
-// The fscanf macros for unsigned integers are:
-#define SCNo8 "o"
-#define SCNu8 "u"
-#define SCNx8 "x"
-#define SCNX8 "X"
-#define SCNoLEAST8 "o"
-#define SCNuLEAST8 "u"
-#define SCNxLEAST8 "x"
-#define SCNXLEAST8 "X"
-#define SCNoFAST8 "o"
-#define SCNuFAST8 "u"
-#define SCNxFAST8 "x"
-#define SCNXFAST8 "X"
-
-#define SCNo16 "ho"
-#define SCNu16 "hu"
-#define SCNx16 "hx"
-#define SCNX16 "hX"
-#define SCNoLEAST16 "ho"
-#define SCNuLEAST16 "hu"
-#define SCNxLEAST16 "hx"
-#define SCNXLEAST16 "hX"
-#define SCNoFAST16 "ho"
-#define SCNuFAST16 "hu"
-#define SCNxFAST16 "hx"
-#define SCNXFAST16 "hX"
-
-#define SCNo32 "lo"
-#define SCNu32 "lu"
-#define SCNx32 "lx"
-#define SCNX32 "lX"
-#define SCNoLEAST32 "lo"
-#define SCNuLEAST32 "lu"
-#define SCNxLEAST32 "lx"
-#define SCNXLEAST32 "lX"
-#define SCNoFAST32 "lo"
-#define SCNuFAST32 "lu"
-#define SCNxFAST32 "lx"
-#define SCNXFAST32 "lX"
-
-#define SCNo64 "I64o"
-#define SCNu64 "I64u"
-#define SCNx64 "I64x"
-#define SCNX64 "I64X"
-#define SCNoLEAST64 "I64o"
-#define SCNuLEAST64 "I64u"
-#define SCNxLEAST64 "I64x"
-#define SCNXLEAST64 "I64X"
-#define SCNoFAST64 "I64o"
-#define SCNuFAST64 "I64u"
-#define SCNxFAST64 "I64x"
-#define SCNXFAST64 "I64X"
-
-#define SCNoMAX "I64o"
-#define SCNuMAX "I64u"
-#define SCNxMAX "I64x"
-#define SCNXMAX "I64X"
-
-#ifdef _WIN64 // [
-# define SCNoPTR "I64o"
-# define SCNuPTR "I64u"
-# define SCNxPTR "I64x"
-# define SCNXPTR "I64X"
-#else // _WIN64 ][
-# define SCNoPTR "lo"
-# define SCNuPTR "lu"
-# define SCNxPTR "lx"
-# define SCNXPTR "lX"
-#endif // _WIN64 ]
-
-#endif // __STDC_FORMAT_MACROS ]
-
-// 7.8.2 Functions for greatest-width integer types
-
-// 7.8.2.1 The imaxabs function
-#define imaxabs _abs64
-
-// 7.8.2.2 The imaxdiv function
-
-// This is modified version of div() function from Microsoft's div.c found
-// in %MSVC.NET%\crt\src\div.c
-#ifdef STATIC_IMAXDIV // [
-static
-#else // STATIC_IMAXDIV ][
-_inline
-#endif // STATIC_IMAXDIV ]
-imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
-{
- imaxdiv_t result;
-
- result.quot = numer / denom;
- result.rem = numer % denom;
-
- if (numer < 0 && result.rem > 0) {
- // did division wrong; must fix up
- ++result.quot;
- result.rem -= denom;
- }
-
- return result;
-}
-
-// 7.8.2.3 The strtoimax and strtoumax functions
-#define strtoimax _strtoi64
-#define strtoumax _strtoui64
-
-// 7.8.2.4 The wcstoimax and wcstoumax functions
-#define wcstoimax _wcstoi64
-#define wcstoumax _wcstoui64
-
-
-#endif // _MSC_INTTYPES_H_ ]
diff --git a/thirdparty/msinttypes/stdint.h b/thirdparty/msinttypes/stdint.h
deleted file mode 100644
index 4fe0ef9a..00000000
--- a/thirdparty/msinttypes/stdint.h
+++ /dev/null
@@ -1,259 +0,0 @@
-// ISO C9x compliant stdint.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006-2013 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the product nor the names of its contributors may
-// be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_STDINT_H_ // [
-#define _MSC_STDINT_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#if _MSC_VER >= 1600 // [
-#include <stdint.h>
-#else // ] _MSC_VER >= 1600 [
-
-#include <limits.h>
-
-// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
-// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
-// or compiler give many errors like this:
-// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
-#ifdef __cplusplus
-extern "C" {
-#endif
-# include <wchar.h>
-#ifdef __cplusplus
-}
-#endif
-
-// Define _W64 macros to mark types changing their size, like intptr_t.
-#ifndef _W64
-# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
-# define _W64 __w64
-# else
-# define _W64
-# endif
-#endif
-
-
-// 7.18.1 Integer types
-
-// 7.18.1.1 Exact-width integer types
-
-// Visual Studio 6 and Embedded Visual C++ 4 doesn't
-// realize that, e.g. char has the same size as __int8
-// so we give up on __intX for them.
-#if (_MSC_VER < 1300)
- typedef signed char int8_t;
- typedef signed short int16_t;
- typedef signed int int32_t;
- typedef unsigned char uint8_t;
- typedef unsigned short uint16_t;
- typedef unsigned int uint32_t;
-#else
- typedef signed __int8 int8_t;
- typedef signed __int16 int16_t;
- typedef signed __int32 int32_t;
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int16 uint16_t;
- typedef unsigned __int32 uint32_t;
-#endif
-typedef signed __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-
-// 7.18.1.2 Minimum-width integer types
-typedef int8_t int_least8_t;
-typedef int16_t int_least16_t;
-typedef int32_t int_least32_t;
-typedef int64_t int_least64_t;
-typedef uint8_t uint_least8_t;
-typedef uint16_t uint_least16_t;
-typedef uint32_t uint_least32_t;
-typedef uint64_t uint_least64_t;
-
-// 7.18.1.3 Fastest minimum-width integer types
-typedef int8_t int_fast8_t;
-typedef int16_t int_fast16_t;
-typedef int32_t int_fast32_t;
-typedef int64_t int_fast64_t;
-typedef uint8_t uint_fast8_t;
-typedef uint16_t uint_fast16_t;
-typedef uint32_t uint_fast32_t;
-typedef uint64_t uint_fast64_t;
-
-// 7.18.1.4 Integer types capable of holding object pointers
-#ifdef _WIN64 // [
- typedef signed __int64 intptr_t;
- typedef unsigned __int64 uintptr_t;
-#else // _WIN64 ][
- typedef _W64 signed int intptr_t;
- typedef _W64 unsigned int uintptr_t;
-#endif // _WIN64 ]
-
-// 7.18.1.5 Greatest-width integer types
-typedef int64_t intmax_t;
-typedef uint64_t uintmax_t;
-
-
-// 7.18.2 Limits of specified-width integer types
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
-
-// 7.18.2.1 Limits of exact-width integer types
-#define INT8_MIN ((int8_t)_I8_MIN)
-#define INT8_MAX _I8_MAX
-#define INT16_MIN ((int16_t)_I16_MIN)
-#define INT16_MAX _I16_MAX
-#define INT32_MIN ((int32_t)_I32_MIN)
-#define INT32_MAX _I32_MAX
-#define INT64_MIN ((int64_t)_I64_MIN)
-#define INT64_MAX _I64_MAX
-#define UINT8_MAX _UI8_MAX
-#define UINT16_MAX _UI16_MAX
-#define UINT32_MAX _UI32_MAX
-#define UINT64_MAX _UI64_MAX
-
-// 7.18.2.2 Limits of minimum-width integer types
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define INT_LEAST64_MIN INT64_MIN
-#define INT_LEAST64_MAX INT64_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define UINT_LEAST64_MAX UINT64_MAX
-
-// 7.18.2.3 Limits of fastest minimum-width integer types
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define INT_FAST64_MIN INT64_MIN
-#define INT_FAST64_MAX INT64_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-#define UINT_FAST64_MAX UINT64_MAX
-
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
-# define INTPTR_MIN INT64_MIN
-# define INTPTR_MAX INT64_MAX
-# define UINTPTR_MAX UINT64_MAX
-#else // _WIN64 ][
-# define INTPTR_MIN INT32_MIN
-# define INTPTR_MAX INT32_MAX
-# define UINTPTR_MAX UINT32_MAX
-#endif // _WIN64 ]
-
-// 7.18.2.5 Limits of greatest-width integer types
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-#define UINTMAX_MAX UINT64_MAX
-
-// 7.18.3 Limits of other integer types
-
-#ifdef _WIN64 // [
-# define PTRDIFF_MIN _I64_MIN
-# define PTRDIFF_MAX _I64_MAX
-#else // _WIN64 ][
-# define PTRDIFF_MIN _I32_MIN
-# define PTRDIFF_MAX _I32_MAX
-#endif // _WIN64 ]
-
-#define SIG_ATOMIC_MIN INT_MIN
-#define SIG_ATOMIC_MAX INT_MAX
-
-#ifndef SIZE_MAX // [
-# ifdef _WIN64 // [
-# define SIZE_MAX _UI64_MAX
-# else // _WIN64 ][
-# define SIZE_MAX _UI32_MAX
-# endif // _WIN64 ]
-#endif // SIZE_MAX ]
-
-// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
-#ifndef WCHAR_MIN // [
-# define WCHAR_MIN 0
-#endif // WCHAR_MIN ]
-#ifndef WCHAR_MAX // [
-# define WCHAR_MAX _UI16_MAX
-#endif // WCHAR_MAX ]
-
-#define WINT_MIN 0
-#define WINT_MAX _UI16_MAX
-
-#endif // __STDC_LIMIT_MACROS ]
-
-
-// 7.18.4 Limits of other integer types
-
-#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
-
-// 7.18.4.1 Macros for minimum-width integer constants
-
-#define INT8_C(val) val##i8
-#define INT16_C(val) val##i16
-#define INT32_C(val) val##i32
-#define INT64_C(val) val##i64
-
-#define UINT8_C(val) val##ui8
-#define UINT16_C(val) val##ui16
-#define UINT32_C(val) val##ui32
-#define UINT64_C(val) val##ui64
-
-// 7.18.4.2 Macros for greatest-width integer constants
-// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
-// Check out Issue 9 for the details.
-#ifndef INTMAX_C // [
-# define INTMAX_C INT64_C
-#endif // INTMAX_C ]
-#ifndef UINTMAX_C // [
-# define UINTMAX_C UINT64_C
-#endif // UINTMAX_C ]
-
-#endif // __STDC_CONSTANT_MACROS ]
-
-#endif // _MSC_VER >= 1600 ]
-
-#endif // _MSC_STDINT_H_ ]
diff --git a/thirdparty/qjson/.gitignore b/thirdparty/qjson/.gitignore
deleted file mode 100644
index 72337ffa..00000000
--- a/thirdparty/qjson/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-moc_*.cxx*
diff --git a/thirdparty/qjson/CMakeLists.txt b/thirdparty/qjson/CMakeLists.txt
deleted file mode 100644
index f142371a..00000000
--- a/thirdparty/qjson/CMakeLists.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-add_definitions (
- -DQT_NO_CAST_FROM_ASCII
- -DQT_NO_CAST_TO_ASCII
- -DQT_NO_DEBUG_OUTPUT
-)
-
-set (QT_DONT_USE_QTGUI TRUE)
-
-include (${QT_USE_FILE})
-
-include_directories (${CMAKE_CURRENT_BINARY_DIR})
-
-set (qjson_MOC_HDRS
- parserrunnable.h
- #serializerrunnable.h
-)
-
-qt4_wrap_cpp (qjson_MOC_SRCS ${qjson_MOC_HDRS})
-
-set (qjson_SRCS
- parser.cpp
- qobjecthelper.cpp
- json_scanner.cpp
- json_parser.cc
- parserrunnable.cpp
- #serializer.cpp
- #serializerrunnable.cpp
-)
-
-add_library (qjson_bundled STATIC EXCLUDE_FROM_ALL
- ${qjson_SRCS}
- ${qjson_MOC_SRCS}
-)
-
-install (
- FILES COPYING.lib
- DESTINATION ${DOC_INSTALL_DIR}
- RENAME LICENSE-qjson.txt
-)
diff --git a/thirdparty/qjson/COPYING.lib b/thirdparty/qjson/COPYING.lib
deleted file mode 100644
index 08f25cd2..00000000
--- a/thirdparty/qjson/COPYING.lib
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License version 2.1, as published by the Free Software Foundation.
-
-
- 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 GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/thirdparty/qjson/README b/thirdparty/qjson/README
deleted file mode 100644
index fe4853de..00000000
--- a/thirdparty/qjson/README
+++ /dev/null
@@ -1,27 +0,0 @@
-QJson
--------------------------------------------------
-Website: http://qjson.sourceforge.net/
-Mailing List: https://lists.sourceforge.net/mailman/listinfo/qjson-devel
-
-Project Lead/Maintainer (2008-current):
- Flavio Castelli <flavio@castelli.name>
-
-Install
--------
- For installation or compiling instructions, see the INSTALL file.
-
-License
--------
- This library is licensed under the Lesser GNU General Public License version 2.1.
- See the COPYING.lib file for more information.
-
-Description
------------
- JSON (JavaScript Object Notation) is a lightweight data-interchange format.
- It can represents integer, real number, string, an ordered sequence of value, and a collection of name/value pairs.
-
- QJson is a qt-based library that maps JSON data to QVariant objects.
- JSON arrays will be mapped to QVariantList instances, while JSON's objects will be mapped to QVariantMap.
-
-Happy hacking
-Flavio
diff --git a/thirdparty/qjson/json_parser.cc b/thirdparty/qjson/json_parser.cc
deleted file mode 100644
index 620e135a..00000000
--- a/thirdparty/qjson/json_parser.cc
+++ /dev/null
@@ -1,1116 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Skeleton implementation for Bison LALR(1) parsers in C++
-
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program 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
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-
-#include "json_parser.hh"
-
-/* User implementation prologue. */
-
-
-/* Line 317 of lalr1.cc. */
-#line 43 "json_parser.cc"
-
-#ifndef YY_
-# if YYENABLE_NLS
-# if ENABLE_NLS
-# include <libintl.h> /* FIXME: INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
-# endif
-# endif
-# ifndef YY_
-# define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E. */
-#define YYUSE(e) ((void) (e))
-
-/* A pseudo ostream that takes yydebug_ into account. */
-# define YYCDEBUG \
- for (bool yydebugcond_ = yydebug_; yydebugcond_; yydebugcond_ = false) \
- (*yycdebug_)
-
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug_) \
- { \
- *yycdebug_ << Title << ' '; \
- yy_symbol_print_ ((Type), (Value), (Location)); \
- *yycdebug_ << std::endl; \
- } \
-} while (false)
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug_) \
- yy_reduce_print_ (Rule); \
-} while (false)
-
-# define YY_STACK_PRINT() \
-do { \
- if (yydebug_) \
- yystack_print_ (); \
-} while (false)
-
-#else /* !YYDEBUG */
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_REDUCE_PRINT(Rule)
-# define YY_STACK_PRINT()
-
-#endif /* !YYDEBUG */
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-namespace yy
-{
-#if YYERROR_VERBOSE
-
- /* Return YYSTR after stripping away unnecessary quotes and
- backslashes, so that it's suitable for yyerror. The heuristic is
- that double-quoting is unnecessary unless the string contains an
- apostrophe, a comma, or backslash (other than backslash-backslash).
- YYSTR is taken from yytname. */
- std::string
- json_parser::yytnamerr_ (const char *yystr)
- {
- if (*yystr == '"')
- {
- std::string yyr = "";
- char const *yyp = yystr;
-
- for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- yyr += *yyp;
- break;
-
- case '"':
- return yyr;
- }
- do_not_strip_quotes: ;
- }
-
- return yystr;
- }
-
-#endif
-
- /// Build a parser object.
- json_parser::json_parser (QJson::ParserPrivate* driver_yyarg)
- : yydebug_ (false),
- yycdebug_ (&std::cerr),
- driver (driver_yyarg)
- {
- }
-
- json_parser::~json_parser ()
- {
- }
-
-#if YYDEBUG
- /*--------------------------------.
- | Print this symbol on YYOUTPUT. |
- `--------------------------------*/
-
- inline void
- json_parser::yy_symbol_value_print_ (int yytype,
- const semantic_type* yyvaluep, const location_type* yylocationp)
- {
- YYUSE (yylocationp);
- YYUSE (yyvaluep);
- switch (yytype)
- {
- default:
- break;
- }
- }
-
-
- void
- json_parser::yy_symbol_print_ (int yytype,
- const semantic_type* yyvaluep, const location_type* yylocationp)
- {
- *yycdebug_ << (yytype < yyntokens_ ? "token" : "nterm")
- << ' ' << yytname_[yytype] << " ("
- << *yylocationp << ": ";
- yy_symbol_value_print_ (yytype, yyvaluep, yylocationp);
- *yycdebug_ << ')';
- }
-#endif /* ! YYDEBUG */
-
- void
- json_parser::yydestruct_ (const char* yymsg,
- int yytype, semantic_type* yyvaluep, location_type* yylocationp)
- {
- YYUSE (yylocationp);
- YYUSE (yymsg);
- YYUSE (yyvaluep);
-
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
- switch (yytype)
- {
-
- default:
- break;
- }
- }
-
- void
- json_parser::yypop_ (unsigned int n)
- {
- yystate_stack_.pop (n);
- yysemantic_stack_.pop (n);
- yylocation_stack_.pop (n);
- }
-
- std::ostream&
- json_parser::debug_stream () const
- {
- return *yycdebug_;
- }
-
- void
- json_parser::set_debug_stream (std::ostream& o)
- {
- yycdebug_ = &o;
- }
-
-
- json_parser::debug_level_type
- json_parser::debug_level () const
- {
- return yydebug_;
- }
-
- void
- json_parser::set_debug_level (debug_level_type l)
- {
- yydebug_ = l;
- }
-
-
- int
- json_parser::parse ()
- {
- /// Look-ahead and look-ahead in internal form.
- int yychar = yyempty_;
- int yytoken = 0;
-
- /* State. */
- int yyn;
- int yylen = 0;
- int yystate = 0;
-
- /* Error handling. */
- int yynerrs_ = 0;
- int yyerrstatus_ = 0;
-
- /// Semantic value of the look-ahead.
- semantic_type yylval;
- /// Location of the look-ahead.
- location_type yylloc;
- /// The locations where the error started and ended.
- location yyerror_range[2];
-
- /// $$.
- semantic_type yyval;
- /// @$.
- location_type yyloc;
-
- int yyresult;
-
- YYCDEBUG << "Starting parse" << std::endl;
-
-
- /* Initialize the stacks. The initial state will be pushed in
- yynewstate, since the latter expects the semantical and the
- location values to have been already stored, initialize these
- stacks with a primary value. */
- yystate_stack_ = state_stack_type (0);
- yysemantic_stack_ = semantic_stack_type (0);
- yylocation_stack_ = location_stack_type (0);
- yysemantic_stack_.push (yylval);
- yylocation_stack_.push (yylloc);
-
- /* New state. */
- yynewstate:
- yystate_stack_.push (yystate);
- YYCDEBUG << "Entering state " << yystate << std::endl;
- goto yybackup;
-
- /* Backup. */
- yybackup:
-
- /* Try to take a decision without look-ahead. */
- yyn = yypact_[yystate];
- if (yyn == yypact_ninf_)
- goto yydefault;
-
- /* Read a look-ahead token. */
- if (yychar == yyempty_)
- {
- YYCDEBUG << "Reading a token: ";
- yychar = yylex (&yylval, &yylloc, driver);
- }
-
-
- /* Convert token to internal form. */
- if (yychar <= yyeof_)
- {
- yychar = yytoken = yyeof_;
- YYCDEBUG << "Now at end of input." << std::endl;
- }
- else
- {
- yytoken = yytranslate_ (yychar);
- YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken)
- goto yydefault;
-
- /* Reduce or error. */
- yyn = yytable_[yyn];
- if (yyn <= 0)
- {
- if (yyn == 0 || yyn == yytable_ninf_)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
-
- /* Accept? */
- if (yyn == yyfinal_)
- goto yyacceptlab;
-
- /* Shift the look-ahead token. */
- YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the token being shifted unless it is eof. */
- if (yychar != yyeof_)
- yychar = yyempty_;
-
- yysemantic_stack_.push (yylval);
- yylocation_stack_.push (yylloc);
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus_)
- --yyerrstatus_;
-
- yystate = yyn;
- goto yynewstate;
-
- /*-----------------------------------------------------------.
- | yydefault -- do the default action for the current state. |
- `-----------------------------------------------------------*/
- yydefault:
- yyn = yydefact_[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
-
- /*-----------------------------.
- | yyreduce -- Do a reduction. |
- `-----------------------------*/
- yyreduce:
- yylen = yyr2_[yyn];
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'. Otherwise, use the top of the stack.
-
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. */
- if (yylen)
- yyval = yysemantic_stack_[yylen - 1];
- else
- yyval = yysemantic_stack_[0];
-
- {
- slice<location_type, location_stack_type> slice (yylocation_stack_, yylen);
- YYLLOC_DEFAULT (yyloc, slice, yylen);
- }
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 2:
-#line 84 "json_parser.yy"
- {
- driver->m_result = (yysemantic_stack_[(1) - (1)]);
- qjsonDebug() << "json_parser - parsing finished";
- ;}
- break;
-
- case 3:
-#line 89 "json_parser.yy"
- { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
- break;
-
- case 4:
-#line 91 "json_parser.yy"
- {
- qCritical()<< "json_parser - syntax error found, "
- << "forcing abort, Line" << (yyloc).begin.line << "Column" << (yyloc).begin.column;
- YYABORT;
- ;}
- break;
-
- case 6:
-#line 98 "json_parser.yy"
- { (yyval) = (yysemantic_stack_[(3) - (2)]); ;}
- break;
-
- case 7:
-#line 100 "json_parser.yy"
- { (yyval) = QVariant (QVariantMap()); ;}
- break;
-
- case 8:
-#line 101 "json_parser.yy"
- {
- QVariantMap members = (yysemantic_stack_[(2) - (2)]).toMap();
- (yysemantic_stack_[(2) - (2)]) = QVariant(); // Allow reuse of map
- (yyval) = QVariant(members.unite ((yysemantic_stack_[(2) - (1)]).toMap()));
- ;}
- break;
-
- case 9:
-#line 107 "json_parser.yy"
- { (yyval) = QVariant (QVariantMap()); ;}
- break;
-
- case 10:
-#line 108 "json_parser.yy"
- {
- QVariantMap members = (yysemantic_stack_[(3) - (3)]).toMap();
- (yysemantic_stack_[(3) - (3)]) = QVariant(); // Allow reuse of map
- (yyval) = QVariant(members.unite ((yysemantic_stack_[(3) - (2)]).toMap()));
- ;}
- break;
-
- case 11:
-#line 114 "json_parser.yy"
- {
- QVariantMap pair;
- pair.insert ((yysemantic_stack_[(3) - (1)]).toString(), QVariant((yysemantic_stack_[(3) - (3)])));
- (yyval) = QVariant (pair);
- ;}
- break;
-
- case 12:
-#line 120 "json_parser.yy"
- { (yyval) = (yysemantic_stack_[(3) - (2)]); ;}
- break;
-
- case 13:
-#line 122 "json_parser.yy"
- { (yyval) = QVariant (QVariantList()); ;}
- break;
-
- case 14:
-#line 123 "json_parser.yy"
- {
- QVariantList members = (yysemantic_stack_[(2) - (2)]).toList();
- (yysemantic_stack_[(2) - (2)]) = QVariant(); // Allow reuse of list
- members.prepend ((yysemantic_stack_[(2) - (1)]));
- (yyval) = QVariant(members);
- ;}
- break;
-
- case 15:
-#line 130 "json_parser.yy"
- { (yyval) = QVariant (QVariantList()); ;}
- break;
-
- case 16:
-#line 131 "json_parser.yy"
- {
- QVariantList members = (yysemantic_stack_[(3) - (3)]).toList();
- (yysemantic_stack_[(3) - (3)]) = QVariant(); // Allow reuse of list
- members.prepend ((yysemantic_stack_[(3) - (2)]));
- (yyval) = QVariant(members);
- ;}
- break;
-
- case 17:
-#line 138 "json_parser.yy"
- { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
- break;
-
- case 18:
-#line 139 "json_parser.yy"
- { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
- break;
-
- case 19:
-#line 140 "json_parser.yy"
- { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
- break;
-
- case 20:
-#line 141 "json_parser.yy"
- { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
- break;
-
- case 21:
-#line 142 "json_parser.yy"
- { (yyval) = QVariant (true); ;}
- break;
-
- case 22:
-#line 143 "json_parser.yy"
- { (yyval) = QVariant (false); ;}
- break;
-
- case 23:
-#line 144 "json_parser.yy"
- {
- QVariant null_variant;
- (yyval) = null_variant;
- ;}
- break;
-
- case 24:
-#line 149 "json_parser.yy"
- { (yyval) = QVariant(QVariant::Double); (yyval).setValue( -std::numeric_limits<double>::infinity() ); ;}
- break;
-
- case 25:
-#line 150 "json_parser.yy"
- { (yyval) = QVariant(QVariant::Double); (yyval).setValue( std::numeric_limits<double>::infinity() ); ;}
- break;
-
- case 26:
-#line 151 "json_parser.yy"
- { (yyval) = QVariant(QVariant::Double); (yyval).setValue( std::numeric_limits<double>::quiet_NaN() ); ;}
- break;
-
- case 28:
-#line 154 "json_parser.yy"
- {
- if ((yysemantic_stack_[(1) - (1)]).toByteArray().startsWith('-')) {
- (yyval) = QVariant (QVariant::LongLong);
- (yyval).setValue((yysemantic_stack_[(1) - (1)]).toLongLong());
- }
- else {
- (yyval) = QVariant (QVariant::ULongLong);
- (yyval).setValue((yysemantic_stack_[(1) - (1)]).toULongLong());
- }
- ;}
- break;
-
- case 29:
-#line 164 "json_parser.yy"
- {
- const QByteArray value = (yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray();
- (yyval) = QVariant(QVariant::Double);
- (yyval).setValue(value.toDouble());
- ;}
- break;
-
- case 30:
-#line 169 "json_parser.yy"
- { (yyval) = QVariant ((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;}
- break;
-
- case 31:
-#line 170 "json_parser.yy"
- {
- const QByteArray value = (yysemantic_stack_[(3) - (1)]).toByteArray() + (yysemantic_stack_[(3) - (2)]).toByteArray() + (yysemantic_stack_[(3) - (3)]).toByteArray();
- (yyval) = QVariant (value);
- ;}
- break;
-
- case 32:
-#line 175 "json_parser.yy"
- { (yyval) = QVariant ((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;}
- break;
-
- case 33:
-#line 176 "json_parser.yy"
- { (yyval) = QVariant (QByteArray("-") + (yysemantic_stack_[(3) - (2)]).toByteArray() + (yysemantic_stack_[(3) - (3)]).toByteArray()); ;}
- break;
-
- case 34:
-#line 178 "json_parser.yy"
- { (yyval) = QVariant (QByteArray("")); ;}
- break;
-
- case 35:
-#line 179 "json_parser.yy"
- {
- (yyval) = QVariant((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray());
- ;}
- break;
-
- case 36:
-#line 183 "json_parser.yy"
- {
- (yyval) = QVariant(QByteArray(".") + (yysemantic_stack_[(2) - (2)]).toByteArray());
- ;}
- break;
-
- case 37:
-#line 187 "json_parser.yy"
- { (yyval) = QVariant((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;}
- break;
-
- case 38:
-#line 189 "json_parser.yy"
- { (yyval) = (yysemantic_stack_[(3) - (2)]); ;}
- break;
-
- case 39:
-#line 191 "json_parser.yy"
- { (yyval) = QVariant (QString(QLatin1String(""))); ;}
- break;
-
- case 40:
-#line 192 "json_parser.yy"
- {
- (yyval) = (yysemantic_stack_[(1) - (1)]);
- ;}
- break;
-
-
- /* Line 675 of lalr1.cc. */
-#line 628 "json_parser.cc"
- default: break;
- }
- YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc);
-
- yypop_ (yylen);
- yylen = 0;
- YY_STACK_PRINT ();
-
- yysemantic_stack_.push (yyval);
- yylocation_stack_.push (yyloc);
-
- /* Shift the result of the reduction. */
- yyn = yyr1_[yyn];
- yystate = yypgoto_[yyn - yyntokens_] + yystate_stack_[0];
- if (0 <= yystate && yystate <= yylast_
- && yycheck_[yystate] == yystate_stack_[0])
- yystate = yytable_[yystate];
- else
- yystate = yydefgoto_[yyn - yyntokens_];
- goto yynewstate;
-
- /*------------------------------------.
- | yyerrlab -- here on detecting error |
- `------------------------------------*/
- yyerrlab:
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus_)
- {
- ++yynerrs_;
- error (yylloc, yysyntax_error_ (yystate, yytoken));
- }
-
- yyerror_range[0] = yylloc;
- if (yyerrstatus_ == 3)
- {
- /* If just tried and failed to reuse look-ahead token after an
- error, discard it. */
-
- if (yychar <= yyeof_)
- {
- /* Return failure if at end of input. */
- if (yychar == yyeof_)
- YYABORT;
- }
- else
- {
- yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc);
- yychar = yyempty_;
- }
- }
-
- /* Else will try to reuse look-ahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
- /*---------------------------------------------------.
- | yyerrorlab -- error raised explicitly by YYERROR. |
- `---------------------------------------------------*/
- yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (false)
- goto yyerrorlab;
-
- yyerror_range[0] = yylocation_stack_[yylen - 1];
- /* Do not reclaim the symbols of the rule which action triggered
- this YYERROR. */
- yypop_ (yylen);
- yylen = 0;
- yystate = yystate_stack_[0];
- goto yyerrlab1;
-
- /*-------------------------------------------------------------.
- | yyerrlab1 -- common code for both syntax error and YYERROR. |
- `-------------------------------------------------------------*/
- yyerrlab1:
- yyerrstatus_ = 3; /* Each real token shifted decrements this. */
-
- for (;;)
- {
- yyn = yypact_[yystate];
- if (yyn != yypact_ninf_)
- {
- yyn += yyterror_;
- if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
- {
- yyn = yytable_[yyn];
- if (0 < yyn)
- break;
- }
- }
-
- /* Pop the current state because it cannot handle the error token. */
- if (yystate_stack_.height () == 1)
- YYABORT;
-
- yyerror_range[0] = yylocation_stack_[0];
- yydestruct_ ("Error: popping",
- yystos_[yystate],
- &yysemantic_stack_[0], &yylocation_stack_[0]);
- yypop_ ();
- yystate = yystate_stack_[0];
- YY_STACK_PRINT ();
- }
-
- if (yyn == yyfinal_)
- goto yyacceptlab;
-
- yyerror_range[1] = yylloc;
- // Using YYLLOC is tempting, but would change the location of
- // the look-ahead. YYLOC is available though.
- YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
- yysemantic_stack_.push (yylval);
- yylocation_stack_.push (yyloc);
-
- /* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos_[yyn],
- &yysemantic_stack_[0], &yylocation_stack_[0]);
-
- yystate = yyn;
- goto yynewstate;
-
- /* Accept. */
- yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
- /* Abort. */
- yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
- yyreturn:
- if (yychar != yyeof_ && yychar != yyempty_)
- yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc);
-
- /* Do not reclaim the symbols of the rule which action triggered
- this YYABORT or YYACCEPT. */
- yypop_ (yylen);
- while (yystate_stack_.height () != 1)
- {
- yydestruct_ ("Cleanup: popping",
- yystos_[yystate_stack_[0]],
- &yysemantic_stack_[0],
- &yylocation_stack_[0]);
- yypop_ ();
- }
-
- return yyresult;
- }
-
- // Generate an error message.
- std::string
- json_parser::yysyntax_error_ (int yystate, int tok)
- {
- std::string res;
- YYUSE (yystate);
-#if YYERROR_VERBOSE
- int yyn = yypact_[yystate];
- if (yypact_ninf_ < yyn && yyn <= yylast_)
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = yylast_ - yyn + 1;
- int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_;
- int count = 0;
- for (int x = yyxbegin; x < yyxend; ++x)
- if (yycheck_[x + yyn] == x && x != yyterror_)
- ++count;
-
- // FIXME: This method of building the message is not compatible
- // with internationalization. It should work like yacc.c does it.
- // That is, first build a string that looks like this:
- // "syntax error, unexpected %s or %s or %s"
- // Then, invoke YY_ on this string.
- // Finally, use the string as a format to output
- // yytname_[tok], etc.
- // Until this gets fixed, this message appears in English only.
- res = "syntax error, unexpected ";
- res += yytnamerr_ (yytname_[tok]);
- if (count < 5)
- {
- count = 0;
- for (int x = yyxbegin; x < yyxend; ++x)
- if (yycheck_[x + yyn] == x && x != yyterror_)
- {
- res += (!count++) ? ", expecting " : " or ";
- res += yytnamerr_ (yytname_[x]);
- }
- }
- }
- else
-#endif
- res = YY_("syntax error");
- return res;
- }
-
-
- /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
- const signed char json_parser::yypact_ninf_ = -21;
- const signed char
- json_parser::yypact_[] =
- {
- 3, -21, -21, -6, 31, -10, 0, -21, -21, -21,
- 6, -21, -21, 25, -21, -21, -21, -21, -21, -21,
- -5, -21, 22, 19, 21, 23, 24, 0, -21, 0,
- -21, -21, 13, -21, 0, 0, 29, -21, -21, -6,
- -21, 31, -21, 31, -21, -21, -21, -21, -21, -21,
- -21, 19, -21, 24, -21, -21
- };
-
- /* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
- doesn't specify something else to do. Zero means the default is an
- error. */
- const unsigned char
- json_parser::yydefact_[] =
- {
- 0, 5, 4, 7, 13, 0, 34, 21, 22, 23,
- 39, 25, 26, 0, 2, 19, 20, 3, 18, 27,
- 28, 17, 0, 9, 0, 0, 15, 34, 24, 34,
- 32, 40, 0, 1, 34, 34, 29, 30, 6, 0,
- 8, 0, 12, 0, 14, 33, 35, 38, 36, 37,
- 31, 9, 11, 15, 10, 16
- };
-
- /* YYPGOTO[NTERM-NUM]. */
- const signed char
- json_parser::yypgoto_[] =
- {
- -21, -21, -21, -21, -21, -20, 4, -21, -21, -18,
- -4, -21, -21, -21, -14, -21, -3, -1, -21
- };
-
- /* YYDEFGOTO[NTERM-NUM]. */
- const signed char
- json_parser::yydefgoto_[] =
- {
- -1, 13, 14, 15, 22, 40, 23, 16, 25, 44,
- 17, 18, 19, 20, 30, 36, 37, 21, 32
- };
-
- /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says. */
- const signed char json_parser::yytable_ninf_ = -1;
- const unsigned char
- json_parser::yytable_[] =
- {
- 26, 27, 24, 1, 2, 34, 3, 35, 4, 28,
- 10, 29, 5, 45, 6, 46, 7, 8, 9, 10,
- 48, 49, 11, 12, 31, 33, 38, 39, 41, 42,
- 47, 54, 43, 50, 3, 55, 4, 52, 24, 53,
- 5, 35, 6, 51, 7, 8, 9, 10, 0, 0,
- 11, 12
- };
-
- /* YYCHECK. */
- const signed char
- json_parser::yycheck_[] =
- {
- 4, 11, 3, 0, 1, 10, 3, 12, 5, 19,
- 16, 11, 9, 27, 11, 29, 13, 14, 15, 16,
- 34, 35, 19, 20, 18, 0, 4, 8, 7, 6,
- 17, 51, 8, 36, 3, 53, 5, 41, 39, 43,
- 9, 12, 11, 39, 13, 14, 15, 16, -1, -1,
- 19, 20
- };
-
- /* STOS_[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
- const unsigned char
- json_parser::yystos_[] =
- {
- 0, 0, 1, 3, 5, 9, 11, 13, 14, 15,
- 16, 19, 20, 22, 23, 24, 28, 31, 32, 33,
- 34, 38, 25, 27, 38, 29, 31, 11, 19, 11,
- 35, 18, 39, 0, 10, 12, 36, 37, 4, 8,
- 26, 7, 6, 8, 30, 35, 35, 17, 35, 35,
- 37, 27, 31, 31, 26, 30
- };
-
-#if YYDEBUG
- /* TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding
- to YYLEX-NUM. */
- const unsigned short int
- json_parser::yytoken_number_[] =
- {
- 0, 256, 257, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18
- };
-#endif
-
- /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
- const unsigned char
- json_parser::yyr1_[] =
- {
- 0, 21, 22, 23, 23, 23, 24, 25, 25, 26,
- 26, 27, 28, 29, 29, 30, 30, 31, 31, 31,
- 31, 31, 31, 31, 32, 32, 32, 32, 33, 33,
- 33, 33, 34, 34, 35, 35, 36, 37, 38, 39,
- 39
- };
-
- /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
- const unsigned char
- json_parser::yyr2_[] =
- {
- 0, 2, 1, 1, 1, 1, 3, 0, 2, 0,
- 3, 3, 3, 0, 2, 0, 3, 1, 1, 1,
- 1, 1, 1, 1, 2, 1, 1, 1, 1, 2,
- 2, 3, 2, 3, 0, 2, 2, 2, 3, 0,
- 1
- };
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
- /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at \a yyntokens_, nonterminals. */
- const char*
- const json_parser::yytname_[] =
- {
- "\"end of file\"", "error", "$undefined", "\"{\"", "\"}\"", "\"[\"",
- "\"]\"", "\":\"", "\",\"", "\"-\"", "\".\"", "\"digit\"",
- "\"exponential\"", "\"true\"", "\"false\"", "\"null\"",
- "\"open quotation mark\"", "\"close quotation mark\"", "\"string\"",
- "\"Infinity\"", "\"NaN\"", "$accept", "start", "data", "object",
- "members", "r_members", "pair", "array", "values", "r_values", "value",
- "special_or_number", "number", "int", "digits", "fract", "exp", "string",
- "string_arg", 0
- };
-#endif
-
-#if YYDEBUG
- /* YYRHS -- A `-1'-separated list of the rules' RHS. */
- const json_parser::rhs_number_type
- json_parser::yyrhs_[] =
- {
- 22, 0, -1, 23, -1, 31, -1, 1, -1, 0,
- -1, 3, 25, 4, -1, -1, 27, 26, -1, -1,
- 8, 27, 26, -1, 38, 7, 31, -1, 5, 29,
- 6, -1, -1, 31, 30, -1, -1, 8, 31, 30,
- -1, 38, -1, 32, -1, 24, -1, 28, -1, 13,
- -1, 14, -1, 15, -1, 9, 19, -1, 19, -1,
- 20, -1, 33, -1, 34, -1, 34, 36, -1, 34,
- 37, -1, 34, 36, 37, -1, 11, 35, -1, 9,
- 11, 35, -1, -1, 11, 35, -1, 10, 35, -1,
- 12, 35, -1, 16, 39, 17, -1, -1, 18, -1
- };
-
- /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
- const unsigned char
- json_parser::yyprhs_[] =
- {
- 0, 0, 3, 5, 7, 9, 11, 15, 16, 19,
- 20, 24, 28, 32, 33, 36, 37, 41, 43, 45,
- 47, 49, 51, 53, 55, 58, 60, 62, 64, 66,
- 69, 72, 76, 79, 83, 84, 87, 90, 93, 97,
- 98
- };
-
- /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
- const unsigned char
- json_parser::yyrline_[] =
- {
- 0, 84, 84, 89, 90, 96, 98, 100, 101, 107,
- 108, 114, 120, 122, 123, 130, 131, 138, 139, 140,
- 141, 142, 143, 144, 149, 150, 151, 152, 154, 164,
- 169, 170, 175, 176, 178, 179, 183, 187, 189, 191,
- 192
- };
-
- // Print the state stack on the debug stream.
- void
- json_parser::yystack_print_ ()
- {
- *yycdebug_ << "Stack now";
- for (state_stack_type::const_iterator i = yystate_stack_.begin ();
- i != yystate_stack_.end (); ++i)
- *yycdebug_ << ' ' << *i;
- *yycdebug_ << std::endl;
- }
-
- // Report on the debug stream that the rule \a yyrule is going to be reduced.
- void
- json_parser::yy_reduce_print_ (int yyrule)
- {
- unsigned int yylno = yyrline_[yyrule];
- int yynrhs = yyr2_[yyrule];
- /* Print the symbols being reduced, and their result. */
- *yycdebug_ << "Reducing stack by rule " << yyrule - 1
- << " (line " << yylno << "), ";
- /* The symbols being reduced. */
- for (int yyi = 0; yyi < yynrhs; yyi++)
- YY_SYMBOL_PRINT (" $" << yyi + 1 << " =",
- yyrhs_[yyprhs_[yyrule] + yyi],
- &(yysemantic_stack_[(yynrhs) - (yyi + 1)]),
- &(yylocation_stack_[(yynrhs) - (yyi + 1)]));
- }
-#endif // YYDEBUG
-
- /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
- json_parser::token_number_type
- json_parser::yytranslate_ (int t)
- {
- static
- const token_number_type
- translate_table[] =
- {
- 0, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2
- };
- if ((unsigned int) t <= yyuser_token_number_max_)
- return translate_table[t];
- else
- return yyundef_token_;
- }
-
- const int json_parser::yyeof_ = 0;
- const int json_parser::yylast_ = 51;
- const int json_parser::yynnts_ = 19;
- const int json_parser::yyempty_ = -2;
- const int json_parser::yyfinal_ = 33;
- const int json_parser::yyterror_ = 1;
- const int json_parser::yyerrcode_ = 256;
- const int json_parser::yyntokens_ = 21;
-
- const unsigned int json_parser::yyuser_token_number_max_ = 257;
- const json_parser::token_number_type json_parser::yyundef_token_ = 2;
-
-} // namespace yy
-
-#line 196 "json_parser.yy"
-
-
-int yy::yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver)
-{
- JSonScanner* scanner = driver->m_scanner;
- yylval->clear();
- int ret = scanner->yylex(yylval, yylloc);
-
- qjsonDebug() << "json_parser::yylex - calling scanner yylval==|"
- << yylval->toByteArray() << "|, ret==|" << QString::number(ret) << "|";
-
- return ret;
-}
-
-void yy::json_parser::error (const yy::location& yyloc,
- const std::string& error)
-{
- /*qjsonDebug() << yyloc.begin.line;
- qjsonDebug() << yyloc.begin.column;
- qjsonDebug() << yyloc.end.line;
- qjsonDebug() << yyloc.end.column;*/
- qjsonDebug() << "json_parser::error [line" << yyloc.end.line << "] -" << error.c_str() ;
- driver->setError(QString::fromLatin1(error.c_str()), yyloc.end.line);
-}
-
diff --git a/thirdparty/qjson/json_parser.hh b/thirdparty/qjson/json_parser.hh
deleted file mode 100644
index e61ca7c6..00000000
--- a/thirdparty/qjson/json_parser.hh
+++ /dev/null
@@ -1,325 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Skeleton interface for Bison LALR(1) parsers in C++
-
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program 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
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* C++ LALR(1) parser skeleton written by Akim Demaille. */
-
-#ifndef PARSER_HEADER_H
-# define PARSER_HEADER_H
-
-#include <string>
-#include <iostream>
-#include "stack.hh"
-
-namespace yy
-{
- class position;
- class location;
-}
-
-/* First part of user declarations. */
-#line 25 "json_parser.yy"
-
- #include "parser_p.h"
- #include "json_scanner.h"
- #include "qjson_debug.h"
-
- #include <QtCore/QByteArray>
- #include <QtCore/QMap>
- #include <QtCore/QString>
- #include <QtCore/QVariant>
-
- #include <limits>
-
- class JSonScanner;
-
- namespace QJson {
- class Parser;
- }
-
- #define YYERROR_VERBOSE 1
-
-
-/* Line 35 of lalr1.cc. */
-#line 75 "json_parser.hh"
-
-#include "location.hh"
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 1
-#endif
-
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
-do { \
- if (N) \
- { \
- (Current).begin = (Rhs)[1].begin; \
- (Current).end = (Rhs)[N].end; \
- } \
- else \
- { \
- (Current).begin = (Current).end = (Rhs)[0].end; \
- } \
-} while (false)
-#endif
-
-namespace yy
-{
-
- /// A Bison parser.
- class json_parser
- {
- public:
- /// Symbol semantic values.
-#ifndef YYSTYPE
- typedef int semantic_type;
-#else
- typedef YYSTYPE semantic_type;
-#endif
- /// Symbol locations.
- typedef location location_type;
- /// Tokens.
- struct token
- {
- /* Tokens. */
- enum yytokentype {
- END = 0,
- CURLY_BRACKET_OPEN = 1,
- CURLY_BRACKET_CLOSE = 2,
- SQUARE_BRACKET_OPEN = 3,
- SQUARE_BRACKET_CLOSE = 4,
- COLON = 5,
- COMMA = 6,
- MINUS = 7,
- DOT = 8,
- DIGIT = 9,
- E = 10,
- TRUE_VAL = 11,
- FALSE_VAL = 12,
- NULL_VAL = 13,
- QUOTMARKOPEN = 14,
- QUOTMARKCLOSE = 15,
- STRING = 16,
- INFINITY_VAL = 17,
- NAN_VAL = 18
- };
-
- };
- /// Token type.
- typedef token::yytokentype token_type;
-
- /// Build a parser object.
- json_parser (QJson::ParserPrivate* driver_yyarg);
- virtual ~json_parser ();
-
- /// Parse.
- /// \returns 0 iff parsing succeeded.
- virtual int parse ();
-
- /// The current debugging stream.
- std::ostream& debug_stream () const;
- /// Set the current debugging stream.
- void set_debug_stream (std::ostream &);
-
- /// Type for debugging levels.
- typedef int debug_level_type;
- /// The current debugging level.
- debug_level_type debug_level () const;
- /// Set the current debugging level.
- void set_debug_level (debug_level_type l);
-
- private:
- /// Report a syntax error.
- /// \param loc where the syntax error is found.
- /// \param msg a description of the syntax error.
- virtual void error (const location_type& loc, const std::string& msg);
-
- /// Generate an error message.
- /// \param state the state where the error occurred.
- /// \param tok the look-ahead token.
- virtual std::string yysyntax_error_ (int yystate, int tok);
-
-#if YYDEBUG
- /// \brief Report a symbol value on the debug stream.
- /// \param yytype The token type.
- /// \param yyvaluep Its semantic value.
- /// \param yylocationp Its location.
- virtual void yy_symbol_value_print_ (int yytype,
- const semantic_type* yyvaluep,
- const location_type* yylocationp);
- /// \brief Report a symbol on the debug stream.
- /// \param yytype The token type.
- /// \param yyvaluep Its semantic value.
- /// \param yylocationp Its location.
- virtual void yy_symbol_print_ (int yytype,
- const semantic_type* yyvaluep,
- const location_type* yylocationp);
-#endif /* ! YYDEBUG */
-
-
- /// State numbers.
- typedef int state_type;
- /// State stack type.
- typedef stack<state_type> state_stack_type;
- /// Semantic value stack type.
- typedef stack<semantic_type> semantic_stack_type;
- /// location stack type.
- typedef stack<location_type> location_stack_type;
-
- /// The state stack.
- state_stack_type yystate_stack_;
- /// The semantic value stack.
- semantic_stack_type yysemantic_stack_;
- /// The location stack.
- location_stack_type yylocation_stack_;
-
- /// Internal symbol numbers.
- typedef unsigned char token_number_type;
- /* Tables. */
- /// For a state, the index in \a yytable_ of its portion.
- static const signed char yypact_[];
- static const signed char yypact_ninf_;
-
- /// For a state, default rule to reduce.
- /// Unless\a yytable_ specifies something else to do.
- /// Zero means the default is an error.
- static const unsigned char yydefact_[];
-
- static const signed char yypgoto_[];
- static const signed char yydefgoto_[];
-
- /// What to do in a state.
- /// \a yytable_[yypact_[s]]: what to do in state \a s.
- /// - if positive, shift that token.
- /// - if negative, reduce the rule which number is the opposite.
- /// - if zero, do what YYDEFACT says.
- static const unsigned char yytable_[];
- static const signed char yytable_ninf_;
-
- static const signed char yycheck_[];
-
- /// For a state, its accessing symbol.
- static const unsigned char yystos_[];
-
- /// For a rule, its LHS.
- static const unsigned char yyr1_[];
- /// For a rule, its RHS length.
- static const unsigned char yyr2_[];
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
- /// For a symbol, its name in clear.
- static const char* const yytname_[];
-#endif
-
-#if YYERROR_VERBOSE
- /// Convert the symbol name \a n to a form suitable for a diagnostic.
- virtual std::string yytnamerr_ (const char *n);
-#endif
-
-#if YYDEBUG
- /// A type to store symbol numbers and -1.
- typedef signed char rhs_number_type;
- /// A `-1'-separated list of the rules' RHS.
- static const rhs_number_type yyrhs_[];
- /// For each rule, the index of the first RHS symbol in \a yyrhs_.
- static const unsigned char yyprhs_[];
- /// For each rule, its source line number.
- static const unsigned char yyrline_[];
- /// For each scanner token number, its symbol number.
- static const unsigned short int yytoken_number_[];
- /// Report on the debug stream that the rule \a r is going to be reduced.
- virtual void yy_reduce_print_ (int r);
- /// Print the state stack on the debug stream.
- virtual void yystack_print_ ();
-#endif
-
- /// Convert a scanner token number \a t to a symbol number.
- token_number_type yytranslate_ (int t);
-
- /// \brief Reclaim the memory associated to a symbol.
- /// \param yymsg Why this token is reclaimed.
- /// \param yytype The symbol type.
- /// \param yyvaluep Its semantic value.
- /// \param yylocationp Its location.
- inline void yydestruct_ (const char* yymsg,
- int yytype,
- semantic_type* yyvaluep,
- location_type* yylocationp);
-
- /// Pop \a n symbols the three stacks.
- inline void yypop_ (unsigned int n = 1);
-
- /* Constants. */
- static const int yyeof_;
- /* LAST_ -- Last index in TABLE_. */
- static const int yylast_;
- static const int yynnts_;
- static const int yyempty_;
- static const int yyfinal_;
- static const int yyterror_;
- static const int yyerrcode_;
- static const int yyntokens_;
- static const unsigned int yyuser_token_number_max_;
- static const token_number_type yyundef_token_;
-
- /* Debugging. */
- int yydebug_;
- std::ostream* yycdebug_;
-
-
- /* User arguments. */
- QJson::ParserPrivate* driver;
- };
-}
-
-
-#endif /* ! defined PARSER_HEADER_H */
diff --git a/thirdparty/qjson/json_parser.yy b/thirdparty/qjson/json_parser.yy
deleted file mode 100644
index 2540889b..00000000
--- a/thirdparty/qjson/json_parser.yy
+++ /dev/null
@@ -1,219 +0,0 @@
-/* This file is part of QJSon
- *
- * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-%skeleton "lalr1.cc"
-%defines
-%define "parser_class_name" "json_parser"
-
-%{
- #include "parser_p.h"
- #include "json_scanner.h"
- #include "qjson_debug.h"
-
- #include <QtCore/QByteArray>
- #include <QtCore/QMap>
- #include <QtCore/QString>
- #include <QtCore/QVariant>
-
- #include <limits>
-
- class JSonScanner;
-
- namespace QJson {
- class Parser;
- }
-
- #define YYERROR_VERBOSE 1
-%}
-
-%parse-param { QJson::ParserPrivate* driver }
-%lex-param { QJson::ParserPrivate* driver }
-
-%locations
-
-%debug
-%error-verbose
-
-%token END 0 "end of file"
-
-%token CURLY_BRACKET_OPEN 1 "{"
-%token CURLY_BRACKET_CLOSE 2 "}"
-%token SQUARE_BRACKET_OPEN 3 "["
-%token SQUARE_BRACKET_CLOSE 4 "]"
-
-%token COLON 5 ":"
-%token COMMA 6 ","
-%token MINUS 7 "-"
-%token DOT 8 "."
-%token DIGIT 9 "digit"
-%token E 10 "exponential"
-%token TRUE_VAL 11 "true"
-%token FALSE_VAL 12 "false"
-%token NULL_VAL 13 "null"
-%token QUOTMARKOPEN 14 "open quotation mark"
-%token QUOTMARKCLOSE 15 "close quotation mark"
-
-%token STRING 16 "string"
-%token INFINITY_VAL 17 "Infinity"
-%token NAN_VAL 18 "NaN"
-
-// define the initial token
-%start start
-
-%%
-
-// grammar rules
-
-start: data {
- driver->m_result = $1;
- qjsonDebug() << "json_parser - parsing finished";
- };
-
-data: value { $$ = $1; }
- | error
- {
- qCritical()<< "json_parser - syntax error found, "
- << "forcing abort, Line" << @$.begin.line << "Column" << @$.begin.column;
- YYABORT;
- }
- | END;
-
-object: CURLY_BRACKET_OPEN members CURLY_BRACKET_CLOSE { $$ = $2; };
-
-members: /* empty */ { $$ = QVariant (QVariantMap()); }
- | pair r_members {
- QVariantMap members = $2.toMap();
- $2 = QVariant(); // Allow reuse of map
- $$ = QVariant(members.unite ($1.toMap()));
- };
-
-r_members: /* empty */ { $$ = QVariant (QVariantMap()); }
- | COMMA pair r_members {
- QVariantMap members = $3.toMap();
- $3 = QVariant(); // Allow reuse of map
- $$ = QVariant(members.unite ($2.toMap()));
- };
-
-pair: string COLON value {
- QVariantMap pair;
- pair.insert ($1.toString(), QVariant($3));
- $$ = QVariant (pair);
- };
-
-array: SQUARE_BRACKET_OPEN values SQUARE_BRACKET_CLOSE { $$ = $2; };
-
-values: /* empty */ { $$ = QVariant (QVariantList()); }
- | value r_values {
- QVariantList members = $2.toList();
- $2 = QVariant(); // Allow reuse of list
- members.prepend ($1);
- $$ = QVariant(members);
- };
-
-r_values: /* empty */ { $$ = QVariant (QVariantList()); }
- | COMMA value r_values {
- QVariantList members = $3.toList();
- $3 = QVariant(); // Allow reuse of list
- members.prepend ($2);
- $$ = QVariant(members);
- };
-
-value: string { $$ = $1; }
- | special_or_number { $$ = $1; }
- | object { $$ = $1; }
- | array { $$ = $1; }
- | TRUE_VAL { $$ = QVariant (true); }
- | FALSE_VAL { $$ = QVariant (false); }
- | NULL_VAL {
- QVariant null_variant;
- $$ = null_variant;
- };
-
-special_or_number: MINUS INFINITY_VAL { $$ = QVariant(QVariant::Double); $$.setValue( -std::numeric_limits<double>::infinity() ); }
- | INFINITY_VAL { $$ = QVariant(QVariant::Double); $$.setValue( std::numeric_limits<double>::infinity() ); }
- | NAN_VAL { $$ = QVariant(QVariant::Double); $$.setValue( std::numeric_limits<double>::quiet_NaN() ); }
- | number;
-
-number: int {
- if ($1.toByteArray().startsWith('-')) {
- $$ = QVariant (QVariant::LongLong);
- $$.setValue($1.toLongLong());
- }
- else {
- $$ = QVariant (QVariant::ULongLong);
- $$.setValue($1.toULongLong());
- }
- }
- | int fract {
- const QByteArray value = $1.toByteArray() + $2.toByteArray();
- $$ = QVariant(QVariant::Double);
- $$.setValue(value.toDouble());
- }
- | int exp { $$ = QVariant ($1.toByteArray() + $2.toByteArray()); }
- | int fract exp {
- const QByteArray value = $1.toByteArray() + $2.toByteArray() + $3.toByteArray();
- $$ = QVariant (value);
- };
-
-int: DIGIT digits { $$ = QVariant ($1.toByteArray() + $2.toByteArray()); }
- | MINUS DIGIT digits { $$ = QVariant (QByteArray("-") + $2.toByteArray() + $3.toByteArray()); };
-
-digits: /* empty */ { $$ = QVariant (QByteArray("")); }
- | DIGIT digits {
- $$ = QVariant($1.toByteArray() + $2.toByteArray());
- };
-
-fract: DOT digits {
- $$ = QVariant(QByteArray(".") + $2.toByteArray());
- };
-
-exp: E digits { $$ = QVariant($1.toByteArray() + $2.toByteArray()); };
-
-string: QUOTMARKOPEN string_arg QUOTMARKCLOSE { $$ = $2; };
-
-string_arg: /*empty */ { $$ = QVariant (QString(QLatin1String(""))); }
- | STRING {
- $$ = $1;
- };
-
-%%
-
-int yy::yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver)
-{
- JSonScanner* scanner = driver->m_scanner;
- yylval->clear();
- int ret = scanner->yylex(yylval, yylloc);
-
- qjsonDebug() << "json_parser::yylex - calling scanner yylval==|"
- << yylval->toByteArray() << "|, ret==|" << QString::number(ret) << "|";
-
- return ret;
-}
-
-void yy::json_parser::error (const yy::location& yyloc,
- const std::string& error)
-{
- /*qjsonDebug() << yyloc.begin.line;
- qjsonDebug() << yyloc.begin.column;
- qjsonDebug() << yyloc.end.line;
- qjsonDebug() << yyloc.end.column;*/
- qjsonDebug() << "json_parser::error [line" << yyloc.end.line << "] -" << error.c_str() ;
- driver->setError(QString::fromLatin1(error.c_str()), yyloc.end.line);
-}
diff --git a/thirdparty/qjson/json_scanner.cpp b/thirdparty/qjson/json_scanner.cpp
deleted file mode 100644
index de0ddc23..00000000
--- a/thirdparty/qjson/json_scanner.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/* This file is part of QJson
- *
- * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "qjson_debug.h"
-#include "json_scanner.h"
-#include "json_parser.hh"
-
-#include <ctype.h>
-
-#include <QtCore/QDebug>
-#include <QtCore/QRegExp>
-
-#include <cassert>
-
-bool ishexnstring(const QString& string) {
- for (int i = 0; i < string.length(); i++) {
- if (isxdigit(string[i] == 0))
- return false;
- }
- return true;
-}
-
-JSonScanner::JSonScanner(QIODevice* io)
- : m_allowSpecialNumbers(false),
- m_io (io)
-{
- m_quotmarkClosed = true;
- m_quotmarkCount = 0;
-}
-
-void JSonScanner::allowSpecialNumbers(bool allow) {
- m_allowSpecialNumbers = allow;
-}
-
-static QString unescape( const QByteArray& ba, bool* ok ) {
- assert( ok );
- *ok = false;
- QString res;
- QByteArray seg;
- bool bs = false;
- for ( int i = 0, size = ba.size(); i < size; ++i ) {
- const char ch = ba[i];
- if ( !bs ) {
- if ( ch == '\\' )
- bs = true;
- else
- seg += ch;
- } else {
- bs = false;
- switch ( ch ) {
- case 'b':
- seg += '\b';
- break;
- case 'f':
- seg += '\f';
- break;
- case 'n':
- seg += '\n';
- break;
- case 'r':
- seg += '\r';
- break;
- case 't':
- seg += '\t';
- break;
- case 'u':
- {
- res += QString::fromUtf8( seg );
- seg.clear();
-
- if ( i > size - 5 ) {
- //error
- return QString();
- }
-
- const QString hex_digit1 = QString::fromUtf8( ba.mid( i + 1, 2 ) );
- const QString hex_digit2 = QString::fromUtf8( ba.mid( i + 3, 2 ) );
- i += 4;
-
- if ( !ishexnstring( hex_digit1 ) || !ishexnstring( hex_digit2 ) ) {
- qCritical() << "Not an hex string:" << hex_digit1 << hex_digit2;
- return QString();
- }
- bool hexOk;
- const ushort hex_code1 = hex_digit1.toShort( &hexOk, 16 );
- if (!hexOk) {
- qCritical() << "error converting hex value to short:" << hex_digit1;
- return QString();
- }
- const ushort hex_code2 = hex_digit2.toShort( &hexOk, 16 );
- if (!hexOk) {
- qCritical() << "error converting hex value to short:" << hex_digit2;
- return QString();
- }
-
- res += QChar(hex_code2, hex_code1);
- break;
- }
- case '\\':
- seg += '\\';
- break;
- default:
- seg += ch;
- break;
- }
- }
- }
- res += QString::fromUtf8( seg );
- *ok = true;
- return res;
-}
-
-int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc)
-{
- char ch;
-
- if (!m_io->isOpen()) {
- qCritical() << "JSonScanner::yylex - io device is not open";
- return -1;
- }
-
- yylloc->step();
-
- do {
- bool ret;
- if (m_io->atEnd()) {
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::END";
- return yy::json_parser::token::END;
- }
- else
- ret = m_io->getChar(&ch);
-
- if (!ret) {
- qCritical() << "JSonScanner::yylex - error reading from io device";
- return -1;
- }
-
- qjsonDebug() << "JSonScanner::yylex - got |" << ch << "|";
- yylloc->columns();
-
- if (ch == '\n' || ch == '\r')
- yylloc->lines();
- } while (m_quotmarkClosed && (isspace(ch) != 0));
-
- if (m_quotmarkClosed && ((ch == 't') || (ch == 'T'))) {
- const QByteArray buf = m_io->peek(3).toLower();
- if (buf == "rue") {
- m_io->read (3);
- yylloc->columns(3);
- qjsonDebug() << "JSonScanner::yylex - TRUE_VAL";
- return yy::json_parser::token::TRUE_VAL;
- }
- }
- else if (m_quotmarkClosed && ((ch == 'n') || (ch == 'N'))) {
- const QByteArray buf = m_io->peek(3).toLower();
- if (buf == "ull") {
- m_io->read (3);
- yylloc->columns(3);
- qjsonDebug() << "JSonScanner::yylex - NULL_VAL";
- return yy::json_parser::token::NULL_VAL;
- } else if (buf.startsWith("an") && m_allowSpecialNumbers) {
- m_io->read(2);
- yylloc->columns(2);
- qjsonDebug() << "JSonScanner::yylex - NAN_VAL";
- return yy::json_parser::token::NAN_VAL;
-
- }
- }
- else if (m_quotmarkClosed && ((ch == 'f') || (ch == 'F'))) {
- // check false value
- const QByteArray buf = m_io->peek(4).toLower();
- if (buf.length() == 4) {
- if (buf == "alse") {
- m_io->read (4);
- yylloc->columns(4);
- qjsonDebug() << "JSonScanner::yylex - FALSE_VAL";
- return yy::json_parser::token::FALSE_VAL;
- }
- }
- }
- else if (m_quotmarkClosed && ((ch == 'e') || (ch == 'E'))) {
- QByteArray ret(1, ch);
- const QByteArray buf = m_io->peek(1);
- if (!buf.isEmpty()) {
- if ((buf[0] == '+' ) || (buf[0] == '-' )) {
- ret += m_io->read (1);
- yylloc->columns();
- }
- }
- *yylval = QVariant(QString::fromUtf8(ret));
- return yy::json_parser::token::E;
- }
- else if (m_allowSpecialNumbers && m_quotmarkClosed && ((ch == 'I') || (ch == 'i'))) {
- QByteArray ret(1, ch);
- const QByteArray buf = m_io->peek(7);
- if (buf == "nfinity") {
- m_io->read(7);
- yylloc->columns(7);
- qjsonDebug() << "JSonScanner::yylex - INFINITY_VAL";
- return yy::json_parser::token::INFINITY_VAL;
- }
- }
-
- if (ch != '"' && !m_quotmarkClosed) {
- // we're inside a " " block
- QByteArray raw;
- raw += ch;
- char prevCh = ch;
- bool escape_on = (ch == '\\') ? true : false;
-
- while ( true ) {
- char nextCh;
- qint64 ret = m_io->peek(&nextCh, 1);
- if (ret != 1) {
- if (m_io->atEnd())
- return yy::json_parser::token::END;
- else
- return -1;
- } else if ( !escape_on && nextCh == '\"' ) {
- bool ok;
- const QString str = unescape( raw, &ok );
- *yylval = ok ? str : QString();
- return ok ? yy::json_parser::token::STRING : -1;
- }
-#if 0
- if ( prevCh == '\\' && nextCh != '"' && nextCh != '\\' && nextCh != '/' &&
- nextCh != 'b' && nextCh != 'f' && nextCh != 'n' &&
- nextCh != 'r' && nextCh != 't' && nextCh != 'u') {
- qjsonDebug() << "Just read" << nextCh;
- qjsonDebug() << "JSonScanner::yylex - error decoding escaped sequence";
- return -1;
- }
-#endif
- m_io->read(1); // consume
- raw += nextCh;
- prevCh = nextCh;
- if (escape_on)
- escape_on = false;
- else
- escape_on = (prevCh == '\\') ? true : false;
-#if 0
- if (nextCh == '\\') {
- char buf;
- if (m_io->getChar (&buf)) {
- yylloc->columns();
- if (((buf != '"') && (buf != '\\') && (buf != '/') &&
- (buf != 'b') && (buf != 'f') && (buf != 'n') &&
- (buf != 'r') && (buf != 't') && (buf != 'u'))) {
- qjsonDebug() << "Just read" << buf;
- qjsonDebug() << "JSonScanner::yylex - error decoding escaped sequence";
- return -1;
- }
- } else {
- qCritical() << "JSonScanner::yylex - error decoding escaped sequence : io error";
- return -1;
- }
- }
-#endif
- }
- }
- else if (isdigit(ch) != 0 && m_quotmarkClosed) {
- bool ok;
- QByteArray numArray = QByteArray::fromRawData( &ch, 1 * sizeof(char) );
- qulonglong number = numArray.toULongLong(&ok);
- if (!ok) {
- //This shouldn't happen
- qCritical() << "JSonScanner::yylex - error while converting char to ulonglong, returning -1";
- return -1;
- }
- if (number == 0) {
- // we have to return immediately otherwise numbers like
- // 2.04 will be converted to 2.4
- *yylval = QVariant(number);
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DIGIT";
- return yy::json_parser::token::DIGIT;
- }
-
- char nextCh;
- qint64 ret = m_io->peek(&nextCh, 1);
- while (ret == 1 && isdigit(nextCh)) {
- m_io->read(1); //consume
- yylloc->columns(1);
- numArray = QByteArray::fromRawData( &nextCh, 1 * sizeof(char) );
- number = number * 10 + numArray.toULongLong(&ok);
- if (!ok) {
- //This shouldn't happen
- qCritical() << "JSonScanner::yylex - error while converting char to ulonglong, returning -1";
- return -1;
- }
- ret = m_io->peek(&nextCh, 1);
- }
-
- *yylval = QVariant(number);
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DIGIT";
- return yy::json_parser::token::DIGIT;
- }
- else if (isalnum(ch) != 0) {
- *yylval = QVariant(QString(QChar::fromLatin1(ch)));
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::WORD ("
- << ch << ")";
- return yy::json_parser::token::STRING;
- }
- else if (ch == ':') {
- // set yylval
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::COLON";
- return yy::json_parser::token::COLON;
- }
- else if (ch == '"') {
- // yy::json_parser::token::QUOTMARK (")
-
- // set yylval
- m_quotmarkCount++;
- if (m_quotmarkCount %2 == 0) {
- m_quotmarkClosed = true;
- m_quotmarkCount = 0;
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::QUOTMARKCLOSE";
- return yy::json_parser::token::QUOTMARKCLOSE;
- }
- else {
- m_quotmarkClosed = false;
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::QUOTMARKOPEN";
- return yy::json_parser::token::QUOTMARKOPEN;
- }
- }
- else if (ch == ',') {
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::COMMA";
- return yy::json_parser::token::COMMA;
- }
- else if (ch == '.') {
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DOT";
- return yy::json_parser::token::DOT;
- }
- else if (ch == '-') {
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::MINUS";
- return yy::json_parser::token::MINUS;
- }
- else if (ch == '[') {
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_OPEN";
- return yy::json_parser::token::SQUARE_BRACKET_OPEN;
- }
- else if (ch == ']') {
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_CLOSE";
- return yy::json_parser::token::SQUARE_BRACKET_CLOSE;
- }
- else if (ch == '{') {
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_OPEN";
- return yy::json_parser::token::CURLY_BRACKET_OPEN;
- }
- else if (ch == '}') {
- qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_CLOSE";
- return yy::json_parser::token::CURLY_BRACKET_CLOSE;
- }
-
- //unknown char!
- //TODO yyerror?
- qCritical() << "JSonScanner::yylex - unknown char, returning -1";
- return -1;
-}
-
-
diff --git a/thirdparty/qjson/json_scanner.h b/thirdparty/qjson/json_scanner.h
deleted file mode 100644
index f13e565f..00000000
--- a/thirdparty/qjson/json_scanner.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* This file is part of QJson
- *
- * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef _JSON_SCANNER
-#define _JSON_SCANNER
-
-#include <fstream>
-#include <string>
-
-#include <QtCore/QIODevice>
-#include <QtCore/QVariant>
-
-#define YYSTYPE QVariant
-
-#include "parser_p.h"
-
-namespace yy {
- class location;
- int yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver);
-}
-
-class JSonScanner
-{
- public:
- explicit JSonScanner(QIODevice* io);
- int yylex(YYSTYPE* yylval, yy::location *yylloc);
- void allowSpecialNumbers(bool allow);
-
- protected:
- bool m_quotmarkClosed;
- bool m_allowSpecialNumbers;
- unsigned int m_quotmarkCount;
- QIODevice* m_io;
-};
-
-#endif
-
diff --git a/thirdparty/qjson/location.hh b/thirdparty/qjson/location.hh
deleted file mode 100644
index 485fd77c..00000000
--- a/thirdparty/qjson/location.hh
+++ /dev/null
@@ -1,145 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Locations for Bison parsers in C++
-
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program 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
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/**
- ** \file location.hh
- ** Define the yy::location class.
- */
-
-#ifndef BISON_LOCATION_HH
-# define BISON_LOCATION_HH
-
-# include <iostream>
-# include <string>
-# include "position.hh"
-
-namespace yy
-{
-
- /// Abstract a location.
- class location
- {
- public:
-
- /// Construct a location.
- location ()
- : begin (), end ()
- {
- }
-
-
- /// Initialization.
- inline void initialize (std::string* fn)
- {
- begin.initialize (fn);
- end = begin;
- }
-
- /** \name Line and Column related manipulators
- ** \{ */
- public:
- /// Reset initial location to final location.
- inline void step ()
- {
- begin = end;
- }
-
- /// Extend the current location to the COUNT next columns.
- inline void columns (unsigned int count = 1)
- {
- end += count;
- }
-
- /// Extend the current location to the COUNT next lines.
- inline void lines (unsigned int count = 1)
- {
- end.lines (count);
- }
- /** \} */
-
-
- public:
- /// Beginning of the located region.
- position begin;
- /// End of the located region.
- position end;
- };
-
- /// Join two location objects to create a location.
- inline const location operator+ (const location& begin, const location& end)
- {
- location res = begin;
- res.end = end.end;
- return res;
- }
-
- /// Add two location objects.
- inline const location operator+ (const location& begin, unsigned int width)
- {
- location res = begin;
- res.columns (width);
- return res;
- }
-
- /// Add and assign a location.
- inline location& operator+= (location& res, unsigned int width)
- {
- res.columns (width);
- return res;
- }
-
- /** \brief Intercept output stream redirection.
- ** \param ostr the destination output stream
- ** \param loc a reference to the location to redirect
- **
- ** Avoid duplicate information.
- */
- inline std::ostream& operator<< (std::ostream& ostr, const location& loc)
- {
- position last = loc.end - 1;
- ostr << loc.begin;
- if (last.filename
- && (!loc.begin.filename
- || *loc.begin.filename != *last.filename))
- ostr << '-' << last;
- else if (loc.begin.line != last.line)
- ostr << '-' << last.line << '.' << last.column;
- else if (loc.begin.column != last.column)
- ostr << '-' << last.column;
- return ostr;
- }
-
-}
-
-#endif // not BISON_LOCATION_HH
diff --git a/thirdparty/qjson/parser.cpp b/thirdparty/qjson/parser.cpp
deleted file mode 100644
index e203b876..00000000
--- a/thirdparty/qjson/parser.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/* This file is part of QJson
- *
- * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "parser.h"
-#include "parser_p.h"
-#include "json_parser.hh"
-#include "json_scanner.h"
-
-#include <QtCore/QBuffer>
-#include <QtCore/QStringList>
-#include <QtCore/QTextStream>
-#include <QtCore/QDebug>
-
-using namespace QJson;
-
-ParserPrivate::ParserPrivate() :
- m_scanner(0)
- , m_negate(false)
- , m_error(false)
- , m_errorLine(0)
- , m_specialNumbersAllowed(false)
-{
-}
-
-ParserPrivate::~ParserPrivate()
-{
- delete m_scanner;
-}
-
-void ParserPrivate::setError(QString errorMsg, int errorLine) {
- m_error = true;
- m_errorMsg = errorMsg;
- m_errorLine = errorLine;
-}
-
-Parser::Parser() :
- d(new ParserPrivate)
-{
-}
-
-Parser::~Parser()
-{
- delete d;
-}
-
-QVariant Parser::parse (QIODevice* io, bool* ok)
-{
- d->m_errorMsg.clear();
- delete d->m_scanner;
- d->m_scanner = 0;
-
- if (!io->isOpen()) {
- if (!io->open(QIODevice::ReadOnly)) {
- if (ok != 0)
- *ok = false;
- qCritical ("Error opening device");
- return QVariant();
- }
- }
-
- if (!io->isReadable()) {
- if (ok != 0)
- *ok = false;
- qCritical ("Device is not readable");
- io->close();
- return QVariant();
- }
-
- d->m_scanner = new JSonScanner (io);
- d->m_scanner->allowSpecialNumbers(d->m_specialNumbersAllowed);
- yy::json_parser parser(d);
- parser.parse();
-
- delete d->m_scanner;
- d->m_scanner = 0;
-
- if (ok != 0)
- *ok = !d->m_error;
-
- io->close();
- return d->m_result;
-}
-
-QVariant Parser::parse(const QByteArray& jsonString, bool* ok) {
- QBuffer buffer;
- buffer.open(QBuffer::ReadWrite);
- buffer.write(jsonString);
- buffer.seek(0);
- return parse (&buffer, ok);
-}
-
-QString Parser::errorString() const
-{
- return d->m_errorMsg;
-}
-
-int Parser::errorLine() const
-{
- return d->m_errorLine;
-}
-
-void QJson::Parser::allowSpecialNumbers(bool allowSpecialNumbers) {
- d->m_specialNumbersAllowed = allowSpecialNumbers;
-}
-
-bool Parser::specialNumbersAllowed() const {
- return d->m_specialNumbersAllowed;
-}
diff --git a/thirdparty/qjson/parser.h b/thirdparty/qjson/parser.h
deleted file mode 100644
index 6fb58d89..00000000
--- a/thirdparty/qjson/parser.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* This file is part of QJson
- *
- * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef QJSON_PARSER_H
-#define QJSON_PARSER_H
-
-#include "qjson_export.h"
-
-class QIODevice;
-class QVariant;
-
-namespace QJson {
-
- class ParserPrivate;
-
- /**
- * @brief Main class used to convert JSON data to QVariant objects
- */
- class QJSON_EXPORT Parser
- {
- public:
- Parser();
- ~Parser();
-
- /**
- * Read JSON string from the I/O Device and converts it to a QVariant object
- * @param io Input output device
- * @param ok if a conversion error occurs, *ok is set to false; otherwise *ok is set to true.
- * @returns a QVariant object generated from the JSON string
- */
- QVariant parse(QIODevice* io, bool* ok = 0);
-
- /**
- * This is a method provided for convenience.
- * @param jsonData data containing the JSON object representation
- * @param ok if a conversion error occurs, *ok is set to false; otherwise *ok is set to true.
- * @returns a QVariant object generated from the JSON string
- * @sa errorString
- * @sa errorLine
- */
- QVariant parse(const QByteArray& jsonData, bool* ok = 0);
-
- /**
- * This method returns the error message
- * @returns a QString object containing the error message of the last parse operation
- * @sa errorLine
- */
- QString errorString() const;
-
- /**
- * This method returns line number where the error occurred
- * @returns the line number where the error occurred
- * @sa errorString
- */
- int errorLine() const;
-
- /**
- * Sets whether special numbers (Infinity, -Infinity, NaN) are allowed as an extension to
- * the standard
- * @param allowSpecialNumbers new value of whether special numbers are allowed
- * @sa specialNumbersAllowed
- */
- void allowSpecialNumbers(bool allowSpecialNumbers);
-
- /**
- * @returns whether special numbers (Infinity, -Infinity, NaN) are allowed
- * @sa allowSpecialNumbers
- */
- bool specialNumbersAllowed() const;
-
- private:
- Q_DISABLE_COPY(Parser)
- ParserPrivate* const d;
- };
-}
-
-#endif // QJSON_PARSER_H
diff --git a/thirdparty/qjson/parser_p.h b/thirdparty/qjson/parser_p.h
deleted file mode 100644
index aae86a12..00000000
--- a/thirdparty/qjson/parser_p.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* This file is part of QJson
- *
- * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
- * Copyright (C) 2009 Michael Leupold <lemma@confuego.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef QJSON_PARSER_P_H
-#define QJSON_PARSER_P_H
-
-#include "parser.h"
-
-#include <QtCore/QString>
-#include <QtCore/QVariant>
-
-class JSonScanner;
-
-namespace yy {
- class json_parser;
-}
-
-namespace QJson {
-
- class ParserPrivate
- {
- public:
- ParserPrivate();
- ~ParserPrivate();
-
- void setError(QString errorMsg, int line);
-
- JSonScanner* m_scanner;
- bool m_negate;
- bool m_error;
- int m_errorLine;
- QString m_errorMsg;
- QVariant m_result;
- bool m_specialNumbersAllowed;
- };
-}
-
-#endif // QJSON_PARSER_H
diff --git a/thirdparty/qjson/parserrunnable.cpp b/thirdparty/qjson/parserrunnable.cpp
deleted file mode 100644
index 88baf4cf..00000000
--- a/thirdparty/qjson/parserrunnable.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This file is part of qjson
- *
- * Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "parserrunnable.h"
-
-#include "parser.h"
-
-#include <QtCore/QDebug>
-#include <QtCore/QVariant>
-
-using namespace QJson;
-
-class QJson::ParserRunnable::Private
-{
- public:
- QByteArray m_data;
-};
-
-ParserRunnable::ParserRunnable(QObject* parent)
- : QObject(parent),
- QRunnable(),
- d(new Private)
-{
- qRegisterMetaType<QVariant>("QVariant");
-}
-
-ParserRunnable::~ParserRunnable()
-{
- delete d;
-}
-
-void ParserRunnable::setData( const QByteArray& data ) {
- d->m_data = data;
-}
-
-void ParserRunnable::run()
-{
- qDebug() << Q_FUNC_INFO;
-
- bool ok;
- Parser parser;
- QVariant result = parser.parse (d->m_data, &ok);
- if (ok) {
- qDebug() << "successfully converted json item to QVariant object";
- emit parsingFinished(result, true, QString());
- } else {
- const QString errorText = tr("An error occurred while parsing json: %1").arg(parser.errorString());
- qCritical() << errorText;
- emit parsingFinished(QVariant(), false, errorText);
- }
-}
diff --git a/thirdparty/qjson/parserrunnable.h b/thirdparty/qjson/parserrunnable.h
deleted file mode 100644
index 2badeb64..00000000
--- a/thirdparty/qjson/parserrunnable.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* This file is part of qjson
- *
- * Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef PARSERRUNNABLE_H
-#define PARSERRUNNABLE_H
-
-#include "qjson_export.h"
-
-#include <QtCore/QObject>
-#include <QtCore/QRunnable>
-
-class QVariant;
-
-namespace QJson {
- /**
- * @brief Convenience class for converting JSON data to QVariant objects using a dedicated thread
- */
- class QJSON_EXPORT ParserRunnable : public QObject, public QRunnable
- {
- Q_OBJECT
- public:
- /**
- * This signal is emitted when the conversion process has been completed
- * @param data contains the JSON data that has to be converted
- * @param parent parent of the object
- **/
- explicit ParserRunnable(QObject* parent = 0);
- ~ParserRunnable();
-
- void setData( const QByteArray& data );
-
- void run();
-
- Q_SIGNALS:
- /**
- * This signal is emitted when the parsing process has been completed
- * @param json contains the result of the parsing
- * @param ok if a parsing error occurs ok is set to false, otherwise it's set to true.
- * @param error_msg contains a string explaining the failure reason
- **/
- void parsingFinished(const QVariant& json, bool ok, const QString& error_msg);
-
- private:
- Q_DISABLE_COPY(ParserRunnable)
- class Private;
- Private* const d;
- };
-}
-
-#endif // PARSERRUNNABLE_H
diff --git a/thirdparty/qjson/position.hh b/thirdparty/qjson/position.hh
deleted file mode 100644
index 27331d0d..00000000
--- a/thirdparty/qjson/position.hh
+++ /dev/null
@@ -1,142 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Positions for Bison parsers in C++
-
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program 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
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/**
- ** \file position.hh
- ** Define the yy::position class.
- */
-
-#ifndef BISON_POSITION_HH
-# define BISON_POSITION_HH
-
-# include <iostream>
-# include <string>
-
-namespace yy
-{
- /// Abstract a position.
- class position
- {
- public:
-
- /// Construct a position.
- position ()
- : filename (0), line (1), column (0)
- {
- }
-
-
- /// Initialization.
- inline void initialize (std::string* fn)
- {
- filename = fn;
- line = 1;
- column = 0;
- }
-
- /** \name Line and Column related manipulators
- ** \{ */
- public:
- /// (line related) Advance to the COUNT next lines.
- inline void lines (int count = 1)
- {
- column = 0;
- line += count;
- }
-
- /// (column related) Advance to the COUNT next columns.
- inline void columns (int count = 1)
- {
- int leftmost = 0;
- int current = column;
- if (leftmost <= current + count)
- column += count;
- else
- column = 0;
- }
- /** \} */
-
- public:
- /// File name to which this position refers.
- std::string* filename;
- /// Current line number.
- unsigned int line;
- /// Current column number.
- unsigned int column;
- };
-
- /// Add and assign a position.
- inline const position&
- operator+= (position& res, const int width)
- {
- res.columns (width);
- return res;
- }
-
- /// Add two position objects.
- inline const position
- operator+ (const position& begin, const int width)
- {
- position res = begin;
- return res += width;
- }
-
- /// Add and assign a position.
- inline const position&
- operator-= (position& res, const int width)
- {
- return res += -width;
- }
-
- /// Add two position objects.
- inline const position
- operator- (const position& begin, const int width)
- {
- return begin + -width;
- }
-
- /** \brief Intercept output stream redirection.
- ** \param ostr the destination output stream
- ** \param pos a reference to the position to redirect
- */
- inline std::ostream&
- operator<< (std::ostream& ostr, const position& pos)
- {
- if (pos.filename)
- ostr << *pos.filename << ':';
- return ostr << pos.line << '.' << pos.column;
- }
-
-}
-#endif // not BISON_POSITION_HH
diff --git a/thirdparty/qjson/qjson_debug.h b/thirdparty/qjson/qjson_debug.h
deleted file mode 100644
index 0a511aee..00000000
--- a/thirdparty/qjson/qjson_debug.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* This file is part of qjson
- *
- * Copyright (C) 2009 Michael Leupold <lemma@confuego.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef QJSON_DEBUG_H
-#define QJSON_DEBUG_H
-
-#include <QtCore/QDebug>
-
-// define qjsonDebug()
-#ifdef QJSON_VERBOSE_DEBUG_OUTPUT
- inline QDebug qjsonDebug() { return QDebug(QtDebugMsg); }
-#else
- inline QNoDebug qjsonDebug() { return QNoDebug(); }
-#endif
-
-#endif
diff --git a/thirdparty/qjson/qjson_export.h b/thirdparty/qjson/qjson_export.h
deleted file mode 100644
index 9a807b91..00000000
--- a/thirdparty/qjson/qjson_export.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* This file is part of the KDE project
- Copyright (C) 2009 Pino Toscano <pino@kde.org>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License version 2.1, as published by the Free Software Foundation.
-
-
- 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 GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#ifndef QJSON_EXPORT_H
-#define QJSON_EXPORT_H
-
-#include <QtCore/qglobal.h>
-
-#ifndef QJSON_EXPORT
-# if defined(QJSON_MAKEDLL)
- /* We are building this library */
-# define QJSON_EXPORT Q_DECL_EXPORT
-# else
- /* We are using this library */
-# define QJSON_EXPORT Q_DECL_IMPORT
-# endif
-#endif
-
-#endif
diff --git a/thirdparty/qjson/qobjecthelper.cpp b/thirdparty/qjson/qobjecthelper.cpp
deleted file mode 100644
index b756488f..00000000
--- a/thirdparty/qjson/qobjecthelper.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* This file is part of qjson
- *
- * Copyright (C) 2009 Till Adam <adam@kde.org>
- * Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#include "qobjecthelper.h"
-
-#include <QtCore/QMetaObject>
-#include <QtCore/QMetaProperty>
-#include <QtCore/QObject>
-
-using namespace QJson;
-
-class QObjectHelper::QObjectHelperPrivate {
-};
-
-QObjectHelper::QObjectHelper()
- : d (new QObjectHelperPrivate)
-{
-}
-
-QObjectHelper::~QObjectHelper()
-{
- delete d;
-}
-
-QVariantMap QObjectHelper::qobject2qvariant( const QObject* object,
- const QStringList& ignoredProperties)
-{
- QVariantMap result;
- const QMetaObject *metaobject = object->metaObject();
- int count = metaobject->propertyCount();
- for (int i=0; i<count; ++i) {
- QMetaProperty metaproperty = metaobject->property(i);
- const char *name = metaproperty.name();
-
- if (ignoredProperties.contains(QLatin1String(name)) || (!metaproperty.isReadable()))
- continue;
-
- QVariant value = object->property(name);
- result[QLatin1String(name)] = value;
- }
- return result;
-}
-
-void QObjectHelper::qvariant2qobject(const QVariantMap& variant, QObject* object)
-{
- const QMetaObject *metaobject = object->metaObject();
-
- QVariantMap::const_iterator iter;
- for (iter = variant.constBegin(); iter != variant.constEnd(); ++iter) {
- int pIdx = metaobject->indexOfProperty( iter.key().toAscii() );
-
- if ( pIdx < 0 ) {
- continue;
- }
-
- QMetaProperty metaproperty = metaobject->property( pIdx );
- QVariant::Type type = metaproperty.type();
- QVariant v( iter.value() );
- if ( v.canConvert( type ) ) {
- v.convert( type );
- metaproperty.write( object, v );
- } else if (QString(QLatin1String("QVariant")).compare(QLatin1String(metaproperty.typeName())) == 0) {
- metaproperty.write( object, v );
- }
- }
-}
diff --git a/thirdparty/qjson/qobjecthelper.h b/thirdparty/qjson/qobjecthelper.h
deleted file mode 100644
index 514ca1fa..00000000
--- a/thirdparty/qjson/qobjecthelper.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* This file is part of qjson
- *
- * Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef QOBJECTHELPER_H
-#define QOBJECTHELPER_H
-
-#include "qjson_export.h"
-
-#include <QtCore/QLatin1String>
-#include <QtCore/QStringList>
-#include <QtCore/QVariantMap>
-
-class QObject;
-
-namespace QJson {
- /**
- * @brief Class used to convert QObject into QVariant and vivce-versa.
- * During these operations only the class attributes defined as properties will
- * be considered.
- * Properties marked as 'non-stored' will be ignored.
- *
- * Suppose the declaration of the Person class looks like this:
- * \code
- * class Person : public QObject
- {
- Q_OBJECT
-
- Q_PROPERTY(QString name READ name WRITE setName)
- Q_PROPERTY(int phoneNumber READ phoneNumber WRITE setPhoneNumber)
- Q_PROPERTY(Gender gender READ gender WRITE setGender)
- Q_PROPERTY(QDate dob READ dob WRITE setDob)
- Q_ENUMS(Gender)
-
- public:
- Person(QObject* parent = 0);
- ~Person();
-
- QString name() const;
- void setName(const QString& name);
-
- int phoneNumber() const;
- void setPhoneNumber(const int phoneNumber);
-
- enum Gender {Male, Female};
- void setGender(Gender gender);
- Gender gender() const;
-
- QDate dob() const;
- void setDob(const QDate& dob);
-
- private:
- QString m_name;
- int m_phoneNumber;
- Gender m_gender;
- QDate m_dob;
- };
- \endcode
-
- The following code will serialize an instance of Person to JSON :
-
- \code
- Person person;
- person.setName("Flavio");
- person.setPhoneNumber(123456);
- person.setGender(Person::Male);
- person.setDob(QDate(1982, 7, 12));
-
- QVariantMap variant = QObjectHelper::qobject2qvariant(&person);
- Serializer serializer;
- qDebug() << serializer.serialize( variant);
- \endcode
-
- The generated output will be:
- \code
- { "dob" : "1982-07-12", "gender" : 0, "name" : "Flavio", "phoneNumber" : 123456 }
- \endcode
-
- It's also possible to initialize a QObject using the values stored inside of
- a QVariantMap.
-
- Suppose you have the following JSON data stored into a QString:
- \code
- { "dob" : "1982-07-12", "gender" : 0, "name" : "Flavio", "phoneNumber" : 123456 }
- \endcode
-
- The following code will initialize an already allocated instance of Person
- using the JSON values:
- \code
- Parser parser;
- QVariant variant = parser.parse(json);
-
- Person person;
- QObjectHelper::qvariant2qobject(variant.toMap(), &person);
- \endcode
-
- \sa Parser
- \sa Serializer
- */
- class QJSON_EXPORT QObjectHelper {
- public:
- QObjectHelper();
- ~QObjectHelper();
-
- /**
- * This method converts a QObject instance into a QVariantMap.
- *
- * @param object The QObject instance to be converted.
- * @param ignoredProperties Properties that won't be converted.
- */
- static QVariantMap qobject2qvariant( const QObject* object,
- const QStringList& ignoredProperties = QStringList(QString(QLatin1String("objectName"))));
-
- /**
- * This method converts a QVariantMap instance into a QObject
- *
- * @param object The QObject instance to be converted.
- */
- static void qvariant2qobject(const QVariantMap& variant, QObject* object);
-
- private:
- Q_DISABLE_COPY(QObjectHelper)
- class QObjectHelperPrivate;
- QObjectHelperPrivate* const d;
- };
-}
-
-#endif // QOBJECTHELPER_H
diff --git a/thirdparty/qjson/serializer.cpp b/thirdparty/qjson/serializer.cpp
deleted file mode 100644
index 41407c27..00000000
--- a/thirdparty/qjson/serializer.cpp
+++ /dev/null
@@ -1,322 +0,0 @@
-/* This file is part of qjson
- *
- * Copyright (C) 2009 Till Adam <adam@kde.org>
- * Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "serializer.h"
-
-#include <QtCore/QDataStream>
-#include <QtCore/QStringList>
-#include <QtCore/QVariant>
-
-#include <cmath>
-
-#ifdef _MSC_VER // using MSVC compiler
-#include <float.h>
-#endif
-
-using namespace QJson;
-
-class Serializer::SerializerPrivate {
- public:
- SerializerPrivate() :
- specialNumbersAllowed(false),
- indentMode(QJson::IndentNone),
- doublePrecision(6) {
- }
- bool specialNumbersAllowed;
- IndentMode indentMode;
- int doublePrecision;
- QByteArray buildIndent(int spaces);
- QByteArray serialize( const QVariant &v, int reserved = 0);
- QString sanitizeString( QString str );
- QByteArray join( const QList<QByteArray>& list, const QByteArray& sep );
-};
-
-QByteArray Serializer::SerializerPrivate::join( const QList<QByteArray>& list, const QByteArray& sep ) {
- QByteArray res;
- Q_FOREACH( const QByteArray& i, list ) {
- if ( !res.isEmpty() )
- res += sep;
- res += i;
- }
- return res;
-}
-
-QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, int reserved )
-{
- QByteArray str;
- bool error = false;
- QByteArray indent;
-
- if ( ! v.isValid() ) { // invalid or null?
- str = "null";
- } else if (( v.type() == QVariant::List ) || ( v.type() == QVariant::StringList )){ // an array or a stringlist?
- const QVariantList list = v.toList();
- QList<QByteArray> values;
- Q_FOREACH( const QVariant& var, list )
- {
- reserved++;
- QByteArray serializedValue = serialize( var,reserved );
- reserved--;
- if ( serializedValue.isNull() ) {
- error = true;
- break;
- }
- values << serializedValue;
- }
-
- if (indentMode == QJson::IndentMinimum) {
- QByteArray indent = buildIndent(reserved - 1);
- str = "[\n" + join( values, ",\n" ) + "\n" + indent + "]";
- }
- else if (indentMode == QJson::IndentMedium || indentMode == QJson::IndentFull) {
- QByteArray indent = buildIndent(reserved);
- str = "[\n" + join( values, ",\n" ) + "\n" + indent + "]";
- }
- else if (indentMode == QJson::IndentCompact) {
- str = "[" + join( values, "," ) + "]";
- }
- else {
- str = "[ " + join( values, ", " ) + " ]";
- }
-
- } else if ( v.type() == QVariant::Map ) { // variant is a map?
- const QVariantMap vmap = v.toMap();
- QMapIterator<QString, QVariant> it( vmap );
-
- if (indentMode == QJson::IndentMinimum) {
- QByteArray indent = buildIndent(reserved);
- str = indent + "{ ";
- }
- else if (indentMode == QJson::IndentMedium || indentMode == QJson::IndentFull) {
- QByteArray indent = buildIndent(reserved);
- QByteArray nextindent = buildIndent(reserved + 1);
- str = indent + "{\n" + nextindent;
- }
- else if (indentMode == QJson::IndentCompact) {
- str = "{";
- }
- else {
- str = "{ ";
- }
-
- QList<QByteArray> pairs;
- while ( it.hasNext() ) {
- it.next();
- reserved++;
- QByteArray serializedValue = serialize( it.value() , reserved);
- reserved--;
- if ( serializedValue.isNull() ) {
- error = true;
- break;
- }
- QByteArray key = sanitizeString( it.key() ).toUtf8();
- QByteArray value = serializedValue;
- if (indentMode == QJson::IndentCompact) {
- pairs << key + ":" + value;
- } else {
- pairs << key + " : " + value;
- }
- }
-
- if (indentMode == QJson::IndentFull) {
- QByteArray indent = buildIndent(reserved + 1);
- str += join( pairs, ",\n" + indent);
- }
- else if (indentMode == QJson::IndentCompact) {
- str += join( pairs, "," );
- }
- else {
- str += join( pairs, ", " );
- }
-
- if (indentMode == QJson::IndentMedium || indentMode == QJson::IndentFull) {
- QByteArray indent = buildIndent(reserved);
- str += "\n" + indent + "}";
- }
- else if (indentMode == QJson::IndentCompact) {
- str += "}";
- }
- else {
- str += " }";
- }
-
- } else if (( v.type() == QVariant::String ) || ( v.type() == QVariant::ByteArray )) { // a string or a byte array?
- str = sanitizeString( v.toString() ).toUtf8();
- } else if (( v.type() == QVariant::Double) || ((QMetaType::Type)v.type() == QMetaType::Float)) { // a double or a float?
- const double value = v.toDouble();
-#if defined _WIN32 && !defined(Q_OS_SYMBIAN)
- const bool special = _isnan(value) || !_finite(value);
-#elif defined(Q_OS_SYMBIAN) || defined(Q_OS_ANDROID)
- const bool special = isnan(value) || isinf(value);
-#else
- const bool special = std::isnan(value) || std::isinf(value);
-#endif
- if (special) {
- if (specialNumbersAllowed) {
-#if defined _WIN32 && !defined(Q_OS_SYMBIAN)
- if (_isnan(value)) {
-#elif defined(Q_OS_SYMBIAN) || defined(Q_OS_ANDROID)
- if (isnan(value)) {
-#else
- if (std::isnan(value)) {
-#endif
- str += "NaN";
- } else {
- if (value<0) {
- str += '-';
- }
- str += "Infinity";
- }
- } else {
- qCritical("Attempt to write NaN or infinity, which is not supported by json");
- error = true;
- }
- } else {
- str = QByteArray::number( value , 'g', doublePrecision);
- if( ! str.contains( "." ) && ! str.contains( "e" ) ) {
- str += ".0";
- }
- }
- } else if ( v.type() == QVariant::Bool ) { // boolean value?
- str = ( v.toBool() ? "true" : "false" );
- } else if ( v.type() == QVariant::ULongLong ) { // large unsigned number?
- str = QByteArray::number( v.value<qulonglong>() );
- } else if ( v.canConvert<qlonglong>() ) { // any signed number?
- str = QByteArray::number( v.value<qlonglong>() );
- } else if ( v.canConvert<QString>() ){ // can value be converted to string?
- // this will catch QDate, QDateTime, QUrl, ...
- str = sanitizeString( v.toString() ).toUtf8();
- //TODO: catch other values like QImage, QRect, ...
- } else {
- error = true;
- }
- if ( !error )
- {
- return str;
- }
- else
- return QByteArray();
-}
-
-QByteArray Serializer::SerializerPrivate::buildIndent(int spaces)
-{
- QByteArray indent;
- if (spaces < 0) {
- spaces = 0;
- }
- for (int i = 0; i < spaces; i++ ) {
- indent += " ";
- }
- return indent;
-}
-
-QString Serializer::SerializerPrivate::sanitizeString( QString str )
-{
- str.replace( QLatin1String( "\\" ), QLatin1String( "\\\\" ) );
-
- // escape unicode chars
- QString result;
- const ushort* unicode = str.utf16();
- unsigned int i = 0;
-
- while ( unicode[ i ] ) {
- if ( unicode[ i ] < 128 ) {
- result.append( QChar( unicode[ i ] ) );
- }
- else {
- QString hexCode = QString::number( unicode[ i ], 16 ).rightJustified( 4,
- QLatin1Char('0') );
-
- result.append( QLatin1String ("\\u") ).append( hexCode );
- }
- ++i;
- }
- str = result;
-
- str.replace( QLatin1String( "\"" ), QLatin1String( "\\\"" ) );
- str.replace( QLatin1String( "\b" ), QLatin1String( "\\b" ) );
- str.replace( QLatin1String( "\f" ), QLatin1String( "\\f" ) );
- str.replace( QLatin1String( "\n" ), QLatin1String( "\\n" ) );
- str.replace( QLatin1String( "\r" ), QLatin1String( "\\r" ) );
- str.replace( QLatin1String( "\t" ), QLatin1String( "\\t" ) );
-
- return QString( QLatin1String( "\"%1\"" ) ).arg( str );
-}
-
-Serializer::Serializer()
- : d( new SerializerPrivate )
-{
-}
-
-Serializer::~Serializer() {
- delete d;
-}
-
-void Serializer::serialize( const QVariant& v, QIODevice* io, bool* ok)
-{
- Q_ASSERT( io );
- if (ok)
- *ok = false;
-
- if (!io->isOpen()) {
- if (!io->open(QIODevice::WriteOnly)) {
- qCritical ("Error opening device");
- return;
- }
- }
-
- if (!io->isWritable()) {
- qCritical ("Device is not readable");
- io->close();
- return;
- }
-
- const QByteArray str = serialize( v );
- if (io->write(str) == str.count()) {
- if (ok)
- *ok = true;
- }
-}
-
-QByteArray Serializer::serialize( const QVariant &v)
-{
- return d->serialize(v);
-}
-
-void QJson::Serializer::allowSpecialNumbers(bool allow) {
- d->specialNumbersAllowed = allow;
-}
-
-bool QJson::Serializer::specialNumbersAllowed() const {
- return d->specialNumbersAllowed;
-}
-
-void QJson::Serializer::setIndentMode(IndentMode mode) {
- d->indentMode = mode;
-}
-
-void QJson::Serializer::setDoublePrecision(int precision) {
- d->doublePrecision = precision;
-}
-
-IndentMode QJson::Serializer::indentMode() const {
- return d->indentMode;
-}
diff --git a/thirdparty/qjson/serializer.h b/thirdparty/qjson/serializer.h
deleted file mode 100644
index 66b349cf..00000000
--- a/thirdparty/qjson/serializer.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* This file is part of qjson
- *
- * Copyright (C) 2009 Till Adam <adam@kde.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef QJSON_SERIALIZER_H
-#define QJSON_SERIALIZER_H
-
-#include "qjson_export.h"
-
-class QIODevice;
-class QString;
-class QVariant;
-
-namespace QJson {
- /**
- * @brief How the indentation should work.
- *
- * none (default) : { "foo" : 0, "foo1" : 1, "foo2" : [ { "foo3" : 3, "foo4" : 4 } ] }
- *
- * compact : {"foo":0,"foo1":1,"foo2":[{"foo3":3,"foo4":4}]}
- *
- * minimum : { "foo" : 0, "foo1" : 1, "foo2" : [
- * { "foo3" : 3, "foo4" : 4 }
- * ] }
- *
- * medium : {
- * "foo" : 0, "foo1" : 1, "foo2" : [
- * {
- * "foo3" : 3, "foo4" : 4
- * }
- * ]
- * }
- * full : {
- * "foo" : 0,
- * "foo1" : 1,
- * "foo2" : [
- * {
- * "foo3" : 3,
- * "foo4" : 4
- * }
- * ]
- * }
- */
- enum IndentMode {
- IndentNone,
- IndentCompact,
- IndentMinimum,
- IndentMedium,
- IndentFull
- };
- /**
- * @brief Main class used to convert QVariant objects to JSON data.
- *
- * QVariant objects are converted to a string containing the JSON data.
- * If QVariant object is empty or not valid a <em>null</em> json object is returned.
- */
- class QJSON_EXPORT Serializer {
- public:
- Serializer();
- ~Serializer();
-
- /**
- * This method generates a textual JSON representation and outputs it to the
- * passed in I/O Device.
- * @param variant The JSON document in its in-memory representation as generated by the
- * parser.
- * @param out Input output device
- * @param ok if a conversion error occurs, *ok is set to false; otherwise *ok is set to true
- */
- void serialize( const QVariant& variant, QIODevice* out, bool* ok = 0);
-
- /**
- * This is a method provided for convenience. It turns the passed in in-memory
- * representation of the JSON document into a textual one, which is returned.
- * If the returned string is empty, the document was empty. If it was null, there
- * was a parsing error.
- *
- * @param variant The JSON document in its in-memory representation as generated by the
- * parser.
- */
-
- QByteArray serialize( const QVariant& variant);
-
- /**
- * Allow or disallow writing of NaN and/or Infinity (as an extension to QJson)
- */
- void allowSpecialNumbers(bool allow);
-
- /**
- * Is Nan and/or Infinity allowed?
- */
- bool specialNumbersAllowed() const;
-
- /**
- * set output indentation mode as defined in QJson::IndentMode
- */
- void setIndentMode(IndentMode mode = QJson::IndentNone);
-
-
- /**
- * set double precision used while converting Double
- * \sa QByteArray::number
- */
- void setDoublePrecision(int precision);
-
- /**
- * Returns one of the indentation modes defined in QJson::IndentMode
- */
- IndentMode indentMode() const;
-
- private:
- Q_DISABLE_COPY(Serializer)
- class SerializerPrivate;
- SerializerPrivate* const d;
- };
-}
-
-#endif // QJSON_SERIALIZER_H
diff --git a/thirdparty/qjson/serializerrunnable.cpp b/thirdparty/qjson/serializerrunnable.cpp
deleted file mode 100644
index 9ebf68b7..00000000
--- a/thirdparty/qjson/serializerrunnable.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "serializerrunnable.h"
-
-/* This file is part of qjson
- *
- * Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
- * 2009 Frank Osterfeld <osterfeld@kde.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "parserrunnable.h"
-#include "serializer.h"
-
-#include <QtCore/QDebug>
-#include <QtCore/QVariant>
-
-using namespace QJson;
-
-class SerializerRunnable::Private
-{
-public:
- QVariant json;
-};
-
-SerializerRunnable::SerializerRunnable(QObject* parent)
- : QObject(parent),
- QRunnable(),
- d(new Private)
-{
- qRegisterMetaType<QVariant>("QVariant");
-}
-
-SerializerRunnable::~SerializerRunnable()
-{
- delete d;
-}
-
-void SerializerRunnable::setJsonObject( const QVariant& json )
-{
- d->json = json;
-}
-
-void SerializerRunnable::run()
-{
- Serializer serializer;
- emit parsingFinished( Serializer().serialize( d->json ), true, QString() );
-}
diff --git a/thirdparty/qjson/serializerrunnable.h b/thirdparty/qjson/serializerrunnable.h
deleted file mode 100644
index d665fc51..00000000
--- a/thirdparty/qjson/serializerrunnable.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* This file is part of qjson
- *
- * Copyright (C) 2009 Frank Osterfeld <osterfeld@kde.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software Foundation.
- *
- *
- * 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 GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef SERIALIZERRUNNABLE_H
-#define SERIALIZERRUNNABLE_H
-
-#include "qjson_export.h"
-
-#include <QtCore/QObject>
-#include <QtCore/QRunnable>
-
-class QByteArray;
-class QString;
-class QVariant;
-
-namespace QJson {
- /**
- * @brief Convenience class for converting JSON data to QVariant objects using a dedicated thread
- */
- class QJSON_EXPORT SerializerRunnable : public QObject, public QRunnable
- {
- Q_OBJECT
- public:
- /**
- * This signal is emitted when the conversion process has been completed
- * @param data contains the JSON data that has to be converted
- * @param parent parent of the object
- **/
- explicit SerializerRunnable(QObject* parent = 0);
- ~SerializerRunnable();
-
- /**
- * Sets the json object to serialize.
- *
- * @param json QVariant containing the json representation to be serialized
- */
- void setJsonObject( const QVariant& json );
-
- /* reimp */ void run();
-
- Q_SIGNALS:
- /**
- * This signal is emitted when the serialization process has been completed
- * @param serialized contains the result of the serialization
- * @param ok if a serialization error occurs ok is set to false, otherwise it's set to true.
- * @param error_msg contains a string explaining the failure reason
- **/
- void parsingFinished(const QByteArray& serialized, bool ok, const QString& error_msg);
-
- private:
- Q_DISABLE_COPY(SerializerRunnable)
- class Private;
- Private* const d;
- };
-}
-
-#endif // SERIALIZERRUNNABLE_H
diff --git a/thirdparty/qjson/stack.hh b/thirdparty/qjson/stack.hh
deleted file mode 100644
index 754b6640..00000000
--- a/thirdparty/qjson/stack.hh
+++ /dev/null
@@ -1,129 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Stack handling for Bison parsers in C++
-
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program 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
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-#ifndef BISON_STACK_HH
-# define BISON_STACK_HH
-
-#include <deque>
-
-namespace yy
-{
- template <class T, class S = std::deque<T> >
- class stack
- {
- public:
-
- // Hide our reversed order.
- typedef typename S::reverse_iterator iterator;
- typedef typename S::const_reverse_iterator const_iterator;
-
- stack () : seq_ ()
- {
- }
-
- stack (unsigned int n) : seq_ (n)
- {
- }
-
- inline
- T&
- operator [] (unsigned int i)
- {
- return seq_[i];
- }
-
- inline
- const T&
- operator [] (unsigned int i) const
- {
- return seq_[i];
- }
-
- inline
- void
- push (const T& t)
- {
- seq_.push_front (t);
- }
-
- inline
- void
- pop (unsigned int n = 1)
- {
- for (; n; --n)
- seq_.pop_front ();
- }
-
- inline
- unsigned int
- height () const
- {
- return seq_.size ();
- }
-
- inline const_iterator begin () const { return seq_.rbegin (); }
- inline const_iterator end () const { return seq_.rend (); }
-
- private:
-
- S seq_;
- };
-
- /// Present a slice of the top of a stack.
- template <class T, class S = stack<T> >
- class slice
- {
- public:
-
- slice (const S& stack,
- unsigned int range) : stack_ (stack),
- range_ (range)
- {
- }
-
- inline
- const T&
- operator [] (unsigned int i) const
- {
- return stack_[range_ - i];
- }
-
- private:
-
- const S& stack_;
- unsigned int range_;
- };
-}
-
-#endif // not BISON_STACK_HH
diff --git a/thirdparty/snappy/CMakeLists.txt b/thirdparty/snappy/CMakeLists.txt
index 25281a6b..dbe8b706 100644
--- a/thirdparty/snappy/CMakeLists.txt
+++ b/thirdparty/snappy/CMakeLists.txt
@@ -4,21 +4,18 @@ add_definitions (
)
# Adjust warnings
-if (CMAKE_COMPILER_IS_GNUCXX)
- add_definitions (-Wno-unused-function)
+if (NOT MSVC)
+ add_compiler_flags (-Wno-unused-function)
+ add_compiler_flags (-fstrict-aliasing)
endif ()
-add_library (snappy_bundled STATIC EXCLUDE_FROM_ALL
+add_convenience_library (snappy_bundled EXCLUDE_FROM_ALL
snappy.cc
snappy-sinksource.cc
snappy-stubs-internal.cc
snappy-c.cc
)
-set_target_properties (snappy_bundled PROPERTIES
- COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}"
-)
-
install (
FILES COPYING
DESTINATION ${DOC_INSTALL_DIR}
diff --git a/thirdparty/snappy/COPYING b/thirdparty/snappy/COPYING
index 8d6bd9fe..4816c430 100644
--- a/thirdparty/snappy/COPYING
+++ b/thirdparty/snappy/COPYING
@@ -26,3 +26,29 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===
+
+Some of the benchmark data in util/zippy/testdata is licensed differently:
+
+ - fireworks.jpeg is Copyright 2013 Steinar H. Gunderson, and
+ is licensed under the Creative Commons Attribution 3.0 license
+ (CC-BY-3.0). See https://creativecommons.org/licenses/by/3.0/
+ for more information.
+
+ - kppkn.gtb is taken from the Gaviota chess tablebase set, and
+ is licensed under the MIT License. See
+ https://sites.google.com/site/gaviotachessengine/Home/endgame-tablebases-1
+ for more information.
+
+ - paper-100k.pdf is an excerpt (bytes 92160 to 194560) from the paper
+ “Combinatorial Modeling of Chromatin Features Quantitatively Predicts DNA
+ Replication Timing in _Drosophila_†by Federico Comoglio and Renato Paro,
+ which is licensed under the CC-BY license. See
+ http://www.ploscompbiol.org/static/license for more ifnormation.
+
+ - alice29.txt, asyoulik.txt, plrabn12.txt and lcet10.txt are from Project
+ Gutenberg. The first three have expired copyrights and are in the public
+ domain; the latter does not have expired copyright, but is still in the
+ public domain according to the license information
+ (http://www.gutenberg.org/ebooks/53).
diff --git a/thirdparty/snappy/ChangeLog b/thirdparty/snappy/ChangeLog
index f79491b5..edd46dd7 100644
--- a/thirdparty/snappy/ChangeLog
+++ b/thirdparty/snappy/ChangeLog
@@ -1,4 +1,703 @@
------------------------------------------------------------------------
+r83 | snappy.mirrorbot@gmail.com | 2014-02-19 11:31:49 +0100 (Wed, 19 Feb 2014) | 9 lines
+
+Fix public issue 82: Stop distributing benchmark data files that have
+unclear or unsuitable licensing.
+
+In general, we replace the files we can with liberally licensed data,
+and remove all the others (in particular all the parts of the Canterbury
+corpus that are not clearly in the public domain). The replacements
+do not always have the exact same characteristics as the original ones,
+but they are more than good enough to be useful for benchmarking.
+
+------------------------------------------------------------------------
+r82 | snappy.mirrorbot@gmail.com | 2013-10-25 15:31:27 +0200 (Fri, 25 Oct 2013) | 8 lines
+
+Add support for padding in the Snappy framed format.
+
+This is specifically motivated by DICOM's demands that embedded data
+must be of an even number of bytes, but could in principle be used for
+any sort of padding/alignment needed.
+
+R=sanjay
+
+------------------------------------------------------------------------
+r81 | snappy.mirrorbot@gmail.com | 2013-10-15 17:21:31 +0200 (Tue, 15 Oct 2013) | 4 lines
+
+Release Snappy 1.1.1.
+
+R=jeff
+
+------------------------------------------------------------------------
+r80 | snappy.mirrorbot@gmail.com | 2013-08-13 14:55:00 +0200 (Tue, 13 Aug 2013) | 6 lines
+
+Add autoconf tests for size_t and ssize_t. Sort-of resolves public issue 79;
+it would solve the problem if MSVC typically used autoconf. However, it gives
+a natural place (config.h) to put the typedef even for MSVC.
+
+R=jsbell
+
+------------------------------------------------------------------------
+r79 | snappy.mirrorbot@gmail.com | 2013-07-29 13:06:44 +0200 (Mon, 29 Jul 2013) | 14 lines
+
+When we compare the number of bytes produced with the offset for a
+backreference, make the signedness of the bytes produced clear,
+by sticking it into a size_t. This avoids a signed/unsigned compare
+warning from MSVC (public issue 71), and also is slightly clearer.
+
+Since the line is now so long the explanatory comment about the -1u
+trick has to go somewhere else anyway, I used the opportunity to
+explain it in slightly more detail.
+
+This is a purely stylistic change; the emitted assembler from GCC
+is identical.
+
+R=jeff
+
+------------------------------------------------------------------------
+r78 | snappy.mirrorbot@gmail.com | 2013-06-30 21:24:03 +0200 (Sun, 30 Jun 2013) | 111 lines
+
+In the fast path for decompressing literals, instead of checking
+whether there's 16 bytes free and then checking right afterwards
+(when having subtracted the literal size) that there are now
+5 bytes free, just check once for 21 bytes. This skips a compare
+and a branch; although it is easily predictable, it is still
+a few cycles on a fast path that we would like to get rid of.
+
+Benchmarking this yields very confusing results. On open-source
+GCC 4.8.1 on Haswell, we get exactly the expected results; the
+benchmarks where we hit the fast path for literals (in particular
+the two HTML benchmarks and the protobuf benchmark) give very nice
+speedups, and the others are not really affected.
+
+However, benchmarks with Google's GCC branch on other hardware
+is much less clear. It seems that we have a weak loss in some cases
+(and the win for the “typical†win cases are not nearly as clear),
+but that it depends on microarchitecture and plain luck in how we run
+the benchmark. Looking at the generated assembler, it seems that
+the removal of the if causes other large-scale changes in how the
+function is laid out, which makes it likely that this is just bad luck.
+
+Thus, we should keep this change, even though its exact current impact is
+unclear; it's a sensible change per se, and dropping it on the basis of
+microoptimization for a given compiler (or even branch of a compiler)
+would seem like a bad strategy in the long run.
+
+Microbenchmark results (all in 64-bit, opt mode):
+
+ Nehalem, Google GCC:
+
+ Benchmark Base (ns) New (ns) Improvement
+ ------------------------------------------------------------------------------
+ BM_UFlat/0 76747 75591 1.3GB/s html +1.5%
+ BM_UFlat/1 765756 757040 886.3MB/s urls +1.2%
+ BM_UFlat/2 10867 10893 10.9GB/s jpg -0.2%
+ BM_UFlat/3 124 131 1.4GB/s jpg_200 -5.3%
+ BM_UFlat/4 31663 31596 2.8GB/s pdf +0.2%
+ BM_UFlat/5 314162 308176 1.2GB/s html4 +1.9%
+ BM_UFlat/6 29668 29746 790.6MB/s cp -0.3%
+ BM_UFlat/7 12958 13386 796.4MB/s c -3.2%
+ BM_UFlat/8 3596 3682 966.0MB/s lsp -2.3%
+ BM_UFlat/9 1019193 1033493 953.3MB/s xls -1.4%
+ BM_UFlat/10 239 247 775.3MB/s xls_200 -3.2%
+ BM_UFlat/11 236411 240271 606.9MB/s txt1 -1.6%
+ BM_UFlat/12 206639 209768 571.2MB/s txt2 -1.5%
+ BM_UFlat/13 627803 635722 641.4MB/s txt3 -1.2%
+ BM_UFlat/14 845932 857816 538.2MB/s txt4 -1.4%
+ BM_UFlat/15 402107 391670 1.2GB/s bin +2.7%
+ BM_UFlat/16 283 279 683.6MB/s bin_200 +1.4%
+ BM_UFlat/17 46070 46815 781.5MB/s sum -1.6%
+ BM_UFlat/18 5053 5163 782.0MB/s man -2.1%
+ BM_UFlat/19 79721 76581 1.4GB/s pb +4.1%
+ BM_UFlat/20 251158 252330 697.5MB/s gaviota -0.5%
+ Sum of all benchmarks 4966150 4980396 -0.3%
+
+
+ Sandy Bridge, Google GCC:
+
+ Benchmark Base (ns) New (ns) Improvement
+ ------------------------------------------------------------------------------
+ BM_UFlat/0 42850 42182 2.3GB/s html +1.6%
+ BM_UFlat/1 525660 515816 1.3GB/s urls +1.9%
+ BM_UFlat/2 7173 7283 16.3GB/s jpg -1.5%
+ BM_UFlat/3 92 91 2.1GB/s jpg_200 +1.1%
+ BM_UFlat/4 15147 14872 5.9GB/s pdf +1.8%
+ BM_UFlat/5 199936 192116 2.0GB/s html4 +4.1%
+ BM_UFlat/6 12796 12443 1.8GB/s cp +2.8%
+ BM_UFlat/7 6588 6400 1.6GB/s c +2.9%
+ BM_UFlat/8 2010 1951 1.8GB/s lsp +3.0%
+ BM_UFlat/9 761124 763049 1.3GB/s xls -0.3%
+ BM_UFlat/10 186 189 1016.1MB/s xls_200 -1.6%
+ BM_UFlat/11 159354 158460 918.6MB/s txt1 +0.6%
+ BM_UFlat/12 139732 139950 856.1MB/s txt2 -0.2%
+ BM_UFlat/13 429917 425027 961.7MB/s txt3 +1.2%
+ BM_UFlat/14 585255 587324 785.8MB/s txt4 -0.4%
+ BM_UFlat/15 276186 266173 1.8GB/s bin +3.8%
+ BM_UFlat/16 205 207 925.5MB/s bin_200 -1.0%
+ BM_UFlat/17 24925 24935 1.4GB/s sum -0.0%
+ BM_UFlat/18 2632 2576 1.5GB/s man +2.2%
+ BM_UFlat/19 40546 39108 2.8GB/s pb +3.7%
+ BM_UFlat/20 175803 168209 1048.9MB/s gaviota +4.5%
+ Sum of all benchmarks 3408117 3368361 +1.2%
+
+
+ Haswell, upstream GCC 4.8.1:
+
+ Benchmark Base (ns) New (ns) Improvement
+ ------------------------------------------------------------------------------
+ BM_UFlat/0 46308 40641 2.3GB/s html +13.9%
+ BM_UFlat/1 513385 514706 1.3GB/s urls -0.3%
+ BM_UFlat/2 6197 6151 19.2GB/s jpg +0.7%
+ BM_UFlat/3 61 61 3.0GB/s jpg_200 +0.0%
+ BM_UFlat/4 13551 13429 6.5GB/s pdf +0.9%
+ BM_UFlat/5 198317 190243 2.0GB/s html4 +4.2%
+ BM_UFlat/6 14768 12560 1.8GB/s cp +17.6%
+ BM_UFlat/7 6453 6447 1.6GB/s c +0.1%
+ BM_UFlat/8 1991 1980 1.8GB/s lsp +0.6%
+ BM_UFlat/9 766947 770424 1.2GB/s xls -0.5%
+ BM_UFlat/10 170 169 1.1GB/s xls_200 +0.6%
+ BM_UFlat/11 164350 163554 888.7MB/s txt1 +0.5%
+ BM_UFlat/12 145444 143830 832.1MB/s txt2 +1.1%
+ BM_UFlat/13 437849 438413 929.2MB/s txt3 -0.1%
+ BM_UFlat/14 603587 605309 759.8MB/s txt4 -0.3%
+ BM_UFlat/15 249799 248067 1.9GB/s bin +0.7%
+ BM_UFlat/16 191 188 1011.4MB/s bin_200 +1.6%
+ BM_UFlat/17 26064 24778 1.4GB/s sum +5.2%
+ BM_UFlat/18 2620 2601 1.5GB/s man +0.7%
+ BM_UFlat/19 44551 37373 3.0GB/s pb +19.2%
+ BM_UFlat/20 165408 164584 1.0GB/s gaviota +0.5%
+ Sum of all benchmarks 3408011 3385508 +0.7%
+
+------------------------------------------------------------------------
+r77 | snappy.mirrorbot@gmail.com | 2013-06-14 23:42:26 +0200 (Fri, 14 Jun 2013) | 92 lines
+
+Make the two IncrementalCopy* functions take in an ssize_t instead of a len,
+in order to avoid having to do 32-to-64-bit signed conversions on a hot path
+during decompression. (Also fixes some MSVC warnings, mentioned in public
+issue 75, but more of those remain.) They cannot be size_t because we expect
+them to go negative and test for that.
+
+This saves a few movzwl instructions, yielding ~2% speedup in decompression.
+
+
+Sandy Bridge:
+
+Benchmark Base (ns) New (ns) Improvement
+-------------------------------------------------------------------------------------------------
+BM_UFlat/0 48009 41283 2.3GB/s html +16.3%
+BM_UFlat/1 531274 513419 1.3GB/s urls +3.5%
+BM_UFlat/2 7378 7062 16.8GB/s jpg +4.5%
+BM_UFlat/3 92 92 2.0GB/s jpg_200 +0.0%
+BM_UFlat/4 15057 14974 5.9GB/s pdf +0.6%
+BM_UFlat/5 204323 193140 2.0GB/s html4 +5.8%
+BM_UFlat/6 13282 12611 1.8GB/s cp +5.3%
+BM_UFlat/7 6511 6504 1.6GB/s c +0.1%
+BM_UFlat/8 2014 2030 1.7GB/s lsp -0.8%
+BM_UFlat/9 775909 768336 1.3GB/s xls +1.0%
+BM_UFlat/10 182 184 1043.2MB/s xls_200 -1.1%
+BM_UFlat/11 167352 161630 901.2MB/s txt1 +3.5%
+BM_UFlat/12 147393 142246 842.8MB/s txt2 +3.6%
+BM_UFlat/13 449960 432853 944.4MB/s txt3 +4.0%
+BM_UFlat/14 620497 594845 775.9MB/s txt4 +4.3%
+BM_UFlat/15 265610 267356 1.8GB/s bin -0.7%
+BM_UFlat/16 206 205 932.7MB/s bin_200 +0.5%
+BM_UFlat/17 25561 24730 1.4GB/s sum +3.4%
+BM_UFlat/18 2620 2644 1.5GB/s man -0.9%
+BM_UFlat/19 45766 38589 2.9GB/s pb +18.6%
+BM_UFlat/20 171107 169832 1039.5MB/s gaviota +0.8%
+Sum of all benchmarks 3500103 3394565 +3.1%
+
+
+Westmere:
+
+Benchmark Base (ns) New (ns) Improvement
+-------------------------------------------------------------------------------------------------
+BM_UFlat/0 72624 71526 1.3GB/s html +1.5%
+BM_UFlat/1 735821 722917 930.8MB/s urls +1.8%
+BM_UFlat/2 10450 10172 11.7GB/s jpg +2.7%
+BM_UFlat/3 117 117 1.6GB/s jpg_200 +0.0%
+BM_UFlat/4 29817 29648 3.0GB/s pdf +0.6%
+BM_UFlat/5 297126 293073 1.3GB/s html4 +1.4%
+BM_UFlat/6 28252 27994 842.0MB/s cp +0.9%
+BM_UFlat/7 12672 12391 862.1MB/s c +2.3%
+BM_UFlat/8 3507 3425 1040.9MB/s lsp +2.4%
+BM_UFlat/9 1004268 969395 1018.0MB/s xls +3.6%
+BM_UFlat/10 233 227 844.8MB/s xls_200 +2.6%
+BM_UFlat/11 230054 224981 647.8MB/s txt1 +2.3%
+BM_UFlat/12 201229 196447 610.5MB/s txt2 +2.4%
+BM_UFlat/13 609547 596761 685.3MB/s txt3 +2.1%
+BM_UFlat/14 824362 804821 573.8MB/s txt4 +2.4%
+BM_UFlat/15 371095 374899 1.3GB/s bin -1.0%
+BM_UFlat/16 267 267 717.8MB/s bin_200 +0.0%
+BM_UFlat/17 44623 43828 835.9MB/s sum +1.8%
+BM_UFlat/18 5077 4815 841.0MB/s man +5.4%
+BM_UFlat/19 74964 73210 1.5GB/s pb +2.4%
+BM_UFlat/20 237987 236745 746.0MB/s gaviota +0.5%
+Sum of all benchmarks 4794092 4697659 +2.1%
+
+
+Istanbul:
+
+Benchmark Base (ns) New (ns) Improvement
+-------------------------------------------------------------------------------------------------
+BM_UFlat/0 98614 96376 1020.4MB/s html +2.3%
+BM_UFlat/1 963740 953241 707.2MB/s urls +1.1%
+BM_UFlat/2 25042 24769 4.8GB/s jpg +1.1%
+BM_UFlat/3 180 180 1065.6MB/s jpg_200 +0.0%
+BM_UFlat/4 45942 45403 1.9GB/s pdf +1.2%
+BM_UFlat/5 400135 390226 1008.2MB/s html4 +2.5%
+BM_UFlat/6 37768 37392 631.9MB/s cp +1.0%
+BM_UFlat/7 18585 18200 588.2MB/s c +2.1%
+BM_UFlat/8 5751 5690 627.7MB/s lsp +1.1%
+BM_UFlat/9 1543154 1542209 641.4MB/s xls +0.1%
+BM_UFlat/10 381 388 494.6MB/s xls_200 -1.8%
+BM_UFlat/11 339715 331973 440.1MB/s txt1 +2.3%
+BM_UFlat/12 294807 289418 415.4MB/s txt2 +1.9%
+BM_UFlat/13 906160 884094 463.3MB/s txt3 +2.5%
+BM_UFlat/14 1224221 1198435 386.1MB/s txt4 +2.2%
+BM_UFlat/15 516277 502923 979.5MB/s bin +2.7%
+BM_UFlat/16 405 402 477.2MB/s bin_200 +0.7%
+BM_UFlat/17 61640 60621 605.6MB/s sum +1.7%
+BM_UFlat/18 7326 7383 549.5MB/s man -0.8%
+BM_UFlat/19 94720 92653 1.2GB/s pb +2.2%
+BM_UFlat/20 360435 346687 510.6MB/s gaviota +4.0%
+Sum of all benchmarks 6944998 6828663 +1.7%
+
+------------------------------------------------------------------------
+r76 | snappy.mirrorbot@gmail.com | 2013-06-13 18:19:52 +0200 (Thu, 13 Jun 2013) | 9 lines
+
+Add support for uncompressing to iovecs (scatter I/O).
+Windows does not have struct iovec defined anywhere,
+so we define our own version that's equal to what UNIX
+typically has.
+
+The bulk of this patch was contributed by Mohit Aron.
+
+R=jeff
+
+------------------------------------------------------------------------
+r75 | snappy.mirrorbot@gmail.com | 2013-06-12 21:51:15 +0200 (Wed, 12 Jun 2013) | 4 lines
+
+Some code reorganization needed for an internal change.
+
+R=fikes
+
+------------------------------------------------------------------------
+r74 | snappy.mirrorbot@gmail.com | 2013-04-09 17:33:30 +0200 (Tue, 09 Apr 2013) | 4 lines
+
+Supports truncated test data in zippy benchmark.
+
+R=sesse
+
+------------------------------------------------------------------------
+r73 | snappy.mirrorbot@gmail.com | 2013-02-05 15:36:15 +0100 (Tue, 05 Feb 2013) | 4 lines
+
+Release Snappy 1.1.0.
+
+R=sanjay
+
+------------------------------------------------------------------------
+r72 | snappy.mirrorbot@gmail.com | 2013-02-05 15:30:05 +0100 (Tue, 05 Feb 2013) | 9 lines
+
+Make ./snappy_unittest pass without "srcdir" being defined.
+
+Previously, snappy_unittests would read from an absolute path /testdata/..;
+convert it to use a relative path instead.
+
+Patch from Marc-Antonie Ruel.
+
+R=maruel
+
+------------------------------------------------------------------------
+r71 | snappy.mirrorbot@gmail.com | 2013-01-18 13:16:36 +0100 (Fri, 18 Jan 2013) | 287 lines
+
+Increase the Zippy block size from 32 kB to 64 kB, winning ~3% density
+while being effectively performance neutral.
+
+The longer story about density is that we win 3-6% density on the benchmarks
+where this has any effect at all; many of the benchmarks (cp, c, lsp, man)
+are smaller than 32 kB and thus will have no effect. Binary data also seems
+to win little or nothing; of course, the already-compressed data wins nothing.
+The protobuf benchmark wins as much as ~18% depending on architecture,
+but I wouldn't be too sure that this is representative of protobuf data in
+general.
+
+As of performance, we lose a tiny amount since we get more tags (e.g., a long
+literal might be broken up into literal-copy-literal), but we win it back with
+less clearing of the hash table, and more opportunities to skip incompressible
+data (e.g. in the jpg benchmark). Decompression seems to get ever so slightly
+slower, again due to more tags. The total net change is about as close to zero
+as we can get, so the end effect seems to be simply more density and no
+real performance change.
+
+The comment about not changing kBlockSize, scary as it is, is not really
+relevant, since we're never going to have a block-level decompressor without
+explicitly marked blocks. Replace it with something more appropriate.
+
+This affects the framing format, but it's okay to change it since it basically
+has no users yet.
+
+
+Density (note that cp, c, lsp and man are all smaller than 32 kB):
+
+ Benchmark Description Base (%) New (%) Improvement
+ --------------------------------------------------------------
+ ZFlat/0 html 22.57 22.31 +5.6%
+ ZFlat/1 urls 50.89 47.77 +6.5%
+ ZFlat/2 jpg 99.88 99.87 +0.0%
+ ZFlat/3 pdf 82.13 82.07 +0.1%
+ ZFlat/4 html4 23.55 22.51 +4.6%
+ ZFlat/5 cp 48.12 48.12 +0.0%
+ ZFlat/6 c 42.40 42.40 +0.0%
+ ZFlat/7 lsp 48.37 48.37 +0.0%
+ ZFlat/8 xls 41.34 41.23 +0.3%
+ ZFlat/9 txt1 59.81 57.87 +3.4%
+ ZFlat/10 txt2 64.07 61.93 +3.5%
+ ZFlat/11 txt3 57.11 54.92 +4.0%
+ ZFlat/12 txt4 68.35 66.22 +3.2%
+ ZFlat/13 bin 18.21 18.11 +0.6%
+ ZFlat/14 sum 51.88 48.96 +6.0%
+ ZFlat/15 man 59.36 59.36 +0.0%
+ ZFlat/16 pb 23.15 19.64 +17.9%
+ ZFlat/17 gaviota 38.27 37.72 +1.5%
+ Geometric mean 45.51 44.15 +3.1%
+
+
+Microbenchmarks (64-bit, opt):
+
+Westmere 2.8 GHz:
+
+ Benchmark Base (ns) New (ns) Improvement
+ -------------------------------------------------------------------------------------------------
+ BM_UFlat/0 75342 75027 1.3GB/s html +0.4%
+ BM_UFlat/1 723767 744269 899.6MB/s urls -2.8%
+ BM_UFlat/2 10072 10072 11.7GB/s jpg +0.0%
+ BM_UFlat/3 30747 30388 2.9GB/s pdf +1.2%
+ BM_UFlat/4 307353 306063 1.2GB/s html4 +0.4%
+ BM_UFlat/5 28593 28743 816.3MB/s cp -0.5%
+ BM_UFlat/6 12958 12998 818.1MB/s c -0.3%
+ BM_UFlat/7 3700 3792 935.8MB/s lsp -2.4%
+ BM_UFlat/8 999685 999905 982.1MB/s xls -0.0%
+ BM_UFlat/9 232954 230079 630.4MB/s txt1 +1.2%
+ BM_UFlat/10 200785 201468 592.6MB/s txt2 -0.3%
+ BM_UFlat/11 617267 610968 666.1MB/s txt3 +1.0%
+ BM_UFlat/12 821595 822475 558.7MB/s txt4 -0.1%
+ BM_UFlat/13 377097 377632 1.3GB/s bin -0.1%
+ BM_UFlat/14 45476 45260 805.8MB/s sum +0.5%
+ BM_UFlat/15 4985 5003 805.7MB/s man -0.4%
+ BM_UFlat/16 80813 77494 1.4GB/s pb +4.3%
+ BM_UFlat/17 251792 241553 727.7MB/s gaviota +4.2%
+ BM_UValidate/0 40343 40354 2.4GB/s html -0.0%
+ BM_UValidate/1 426890 451574 1.4GB/s urls -5.5%
+ BM_UValidate/2 187 179 661.9GB/s jpg +4.5%
+ BM_UValidate/3 13783 13827 6.4GB/s pdf -0.3%
+ BM_UValidate/4 162393 163335 2.3GB/s html4 -0.6%
+ BM_UDataBuffer/0 93756 93302 1046.7MB/s html +0.5%
+ BM_UDataBuffer/1 886714 916292 730.7MB/s urls -3.2%
+ BM_UDataBuffer/2 15861 16401 7.2GB/s jpg -3.3%
+ BM_UDataBuffer/3 38934 39224 2.2GB/s pdf -0.7%
+ BM_UDataBuffer/4 381008 379428 1029.5MB/s html4 +0.4%
+ BM_UCord/0 92528 91098 1072.0MB/s html +1.6%
+ BM_UCord/1 858421 885287 756.3MB/s urls -3.0%
+ BM_UCord/2 13140 13464 8.8GB/s jpg -2.4%
+ BM_UCord/3 39012 37773 2.3GB/s pdf +3.3%
+ BM_UCord/4 376869 371267 1052.1MB/s html4 +1.5%
+ BM_UCordString/0 75810 75303 1.3GB/s html +0.7%
+ BM_UCordString/1 735290 753841 888.2MB/s urls -2.5%
+ BM_UCordString/2 11945 13113 9.0GB/s jpg -8.9%
+ BM_UCordString/3 33901 32562 2.7GB/s pdf +4.1%
+ BM_UCordString/4 310985 309390 1.2GB/s html4 +0.5%
+ BM_UCordValidate/0 40952 40450 2.4GB/s html +1.2%
+ BM_UCordValidate/1 433842 456531 1.4GB/s urls -5.0%
+ BM_UCordValidate/2 1179 1173 100.8GB/s jpg +0.5%
+ BM_UCordValidate/3 14481 14392 6.1GB/s pdf +0.6%
+ BM_UCordValidate/4 164364 164151 2.3GB/s html4 +0.1%
+ BM_ZFlat/0 160610 156601 623.6MB/s html (22.31 %) +2.6%
+ BM_ZFlat/1 1995238 1993582 335.9MB/s urls (47.77 %) +0.1%
+ BM_ZFlat/2 30133 24983 4.7GB/s jpg (99.87 %) +20.6%
+ BM_ZFlat/3 74453 73128 1.2GB/s pdf (82.07 %) +1.8%
+ BM_ZFlat/4 647674 633729 616.4MB/s html4 (22.51 %) +2.2%
+ BM_ZFlat/5 76259 76090 308.4MB/s cp (48.12 %) +0.2%
+ BM_ZFlat/6 31106 31084 342.1MB/s c (42.40 %) +0.1%
+ BM_ZFlat/7 10507 10443 339.8MB/s lsp (48.37 %) +0.6%
+ BM_ZFlat/8 1811047 1793325 547.6MB/s xls (41.23 %) +1.0%
+ BM_ZFlat/9 597903 581793 249.3MB/s txt1 (57.87 %) +2.8%
+ BM_ZFlat/10 525320 514522 232.0MB/s txt2 (61.93 %) +2.1%
+ BM_ZFlat/11 1596591 1551636 262.3MB/s txt3 (54.92 %) +2.9%
+ BM_ZFlat/12 2134523 2094033 219.5MB/s txt4 (66.22 %) +1.9%
+ BM_ZFlat/13 593024 587869 832.6MB/s bin (18.11 %) +0.9%
+ BM_ZFlat/14 114746 110666 329.5MB/s sum (48.96 %) +3.7%
+ BM_ZFlat/15 14376 14485 278.3MB/s man (59.36 %) -0.8%
+ BM_ZFlat/16 167908 150070 753.6MB/s pb (19.64 %) +11.9%
+ BM_ZFlat/17 460228 442253 397.5MB/s gaviota (37.72 %) +4.1%
+ BM_ZCord/0 164896 160241 609.4MB/s html +2.9%
+ BM_ZCord/1 2070239 2043492 327.7MB/s urls +1.3%
+ BM_ZCord/2 54402 47002 2.5GB/s jpg +15.7%
+ BM_ZCord/3 85871 83832 1073.1MB/s pdf +2.4%
+ BM_ZCord/4 664078 648825 602.0MB/s html4 +2.4%
+ BM_ZDataBuffer/0 174874 172549 566.0MB/s html +1.3%
+ BM_ZDataBuffer/1 2134410 2139173 313.0MB/s urls -0.2%
+ BM_ZDataBuffer/2 71911 69551 1.7GB/s jpg +3.4%
+ BM_ZDataBuffer/3 98236 99727 902.1MB/s pdf -1.5%
+ BM_ZDataBuffer/4 710776 699104 558.8MB/s html4 +1.7%
+ Sum of all benchmarks 27358908 27200688 +0.6%
+
+
+Sandy Bridge 2.6 GHz:
+
+ Benchmark Base (ns) New (ns) Improvement
+ -------------------------------------------------------------------------------------------------
+ BM_UFlat/0 49356 49018 1.9GB/s html +0.7%
+ BM_UFlat/1 516764 531955 1.2GB/s urls -2.9%
+ BM_UFlat/2 6982 7304 16.2GB/s jpg -4.4%
+ BM_UFlat/3 15285 15598 5.6GB/s pdf -2.0%
+ BM_UFlat/4 206557 206669 1.8GB/s html4 -0.1%
+ BM_UFlat/5 13681 13567 1.7GB/s cp +0.8%
+ BM_UFlat/6 6571 6592 1.6GB/s c -0.3%
+ BM_UFlat/7 2008 1994 1.7GB/s lsp +0.7%
+ BM_UFlat/8 775700 773286 1.2GB/s xls +0.3%
+ BM_UFlat/9 165578 164480 881.8MB/s txt1 +0.7%
+ BM_UFlat/10 143707 144139 828.2MB/s txt2 -0.3%
+ BM_UFlat/11 443026 436281 932.8MB/s txt3 +1.5%
+ BM_UFlat/12 603129 595856 771.2MB/s txt4 +1.2%
+ BM_UFlat/13 271682 270450 1.8GB/s bin +0.5%
+ BM_UFlat/14 26200 25666 1.4GB/s sum +2.1%
+ BM_UFlat/15 2620 2608 1.5GB/s man +0.5%
+ BM_UFlat/16 48908 47756 2.3GB/s pb +2.4%
+ BM_UFlat/17 174638 170346 1031.9MB/s gaviota +2.5%
+ BM_UValidate/0 31922 31898 3.0GB/s html +0.1%
+ BM_UValidate/1 341265 363554 1.8GB/s urls -6.1%
+ BM_UValidate/2 160 151 782.8GB/s jpg +6.0%
+ BM_UValidate/3 10402 10380 8.5GB/s pdf +0.2%
+ BM_UValidate/4 129490 130587 2.9GB/s html4 -0.8%
+ BM_UDataBuffer/0 59383 58736 1.6GB/s html +1.1%
+ BM_UDataBuffer/1 619222 637786 1049.8MB/s urls -2.9%
+ BM_UDataBuffer/2 10775 11941 9.9GB/s jpg -9.8%
+ BM_UDataBuffer/3 18002 17930 4.9GB/s pdf +0.4%
+ BM_UDataBuffer/4 259182 259306 1.5GB/s html4 -0.0%
+ BM_UCord/0 59379 57814 1.6GB/s html +2.7%
+ BM_UCord/1 598456 615162 1088.4MB/s urls -2.7%
+ BM_UCord/2 8519 8628 13.7GB/s jpg -1.3%
+ BM_UCord/3 18123 17537 5.0GB/s pdf +3.3%
+ BM_UCord/4 252375 252331 1.5GB/s html4 +0.0%
+ BM_UCordString/0 49494 49790 1.9GB/s html -0.6%
+ BM_UCordString/1 524659 541803 1.2GB/s urls -3.2%
+ BM_UCordString/2 8206 8354 14.2GB/s jpg -1.8%
+ BM_UCordString/3 17235 16537 5.3GB/s pdf +4.2%
+ BM_UCordString/4 210188 211072 1.8GB/s html4 -0.4%
+ BM_UCordValidate/0 31956 31587 3.0GB/s html +1.2%
+ BM_UCordValidate/1 340828 362141 1.8GB/s urls -5.9%
+ BM_UCordValidate/2 783 744 158.9GB/s jpg +5.2%
+ BM_UCordValidate/3 10543 10462 8.4GB/s pdf +0.8%
+ BM_UCordValidate/4 130150 129789 2.9GB/s html4 +0.3%
+ BM_ZFlat/0 113873 111200 878.2MB/s html (22.31 %) +2.4%
+ BM_ZFlat/1 1473023 1489858 449.4MB/s urls (47.77 %) -1.1%
+ BM_ZFlat/2 23569 19486 6.1GB/s jpg (99.87 %) +21.0%
+ BM_ZFlat/3 49178 48046 1.8GB/s pdf (82.07 %) +2.4%
+ BM_ZFlat/4 475063 469394 832.2MB/s html4 (22.51 %) +1.2%
+ BM_ZFlat/5 46910 46816 501.2MB/s cp (48.12 %) +0.2%
+ BM_ZFlat/6 16883 16916 628.6MB/s c (42.40 %) -0.2%
+ BM_ZFlat/7 5381 5447 651.5MB/s lsp (48.37 %) -1.2%
+ BM_ZFlat/8 1466870 1473861 666.3MB/s xls (41.23 %) -0.5%
+ BM_ZFlat/9 468006 464101 312.5MB/s txt1 (57.87 %) +0.8%
+ BM_ZFlat/10 408157 408957 291.9MB/s txt2 (61.93 %) -0.2%
+ BM_ZFlat/11 1253348 1232910 330.1MB/s txt3 (54.92 %) +1.7%
+ BM_ZFlat/12 1702373 1702977 269.8MB/s txt4 (66.22 %) -0.0%
+ BM_ZFlat/13 439792 438557 1116.0MB/s bin (18.11 %) +0.3%
+ BM_ZFlat/14 80766 78851 462.5MB/s sum (48.96 %) +2.4%
+ BM_ZFlat/15 7420 7542 534.5MB/s man (59.36 %) -1.6%
+ BM_ZFlat/16 112043 100126 1.1GB/s pb (19.64 %) +11.9%
+ BM_ZFlat/17 368877 357703 491.4MB/s gaviota (37.72 %) +3.1%
+ BM_ZCord/0 116402 113564 859.9MB/s html +2.5%
+ BM_ZCord/1 1507156 1519911 440.5MB/s urls -0.8%
+ BM_ZCord/2 39860 33686 3.5GB/s jpg +18.3%
+ BM_ZCord/3 56211 54694 1.6GB/s pdf +2.8%
+ BM_ZCord/4 485594 479212 815.1MB/s html4 +1.3%
+ BM_ZDataBuffer/0 123185 121572 803.3MB/s html +1.3%
+ BM_ZDataBuffer/1 1569111 1589380 421.3MB/s urls -1.3%
+ BM_ZDataBuffer/2 53143 49556 2.4GB/s jpg +7.2%
+ BM_ZDataBuffer/3 65725 66826 1.3GB/s pdf -1.6%
+ BM_ZDataBuffer/4 517871 514750 758.9MB/s html4 +0.6%
+ Sum of all benchmarks 20258879 20315484 -0.3%
+
+
+AMD Instanbul 2.4 GHz:
+
+ Benchmark Base (ns) New (ns) Improvement
+ -------------------------------------------------------------------------------------------------
+ BM_UFlat/0 97120 96585 1011.1MB/s html +0.6%
+ BM_UFlat/1 917473 948016 706.3MB/s urls -3.2%
+ BM_UFlat/2 21496 23938 4.9GB/s jpg -10.2%
+ BM_UFlat/3 44751 45639 1.9GB/s pdf -1.9%
+ BM_UFlat/4 391950 391413 998.0MB/s html4 +0.1%
+ BM_UFlat/5 37366 37201 630.7MB/s cp +0.4%
+ BM_UFlat/6 18350 18318 580.5MB/s c +0.2%
+ BM_UFlat/7 5672 5661 626.9MB/s lsp +0.2%
+ BM_UFlat/8 1533390 1529441 642.1MB/s xls +0.3%
+ BM_UFlat/9 335477 336553 431.0MB/s txt1 -0.3%
+ BM_UFlat/10 285140 292080 408.7MB/s txt2 -2.4%
+ BM_UFlat/11 888507 894758 454.9MB/s txt3 -0.7%
+ BM_UFlat/12 1187643 1210928 379.5MB/s txt4 -1.9%
+ BM_UFlat/13 493717 507447 964.5MB/s bin -2.7%
+ BM_UFlat/14 61740 60870 599.1MB/s sum +1.4%
+ BM_UFlat/15 7211 7187 560.9MB/s man +0.3%
+ BM_UFlat/16 97435 93100 1.2GB/s pb +4.7%
+ BM_UFlat/17 362662 356395 493.2MB/s gaviota +1.8%
+ BM_UValidate/0 47475 47118 2.0GB/s html +0.8%
+ BM_UValidate/1 501304 529741 1.2GB/s urls -5.4%
+ BM_UValidate/2 276 243 486.2GB/s jpg +13.6%
+ BM_UValidate/3 16361 16261 5.4GB/s pdf +0.6%
+ BM_UValidate/4 190741 190353 2.0GB/s html4 +0.2%
+ BM_UDataBuffer/0 111080 109771 889.6MB/s html +1.2%
+ BM_UDataBuffer/1 1051035 1085999 616.5MB/s urls -3.2%
+ BM_UDataBuffer/2 25801 25463 4.6GB/s jpg +1.3%
+ BM_UDataBuffer/3 50493 49946 1.8GB/s pdf +1.1%
+ BM_UDataBuffer/4 447258 444138 879.5MB/s html4 +0.7%
+ BM_UCord/0 109350 107909 905.0MB/s html +1.3%
+ BM_UCord/1 1023396 1054964 634.7MB/s urls -3.0%
+ BM_UCord/2 25292 24371 4.9GB/s jpg +3.8%
+ BM_UCord/3 48955 49736 1.8GB/s pdf -1.6%
+ BM_UCord/4 440452 437331 893.2MB/s html4 +0.7%
+ BM_UCordString/0 98511 98031 996.2MB/s html +0.5%
+ BM_UCordString/1 933230 963495 694.9MB/s urls -3.1%
+ BM_UCordString/2 23311 24076 4.9GB/s jpg -3.2%
+ BM_UCordString/3 45568 46196 1.9GB/s pdf -1.4%
+ BM_UCordString/4 397791 396934 984.1MB/s html4 +0.2%
+ BM_UCordValidate/0 47537 46921 2.0GB/s html +1.3%
+ BM_UCordValidate/1 505071 532716 1.2GB/s urls -5.2%
+ BM_UCordValidate/2 1663 1621 72.9GB/s jpg +2.6%
+ BM_UCordValidate/3 16890 16926 5.2GB/s pdf -0.2%
+ BM_UCordValidate/4 192365 191984 2.0GB/s html4 +0.2%
+ BM_ZFlat/0 184708 179103 545.3MB/s html (22.31 %) +3.1%
+ BM_ZFlat/1 2293864 2302950 290.7MB/s urls (47.77 %) -0.4%
+ BM_ZFlat/2 52852 47618 2.5GB/s jpg (99.87 %) +11.0%
+ BM_ZFlat/3 100766 96179 935.3MB/s pdf (82.07 %) +4.8%
+ BM_ZFlat/4 741220 727977 536.6MB/s html4 (22.51 %) +1.8%
+ BM_ZFlat/5 85402 85418 274.7MB/s cp (48.12 %) -0.0%
+ BM_ZFlat/6 36558 36494 291.4MB/s c (42.40 %) +0.2%
+ BM_ZFlat/7 12706 12507 283.7MB/s lsp (48.37 %) +1.6%
+ BM_ZFlat/8 2336823 2335688 420.5MB/s xls (41.23 %) +0.0%
+ BM_ZFlat/9 701804 681153 212.9MB/s txt1 (57.87 %) +3.0%
+ BM_ZFlat/10 606700 597194 199.9MB/s txt2 (61.93 %) +1.6%
+ BM_ZFlat/11 1852283 1803238 225.7MB/s txt3 (54.92 %) +2.7%
+ BM_ZFlat/12 2475527 2443354 188.1MB/s txt4 (66.22 %) +1.3%
+ BM_ZFlat/13 694497 696654 702.6MB/s bin (18.11 %) -0.3%
+ BM_ZFlat/14 136929 129855 280.8MB/s sum (48.96 %) +5.4%
+ BM_ZFlat/15 17172 17124 235.4MB/s man (59.36 %) +0.3%
+ BM_ZFlat/16 190364 171763 658.4MB/s pb (19.64 %) +10.8%
+ BM_ZFlat/17 567285 555190 316.6MB/s gaviota (37.72 %) +2.2%
+ BM_ZCord/0 193490 187031 522.1MB/s html +3.5%
+ BM_ZCord/1 2427537 2415315 277.2MB/s urls +0.5%
+ BM_ZCord/2 85378 81412 1.5GB/s jpg +4.9%
+ BM_ZCord/3 121898 119419 753.3MB/s pdf +2.1%
+ BM_ZCord/4 779564 762961 512.0MB/s html4 +2.2%
+ BM_ZDataBuffer/0 213820 207272 471.1MB/s html +3.2%
+ BM_ZDataBuffer/1 2589010 2586495 258.9MB/s urls +0.1%
+ BM_ZDataBuffer/2 121871 118885 1018.4MB/s jpg +2.5%
+ BM_ZDataBuffer/3 145382 145986 616.2MB/s pdf -0.4%
+ BM_ZDataBuffer/4 868117 852754 458.1MB/s html4 +1.8%
+ Sum of all benchmarks 33771833 33744763 +0.1%
+
+------------------------------------------------------------------------
+r70 | snappy.mirrorbot@gmail.com | 2013-01-06 20:21:26 +0100 (Sun, 06 Jan 2013) | 6 lines
+
+Adjust the Snappy open-source distribution for the changes in Google's
+internal file API.
+
+R=sanjay
+
+
+------------------------------------------------------------------------
+r69 | snappy.mirrorbot@gmail.com | 2013-01-04 12:54:20 +0100 (Fri, 04 Jan 2013) | 15 lines
+
+Change a few ORs to additions where they don't matter. This helps the compiler
+use the LEA instruction more efficiently, since e.g. a + (b << 2) can be encoded
+as one instruction. Even more importantly, it can constant-fold the
+COPY_* enums together with the shifted negative constants, which also saves
+some instructions. (We don't need it for LITERAL, since it happens to be 0.)
+
+I am unsure why the compiler couldn't do this itself, but the theory is that
+it cannot prove that len-1 and len-4 cannot underflow/wrap, and thus can't
+do the optimization safely.
+
+The gains are small but measurable; 0.5-1.0% over the BM_Z* benchmarks
+(measured on Westmere, Sandy Bridge and Istanbul).
+
+R=sanjay
+
+------------------------------------------------------------------------
+r68 | snappy.mirrorbot@gmail.com | 2012-10-08 13:37:16 +0200 (Mon, 08 Oct 2012) | 5 lines
+
+Stop giving -Werror to automake, due to an incompatibility between current
+versions of libtool and automake on non-GNU platforms (e.g. Mac OS X).
+
+R=sanjay
+
+------------------------------------------------------------------------
+r67 | snappy.mirrorbot@gmail.com | 2012-08-17 15:54:47 +0200 (Fri, 17 Aug 2012) | 5 lines
+
+Fix public issue 66: Document GetUncompressedLength better, in particular that
+it leaves the source in a state that's not appropriate for RawUncompress.
+
+R=sanjay
+
+------------------------------------------------------------------------
+r66 | snappy.mirrorbot@gmail.com | 2012-07-31 13:44:44 +0200 (Tue, 31 Jul 2012) | 5 lines
+
+Fix public issue 64: Check for <sys/time.h> at configure time,
+since MSVC seemingly does not have it.
+
+R=sanjay
+
+------------------------------------------------------------------------
+r65 | snappy.mirrorbot@gmail.com | 2012-07-04 11:34:48 +0200 (Wed, 04 Jul 2012) | 10 lines
+
+Handle the case where gettimeofday() goes backwards or returns the same value
+twice; it could cause division by zero in the unit test framework.
+(We already had one fix for this in place, but it was incomplete.)
+
+This could in theory happen on any system, since there are few guarantees
+about gettimeofday(), but seems to only happen in practice on GNU/Hurd, where
+gettimeofday() is cached and only updated ever so often.
+
+R=sanjay
+
+------------------------------------------------------------------------
+r64 | snappy.mirrorbot@gmail.com | 2012-07-04 11:28:33 +0200 (Wed, 04 Jul 2012) | 6 lines
+
+Mark ARMv4 as not supporting unaligned accesses (not just ARMv5 and ARMv6);
+apparently Debian still targets these by default, giving us segfaults on
+armel.
+
+R=sanjay
+
+------------------------------------------------------------------------
+r63 | snappy.mirrorbot@gmail.com | 2012-05-22 11:46:05 +0200 (Tue, 22 May 2012) | 5 lines
+
+Fix public bug #62: Remove an extraneous comma at the end of an enum list,
+causing compile errors when embedded in Mozilla on OpenBSD.
+
+R=sanjay
+
+------------------------------------------------------------------------
+r62 | snappy.mirrorbot@gmail.com | 2012-05-22 11:32:50 +0200 (Tue, 22 May 2012) | 8 lines
+
+Snappy library no longer depends on iostream.
+
+Achieved by moving logging macro definitions to a test-only
+header file, and by changing non-test code to use assert,
+fprintf, and abort instead of LOG/CHECK macros.
+
+R=sesse
+
+------------------------------------------------------------------------
+r61 | snappy.mirrorbot@gmail.com | 2012-02-24 16:46:37 +0100 (Fri, 24 Feb 2012) | 4 lines
+
+Release Snappy 1.0.5.
+
+R=sanjay
+
+------------------------------------------------------------------------
r60 | snappy.mirrorbot@gmail.com | 2012-02-23 18:00:36 +0100 (Thu, 23 Feb 2012) | 57 lines
For 32-bit platforms, do not try to accelerate multiple neighboring
diff --git a/thirdparty/snappy/NEWS b/thirdparty/snappy/NEWS
index 60bbd17d..27a5b176 100644
--- a/thirdparty/snappy/NEWS
+++ b/thirdparty/snappy/NEWS
@@ -1,3 +1,42 @@
+Snappy v1.1.2, February 28th 2014:
+
+This is a maintenance release with no changes to the actual library
+source code.
+
+ * Stop distributing benchmark data files that have unclear
+ or unsuitable licensing.
+
+ * Add support for padding chunks in the framing format.
+
+
+Snappy v1.1.1, October 15th 2013:
+
+ * Add support for uncompressing to iovecs (scatter I/O).
+ The bulk of this patch was contributed by Mohit Aron.
+
+ * Speed up decompression by ~2%; much more so (~13-20%) on
+ a few benchmarks on given compilers and CPUs.
+
+ * Fix a few issues with MSVC compilation.
+
+ * Support truncated test data in the benchmark.
+
+
+Snappy v1.1.0, January 18th 2013:
+
+ * Snappy now uses 64 kB block size instead of 32 kB. On average,
+ this means it compresses about 3% denser (more so for some
+ inputs), at the same or better speeds.
+
+ * libsnappy no longer depends on iostream.
+
+ * Some small performance improvements in compression on x86
+ (0.5–1%).
+
+ * Various portability fixes for ARM-based platforms, for MSVC,
+ and for GNU/Hurd.
+
+
Snappy v1.0.5, February 24th 2012:
* More speed improvements. Exactly how big will depend on
diff --git a/thirdparty/snappy/config.h b/thirdparty/snappy/config.h
index 6e6e7cf6..ab70985d 100644
--- a/thirdparty/snappy/config.h
+++ b/thirdparty/snappy/config.h
@@ -18,34 +18,34 @@
#endif
/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
+/* #undef HAVE_DLFCN_H */
/* Use the gflags package for command-line parsing. */
-#undef HAVE_GFLAGS
+/* #undef HAVE_GFLAGS */
/* Defined when Google Test is available. */
-#undef HAVE_GTEST
+/* #undef HAVE_GTEST */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `fastlz' library (-lfastlz). */
-#undef HAVE_LIBFASTLZ
+/* #undef HAVE_LIBFASTLZ */
/* Define to 1 if you have the `lzf' library (-llzf). */
-#undef HAVE_LIBLZF
+/* #undef HAVE_LIBLZF */
/* Define to 1 if you have the `lzo2' library (-llzo2). */
-#undef HAVE_LIBLZO2
+/* #undef HAVE_LIBLZO2 */
/* Define to 1 if you have the `quicklz' library (-lquicklz). */
-#undef HAVE_LIBQUICKLZ
+/* #undef HAVE_LIBQUICKLZ */
/* Define to 1 if you have the `z' library (-lz). */
-#undef HAVE_LIBZ
+/* #undef HAVE_LIBZ */
/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
+/* #undef HAVE_MEMORY_H */
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
@@ -57,31 +57,36 @@
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
+/* #undef HAVE_STRINGS_H */
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/byteswap.h> header file. */
-#undef HAVE_SYS_BYTESWAP_H
+/* #undef HAVE_SYS_BYTESWAP_H */
/* Define to 1 if you have the <sys/endian.h> header file. */
-#undef HAVE_SYS_ENDIAN_H
+/* #undef HAVE_SYS_ENDIAN_H */
/* Define to 1 if you have the <sys/mman.h> header file. */
-#undef HAVE_SYS_MMAN_H
+/* #undef HAVE_SYS_MMAN_H */
/* Define to 1 if you have the <sys/resource.h> header file. */
-#undef HAVE_SYS_RESOURCE_H
+/* #undef HAVE_SYS_RESOURCE_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
+/* #undef HAVE_SYS_STAT_H */
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+/* #undef HAVE_SYS_TIME_H */
/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
+#if !defined(_MSC_VER)
+# define HAVE_SYS_TYPES_H 1
+#endif
/* Define to 1 if you have the <unistd.h> header file. */
-#if !defined(_WIN32)
+#if !defined(_MSC_VER)
# define HAVE_UNISTD_H 1
#endif
@@ -92,37 +97,34 @@
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
-#undef LT_OBJDIR
+/* #undef LT_OBJDIR */
/* Name of package */
-#undef PACKAGE
+/* #undef PACKAGE */
/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
+/* #undef PACKAGE_BUGREPORT */
/* Define to the full name of this package. */
-#undef PACKAGE_NAME
+/* #undef PACKAGE_NAME */
/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
+/* #undef PACKAGE_STRING */
/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
+/* #undef PACKAGE_TARNAME */
/* Define to the version of this package. */
-#undef PACKAGE_VERSION
+/* #undef PACKAGE_VERSION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
-#undef VERSION
+/* #undef VERSION */
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
- significant byte first (like Motorola and SPARC, unlike Intel). */
+ significant byte first (like Motorola and SPARC, unlike Intel and VAX). */
#if defined(__GLIBC__)
# include <endian.h>
# if __BYTE_ORDER == __BIG_ENDIAN
@@ -134,3 +136,11 @@
# define WORDS_BIGENDIAN 1
# endif
#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+#if defined(_MSC_VER)
+# define ssize_t int
+#endif
diff --git a/thirdparty/snappy/framing_format.txt b/thirdparty/snappy/framing_format.txt
index 08fda03f..9764e83d 100644
--- a/thirdparty/snappy/framing_format.txt
+++ b/thirdparty/snappy/framing_format.txt
@@ -1,5 +1,5 @@
Snappy framing format description
-Last revised: 2011-12-15
+Last revised: 2013-10-25
This format decribes a framing format for Snappy, allowing compressing to
files or streams that can then more easily be decompressed without having
@@ -15,9 +15,9 @@ decompressor; it is not part of the Snappy core specification.
The file consists solely of chunks, lying back-to-back with no padding
in between. Each chunk consists first a single byte of chunk identifier,
-then a two-byte little-endian length of the chunk in bytes (from 0 to 65535,
-inclusive), and then the data if any. The three bytes of chunk header is not
-counted in the data length.
+then a three-byte little-endian length of the chunk in bytes (from 0 to
+16777215, inclusive), and then the data if any. The four bytes of chunk
+header is not counted in the data length.
The different chunk types are listed below. The first chunk must always
be the stream identifier chunk (see section 4.1, below). The stream
@@ -71,7 +71,7 @@ The stream identifier is always the first element in the stream.
It is exactly six bytes long and contains "sNaPpY" in ASCII. This means that
a valid Snappy framed stream always starts with the bytes
- 0xff 0x06 0x00 0x73 0x4e 0x61 0x50 0x70 0x59
+ 0xff 0x06 0x00 0x00 0x73 0x4e 0x61 0x50 0x70 0x59
The stream identifier chunk can come multiple times in the stream besides
the first; if such a chunk shows up, it should simply be ignored, assuming
@@ -86,9 +86,9 @@ see the compressed format specification. The compressed data is preceded by
the CRC-32C (see section 3) of the _uncompressed_ data.
Note that the data portion of the chunk, i.e., the compressed contents,
-can be at most 65531 bytes (2^16 - 1, minus the checksum).
+can be at most 16777211 bytes (2^24 - 1, minus the checksum).
However, we place an additional restriction that the uncompressed data
-in a chunk must be no longer than 32768 bytes. This allows consumers to
+in a chunk must be no longer than 65536 bytes. This allows consumers to
easily use small fixed-size buffers.
@@ -102,11 +102,22 @@ As in the compressed chunks, the data is preceded by its own masked
CRC-32C (see section 3).
An uncompressed data chunk, like compressed data chunks, should contain
-no more than 32768 data bytes, so the maximum legal chunk length with the
-checksum is 32772.
+no more than 65536 data bytes, so the maximum legal chunk length with the
+checksum is 65540.
-4.4. Reserved unskippable chunks (chunk types 0x02-0x7f)
+4.4. Padding (chunk type 0xfe)
+
+Padding chunks allow a compressor to increase the size of the data stream
+so that it complies with external demands, e.g. that the total number of
+bytes is a multiple of some value.
+
+All bytes of the padding chunk, except the chunk byte itself and the length,
+should be zero, but decompressors must not try to interpret or verify the
+padding data in any way.
+
+
+4.5. Reserved unskippable chunks (chunk types 0x02-0x7f)
These are reserved for future expansion. A decoder that sees such a chunk
should immediately return an error, as it must assume it cannot decode the
@@ -115,10 +126,10 @@ stream correctly.
Future versions of this specification may define meanings for these chunks.
-4.5. Reserved skippable chunks (chunk types 0x80-0xfe)
+4.6. Reserved skippable chunks (chunk types 0x80-0xfd)
These are also reserved for future expansion, but unlike the chunks
-described in 4.4, a decoder seeing these must skip them and continue
+described in 4.5, a decoder seeing these must skip them and continue
decoding.
Future versions of this specification may define meanings for these chunks.
diff --git a/thirdparty/snappy/snappy-c.h b/thirdparty/snappy/snappy-c.h
index 88e1122d..c6c2a860 100644
--- a/thirdparty/snappy/snappy-c.h
+++ b/thirdparty/snappy/snappy-c.h
@@ -46,7 +46,7 @@ extern "C" {
typedef enum {
SNAPPY_OK = 0,
SNAPPY_INVALID_INPUT = 1,
- SNAPPY_BUFFER_TOO_SMALL = 2,
+ SNAPPY_BUFFER_TOO_SMALL = 2
} snappy_status;
/*
diff --git a/thirdparty/snappy/snappy-internal.h b/thirdparty/snappy/snappy-internal.h
index a32eda59..c99d3313 100644
--- a/thirdparty/snappy/snappy-internal.h
+++ b/thirdparty/snappy/snappy-internal.h
@@ -85,7 +85,7 @@ char* CompressFragment(const char* input,
static inline int FindMatchLength(const char* s1,
const char* s2,
const char* s2_limit) {
- DCHECK_GE(s2_limit, s2);
+ assert(s2_limit >= s2);
int matched = 0;
// Find out how long the match is. We loop over the data 64 bits at a
@@ -122,7 +122,7 @@ static inline int FindMatchLength(const char* s1,
const char* s2,
const char* s2_limit) {
// Implementation based on the x86-64 version, above.
- DCHECK_GE(s2_limit, s2);
+ assert(s2_limit >= s2);
int matched = 0;
while (s2 <= s2_limit - 4 &&
diff --git a/thirdparty/snappy/snappy-stubs-internal.h b/thirdparty/snappy/snappy-stubs-internal.h
index 6033cdfb..12393b62 100644
--- a/thirdparty/snappy/snappy-stubs-internal.h
+++ b/thirdparty/snappy/snappy-stubs-internal.h
@@ -35,7 +35,6 @@
#include "config.h"
#endif
-#include <iostream>
#include <string>
#include <assert.h>
@@ -95,87 +94,6 @@ namespace snappy {
static const uint32 kuint32max = static_cast<uint32>(0xFFFFFFFF);
static const int64 kint64max = static_cast<int64>(0x7FFFFFFFFFFFFFFFLL);
-// Logging.
-
-#define LOG(level) LogMessage()
-#define VLOG(level) true ? (void)0 : \
- snappy::LogMessageVoidify() & snappy::LogMessage()
-
-class LogMessage {
- public:
- LogMessage() { }
- ~LogMessage() {
- cerr << endl;
- }
-
- LogMessage& operator<<(const std::string& msg) {
- cerr << msg;
- return *this;
- }
- LogMessage& operator<<(int x) {
- cerr << x;
- return *this;
- }
-};
-
-// Asserts, both versions activated in debug mode only,
-// and ones that are always active.
-
-#define CRASH_UNLESS(condition) \
- PREDICT_TRUE(condition) ? (void)0 : \
- snappy::LogMessageVoidify() & snappy::LogMessageCrash()
-
-class LogMessageCrash : public LogMessage {
- public:
- LogMessageCrash() { }
- ~LogMessageCrash() {
- cerr << endl;
- abort();
- }
-};
-
-// This class is used to explicitly ignore values in the conditional
-// logging macros. This avoids compiler warnings like "value computed
-// is not used" and "statement has no effect".
-
-class LogMessageVoidify {
- public:
- LogMessageVoidify() { }
- // This has to be an operator with a precedence lower than << but
- // higher than ?:
- void operator&(const LogMessage&) { }
-};
-
-#define CHECK(cond) CRASH_UNLESS(cond)
-#define CHECK_LE(a, b) CRASH_UNLESS((a) <= (b))
-#define CHECK_GE(a, b) CRASH_UNLESS((a) >= (b))
-#define CHECK_EQ(a, b) CRASH_UNLESS((a) == (b))
-#define CHECK_NE(a, b) CRASH_UNLESS((a) != (b))
-#define CHECK_LT(a, b) CRASH_UNLESS((a) < (b))
-#define CHECK_GT(a, b) CRASH_UNLESS((a) > (b))
-
-#ifdef NDEBUG
-
-#define DCHECK(cond) CRASH_UNLESS(true)
-#define DCHECK_LE(a, b) CRASH_UNLESS(true)
-#define DCHECK_GE(a, b) CRASH_UNLESS(true)
-#define DCHECK_EQ(a, b) CRASH_UNLESS(true)
-#define DCHECK_NE(a, b) CRASH_UNLESS(true)
-#define DCHECK_LT(a, b) CRASH_UNLESS(true)
-#define DCHECK_GT(a, b) CRASH_UNLESS(true)
-
-#else
-
-#define DCHECK(cond) CHECK(cond)
-#define DCHECK_LE(a, b) CHECK_LE(a, b)
-#define DCHECK_GE(a, b) CHECK_GE(a, b)
-#define DCHECK_EQ(a, b) CHECK_EQ(a, b)
-#define DCHECK_NE(a, b) CHECK_NE(a, b)
-#define DCHECK_LT(a, b) CHECK_LT(a, b)
-#define DCHECK_GT(a, b) CHECK_GT(a, b)
-
-#endif
-
// Potentially unaligned loads and stores.
// x86 and PowerPC can simply do these loads and stores native.
@@ -200,6 +118,8 @@ class LogMessageVoidify {
// This is a mess, but there's not much we can do about it.
#elif defined(__arm__) && \
+ !defined(__ARM_ARCH_4__) && \
+ !defined(__ARM_ARCH_4T__) && \
!defined(__ARM_ARCH_5__) && \
!defined(__ARM_ARCH_5T__) && \
!defined(__ARM_ARCH_5TE__) && \
diff --git a/thirdparty/snappy/snappy-stubs-public.h b/thirdparty/snappy/snappy-stubs-public.h
index 9ee4ca52..6b41bbe9 100644
--- a/thirdparty/snappy/snappy-stubs-public.h
+++ b/thirdparty/snappy/snappy-stubs-public.h
@@ -44,9 +44,13 @@
#include <stddef.h>
#endif
+#if 0
+#include <sys/uio.h>
+#endif
+
#define SNAPPY_MAJOR 1
-#define SNAPPY_MINOR 0
-#define SNAPPY_PATCHLEVEL 5
+#define SNAPPY_MINOR 1
+#define SNAPPY_PATCHLEVEL 2
#define SNAPPY_VERSION \
((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL)
@@ -80,6 +84,15 @@ typedef std::string string;
TypeName(const TypeName&); \
void operator=(const TypeName&)
+#if !0
+// Windows does not have an iovec type, yet the concept is universally useful.
+// It is simple to define it ourselves, so we put it inside our own namespace.
+struct iovec {
+ void* iov_base;
+ size_t iov_len;
+};
+#endif
+
} // namespace snappy
#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
diff --git a/thirdparty/snappy/snappy-stubs-public.h.in b/thirdparty/snappy/snappy-stubs-public.h.in
index f0babcbe..6c181a1c 100644
--- a/thirdparty/snappy/snappy-stubs-public.h.in
+++ b/thirdparty/snappy/snappy-stubs-public.h.in
@@ -44,6 +44,10 @@
#include <stddef.h>
#endif
+#if @ac_cv_have_sys_uio_h@
+#include <sys/uio.h>
+#endif
+
#define SNAPPY_MAJOR @SNAPPY_MAJOR@
#define SNAPPY_MINOR @SNAPPY_MINOR@
#define SNAPPY_PATCHLEVEL @SNAPPY_PATCHLEVEL@
@@ -80,6 +84,15 @@ typedef std::string string;
TypeName(const TypeName&); \
void operator=(const TypeName&)
+#if !@ac_cv_have_sys_uio_h@
+// Windows does not have an iovec type, yet the concept is universally useful.
+// It is simple to define it ourselves, so we put it inside our own namespace.
+struct iovec {
+ void* iov_base;
+ size_t iov_len;
+};
+#endif
+
} // namespace snappy
#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
diff --git a/thirdparty/snappy/snappy-test.cc b/thirdparty/snappy/snappy-test.cc
index 223cd92d..46194109 100644
--- a/thirdparty/snappy/snappy-test.cc
+++ b/thirdparty/snappy/snappy-test.cc
@@ -42,18 +42,25 @@ DEFINE_bool(run_microbenchmarks, true,
namespace snappy {
-string ReadTestDataFile(const string& base) {
+string ReadTestDataFile(const string& base, size_t size_limit) {
string contents;
const char* srcdir = getenv("srcdir"); // This is set by Automake.
+ string prefix;
if (srcdir) {
- File::ReadFileToStringOrDie(
- string(srcdir) + "/testdata/" + base, &contents);
- } else {
- File::ReadFileToStringOrDie("testdata/" + base, &contents);
+ prefix = string(srcdir) + "/";
+ }
+ file::GetContents(prefix + "testdata/" + base, &contents, file::Defaults()
+ ).CheckSuccess();
+ if (size_limit > 0) {
+ contents = contents.substr(0, size_limit);
}
return contents;
}
+string ReadTestDataFile(const string& base) {
+ return ReadTestDataFile(base, 0);
+}
+
string StringPrintf(const char* format, ...) {
char buf[4096];
va_list ap;
@@ -204,27 +211,32 @@ void Benchmark::Run() {
benchmark_runs[run].cpu_time_us = benchmark_cpu_time_us;
}
+ string heading = StringPrintf("%s/%d", name_.c_str(), test_case_num);
+ string human_readable_speed;
+
nth_element(benchmark_runs,
benchmark_runs + kMedianPos,
benchmark_runs + kNumRuns,
BenchmarkCompareCPUTime());
int64 real_time_us = benchmark_runs[kMedianPos].real_time_us;
int64 cpu_time_us = benchmark_runs[kMedianPos].cpu_time_us;
- int64 bytes_per_second = benchmark_bytes_processed * 1000000 / cpu_time_us;
-
- string heading = StringPrintf("%s/%d", name_.c_str(), test_case_num);
- string human_readable_speed;
- if (bytes_per_second < 1024) {
- human_readable_speed = StringPrintf("%dB/s", bytes_per_second);
- } else if (bytes_per_second < 1024 * 1024) {
- human_readable_speed = StringPrintf(
- "%.1fkB/s", bytes_per_second / 1024.0f);
- } else if (bytes_per_second < 1024 * 1024 * 1024) {
- human_readable_speed = StringPrintf(
- "%.1fMB/s", bytes_per_second / (1024.0f * 1024.0f));
+ if (cpu_time_us <= 0) {
+ human_readable_speed = "?";
} else {
- human_readable_speed = StringPrintf(
- "%.1fGB/s", bytes_per_second / (1024.0f * 1024.0f * 1024.0f));
+ int64 bytes_per_second =
+ benchmark_bytes_processed * 1000000 / cpu_time_us;
+ if (bytes_per_second < 1024) {
+ human_readable_speed = StringPrintf("%dB/s", bytes_per_second);
+ } else if (bytes_per_second < 1024 * 1024) {
+ human_readable_speed = StringPrintf(
+ "%.1fkB/s", bytes_per_second / 1024.0f);
+ } else if (bytes_per_second < 1024 * 1024 * 1024) {
+ human_readable_speed = StringPrintf(
+ "%.1fMB/s", bytes_per_second / (1024.0f * 1024.0f));
+ } else {
+ human_readable_speed = StringPrintf(
+ "%.1fGB/s", bytes_per_second / (1024.0f * 1024.0f * 1024.0f));
+ }
}
fprintf(stderr,
diff --git a/thirdparty/snappy/snappy-test.h b/thirdparty/snappy/snappy-test.h
index ef6a9553..0f18bf14 100644
--- a/thirdparty/snappy/snappy-test.h
+++ b/thirdparty/snappy/snappy-test.h
@@ -31,6 +31,9 @@
#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_TEST_H_
#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_TEST_H_
+#include <iostream>
+#include <string>
+
#include "snappy-stubs-internal.h"
#include <stdio.h>
@@ -44,7 +47,9 @@
#include <sys/resource.h>
#endif
+#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
+#endif
#ifdef HAVE_WINDOWS_H
#define WIN32_LEAN_AND_MEAN
@@ -121,13 +126,23 @@ extern "C" {
#endif
namespace {
+
namespace File {
void Init() { }
+} // namespace File
+
+namespace file {
+ int Defaults() { }
- void ReadFileToStringOrDie(const char* filename, string* data) {
- FILE* fp = fopen(filename, "rb");
+ class DummyStatus {
+ public:
+ void CheckSuccess() { }
+ };
+
+ DummyStatus GetContents(const string& filename, string* data, int unused) {
+ FILE* fp = fopen(filename.c_str(), "rb");
if (fp == NULL) {
- perror(filename);
+ perror(filename.c_str());
exit(1);
}
@@ -145,14 +160,12 @@ namespace File {
fclose(fp);
}
- void ReadFileToStringOrDie(const string& filename, string* data) {
- ReadFileToStringOrDie(filename.c_str(), data);
- }
-
- void WriteStringToFileOrDie(const string& str, const char* filename) {
- FILE* fp = fopen(filename, "wb");
+ DummyStatus SetContents(const string& filename,
+ const string& str,
+ int unused) {
+ FILE* fp = fopen(filename.c_str(), "wb");
if (fp == NULL) {
- perror(filename);
+ perror(filename.c_str());
exit(1);
}
@@ -164,7 +177,8 @@ namespace File {
fclose(fp);
}
-} // namespace File
+} // namespace file
+
} // namespace
namespace snappy {
@@ -183,6 +197,8 @@ void Test_Snappy_ReadPastEndOfBuffer();
void Test_Snappy_FindMatchLength();
void Test_Snappy_FindMatchLengthRandom();
+string ReadTestDataFile(const string& base, size_t size_limit);
+
string ReadTestDataFile(const string& base);
// A sprintf() variant that returns a std::string.
@@ -312,6 +328,7 @@ class Benchmark {
(new Benchmark(#benchmark_name, benchmark_name))
extern Benchmark* Benchmark_BM_UFlat;
+extern Benchmark* Benchmark_BM_UIOVec;
extern Benchmark* Benchmark_BM_UValidate;
extern Benchmark* Benchmark_BM_ZFlat;
@@ -462,6 +479,7 @@ static void RunSpecifiedBenchmarks() {
fprintf(stderr, "---------------------------------------------------\n");
snappy::Benchmark_BM_UFlat->Run();
+ snappy::Benchmark_BM_UIOVec->Run();
snappy::Benchmark_BM_UValidate->Run();
snappy::Benchmark_BM_ZFlat->Run();
@@ -496,6 +514,65 @@ static void CompressFile(const char* fname);
static void UncompressFile(const char* fname);
static void MeasureFile(const char* fname);
+// Logging.
+
+#define LOG(level) LogMessage()
+#define VLOG(level) true ? (void)0 : \
+ snappy::LogMessageVoidify() & snappy::LogMessage()
+
+class LogMessage {
+ public:
+ LogMessage() { }
+ ~LogMessage() {
+ cerr << endl;
+ }
+
+ LogMessage& operator<<(const std::string& msg) {
+ cerr << msg;
+ return *this;
+ }
+ LogMessage& operator<<(int x) {
+ cerr << x;
+ return *this;
+ }
+};
+
+// Asserts, both versions activated in debug mode only,
+// and ones that are always active.
+
+#define CRASH_UNLESS(condition) \
+ PREDICT_TRUE(condition) ? (void)0 : \
+ snappy::LogMessageVoidify() & snappy::LogMessageCrash()
+
+class LogMessageCrash : public LogMessage {
+ public:
+ LogMessageCrash() { }
+ ~LogMessageCrash() {
+ cerr << endl;
+ abort();
+ }
+};
+
+// This class is used to explicitly ignore values in the conditional
+// logging macros. This avoids compiler warnings like "value computed
+// is not used" and "statement has no effect".
+
+class LogMessageVoidify {
+ public:
+ LogMessageVoidify() { }
+ // This has to be an operator with a precedence lower than << but
+ // higher than ?:
+ void operator&(const LogMessage&) { }
+};
+
+#define CHECK(cond) CRASH_UNLESS(cond)
+#define CHECK_LE(a, b) CRASH_UNLESS((a) <= (b))
+#define CHECK_GE(a, b) CRASH_UNLESS((a) >= (b))
+#define CHECK_EQ(a, b) CRASH_UNLESS((a) == (b))
+#define CHECK_NE(a, b) CRASH_UNLESS((a) != (b))
+#define CHECK_LT(a, b) CRASH_UNLESS((a) < (b))
+#define CHECK_GT(a, b) CRASH_UNLESS((a) > (b))
+
} // namespace
using snappy::CompressFile;
diff --git a/thirdparty/snappy/snappy.cc b/thirdparty/snappy/snappy.cc
index 4d4eb42a..f8d0d23d 100644
--- a/thirdparty/snappy/snappy.cc
+++ b/thirdparty/snappy/snappy.cc
@@ -82,6 +82,7 @@ enum {
COPY_2_BYTE_OFFSET = 2,
COPY_4_BYTE_OFFSET = 3
};
+static const int kMaximumTagLength = 5; // COPY_4_BYTE_OFFSET plus the actual offset.
// Copy "len" bytes from "src" to "op", one byte at a time. Used for
// handling COPY operations where the input and output regions may
@@ -94,8 +95,8 @@ enum {
// ababababababababababab
// Note that this does not match the semantics of either memcpy()
// or memmove().
-static inline void IncrementalCopy(const char* src, char* op, int len) {
- DCHECK_GT(len, 0);
+static inline void IncrementalCopy(const char* src, char* op, ssize_t len) {
+ assert(len > 0);
do {
*op++ = *src++;
} while (--len > 0);
@@ -136,9 +137,7 @@ namespace {
const int kMaxIncrementCopyOverflow = 10;
-} // namespace
-
-static inline void IncrementalCopyFastPath(const char* src, char* op, int len) {
+inline void IncrementalCopyFastPath(const char* src, char* op, ssize_t len) {
while (op - src < 8) {
UnalignedCopy64(src, op);
len -= op - src;
@@ -152,6 +151,8 @@ static inline void IncrementalCopyFastPath(const char* src, char* op, int len) {
}
}
+} // namespace
+
static inline char* EmitLiteral(char* op,
const char* literal,
int len,
@@ -195,17 +196,17 @@ static inline char* EmitLiteral(char* op,
}
static inline char* EmitCopyLessThan64(char* op, size_t offset, int len) {
- DCHECK_LE(len, 64);
- DCHECK_GE(len, 4);
- DCHECK_LT(offset, 65536);
+ assert(len <= 64);
+ assert(len >= 4);
+ assert(offset < 65536);
if ((len < 12) && (offset < 2048)) {
size_t len_minus_4 = len - 4;
assert(len_minus_4 < 8); // Must fit in 3 bits
- *op++ = COPY_1_BYTE_OFFSET | ((len_minus_4) << 2) | ((offset >> 8) << 5);
+ *op++ = COPY_1_BYTE_OFFSET + ((len_minus_4) << 2) + ((offset >> 8) << 5);
*op++ = offset & 0xff;
} else {
- *op++ = COPY_2_BYTE_OFFSET | ((len-1) << 2);
+ *op++ = COPY_2_BYTE_OFFSET + ((len-1) << 2);
LittleEndian::Store16(op, offset);
op += 2;
}
@@ -253,8 +254,6 @@ uint16* WorkingMemory::GetHashTable(size_t input_size, int* table_size) {
while (htsize < kMaxHashTableSize && htsize < input_size) {
htsize <<= 1;
}
- CHECK_EQ(0, htsize & (htsize - 1)) << ": must be power of two";
- CHECK_LE(htsize, kMaxHashTableSize) << ": hash table too large";
uint16* table;
if (htsize <= ARRAYSIZE(small_table_)) {
@@ -294,8 +293,8 @@ static inline EightBytesReference GetEightBytesAt(const char* ptr) {
}
static inline uint32 GetUint32AtOffset(uint64 v, int offset) {
- DCHECK_GE(offset, 0);
- DCHECK_LE(offset, 4);
+ assert(offset >= 0);
+ assert(offset <= 4);
return v >> (LittleEndian::IsLittleEndian() ? 8 * offset : 32 - 8 * offset);
}
@@ -308,8 +307,8 @@ static inline EightBytesReference GetEightBytesAt(const char* ptr) {
}
static inline uint32 GetUint32AtOffset(const char* v, int offset) {
- DCHECK_GE(offset, 0);
- DCHECK_LE(offset, 4);
+ assert(offset >= 0);
+ assert(offset <= 4);
return UNALIGNED_LOAD32(v + offset);
}
@@ -334,10 +333,10 @@ char* CompressFragment(const char* input,
const int table_size) {
// "ip" is the input pointer, and "op" is the output pointer.
const char* ip = input;
- CHECK_LE(input_size, kBlockSize);
- CHECK_EQ(table_size & (table_size - 1), 0) << ": table must be power of two";
+ assert(input_size <= kBlockSize);
+ assert((table_size & (table_size - 1)) == 0); // table must be power of two
const int shift = 32 - Bits::Log2Floor(table_size);
- DCHECK_EQ(static_cast<int>(kuint32max >> shift), table_size - 1);
+ assert(static_cast<int>(kuint32max >> shift) == table_size - 1);
const char* ip_end = input + input_size;
const char* base_ip = ip;
// Bytes in [next_emit, ip) will be emitted as literal bytes. Or
@@ -349,7 +348,7 @@ char* CompressFragment(const char* input,
const char* ip_limit = input + input_size - kInputMarginBytes;
for (uint32 next_hash = Hash(++ip, shift); ; ) {
- DCHECK_LT(next_emit, ip);
+ assert(next_emit < ip);
// The body of this loop calls EmitLiteral once and then EmitCopy one or
// more times. (The exception is that when we're close to exhausting
// the input we goto emit_remainder.)
@@ -382,7 +381,7 @@ char* CompressFragment(const char* input,
do {
ip = next_ip;
uint32 hash = next_hash;
- DCHECK_EQ(hash, Hash(ip, shift));
+ assert(hash == Hash(ip, shift));
uint32 bytes_between_hash_lookups = skip++ >> 5;
next_ip = ip + bytes_between_hash_lookups;
if (PREDICT_FALSE(next_ip > ip_limit)) {
@@ -390,8 +389,8 @@ char* CompressFragment(const char* input,
}
next_hash = Hash(next_ip, shift);
candidate = base_ip + table[hash];
- DCHECK_GE(candidate, base_ip);
- DCHECK_LT(candidate, ip);
+ assert(candidate >= base_ip);
+ assert(candidate < ip);
table[hash] = ip - base_ip;
} while (PREDICT_TRUE(UNALIGNED_LOAD32(ip) !=
@@ -400,7 +399,7 @@ char* CompressFragment(const char* input,
// Step 2: A 4-byte match has been found. We'll later see if more
// than 4 bytes match. But, prior to the match, input
// bytes [next_emit, ip) are unmatched. Emit them as "literal bytes."
- DCHECK_LE(next_emit + 16, ip_end);
+ assert(next_emit + 16 <= ip_end);
op = EmitLiteral(op, next_emit, ip - next_emit, true);
// Step 3: Call EmitCopy, and then see if another EmitCopy could
@@ -421,7 +420,7 @@ char* CompressFragment(const char* input,
int matched = 4 + FindMatchLength(candidate + 4, ip + 4, ip_end);
ip += matched;
size_t offset = base - candidate;
- DCHECK_EQ(0, memcmp(base, candidate, matched));
+ assert(0 == memcmp(base, candidate, matched));
op = EmitCopy(op, offset, matched);
// We could immediately start working at ip now, but to improve
// compression we first update table[Hash(ip - 1, ...)].
@@ -471,21 +470,26 @@ char* CompressFragment(const char* input,
// bool Append(const char* ip, size_t length);
// bool AppendFromSelf(uint32 offset, size_t length);
//
-// // The difference between TryFastAppend and Append is that TryFastAppend
-// // is allowed to read up to <available> bytes from the input buffer,
-// // whereas Append is allowed to read <length>.
+// // The rules for how TryFastAppend differs from Append are somewhat
+// // convoluted:
// //
-// // Also, TryFastAppend is allowed to return false, declining the append,
-// // without it being a fatal error -- just "return false" would be
-// // a perfectly legal implementation of TryFastAppend. The intention
-// // is for TryFastAppend to allow a fast path in the common case of
-// // a small append.
+// // - TryFastAppend is allowed to decline (return false) at any
+// // time, for any reason -- just "return false" would be
+// // a perfectly legal implementation of TryFastAppend.
+// // The intention is for TryFastAppend to allow a fast path
+// // in the common case of a small append.
+// // - TryFastAppend is allowed to read up to <available> bytes
+// // from the input buffer, whereas Append is allowed to read
+// // <length>. However, if it returns true, it must leave
+// // at least five (kMaximumTagLength) bytes in the input buffer
+// // afterwards, so that there is always enough space to read the
+// // next tag without checking for a refill.
+// // - TryFastAppend must always return decline (return false)
+// // if <length> is 61 or more, as in this case the literal length is not
+// // decoded fully. In practice, this should not be a big problem,
+// // as it is unlikely that one would implement a fast path accepting
+// // this much data.
// //
-// // NOTE(user): TryFastAppend must always return decline (return false)
-// // if <length> is 61 or more, as in this case the literal length is not
-// // decoded fully. In practice, this should not be a big problem,
-// // as it is unlikely that one would implement a fast path accepting
-// // this much data.
// bool TryFastAppend(const char* ip, size_t available, size_t length);
// };
@@ -554,9 +558,9 @@ static uint16 MakeEntry(unsigned int extra,
unsigned int len,
unsigned int copy_offset) {
// Check that all of the fields fit within the allocated space
- DCHECK_EQ(extra, extra & 0x7); // At most 3 bits
- DCHECK_EQ(copy_offset, copy_offset & 0x7); // At most 3 bits
- DCHECK_EQ(len, len & 0x7f); // At most 7 bits
+ assert(extra == (extra & 0x7)); // At most 3 bits
+ assert(copy_offset == (copy_offset & 0x7)); // At most 3 bits
+ assert(len == (len & 0x7f)); // At most 7 bits
return len | (copy_offset << 8) | (extra << 11);
}
@@ -614,9 +618,15 @@ static void ComputeTable() {
}
// Check that each entry was initialized exactly once.
- CHECK_EQ(assigned, 256);
+ if (assigned != 256) {
+ fprintf(stderr, "ComputeTable: assigned only %d of 256\n", assigned);
+ abort();
+ }
for (int i = 0; i < 256; i++) {
- CHECK_NE(dst[i], 0xffff);
+ if (dst[i] == 0xffff) {
+ fprintf(stderr, "ComputeTable: did not assign byte %d\n", i);
+ abort();
+ }
}
if (FLAGS_snappy_dump_decompression_table) {
@@ -631,7 +641,11 @@ static void ComputeTable() {
// Check that computed table matched recorded table
for (int i = 0; i < 256; i++) {
- CHECK_EQ(dst[i], char_table[i]);
+ if (dst[i] != char_table[i]) {
+ fprintf(stderr, "ComputeTable: byte %d: computed (%x), expect (%x)\n",
+ i, static_cast<int>(dst[i]), static_cast<int>(char_table[i]));
+ abort();
+ }
}
}
#endif /* !NDEBUG */
@@ -644,7 +658,7 @@ class SnappyDecompressor {
const char* ip_limit_; // Points just past buffered bytes
uint32 peeked_; // Bytes peeked from reader (need to skip)
bool eof_; // Hit end of input without an error?
- char scratch_[5]; // Temporary buffer for PeekFast() boundaries
+ char scratch_[kMaximumTagLength]; // See RefillTag().
// Ensure that all of the tag metadata for the next tag is available
// in [ip_..ip_limit_-1]. Also ensures that [ip,ip+4] is readable even
@@ -676,7 +690,7 @@ class SnappyDecompressor {
// On succcess, stores the length in *result and returns true.
// On failure, returns false.
bool ReadUncompressedLength(uint32* result) {
- DCHECK(ip_ == NULL); // Must not have read anything yet
+ assert(ip_ == NULL); // Must not have read anything yet
// Length is encoded in 1..5 bytes
*result = 0;
uint32 shift = 0;
@@ -707,7 +721,7 @@ class SnappyDecompressor {
// scope to optimize the <ip_limit_ - ip> expression based on the local
// context, which overall increases speed.
#define MAYBE_REFILL() \
- if (ip_limit_ - ip < 5) { \
+ if (ip_limit_ - ip < kMaximumTagLength) { \
ip_ = ip; \
if (!RefillTag()) return; \
ip = ip_; \
@@ -720,9 +734,11 @@ class SnappyDecompressor {
if ((c & 0x3) == LITERAL) {
size_t literal_length = (c >> 2) + 1u;
if (writer->TryFastAppend(ip, ip_limit_ - ip, literal_length)) {
- DCHECK_LT(literal_length, 61);
+ assert(literal_length < 61);
ip += literal_length;
- MAYBE_REFILL();
+ // NOTE(user): There is no MAYBE_REFILL() here, as TryFastAppend()
+ // will not return true unless there's already at least five spare
+ // bytes in addition to the literal.
continue;
}
if (PREDICT_FALSE(literal_length >= 61)) {
@@ -787,11 +803,11 @@ bool SnappyDecompressor::RefillTag() {
}
// Read the tag character
- DCHECK_LT(ip, ip_limit_);
+ assert(ip < ip_limit_);
const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
const uint32 entry = char_table[c];
const uint32 needed = (entry >> 11) + 1; // +1 byte for 'c'
- DCHECK_LE(needed, sizeof(scratch_));
+ assert(needed <= sizeof(scratch_));
// Read more bytes from reader if needed
uint32 nbuf = ip_limit_ - ip;
@@ -812,10 +828,10 @@ bool SnappyDecompressor::RefillTag() {
nbuf += to_add;
reader_->Skip(to_add);
}
- DCHECK_EQ(nbuf, needed);
+ assert(nbuf == needed);
ip_ = scratch_;
ip_limit_ = scratch_ + needed;
- } else if (nbuf < 5) {
+ } else if (nbuf < kMaximumTagLength) {
// Have enough bytes, but move into scratch_ so that we do not
// read past end of input
memmove(scratch_, ip, nbuf);
@@ -831,27 +847,18 @@ bool SnappyDecompressor::RefillTag() {
}
template <typename Writer>
-static bool InternalUncompress(Source* r,
- Writer* writer,
- uint32 max_len) {
+static bool InternalUncompress(Source* r, Writer* writer) {
// Read the uncompressed length from the front of the compressed input
SnappyDecompressor decompressor(r);
uint32 uncompressed_len = 0;
if (!decompressor.ReadUncompressedLength(&uncompressed_len)) return false;
- return InternalUncompressAllTags(
- &decompressor, writer, uncompressed_len, max_len);
+ return InternalUncompressAllTags(&decompressor, writer, uncompressed_len);
}
template <typename Writer>
static bool InternalUncompressAllTags(SnappyDecompressor* decompressor,
Writer* writer,
- uint32 uncompressed_len,
- uint32 max_len) {
- // Protect against possible DoS attack
- if (static_cast<uint64>(uncompressed_len) > max_len) {
- return false;
- }
-
+ uint32 uncompressed_len) {
writer->SetExpectedLength(uncompressed_len);
// Process the entire input
@@ -880,7 +887,7 @@ size_t Compress(Source* reader, Sink* writer) {
// Get next block to compress (without copying if possible)
size_t fragment_size;
const char* fragment = reader->Peek(&fragment_size);
- DCHECK_NE(fragment_size, 0) << ": premature end of input";
+ assert(fragment_size != 0); // premature end of input
const size_t num_to_read = min(N, kBlockSize);
size_t bytes_read = fragment_size;
@@ -907,11 +914,11 @@ size_t Compress(Source* reader, Sink* writer) {
bytes_read += n;
reader->Skip(n);
}
- DCHECK_EQ(bytes_read, num_to_read);
+ assert(bytes_read == num_to_read);
fragment = scratch;
fragment_size = num_to_read;
}
- DCHECK_EQ(fragment_size, num_to_read);
+ assert(fragment_size == num_to_read);
// Get encoding table for compression
int table_size;
@@ -946,6 +953,183 @@ size_t Compress(Source* reader, Sink* writer) {
}
// -----------------------------------------------------------------------
+// IOVec interfaces
+// -----------------------------------------------------------------------
+
+// A type that writes to an iovec.
+// Note that this is not a "ByteSink", but a type that matches the
+// Writer template argument to SnappyDecompressor::DecompressAllTags().
+class SnappyIOVecWriter {
+ private:
+ const struct iovec* output_iov_;
+ const size_t output_iov_count_;
+
+ // We are currently writing into output_iov_[curr_iov_index_].
+ int curr_iov_index_;
+
+ // Bytes written to output_iov_[curr_iov_index_] so far.
+ size_t curr_iov_written_;
+
+ // Total bytes decompressed into output_iov_ so far.
+ size_t total_written_;
+
+ // Maximum number of bytes that will be decompressed into output_iov_.
+ size_t output_limit_;
+
+ inline char* GetIOVecPointer(int index, size_t offset) {
+ return reinterpret_cast<char*>(output_iov_[index].iov_base) +
+ offset;
+ }
+
+ public:
+ // Does not take ownership of iov. iov must be valid during the
+ // entire lifetime of the SnappyIOVecWriter.
+ inline SnappyIOVecWriter(const struct iovec* iov, size_t iov_count)
+ : output_iov_(iov),
+ output_iov_count_(iov_count),
+ curr_iov_index_(0),
+ curr_iov_written_(0),
+ total_written_(0),
+ output_limit_(-1) {
+ }
+
+ inline void SetExpectedLength(size_t len) {
+ output_limit_ = len;
+ }
+
+ inline bool CheckLength() const {
+ return total_written_ == output_limit_;
+ }
+
+ inline bool Append(const char* ip, size_t len) {
+ if (total_written_ + len > output_limit_) {
+ return false;
+ }
+
+ while (len > 0) {
+ assert(curr_iov_written_ <= output_iov_[curr_iov_index_].iov_len);
+ if (curr_iov_written_ >= output_iov_[curr_iov_index_].iov_len) {
+ // This iovec is full. Go to the next one.
+ if (curr_iov_index_ + 1 >= output_iov_count_) {
+ return false;
+ }
+ curr_iov_written_ = 0;
+ ++curr_iov_index_;
+ }
+
+ const size_t to_write = std::min(
+ len, output_iov_[curr_iov_index_].iov_len - curr_iov_written_);
+ memcpy(GetIOVecPointer(curr_iov_index_, curr_iov_written_),
+ ip,
+ to_write);
+ curr_iov_written_ += to_write;
+ total_written_ += to_write;
+ ip += to_write;
+ len -= to_write;
+ }
+
+ return true;
+ }
+
+ inline bool TryFastAppend(const char* ip, size_t available, size_t len) {
+ const size_t space_left = output_limit_ - total_written_;
+ if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16 &&
+ output_iov_[curr_iov_index_].iov_len - curr_iov_written_ >= 16) {
+ // Fast path, used for the majority (about 95%) of invocations.
+ char* ptr = GetIOVecPointer(curr_iov_index_, curr_iov_written_);
+ UnalignedCopy64(ip, ptr);
+ UnalignedCopy64(ip + 8, ptr + 8);
+ curr_iov_written_ += len;
+ total_written_ += len;
+ return true;
+ }
+
+ return false;
+ }
+
+ inline bool AppendFromSelf(size_t offset, size_t len) {
+ if (offset > total_written_ || offset == 0) {
+ return false;
+ }
+ const size_t space_left = output_limit_ - total_written_;
+ if (len > space_left) {
+ return false;
+ }
+
+ // Locate the iovec from which we need to start the copy.
+ int from_iov_index = curr_iov_index_;
+ size_t from_iov_offset = curr_iov_written_;
+ while (offset > 0) {
+ if (from_iov_offset >= offset) {
+ from_iov_offset -= offset;
+ break;
+ }
+
+ offset -= from_iov_offset;
+ --from_iov_index;
+ assert(from_iov_index >= 0);
+ from_iov_offset = output_iov_[from_iov_index].iov_len;
+ }
+
+ // Copy <len> bytes starting from the iovec pointed to by from_iov_index to
+ // the current iovec.
+ while (len > 0) {
+ assert(from_iov_index <= curr_iov_index_);
+ if (from_iov_index != curr_iov_index_) {
+ const size_t to_copy = std::min(
+ output_iov_[from_iov_index].iov_len - from_iov_offset,
+ len);
+ Append(GetIOVecPointer(from_iov_index, from_iov_offset), to_copy);
+ len -= to_copy;
+ if (len > 0) {
+ ++from_iov_index;
+ from_iov_offset = 0;
+ }
+ } else {
+ assert(curr_iov_written_ <= output_iov_[curr_iov_index_].iov_len);
+ size_t to_copy = std::min(output_iov_[curr_iov_index_].iov_len -
+ curr_iov_written_,
+ len);
+ if (to_copy == 0) {
+ // This iovec is full. Go to the next one.
+ if (curr_iov_index_ + 1 >= output_iov_count_) {
+ return false;
+ }
+ ++curr_iov_index_;
+ curr_iov_written_ = 0;
+ continue;
+ }
+ if (to_copy > len) {
+ to_copy = len;
+ }
+ IncrementalCopy(GetIOVecPointer(from_iov_index, from_iov_offset),
+ GetIOVecPointer(curr_iov_index_, curr_iov_written_),
+ to_copy);
+ curr_iov_written_ += to_copy;
+ from_iov_offset += to_copy;
+ total_written_ += to_copy;
+ len -= to_copy;
+ }
+ }
+
+ return true;
+ }
+
+};
+
+bool RawUncompressToIOVec(const char* compressed, size_t compressed_length,
+ const struct iovec* iov, size_t iov_cnt) {
+ ByteArraySource reader(compressed, compressed_length);
+ return RawUncompressToIOVec(&reader, iov, iov_cnt);
+}
+
+bool RawUncompressToIOVec(Source* compressed, const struct iovec* iov,
+ size_t iov_cnt) {
+ SnappyIOVecWriter output(iov, iov_cnt);
+ return InternalUncompress(compressed, &output);
+}
+
+// -----------------------------------------------------------------------
// Flat array interfaces
// -----------------------------------------------------------------------
@@ -986,7 +1170,7 @@ class SnappyArrayWriter {
inline bool TryFastAppend(const char* ip, size_t available, size_t len) {
char* op = op_;
const size_t space_left = op_limit_ - op;
- if (len <= 16 && available >= 16 && space_left >= 16) {
+ if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16) {
// Fast path, used for the majority (about 95%) of invocations.
UnalignedCopy64(ip, op);
UnalignedCopy64(ip + 8, op + 8);
@@ -1001,7 +1185,16 @@ class SnappyArrayWriter {
char* op = op_;
const size_t space_left = op_limit_ - op;
- if (op - base_ <= offset - 1u) { // -1u catches offset==0
+ // Check if we try to append from before the start of the buffer.
+ // Normally this would just be a check for "produced < offset",
+ // but "produced <= offset - 1u" is equivalent for every case
+ // except the one where offset==0, where the right side will wrap around
+ // to a very big number. This is convenient, as offset==0 is another
+ // invalid case that we also want to catch, so that we do not go
+ // into an infinite loop.
+ assert(op >= base_);
+ size_t produced = op - base_;
+ if (produced <= offset - 1u) {
return false;
}
if (len <= 16 && offset >= 8 && space_left >= 16) {
@@ -1031,7 +1224,7 @@ bool RawUncompress(const char* compressed, size_t n, char* uncompressed) {
bool RawUncompress(Source* compressed, char* uncompressed) {
SnappyArrayWriter output(uncompressed);
- return InternalUncompress(compressed, &output, kuint32max);
+ return InternalUncompress(compressed, &output);
}
bool Uncompress(const char* compressed, size_t n, string* uncompressed) {
@@ -1039,9 +1232,9 @@ bool Uncompress(const char* compressed, size_t n, string* uncompressed) {
if (!GetUncompressedLength(compressed, n, &ulength)) {
return false;
}
- // Protect against possible DoS attack
- if ((static_cast<uint64>(ulength) + uncompressed->size()) >
- uncompressed->max_size()) {
+ // On 32-bit builds: max_size() < kuint32max. Check for that instead
+ // of crashing (e.g., consider externally specified compressed data).
+ if (ulength > uncompressed->max_size()) {
return false;
}
STLStringResizeUninitialized(uncompressed, ulength);
@@ -1071,7 +1264,9 @@ class SnappyDecompressionValidator {
return false;
}
inline bool AppendFromSelf(size_t offset, size_t len) {
- if (produced_ <= offset - 1u) return false; // -1u catches offset==0
+ // See SnappyArrayWriter::AppendFromSelf for an explanation of
+ // the "offset - 1u" trick.
+ if (produced_ <= offset - 1u) return false;
produced_ += len;
return produced_ <= expected_;
}
@@ -1080,7 +1275,7 @@ class SnappyDecompressionValidator {
bool IsValidCompressedBuffer(const char* compressed, size_t n) {
ByteArraySource reader(compressed, n);
SnappyDecompressionValidator writer;
- return InternalUncompress(&reader, &writer, kuint32max);
+ return InternalUncompress(&reader, &writer);
}
void RawCompress(const char* input,
diff --git a/thirdparty/snappy/snappy.h b/thirdparty/snappy/snappy.h
index 8c2075fe..e879e794 100644
--- a/thirdparty/snappy/snappy.h
+++ b/thirdparty/snappy/snappy.h
@@ -56,6 +56,13 @@ namespace snappy {
// number of bytes written.
size_t Compress(Source* source, Sink* sink);
+ // Find the uncompressed length of the given stream, as given by the header.
+ // Note that the true length could deviate from this; the stream could e.g.
+ // be truncated.
+ //
+ // Also note that this leaves "*source" in a state that is unsuitable for
+ // further operations, such as RawUncompress(). You will need to rewind
+ // or recreate the source yourself before attempting any further calls.
bool GetUncompressedLength(Source* source, uint32* result);
// ------------------------------------------------------------------------
@@ -117,6 +124,28 @@ namespace snappy {
// returns false if the message is corrupted and could not be decrypted
bool RawUncompress(Source* compressed, char* uncompressed);
+ // Given data in "compressed[0..compressed_length-1]" generated by
+ // calling the Snappy::Compress routine, this routine
+ // stores the uncompressed data to the iovec "iov". The number of physical
+ // buffers in "iov" is given by iov_cnt and their cumulative size
+ // must be at least GetUncompressedLength(compressed). The individual buffers
+ // in "iov" must not overlap with each other.
+ //
+ // returns false if the message is corrupted and could not be decrypted
+ bool RawUncompressToIOVec(const char* compressed, size_t compressed_length,
+ const struct iovec* iov, size_t iov_cnt);
+
+ // Given data from the byte source 'compressed' generated by calling
+ // the Snappy::Compress routine, this routine stores the uncompressed
+ // data to the iovec "iov". The number of physical
+ // buffers in "iov" is given by iov_cnt and their cumulative size
+ // must be at least GetUncompressedLength(compressed). The individual buffers
+ // in "iov" must not overlap with each other.
+ //
+ // returns false if the message is corrupted and could not be decrypted
+ bool RawUncompressToIOVec(Source* compressed, const struct iovec* iov,
+ size_t iov_cnt);
+
// Returns the maximal size of the compressed representation of
// input data that is "source_bytes" bytes in length;
size_t MaxCompressedLength(size_t source_bytes);
@@ -135,20 +164,20 @@ namespace snappy {
bool IsValidCompressedBuffer(const char* compressed,
size_t compressed_length);
- // *** DO NOT CHANGE THE VALUE OF kBlockSize ***
+ // The size of a compression block. Note that many parts of the compression
+ // code assumes that kBlockSize <= 65536; in particular, the hash table
+ // can only store 16-bit offsets, and EmitCopy() also assumes the offset
+ // is 65535 bytes or less. Note also that if you change this, it will
+ // affect the framing format (see framing_format.txt).
//
- // New Compression code chops up the input into blocks of at most
- // the following size. This ensures that back-references in the
- // output never cross kBlockSize block boundaries. This can be
- // helpful in implementing blocked decompression. However the
- // decompression code should not rely on this guarantee since older
- // compression code may not obey it.
- static const int kBlockLog = 15;
+ // Note that there might be older data around that is compressed with larger
+ // block sizes, so the decompression code should not rely on the
+ // non-existence of long backreferences.
+ static const int kBlockLog = 16;
static const size_t kBlockSize = 1 << kBlockLog;
static const int kMaxHashTableBits = 14;
static const size_t kMaxHashTableSize = 1 << kMaxHashTableBits;
-
} // end namespace snappy
diff --git a/thirdparty/snappy/snappy_unittest.cc b/thirdparty/snappy/snappy_unittest.cc
index f3b9c83c..be7bba6b 100644
--- a/thirdparty/snappy/snappy_unittest.cc
+++ b/thirdparty/snappy/snappy_unittest.cc
@@ -492,6 +492,46 @@ static int VerifyString(const string& input) {
}
+static void VerifyIOVec(const string& input) {
+ string compressed;
+ DataEndingAtUnreadablePage i(input);
+ const size_t written = snappy::Compress(i.data(), i.size(), &compressed);
+ CHECK_EQ(written, compressed.size());
+ CHECK_LE(compressed.size(),
+ snappy::MaxCompressedLength(input.size()));
+ CHECK(snappy::IsValidCompressedBuffer(compressed.data(), compressed.size()));
+
+ // Try uncompressing into an iovec containing a random number of entries
+ // ranging from 1 to 10.
+ char* buf = new char[input.size()];
+ ACMRandom rnd(input.size());
+ int num = rnd.Next() % 10 + 1;
+ if (input.size() < num) {
+ num = input.size();
+ }
+ struct iovec* iov = new iovec[num];
+ int used_so_far = 0;
+ for (int i = 0; i < num; ++i) {
+ iov[i].iov_base = buf + used_so_far;
+ if (i == num - 1) {
+ iov[i].iov_len = input.size() - used_so_far;
+ } else {
+ // Randomly choose to insert a 0 byte entry.
+ if (rnd.OneIn(5)) {
+ iov[i].iov_len = 0;
+ } else {
+ iov[i].iov_len = rnd.Uniform(input.size());
+ }
+ }
+ used_so_far += iov[i].iov_len;
+ }
+ CHECK(snappy::RawUncompressToIOVec(
+ compressed.data(), compressed.size(), iov, num));
+ CHECK(!memcmp(buf, input.data(), input.size()));
+ delete[] iov;
+ delete[] buf;
+}
+
// Test that data compressed by a compressor that does not
// obey block sizes is uncompressed properly.
static void VerifyNonBlockedCompression(const string& input) {
@@ -542,8 +582,11 @@ static int Verify(const string& input) {
VerifyNonBlockedCompression(input);
+ VerifyIOVec(input);
if (!input.empty()) {
- VerifyNonBlockedCompression(Expand(input));
+ const string expanded = Expand(input);
+ VerifyNonBlockedCompression(expanded);
+ VerifyIOVec(input);
}
@@ -611,7 +654,8 @@ TYPED_TEST(CorruptedTest, VerifyCorrupted) {
// try reading stuff in from a bad file.
for (int i = 1; i <= 3; ++i) {
- string data = ReadTestDataFile(StringPrintf("baddata%d.snappy", i).c_str());
+ string data = ReadTestDataFile(StringPrintf("baddata%d.snappy", i).c_str(),
+ 0);
string uncmp;
// check that we don't return a crazy length
size_t ulen;
@@ -663,7 +707,7 @@ static void AppendCopy(string* dst, int offset, int length) {
}
length -= to_copy;
- if ((to_copy < 12) && (offset < 2048)) {
+ if ((to_copy >= 4) && (to_copy < 12) && (offset < 2048)) {
assert(to_copy-4 < 8); // Must fit in 3 bits
dst->push_back(1 | ((to_copy-4) << 2) | ((offset >> 8) << 5));
dst->push_back(offset & 0xff);
@@ -768,10 +812,123 @@ TEST(Snappy, FourByteOffset) {
string uncompressed;
CHECK(snappy::IsValidCompressedBuffer(compressed.data(), compressed.size()));
- CHECK(snappy::Uncompress(compressed.data(), compressed.size(), &uncompressed));
+ CHECK(snappy::Uncompress(compressed.data(), compressed.size(),
+ &uncompressed));
CHECK_EQ(uncompressed, src);
}
+TEST(Snappy, IOVecEdgeCases) {
+ // Test some tricky edge cases in the iovec output that are not necessarily
+ // exercised by random tests.
+
+ // Our output blocks look like this initially (the last iovec is bigger
+ // than depicted):
+ // [ ] [ ] [ ] [ ] [ ]
+ static const int kLengths[] = { 2, 1, 4, 8, 128 };
+
+ struct iovec iov[ARRAYSIZE(kLengths)];
+ for (int i = 0; i < ARRAYSIZE(kLengths); ++i) {
+ iov[i].iov_base = new char[kLengths[i]];
+ iov[i].iov_len = kLengths[i];
+ }
+
+ string compressed;
+ Varint::Append32(&compressed, 22);
+
+ // A literal whose output crosses three blocks.
+ // [ab] [c] [123 ] [ ] [ ]
+ AppendLiteral(&compressed, "abc123");
+
+ // A copy whose output crosses two blocks (source and destination
+ // segments marked).
+ // [ab] [c] [1231] [23 ] [ ]
+ // ^--^ --
+ AppendCopy(&compressed, 3, 3);
+
+ // A copy where the input is, at first, in the block before the output:
+ //
+ // [ab] [c] [1231] [231231 ] [ ]
+ // ^--- ^---
+ // Then during the copy, the pointers move such that the input and
+ // output pointers are in the same block:
+ //
+ // [ab] [c] [1231] [23123123] [ ]
+ // ^- ^-
+ // And then they move again, so that the output pointer is no longer
+ // in the same block as the input pointer:
+ // [ab] [c] [1231] [23123123] [123 ]
+ // ^-- ^--
+ AppendCopy(&compressed, 6, 9);
+
+ // Finally, a copy where the input is from several blocks back,
+ // and it also crosses three blocks:
+ //
+ // [ab] [c] [1231] [23123123] [123b ]
+ // ^ ^
+ // [ab] [c] [1231] [23123123] [123bc ]
+ // ^ ^
+ // [ab] [c] [1231] [23123123] [123bc12 ]
+ // ^- ^-
+ AppendCopy(&compressed, 17, 4);
+
+ CHECK(snappy::RawUncompressToIOVec(
+ compressed.data(), compressed.size(), iov, ARRAYSIZE(iov)));
+ CHECK_EQ(0, memcmp(iov[0].iov_base, "ab", 2));
+ CHECK_EQ(0, memcmp(iov[1].iov_base, "c", 1));
+ CHECK_EQ(0, memcmp(iov[2].iov_base, "1231", 4));
+ CHECK_EQ(0, memcmp(iov[3].iov_base, "23123123", 8));
+ CHECK_EQ(0, memcmp(iov[4].iov_base, "123bc12", 7));
+
+ for (int i = 0; i < ARRAYSIZE(kLengths); ++i) {
+ delete[] reinterpret_cast<char *>(iov[i].iov_base);
+ }
+}
+
+TEST(Snappy, IOVecLiteralOverflow) {
+ static const int kLengths[] = { 3, 4 };
+
+ struct iovec iov[ARRAYSIZE(kLengths)];
+ for (int i = 0; i < ARRAYSIZE(kLengths); ++i) {
+ iov[i].iov_base = new char[kLengths[i]];
+ iov[i].iov_len = kLengths[i];
+ }
+
+ string compressed;
+ Varint::Append32(&compressed, 8);
+
+ AppendLiteral(&compressed, "12345678");
+
+ CHECK(!snappy::RawUncompressToIOVec(
+ compressed.data(), compressed.size(), iov, ARRAYSIZE(iov)));
+
+ for (int i = 0; i < ARRAYSIZE(kLengths); ++i) {
+ delete[] reinterpret_cast<char *>(iov[i].iov_base);
+ }
+}
+
+TEST(Snappy, IOVecCopyOverflow) {
+ static const int kLengths[] = { 3, 4 };
+
+ struct iovec iov[ARRAYSIZE(kLengths)];
+ for (int i = 0; i < ARRAYSIZE(kLengths); ++i) {
+ iov[i].iov_base = new char[kLengths[i]];
+ iov[i].iov_len = kLengths[i];
+ }
+
+ string compressed;
+ Varint::Append32(&compressed, 8);
+
+ AppendLiteral(&compressed, "123");
+ AppendCopy(&compressed, 3, 5);
+
+ CHECK(!snappy::RawUncompressToIOVec(
+ compressed.data(), compressed.size(), iov, ARRAYSIZE(iov)));
+
+ for (int i = 0; i < ARRAYSIZE(kLengths); ++i) {
+ delete[] reinterpret_cast<char *>(iov[i].iov_base);
+ }
+}
+
static bool CheckUncompressedLength(const string& compressed,
size_t* ulength) {
@@ -971,18 +1128,18 @@ TEST(Snappy, FindMatchLengthRandom) {
static void CompressFile(const char* fname) {
string fullinput;
- File::ReadFileToStringOrDie(fname, &fullinput);
+ file::GetContents(fname, &fullinput, file::Defaults()).CheckSuccess();
string compressed;
Compress(fullinput.data(), fullinput.size(), SNAPPY, &compressed, false);
- File::WriteStringToFileOrDie(compressed,
- string(fname).append(".comp").c_str());
+ file::SetContents(string(fname).append(".comp"), compressed, file::Defaults())
+ .CheckSuccess();
}
static void UncompressFile(const char* fname) {
string fullinput;
- File::ReadFileToStringOrDie(fname, &fullinput);
+ file::GetContents(fname, &fullinput, file::Defaults()).CheckSuccess();
size_t uncompLength;
CHECK(CheckUncompressedLength(fullinput, &uncompLength));
@@ -991,13 +1148,13 @@ static void UncompressFile(const char* fname) {
uncompressed.resize(uncompLength);
CHECK(snappy::Uncompress(fullinput.data(), fullinput.size(), &uncompressed));
- File::WriteStringToFileOrDie(uncompressed,
- string(fname).append(".uncomp").c_str());
+ file::SetContents(string(fname).append(".uncomp"), uncompressed,
+ file::Defaults()).CheckSuccess();
}
static void MeasureFile(const char* fname) {
string fullinput;
- File::ReadFileToStringOrDie(fname, &fullinput);
+ file::GetContents(fname, &fullinput, file::Defaults()).CheckSuccess();
printf("%-40s :\n", fname);
int start_len = (FLAGS_start_len < 0) ? fullinput.size() : FLAGS_start_len;
@@ -1030,25 +1187,20 @@ static void MeasureFile(const char* fname) {
static struct {
const char* label;
const char* filename;
+ size_t size_limit;
} files[] = {
- { "html", "html" },
- { "urls", "urls.10K" },
- { "jpg", "house.jpg" },
- { "pdf", "mapreduce-osdi-1.pdf" },
- { "html4", "html_x_4" },
- { "cp", "cp.html" },
- { "c", "fields.c" },
- { "lsp", "grammar.lsp" },
- { "xls", "kennedy.xls" },
- { "txt1", "alice29.txt" },
- { "txt2", "asyoulik.txt" },
- { "txt3", "lcet10.txt" },
- { "txt4", "plrabn12.txt" },
- { "bin", "ptt5" },
- { "sum", "sum" },
- { "man", "xargs.1" },
- { "pb", "geo.protodata" },
- { "gaviota", "kppkn.gtb" },
+ { "html", "html", 0 },
+ { "urls", "urls.10K", 0 },
+ { "jpg", "fireworks.jpeg", 0 },
+ { "jpg_200", "fireworks.jpeg", 200 },
+ { "pdf", "paper-100k.pdf", 0 },
+ { "html4", "html_x_4", 0 },
+ { "txt1", "alice29.txt", 0 },
+ { "txt2", "asyoulik.txt", 0 },
+ { "txt3", "lcet10.txt", 0 },
+ { "txt4", "plrabn12.txt", 0 },
+ { "pb", "geo.protodata", 0 },
+ { "gaviota", "kppkn.gtb", 0 },
};
static void BM_UFlat(int iters, int arg) {
@@ -1057,7 +1209,8 @@ static void BM_UFlat(int iters, int arg) {
// Pick file to process based on "arg"
CHECK_GE(arg, 0);
CHECK_LT(arg, ARRAYSIZE(files));
- string contents = ReadTestDataFile(files[arg].filename);
+ string contents = ReadTestDataFile(files[arg].filename,
+ files[arg].size_limit);
string zcontents;
snappy::Compress(contents.data(), contents.size(), &zcontents);
@@ -1074,7 +1227,7 @@ static void BM_UFlat(int iters, int arg) {
delete[] dst;
}
-BENCHMARK(BM_UFlat)->DenseRange(0, 17);
+BENCHMARK(BM_UFlat)->DenseRange(0, ARRAYSIZE(files) - 1);
static void BM_UValidate(int iters, int arg) {
StopBenchmarkTiming();
@@ -1082,7 +1235,8 @@ static void BM_UValidate(int iters, int arg) {
// Pick file to process based on "arg"
CHECK_GE(arg, 0);
CHECK_LT(arg, ARRAYSIZE(files));
- string contents = ReadTestDataFile(files[arg].filename);
+ string contents = ReadTestDataFile(files[arg].filename,
+ files[arg].size_limit);
string zcontents;
snappy::Compress(contents.data(), contents.size(), &zcontents);
@@ -1098,6 +1252,52 @@ static void BM_UValidate(int iters, int arg) {
}
BENCHMARK(BM_UValidate)->DenseRange(0, 4);
+static void BM_UIOVec(int iters, int arg) {
+ StopBenchmarkTiming();
+
+ // Pick file to process based on "arg"
+ CHECK_GE(arg, 0);
+ CHECK_LT(arg, ARRAYSIZE(files));
+ string contents = ReadTestDataFile(files[arg].filename,
+ files[arg].size_limit);
+
+ string zcontents;
+ snappy::Compress(contents.data(), contents.size(), &zcontents);
+
+ // Uncompress into an iovec containing ten entries.
+ const int kNumEntries = 10;
+ struct iovec iov[kNumEntries];
+ char *dst = new char[contents.size()];
+ int used_so_far = 0;
+ for (int i = 0; i < kNumEntries; ++i) {
+ iov[i].iov_base = dst + used_so_far;
+ if (used_so_far == contents.size()) {
+ iov[i].iov_len = 0;
+ continue;
+ }
+
+ if (i == kNumEntries - 1) {
+ iov[i].iov_len = contents.size() - used_so_far;
+ } else {
+ iov[i].iov_len = contents.size() / kNumEntries;
+ }
+ used_so_far += iov[i].iov_len;
+ }
+
+ SetBenchmarkBytesProcessed(static_cast<int64>(iters) *
+ static_cast<int64>(contents.size()));
+ SetBenchmarkLabel(files[arg].label);
+ StartBenchmarkTiming();
+ while (iters-- > 0) {
+ CHECK(snappy::RawUncompressToIOVec(zcontents.data(), zcontents.size(), iov,
+ kNumEntries));
+ }
+ StopBenchmarkTiming();
+
+ delete[] dst;
+}
+BENCHMARK(BM_UIOVec)->DenseRange(0, 4);
+
static void BM_ZFlat(int iters, int arg) {
StopBenchmarkTiming();
@@ -1105,7 +1305,8 @@ static void BM_ZFlat(int iters, int arg) {
// Pick file to process based on "arg"
CHECK_GE(arg, 0);
CHECK_LT(arg, ARRAYSIZE(files));
- string contents = ReadTestDataFile(files[arg].filename);
+ string contents = ReadTestDataFile(files[arg].filename,
+ files[arg].size_limit);
char* dst = new char[snappy::MaxCompressedLength(contents.size())];
@@ -1126,7 +1327,7 @@ static void BM_ZFlat(int iters, int arg) {
files[arg].label, contents.size(), zsize);
delete[] dst;
}
-BENCHMARK(BM_ZFlat)->DenseRange(0, 17);
+BENCHMARK(BM_ZFlat)->DenseRange(0, ARRAYSIZE(files) - 1);
} // namespace snappy
@@ -1134,7 +1335,6 @@ BENCHMARK(BM_ZFlat)->DenseRange(0, 17);
int main(int argc, char** argv) {
InitGoogle(argv[0], &argc, &argv, true);
- File::Init();
RunSpecifiedBenchmarks();
diff --git a/thirdparty/zlib/CMakeLists.txt b/thirdparty/zlib/CMakeLists.txt
index 710855de..c76f9e7a 100644
--- a/thirdparty/zlib/CMakeLists.txt
+++ b/thirdparty/zlib/CMakeLists.txt
@@ -7,7 +7,7 @@ else ()
add_definitions (-DHAVE_UNISTD_H)
endif ()
-add_library (z_bundled STATIC EXCLUDE_FROM_ALL
+add_convenience_library (z_bundled EXCLUDE_FROM_ALL
adler32.c
compress.c
crc32.c
@@ -25,10 +25,6 @@ add_library (z_bundled STATIC EXCLUDE_FROM_ALL
zutil.c
)
-set_target_properties (z_bundled PROPERTIES
- COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}"
-)
-
install (
FILES README
DESTINATION ${DOC_INSTALL_DIR}
diff --git a/wrappers/.gitignore b/wrappers/.gitignore
index c4724d28..cfd6bdeb 100644
--- a/wrappers/.gitignore
+++ b/wrappers/.gitignore
@@ -3,7 +3,6 @@ d2d1trace.cpp
d3d8trace.cpp
d3d9trace.cpp
dxgitrace.cpp
-dxgitrace.def
ddrawtrace.cpp
dlltrace.cpp
egltrace.cpp
diff --git a/wrappers/CMakeLists.txt b/wrappers/CMakeLists.txt
index ed1757d5..0f71a5f7 100644
--- a/wrappers/CMakeLists.txt
+++ b/wrappers/CMakeLists.txt
@@ -2,15 +2,72 @@
# API tracers
+if (ENABLE_STATIC_LIBGCC)
+ add_linker_flags (-static-libgcc)
+endif ()
+if (ENABLE_STATIC_LIBSTDCXX)
+ # Unfortunately for a long time static libstdcxx didn't built with -fPIC
+ # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=28811
+ include (CheckCXXSourceCompiles)
+ set (CMAKE_REQUIRED_FLAGS ${CMAKE_SHARED_LIBRARY_C_FLAGS})
+ set (CMAKE_REQUIRED_LIBRARIES -shared -static-libgcc -static-libstdc++)
+ check_cxx_source_compiles (
+ "
+ #include <string>
+ std::string s;
+ "
+ STATIC_LIBSTDCXX_PIC
+ )
+ unset (CMAKE_REQUIRED_LIBRARIES)
+ unset (CMAKE_REQUIRED_FLAGS)
+ if (STATIC_LIBSTDCXX_PIC)
+ add_linker_flags (-static-libstdc++)
+ endif ()
+endif ()
+
+macro (target_linker_version_script target version_script)
+ if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT ANDROID)
+ # https://sourceware.org/binutils/docs/ld/VERSION.html
+ set_property (
+ TARGET ${target}
+ APPEND_STRING
+ PROPERTY LINK_FLAGS " -Wl,--version-script=${version_script}"
+ )
+ # XXX: Unfortunately LINK_DEPENDS is ignored in non-Makefile generators
+ # See also http://www.cmake.org/pipermail/cmake/2010-May/037206.html
+ add_custom_target (${target}_version_script
+ DEPENDS ${version_script}
+ VERBATIM
+ )
+ #set_property (
+ # TARGET ${target}
+ # PROPERTY LINK_DEPENDS ${version_script}
+ #)
+ add_dependencies (${target} ${target}_version_script)
+ endif ()
+endmacro ()
+
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
+
include_directories (
- ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/helpers
${CMAKE_BINARY_DIR}/dispatch
${CMAKE_SOURCE_DIR}/dispatch
+ ${CMAKE_SOURCE_DIR}/guids
)
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+add_convenience_library (trace
+ assert.cpp
+)
+target_link_libraries (trace
+ common
+ guids
+ ${SNAPPY_LIBRARIES}
+ ${ZLIB_LIBRARIES} # for crc32
+)
+
if (WIN32)
if (MINGW)
# Silence warnings about @nn suffix mismatch
@@ -19,7 +76,7 @@ if (WIN32)
endif ()
# ddraw.dll
- if (DirectX_D3D_INCLUDE_DIR)
+ if (DirectX_D3D_INCLUDE_FOUND)
include_directories (BEFORE SYSTEM ${DirectX_D3D_INCLUDE_DIR})
add_custom_command (
OUTPUT ddrawtrace.cpp
@@ -38,19 +95,18 @@ if (WIN32)
)
add_library (ddrawtrace MODULE ddraw.def ddrawtrace.cpp)
target_link_libraries (ddrawtrace
- common
- ${ZLIB_LIBRARIES}
- ${SNAPPY_LIBRARIES}
+ trace
)
set_target_properties (ddrawtrace PROPERTIES
PREFIX ""
OUTPUT_NAME ddraw
)
install (TARGETS ddrawtrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
+ install_pdb (ddrawtrace DESTINATION ${WRAPPER_INSTALL_DIR})
endif ()
# d3d8.dll
- if (DirectX_D3D8_INCLUDE_DIR AND DirectX_D3D9_INCLUDE_DIR)
+ if (DirectX_D3D8_INCLUDE_FOUND AND DirectX_D3D9_INCLUDE_FOUND)
include_directories (BEFORE SYSTEM ${DirectX_D3D9_INCLUDE_DIR} ${DirectX_D3D8_INCLUDE_DIR})
add_custom_command (
OUTPUT d3d8trace.cpp
@@ -73,19 +129,18 @@ if (WIN32)
)
target_link_libraries (d3d8trace
d3dhelpers
- common
- ${ZLIB_LIBRARIES}
- ${SNAPPY_LIBRARIES}
+ trace
)
set_target_properties (d3d8trace PROPERTIES
PREFIX ""
OUTPUT_NAME d3d8
)
install (TARGETS d3d8trace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
+ install_pdb (d3d8trace DESTINATION ${WRAPPER_INSTALL_DIR})
endif ()
# d3d9.dll
- if (DirectX_D3D9_INCLUDE_DIR)
+ if (DirectX_D3D9_INCLUDE_FOUND)
include_directories (BEFORE SYSTEM ${DirectX_D3D9_INCLUDE_DIR})
add_custom_command (
OUTPUT d3d9trace.cpp
@@ -98,7 +153,7 @@ if (WIN32)
${CMAKE_SOURCE_DIR}/specs/d3d9.py
${CMAKE_SOURCE_DIR}/specs/d3d9types.py
${CMAKE_SOURCE_DIR}/specs/d3d9caps.py
- ${CMAKE_SOURCE_DIR}/specs/d3d9dxva2.py
+ ${CMAKE_SOURCE_DIR}/specs/dxva2.py
${CMAKE_SOURCE_DIR}/specs/winapi.py
${CMAKE_SOURCE_DIR}/specs/stdapi.py
)
@@ -109,143 +164,56 @@ if (WIN32)
)
target_link_libraries (d3d9trace
d3dhelpers
- common
- ${ZLIB_LIBRARIES}
- ${SNAPPY_LIBRARIES}
+ trace
)
set_target_properties (d3d9trace PROPERTIES
PREFIX ""
OUTPUT_NAME d3d9
)
install (TARGETS d3d9trace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
+ install_pdb (d3d9trace DESTINATION ${WRAPPER_INSTALL_DIR})
endif ()
# dxgi.dll, d3d10.dll, d3d10_1.dll, d3d11.dll
- set (DXGI_MODULES)
- if (DirectX_D3D10_INCLUDE_DIR)
- set (DXGITRACE_DEF ${CMAKE_CURRENT_BINARY_DIR}/dxgitrace.def)
- file (WRITE ${DXGITRACE_DEF} "EXPORTS\n")
- file (APPEND ${DXGITRACE_DEF} "CreateDXGIFactory\n")
- file (APPEND ${DXGITRACE_DEF} "CreateDXGIFactory1\n")
- file (APPEND ${DXGITRACE_DEF} "D3D10CreateDevice\n")
- file (APPEND ${DXGITRACE_DEF} "D3D10CreateDeviceAndSwapChain\n")
-
- include_directories (BEFORE SYSTEM ${DirectX_D3D10_INCLUDE_DIR})
- set (DXGI_MODULES d3d10)
- if (DirectX_D3D10_1_INCLUDE_DIR)
- include_directories (BEFORE SYSTEM ${DirectX_D3D10_1_INCLUDE_DIR})
- set (DXGI_MODULES ${DXGI_MODULES} d3d10_1)
- file (APPEND ${DXGITRACE_DEF} "D3D10CreateDevice1\n")
- file (APPEND ${DXGITRACE_DEF} "D3D10CreateDeviceAndSwapChain1\n")
- endif ()
- if (DirectX_D3D11_INCLUDE_DIR)
- include_directories (BEFORE SYSTEM ${DirectX_D3D11_INCLUDE_DIR})
- set (DXGI_MODULES ${DXGI_MODULES} d3d11)
- if (DirectX_D3D11_1_INCLUDE_DIR)
- include_directories (BEFORE SYSTEM ${DirectX_D3D11_1_INCLUDE_DIR})
- set (DXGI_MODULES ${DXGI_MODULES} d3d11_1)
- endif ()
- file (APPEND ${DXGITRACE_DEF} "D3D11CreateDevice\n")
- file (APPEND ${DXGITRACE_DEF} "D3D11CreateDeviceAndSwapChain\n")
- endif ()
-
+ if (DirectX_D3D11_3_INCLUDE_FOUND)
+ include_directories (BEFORE SYSTEM ${DirectX_D3D11_3_INCLUDE_DIR})
+
add_custom_command (
OUTPUT dxgitrace.cpp
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgitrace.py ${DXGI_MODULES} > ${CMAKE_CURRENT_BINARY_DIR}/dxgitrace.cpp
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dxgitrace.py > ${CMAKE_CURRENT_BINARY_DIR}/dxgitrace.cpp
DEPENDS
dxgitrace.py
dlltrace.py
trace.py
${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
- ${CMAKE_SOURCE_DIR}/specs/d3d10_1.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d11.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d11sdklayers.py
${CMAKE_SOURCE_DIR}/specs/d3d10.py
- ${CMAKE_SOURCE_DIR}/specs/d3d10misc.py
${CMAKE_SOURCE_DIR}/specs/d3d10sdklayers.py
- ${CMAKE_SOURCE_DIR}/specs/d3dcommon.py
- ${CMAKE_SOURCE_DIR}/specs/dxgi1_2.py
${CMAKE_SOURCE_DIR}/specs/dxgi.py
- ${CMAKE_SOURCE_DIR}/specs/dxgitype.py
- ${CMAKE_SOURCE_DIR}/specs/dxgiformat.py
+ ${CMAKE_SOURCE_DIR}/specs/d3d9.py
${CMAKE_SOURCE_DIR}/specs/winapi.py
${CMAKE_SOURCE_DIR}/specs/stdapi.py
)
- add_library (dxgitrace SHARED
- ${DXGITRACE_DEF}
+ add_library (dxgitrace MODULE
+ dxgitrace.def
dxgitrace.cpp
d3dcommonshader.cpp
)
target_link_libraries (dxgitrace
d3dhelpers
- common
- ${ZLIB_LIBRARIES}
- ${SNAPPY_LIBRARIES}
+ trace
)
set_target_properties (dxgitrace
PROPERTIES PREFIX ""
)
- install (TARGETS dxgitrace
- RUNTIME DESTINATION ${WRAPPER_INSTALL_DIR} COMPONENT RUNTIME
- LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR} COMPONENT RUNTIME
- )
-
- # dxgi.dll (empty stub for dxgitrace.dll)
- add_library (dxgistubs MODULE
- dxgi.def
- dxgistubs.cpp
- d3dkmtstubs.cpp
- )
- target_link_libraries (dxgistubs dxgitrace)
- set_target_properties (dxgistubs
- PROPERTIES PREFIX ""
- OUTPUT_NAME dxgi
- )
- install (TARGETS dxgistubs LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
-
- # d3d10.dll (empty stub for dxgitrace.dll)
- add_library (d3d10stubs MODULE
- d3d10.def
- d3d10stubs.cpp
- )
- target_link_libraries (d3d10stubs dxgitrace)
- set_target_properties (d3d10stubs
- PROPERTIES PREFIX ""
- OUTPUT_NAME d3d10
- )
- install (TARGETS d3d10stubs LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
-
- # d3d10_1.dll (empty stub for dxgitrace.dll)
- if (DirectX_D3D10_1_INCLUDE_DIR)
- add_library (d3d10_1stubs MODULE
- d3d10_1.def
- d3d10stubs.cpp
- )
- target_link_libraries (d3d10_1stubs dxgitrace)
- set_target_properties (d3d10_1stubs
- PROPERTIES PREFIX ""
- OUTPUT_NAME d3d10_1
- )
- install (TARGETS d3d10_1stubs LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
- endif ()
-
- # d3d11.dll (empty stub for dxgitrace.dll)
- if (DirectX_D3D11_INCLUDE_DIR)
- add_library (d3d11stubs MODULE
- d3d11.def
- d3d11stubs.cpp
- d3dkmtstubs.cpp
- )
- target_link_libraries (d3d11stubs dxgitrace)
- set_target_properties (d3d11stubs
- PROPERTIES PREFIX ""
- OUTPUT_NAME d3d11
- )
- install (TARGETS d3d11stubs LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
- endif ()
+ install (TARGETS dxgitrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
+ install_pdb (dxgitrace DESTINATION ${WRAPPER_INSTALL_DIR})
endif ()
# d2d1.dll, dwrite.dll
- if (DirectX_D2D1_INCLUDE_DIR)
- include_directories (BEFORE SYSTEM ${DirectX_D2D1_INCLUDE_DIR})
+ if (DirectX_D2D1_1_INCLUDE_FOUND)
+ include_directories (BEFORE SYSTEM ${DirectX_D2D1_1_INCLUDE_DIR})
add_custom_command (
OUTPUT d2d1trace.cpp
@@ -254,42 +222,22 @@ if (WIN32)
d2d1trace.py
trace.py
${CMAKE_SOURCE_DIR}/specs/d2d1.py
- ${CMAKE_SOURCE_DIR}/specs/d2d1.py
- ${CMAKE_SOURCE_DIR}/specs/d2dbasetypes.py
- ${CMAKE_SOURCE_DIR}/specs/d2derr.py
${CMAKE_SOURCE_DIR}/specs/dwrite.py
${CMAKE_SOURCE_DIR}/specs/dcommon.py
${CMAKE_SOURCE_DIR}/specs/dxgi.py
- ${CMAKE_SOURCE_DIR}/specs/dxgitype.py
- ${CMAKE_SOURCE_DIR}/specs/dxgiformat.py
${CMAKE_SOURCE_DIR}/specs/winapi.py
${CMAKE_SOURCE_DIR}/specs/stdapi.py
)
- add_library (d2d1trace SHARED d2d1.def d2d1trace.cpp)
+ add_library (d2d1trace MODULE d2d1trace.def d2d1trace.cpp)
target_link_libraries (d2d1trace
- common
- ${ZLIB_LIBRARIES}
- ${SNAPPY_LIBRARIES}
+ trace
)
set_target_properties (d2d1trace
PROPERTIES PREFIX ""
- OUTPUT_NAME d2d1
- )
- # http://www.cmake.org/pipermail/cmake/2009-March/028221.html
- install (TARGETS d2d1trace
- RUNTIME DESTINATION ${WRAPPER_INSTALL_DIR} COMPONENT RUNTIME
- LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR} COMPONENT RUNTIME
- )
-
- # dwrite.dll is just an empty stub for d2d1.dll
- add_library (dwritetrace MODULE dwrite.def dwritetrace.cpp)
- target_link_libraries (dwritetrace d2d1trace)
- set_target_properties (dwritetrace
- PROPERTIES PREFIX ""
- OUTPUT_NAME dwrite
)
- install (TARGETS dwritetrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
- endif (DirectX_D2D1_INCLUDE_DIR)
+ install (TARGETS d2d1trace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
+ install_pdb (d2d1trace DESTINATION ${WRAPPER_INSTALL_DIR})
+ endif ()
# opengl32.dll
add_custom_command (
@@ -311,20 +259,21 @@ if (WIN32)
add_library (wgltrace MODULE opengl32.def
wgltrace.cpp
glcaps.cpp
+ config.cpp
gltrace_state.cpp
)
add_dependencies (wgltrace glproc)
target_link_libraries (wgltrace
+ glhelpers
glproc_gl
- common
- ${ZLIB_LIBRARIES}
- ${SNAPPY_LIBRARIES}
+ trace
)
set_target_properties (wgltrace PROPERTIES
PREFIX ""
OUTPUT_NAME opengl32
)
install (TARGETS wgltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
+ install_pdb (wgltrace DESTINATION ${WRAPPER_INSTALL_DIR})
elseif (APPLE)
# OpenGL framework
@@ -335,6 +284,7 @@ elseif (APPLE)
cgltrace.py
gltrace.py
trace.py
+ ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
${CMAKE_SOURCE_DIR}/specs/cglapi.py
${CMAKE_SOURCE_DIR}/specs/glapi.py
${CMAKE_SOURCE_DIR}/specs/glparams.py
@@ -345,6 +295,7 @@ elseif (APPLE)
add_library (cgltrace SHARED
cgltrace.cpp
glcaps.cpp
+ config.cpp
gltrace_state.cpp
)
@@ -360,12 +311,11 @@ elseif (APPLE)
)
target_link_libraries (cgltrace
+ glhelpers
glproc_gl
- common
- ${ZLIB_LIBRARIES}
- ${SNAPPY_LIBRARIES}
+ trace
${CMAKE_THREAD_LIBS_INIT}
- dl
+ ${CMAKE_DL_LIBS}
)
install (TARGETS cgltrace FRAMEWORK DESTINATION ${WRAPPER_INSTALL_DIR})
@@ -378,8 +328,8 @@ elseif (X11_FOUND)
glxtrace.py
gltrace.py
trace.py
+ ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
${CMAKE_SOURCE_DIR}/specs/glxapi.py
- ${CMAKE_SOURCE_DIR}/specs/glesapi.py
${CMAKE_SOURCE_DIR}/specs/glapi.py
${CMAKE_SOURCE_DIR}/specs/glparams.py
${CMAKE_SOURCE_DIR}/specs/gltypes.py
@@ -389,6 +339,7 @@ elseif (X11_FOUND)
add_library (glxtrace SHARED
glxtrace.cpp
glcaps.cpp
+ config.cpp
gltrace_state.cpp
dlsym.cpp
)
@@ -399,19 +350,21 @@ elseif (X11_FOUND)
# avoid the default "lib" prefix
PREFIX ""
# Prevent symbol relocations internal to our wrapper library to be
- # overwritten by the application.
- LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions"
+ # overwritten by the application. And fail if there are missing
+ # symbols.
+ LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions -Wl,-z,defs"
)
target_link_libraries (glxtrace
+ glhelpers
glproc_gl
- common
- ${ZLIB_LIBRARIES}
- ${SNAPPY_LIBRARIES}
+ trace
${CMAKE_THREAD_LIBS_INIT}
- dl
+ ${CMAKE_DL_LIBS}
)
+ target_linker_version_script (glxtrace ${CMAKE_CURRENT_SOURCE_DIR}/glxtrace.version)
+
install (TARGETS glxtrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
endif ()
@@ -425,9 +378,9 @@ if (ENABLE_EGL AND NOT WIN32 AND NOT APPLE)
egltrace.py
gltrace.py
trace.py
+ ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
${CMAKE_SOURCE_DIR}/specs/eglapi.py
${CMAKE_SOURCE_DIR}/specs/eglenum.py
- ${CMAKE_SOURCE_DIR}/specs/glesapi.py
${CMAKE_SOURCE_DIR}/specs/glapi.py
${CMAKE_SOURCE_DIR}/specs/glparams.py
${CMAKE_SOURCE_DIR}/specs/gltypes.py
@@ -437,8 +390,8 @@ if (ENABLE_EGL AND NOT WIN32 AND NOT APPLE)
add_library (egltrace SHARED
egltrace.cpp
glcaps.cpp
+ config.cpp
gltrace_state.cpp
- ${CMAKE_SOURCE_DIR}/helpers/eglsize.cpp
dlsym.cpp
)
@@ -448,18 +401,20 @@ if (ENABLE_EGL AND NOT WIN32 AND NOT APPLE)
# avoid the default "lib" prefix
PREFIX ""
# Prevent symbol relocations internal to our wrapper library to be
- # overwritten by the application.
- LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions"
+ # overwritten by the application. And fail if there are missing
+ # symbols.
+ LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions -Wl,-z,defs"
)
target_link_libraries (egltrace
+ glhelpers
glproc_egl
- common
- ${ZLIB_LIBRARIES}
- ${SNAPPY_LIBRARIES}
+ trace
${CMAKE_THREAD_LIBS_INIT}
- dl
+ ${CMAKE_DL_LIBS}
)
+ target_linker_version_script (egltrace ${CMAKE_CURRENT_SOURCE_DIR}/egltrace.version)
+
install (TARGETS egltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
endif ()
diff --git a/wrappers/assert.cpp b/wrappers/assert.cpp
new file mode 100644
index 00000000..993d4171
--- /dev/null
+++ b/wrappers/assert.cpp
@@ -0,0 +1,65 @@
+/**************************************************************************
+ *
+ * Copyright 2015 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/*
+ * It's convenient to just use the standard assert() macro, but on Windows we
+ * want to ensure the messages go to somewhere we can actually see.
+ */
+
+#if defined(_WIN32) && !defined(NDEBUG)
+
+
+#include <assert.h>
+
+#include "os.hpp"
+
+
+extern "C" void
+_assert(const char *_Message, const char *_File, unsigned _Line)
+{
+ os::log("Assertion failed: %s, file %s, line %u\n", _Message, _File, _Line);
+ os::abort();
+}
+
+
+extern "C" void
+_wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line)
+{
+ os::log("Assertion failed: %S, file %S, line %u\n", _Message, _File, _Line);
+ os::abort();
+}
+
+
+// Hack to force this module to be linked on MinGW
+#ifdef __GNUC__
+__attribute__ ((constructor))
+static void
+force_link(void)
+{}
+#endif /* __GNUC__ */
+
+
+#endif /* _WIN32 && !NDEBUG */
diff --git a/wrappers/cgltrace.py b/wrappers/cgltrace.py
index c56edf24..6c72f696 100644
--- a/wrappers/cgltrace.py
+++ b/wrappers/cgltrace.py
@@ -106,4 +106,28 @@ if __name__ == '__main__':
PUBLIC
void * gll_noop = 0;
+
+__attribute__((constructor))
+static void
+_init(void) {
+ /*
+ * XXX: Setting DYLD_IMAGE_SUFFIX to anything (even an empty string)
+ * changes dlopen behavior causing our trick of symlinking a temporary file
+ * to the real OpenGL framework to stop working, leading to infinite
+ * recursion.
+ */
+ if (getenv("DYLD_IMAGE_SUFFIX")) {
+ os::log("error: tracing with DYLD_IMAGE_SUFFIX not supported.\n");
+ os::abort();
+ }
+
+ /*
+ * XXX: Temporary workaround for
+ * https://github.com/apitrace/apitrace/issues/278#issuecomment-46889575
+ * until we have a better way of intercepting applications that
+ * dlopen("libGL.dylib") directly.
+ */
+ setenv("SDL_OPENGL_LIBRARY", "/System/Library/Frameworks/OpenGL.framework/OpenGL", 1);
+}
+
'''
diff --git a/wrappers/config.cpp b/wrappers/config.cpp
new file mode 100644
index 00000000..4d2663e4
--- /dev/null
+++ b/wrappers/config.cpp
@@ -0,0 +1,449 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Brian Paul
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/*
+ * Configuration file support.
+ *
+ * Used to override glGetString/Integer/etc queries.
+ */
+
+
+/*
+ * The format of the file is extremely simple. An example is given in
+ * docs/USAGE.markdown .
+ *
+ * Future improvements:
+ * - An option to simply turn off specific extensions
+ *
+ */
+
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <iostream>
+
+#include "os.hpp"
+#include "os_string.hpp"
+#include "config.hpp"
+
+
+namespace gltrace {
+
+
+/**
+ * Parse the conf->extensions string to generate an array of individual
+ * extension strings which can be queried with glGetStringi().
+ */
+static void
+create_extensions_list(configuration *conf)
+{
+ // count extensions
+ const char *ext = conf->extensions.c_str();
+ conf->numExtensions = 0;
+ while (1) {
+ ext = strstr(ext, "GL_");
+ if (!ext)
+ break;
+
+ conf->numExtensions++;
+ // advance extensions pointer
+ while (*ext && *ext != ' ')
+ ext++;
+ }
+
+ conf->extensionsList =
+ (char **) malloc(conf->numExtensions * sizeof(char *));
+
+ // extract individual extension names
+ int count = 0;
+ const char *extStart = conf->extensions.c_str(), *extEnd;
+ while (1) {
+ extStart = strstr(extStart, "GL_");
+ if (!extStart)
+ break;
+
+ // find end of the name
+ extEnd = extStart;
+ while (*extEnd && *extEnd != ' ')
+ extEnd++;
+
+ // copy extension string name
+ int extLen = extEnd - extStart;
+ conf->extensionsList[count] = (char *) malloc(extLen + 1);
+ memcpy(conf->extensionsList[count], extStart, extLen);
+ conf->extensionsList[count][extLen] = 0;
+ count++;
+
+ // advance to next
+ extStart = extEnd;
+ }
+
+ assert(count == conf->numExtensions);
+}
+
+
+
+static bool
+matchKeyword(const char *string, const char *keyword)
+{
+ if (strncmp(string, keyword, strlen(keyword)) == 0)
+ return true;
+ else
+ return false;
+}
+
+
+static char buffer[10*1000];
+
+static char
+getChar(FILE *f, const char **buf)
+{
+ if (feof(f))
+ return 0;
+
+ if (buf[0][0]) {
+ char c = buf[0][0];
+ (*buf)++;
+ return c;
+ }
+
+ while (1) {
+ // read another line
+ *buf = fgets(buffer, sizeof(buffer), f);
+ if (!buf || !buf[0]) {
+ return 0;
+ }
+ else if (buf[0][0]) {
+ char c = buf[0][0];
+ (*buf)++;
+ return c;
+ }
+ else if (feof(f)) {
+ return 0;
+ }
+ }
+}
+
+
+// Scan 'buf' for a string value of the form: "string" (double-quoted string)
+// Return the string in newly malloc'd memory
+static std::string
+stringValue(FILE *f, const char *buf)
+{
+ std::string result;
+ char c;
+
+ // look for =
+ do {
+ c = getChar(f, &buf);
+ } while (c && c != '=');
+
+ if (!c)
+ return result;
+
+ // look for opening "
+ do {
+ c = getChar(f, &buf);
+ } while (c && c != '\"');
+
+ if (!c)
+ return result;
+
+ // scan characters in the string
+ while (1) {
+ c = getChar(f, &buf);
+ if (!c) {
+ std::cerr << "Error: didn't find closing \" in config file!\n";
+ return result;
+ }
+
+ if (c == '\n') {
+ // convert newlines inside a string into spaces
+ c = ' ';
+ }
+
+ if (c == '\"') {
+ // end of string
+ return result;
+ }
+ else {
+ result.push_back(c);
+ }
+ }
+}
+
+
+// Scan integer value of the form: 12345
+static int
+intValue(FILE *f, const char *buf)
+{
+ char valBuf[100];
+ int valLen = 0;
+ char c;
+
+ // look for =
+ do {
+ c = getChar(f, &buf);
+ } while (c && c != '=');
+
+ if (!c)
+ return 0;
+
+ // scan digits
+ while (1) {
+ c = getChar(f, &buf);
+ if (isdigit(c)) {
+ valBuf[valLen++] = c;
+ }
+ else if (c != ' ') {
+ break;
+ }
+ }
+
+ valBuf[valLen] = 0;
+
+ return atoi(valBuf);
+}
+
+
+
+static void
+parse_file(FILE *f, configuration *conf)
+{
+ do {
+ // read a line
+ char *b = fgets(buffer, sizeof(buffer), f);
+
+ if (!b) {
+ break;
+ }
+ else if (b[0] == '#') {
+ // comment - skip line
+ }
+ else if (b[0] == '\n') {
+ // empty line
+ }
+ else if (matchKeyword(b, "GL_VENDOR")) {
+ conf->vendor = stringValue(f, b + 10);
+ }
+ else if (matchKeyword(b, "GL_VERSION")) {
+ conf->version = stringValue(f, b + 11);
+ }
+ else if (matchKeyword(b, "GL_EXTENSIONS")) {
+ conf->extensions = stringValue(f, b + 14);
+ }
+ else if (matchKeyword(b, "GL_RENDERER")) {
+ conf->renderer = stringValue(f, b + 12);
+ }
+ else if (matchKeyword(b, "GL_SHADING_LANGUAGE_VERSION")) {
+ conf->glslVersion = stringValue(f, b + 28);
+ }
+ else if (matchKeyword(b, "GL_MAX_TEXTURE_SIZE")) {
+ conf->maxTextureSize = intValue(f, b + 20);
+ }
+ else if (matchKeyword(b, "GL_MAJOR_VERSION")) {
+ conf->versionMajor = intValue(f, b + 17);
+ }
+ else if (matchKeyword(b, "GL_MINOR_VERSION")) {
+ conf->versionMinor = intValue(f, b + 17);
+ }
+ else if (matchKeyword(b, "GL_CONTEXT_PROFILE_MASK")) {
+ std::string maskStr = stringValue(f, b + 24);
+ conf->profileMask = 0x0;
+ if (maskStr.find("GL_CONTEXT_CORE_PROFILE_BIT") != std::string::npos)
+ conf->profileMask |= GL_CONTEXT_CORE_PROFILE_BIT;
+ if (maskStr.find("GL_CONTEXT_COMPATIBILITY_PROFILE_BIT") != std::string::npos)
+ conf->profileMask |= GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
+ }
+ else {
+ std::cerr << "Unexpected config variable: " << b << ".\n";
+ break;
+ }
+ } while (!feof(f));
+
+ if (!conf->version.empty()) {
+ // String version was specified, compute integer major/minor versions
+ conf->versionMajor = conf->version[0] - '0';
+ conf->versionMinor = conf->version[2] - '0';
+ assert(conf->versionMajor >= 1 && conf->versionMajor <= 4);
+ assert(conf->versionMinor >= 0 && conf->versionMinor <= 9);
+ }
+ else if (conf->versionMajor) {
+ // Numeric version was specified, update the string
+ if (!conf->version.empty()) {
+ // if version string was specified too, override it
+ conf->version[0] = '0' + conf->versionMajor;
+ conf->version[2] = '0' + conf->versionMinor;
+ }
+ else {
+ // allocate new version string
+ conf->version.clear();
+ conf->version.push_back('0' + conf->versionMajor);
+ conf->version.push_back('.');
+ conf->version.push_back('0' + conf->versionMinor);
+ }
+ }
+
+ if (!conf->extensions.empty()) {
+ create_extensions_list(conf);
+ }
+}
+
+
+// Read the given configuration file and return a new configuration object.
+// Return NULL if anything goes wrong
+static configuration *
+readConfigFile(const char *filename)
+{
+#ifndef NDEBUG
+ os::log("apitrace: attempting to read configuration file: %s\n", filename);
+#endif
+
+ FILE *f = fopen(filename, "r");
+ if (!f)
+ return NULL;
+
+ os::log("apitrace: using configuration file: %s\n", filename);
+
+ configuration *conf = new configuration;
+
+ parse_file(f, conf);
+
+ fclose(f);
+
+ if (1) {
+ // debug
+ os::log("apitrace: config GL_VENDOR = %s\n", conf->vendor.c_str());
+ os::log("apitrace: config GL_VERSION = %s\n", conf->version.c_str());
+ os::log("apitrace: config GL_EXTENSIONS = %s\n", conf->extensions.c_str());
+ os::log("apitrace: config GL_NUM_EXTENSIONS = %d\n", conf->numExtensions);
+ os::log("apitrace: config GL_RENDERER = %s\n", conf->renderer.c_str());
+ os::log("apitrace: config GL_SHADING_LANGUAGE_VERSION = %s\n", conf->glslVersion.c_str());
+ os::log("apitrace: config GL_MAX_TEXTURE_SIZE = %d\n", conf->maxTextureSize);
+ os::log("apitrace: config GL_MAJOR_VERSION = %d\n", conf->versionMajor);
+ os::log("apitrace: config GL_MINOR_VERSION = %d\n", conf->versionMinor);
+ os::log("apitrace: config GL_CONTEXT_PROFILE_MASK = 0x%x\n", conf->profileMask);
+ }
+
+ return conf;
+}
+
+
+// Get pointer to configuration object or NULL if there was no config file.
+const configuration *
+getConfig(void)
+{
+ static bool configured = false;
+ static configuration *config = NULL;
+
+ if (!configured) {
+ os::String configPath;
+ const char *envConfigPath = getenv("GLTRACE_CONF");
+ if (envConfigPath) {
+ configPath = envConfigPath;
+ } else {
+ configPath = os::getConfigDir();
+ configPath.join("apitrace");
+ configPath.join("gltrace.conf");
+ }
+ config = gltrace::readConfigFile(configPath);
+ configured = true;
+ }
+
+ return config;
+}
+
+
+// Return the named string value in the config object, or NULL.
+const GLubyte *
+getConfigString(const configuration *config, GLenum pname)
+{
+ if (!config)
+ return NULL;
+
+ switch (pname) {
+ case GL_VERSION:
+ return (const GLubyte *) config->version.c_str();
+ case GL_VENDOR:
+ return (const GLubyte *) config->vendor.c_str();
+ case GL_EXTENSIONS:
+ return (const GLubyte *) config->extensions.c_str();
+ case GL_RENDERER:
+ return (const GLubyte *) config->renderer.c_str();
+ case GL_SHADING_LANGUAGE_VERSION:
+ return (const GLubyte *) config->glslVersion.c_str();
+ default:
+ return NULL;
+ }
+}
+
+
+// Return named indexed string value from config object, or NULL.
+const GLubyte *
+getConfigStringi(const configuration *config, GLenum pname, GLuint index)
+{
+ if (!config ||
+ pname != GL_EXTENSIONS ||
+ config->extensions.empty() ||
+ index >= config->numExtensions) {
+ return NULL;
+ }
+
+ return (const GLubyte *) config->extensionsList[index];
+}
+
+
+
+// Return named integer value from config object, or 0.
+GLint
+getConfigInteger(const configuration *config, GLenum pname)
+{
+ if (!config)
+ return 0;
+
+ switch (pname) {
+ case GL_MAJOR_VERSION:
+ return config->versionMajor;
+ case GL_MINOR_VERSION:
+ return config->versionMinor;
+ case GL_CONTEXT_PROFILE_MASK:
+ return config->profileMask;
+ case GL_MAX_TEXTURE_SIZE:
+ return config->maxTextureSize;
+ case GL_NUM_EXTENSIONS:
+ return config->numExtensions;
+ default:
+ return 0;
+ }
+}
+
+
+
+} /* namespace gltrace */
diff --git a/wrappers/config.hpp b/wrappers/config.hpp
new file mode 100644
index 00000000..519462cc
--- /dev/null
+++ b/wrappers/config.hpp
@@ -0,0 +1,74 @@
+/**************************************************************************
+ *
+ * Copyright 2015 Brian Paul
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "glimports.hpp"
+
+#include <string>
+
+
+namespace gltrace {
+
+
+struct configuration
+{
+ int versionMajor;
+ int versionMinor;
+ std::string version;
+ std::string vendor;
+ std::string extensions;
+ std::string renderer;
+ std::string glslVersion;
+ GLbitfield profileMask;
+ int maxTextureSize; // 2D texture size
+ int numExtensions;
+ char **extensionsList;
+
+ inline
+ configuration() :
+ versionMajor(0),
+ versionMinor(0),
+ profileMask(0),
+ maxTextureSize(0),
+ numExtensions(0),
+ extensionsList(0)
+ {}
+};
+
+
+const configuration *
+getConfig(void);
+
+const GLubyte *
+getConfigString(const configuration *config, GLenum pname);
+
+const GLubyte *
+getConfigStringi(const configuration *config, GLenum pname, GLuint index);
+
+GLint
+getConfigInteger(const configuration *config, GLenum pname);
+
+
+} /* namespace gltrace */
diff --git a/wrappers/d2d1.def b/wrappers/d2d1trace.def
index a897bf9d..bff177cd 100644
--- a/wrappers/d2d1.def
+++ b/wrappers/d2d1trace.def
@@ -1,5 +1,3 @@
-LIBRARY "d2d1"
-
EXPORTS
D2D1CreateFactory @1
D2D1MakeRotateMatrix @2
diff --git a/wrappers/d2d1trace.py b/wrappers/d2d1trace.py
index 10e14a44..26223005 100644
--- a/wrappers/d2d1trace.py
+++ b/wrappers/d2d1trace.py
@@ -31,7 +31,7 @@ from specs.d2d1 import d2d1
if __name__ == '__main__':
- print '#define INITGUID'
+ print '#include "guids_defs.hpp"'
print
print '#include "trace_writer_local.hpp"'
print '#include "os.hpp"'
diff --git a/wrappers/d3d10.def b/wrappers/d3d10.def
deleted file mode 100644
index 4cf0f7d7..00000000
--- a/wrappers/d3d10.def
+++ /dev/null
@@ -1,31 +0,0 @@
-LIBRARY "d3d10"
-EXPORTS
- D3D10CompileEffectFromMemory
- D3D10CompileShader
- D3D10CreateBlob
- D3D10CreateDevice
- D3D10CreateDeviceAndSwapChain
- D3D10CreateEffectFromMemory
- D3D10CreateEffectPoolFromMemory
- D3D10CreateStateBlock
- D3D10DisassembleEffect
- D3D10DisassembleShader
- D3D10GetGeometryShaderProfile
- D3D10GetInputAndOutputSignatureBlob
- D3D10GetInputSignatureBlob
- D3D10GetOutputSignatureBlob
- D3D10GetPixelShaderProfile
- D3D10GetShaderDebugInfo
- D3D10GetVersion
- D3D10GetVertexShaderProfile
- D3D10PreprocessShader
- D3D10ReflectShader
- D3D10RegisterLayers
- D3D10StateBlockMaskDifference
- D3D10StateBlockMaskDisableAll
- D3D10StateBlockMaskDisableCapture
- D3D10StateBlockMaskEnableAll
- D3D10StateBlockMaskEnableCapture
- D3D10StateBlockMaskGetSetting
- D3D10StateBlockMaskIntersect
- D3D10StateBlockMaskUnion
diff --git a/wrappers/d3d10_1.def b/wrappers/d3d10_1.def
deleted file mode 100644
index 836827a2..00000000
--- a/wrappers/d3d10_1.def
+++ /dev/null
@@ -1,32 +0,0 @@
-LIBRARY "d3d10_1"
-
-EXPORTS
- D3D10CompileEffectFromMemory
- D3D10CompileShader
- D3D10CreateBlob
- D3D10CreateDevice1
- D3D10CreateDeviceAndSwapChain1
- D3D10CreateEffectFromMemory
- D3D10CreateEffectPoolFromMemory
- D3D10CreateStateBlock
- D3D10DisassembleEffect
- D3D10DisassembleShader
- D3D10GetGeometryShaderProfile
- D3D10GetInputAndOutputSignatureBlob
- D3D10GetInputSignatureBlob
- D3D10GetOutputSignatureBlob
- D3D10GetPixelShaderProfile
- D3D10GetShaderDebugInfo
- D3D10GetVersion
- D3D10GetVertexShaderProfile
- D3D10PreprocessShader
- D3D10ReflectShader
- D3D10RegisterLayers
- D3D10StateBlockMaskDifference
- D3D10StateBlockMaskDisableAll
- D3D10StateBlockMaskDisableCapture
- D3D10StateBlockMaskEnableAll
- D3D10StateBlockMaskEnableCapture
- D3D10StateBlockMaskGetSetting
- D3D10StateBlockMaskIntersect
- D3D10StateBlockMaskUnion
diff --git a/wrappers/d3d10stubs.cpp b/wrappers/d3d10stubs.cpp
deleted file mode 100644
index 6f0ef89c..00000000
--- a/wrappers/d3d10stubs.cpp
+++ /dev/null
@@ -1,522 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2012 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-
-/*
- *Stubs for internal D3D10 functions.
- */
-
-
-#include "os.hpp"
-
-#include "d3d10imports.hpp"
-
-
-static HMODULE g_hD3D10Module = NULL;
-
-
-static PROC
-_getD3D10ProcAddress(LPCSTR lpProcName) {
- if (!g_hD3D10Module) {
- char szDll[MAX_PATH] = {0};
- if (!GetSystemDirectoryA(szDll, MAX_PATH)) {
- return NULL;
- }
- strcat(szDll, "\\d3d10.dll");
- g_hD3D10Module = LoadLibraryA(szDll);
- if (!g_hD3D10Module) {
- return NULL;
- }
- }
- return GetProcAddress(g_hD3D10Module, lpProcName);
-}
-
-
-#ifndef NDEBUG
-#define LOG() os::log("%s\n", __FUNCTION__)
-#else
-#define LOG()
-#endif
-
-
-typedef HRESULT (WINAPI *PFN_D3D10COMPILESHADER)(const char *pSrcData, SIZE_T SrcDataSize, const char *pFileName, const D3D10_SHADER_MACRO *pDefines, ID3D10Include *pInclude, const char *pFunctionName, const char *pProfile, UINT Flags, ID3D10Blob **ppShader, ID3D10Blob **ppErrorMsgs);
-static PFN_D3D10COMPILESHADER _D3D10CompileShader_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10CompileShader(const char *pSrcData, SIZE_T SrcDataSize, const char *pFileName, const D3D10_SHADER_MACRO *pDefines, ID3D10Include *pInclude, const char *pFunctionName, const char *pProfile, UINT Flags, ID3D10Blob **ppShader, ID3D10Blob **ppErrorMsgs) {
- const char *_name = "D3D10CompileShader";
- LOG();
- if (!_D3D10CompileShader_ptr) {
- _D3D10CompileShader_ptr = (PFN_D3D10COMPILESHADER)_getD3D10ProcAddress(_name);
- if (!_D3D10CompileShader_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10CompileShader_ptr(pSrcData, SrcDataSize, pFileName, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10DISASSEMBLESHADER)(const void *pShader, SIZE_T BytecodeLength, BOOL EnableColorCode, const char *pComments, ID3D10Blob **ppDisassembly);
-static PFN_D3D10DISASSEMBLESHADER _D3D10DisassembleShader_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10DisassembleShader(const void *pShader, SIZE_T BytecodeLength, BOOL EnableColorCode, const char *pComments, ID3D10Blob **ppDisassembly) {
- const char *_name = "D3D10DisassembleShader";
- LOG();
- if (!_D3D10DisassembleShader_ptr) {
- _D3D10DisassembleShader_ptr = (PFN_D3D10DISASSEMBLESHADER)_getD3D10ProcAddress(_name);
- if (!_D3D10DisassembleShader_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10DisassembleShader_ptr(pShader, BytecodeLength, EnableColorCode, pComments, ppDisassembly);
-}
-
-typedef const char *(WINAPI *PFN_D3D10GETPIXELSHADERPROFILE)(ID3D10Device *pDevice);
-static PFN_D3D10GETPIXELSHADERPROFILE _D3D10GetPixelShaderProfile_ptr = NULL;
-
-EXTERN_C const char *WINAPI
-D3D10GetPixelShaderProfile(ID3D10Device *pDevice) {
- const char *_name = "D3D10GetPixelShaderProfile";
- LOG();
- if (!_D3D10GetPixelShaderProfile_ptr) {
- _D3D10GetPixelShaderProfile_ptr = (PFN_D3D10GETPIXELSHADERPROFILE)_getD3D10ProcAddress(_name);
- if (!_D3D10GetPixelShaderProfile_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10GetPixelShaderProfile_ptr(pDevice);
-}
-
-typedef const char *(WINAPI *PFN_D3D10GETVERTEXSHADERPROFILE)(ID3D10Device *pDevice);
-static PFN_D3D10GETVERTEXSHADERPROFILE _D3D10GetVertexShaderProfile_ptr = NULL;
-
-EXTERN_C const char *WINAPI
-D3D10GetVertexShaderProfile(ID3D10Device *pDevice) {
- const char *_name = "D3D10GetVertexShaderProfile";
- LOG();
- if (!_D3D10GetVertexShaderProfile_ptr) {
- _D3D10GetVertexShaderProfile_ptr = (PFN_D3D10GETVERTEXSHADERPROFILE)_getD3D10ProcAddress(_name);
- if (!_D3D10GetVertexShaderProfile_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10GetVertexShaderProfile_ptr(pDevice);
-}
-
-typedef const char *(WINAPI *PFN_D3D10GETGEOMETRYSHADERPROFILE)(ID3D10Device *pDevice);
-static PFN_D3D10GETGEOMETRYSHADERPROFILE _D3D10GetGeometryShaderProfile_ptr = NULL;
-
-EXTERN_C const char *WINAPI
-D3D10GetGeometryShaderProfile(ID3D10Device *pDevice) {
- const char *_name = "D3D10GetGeometryShaderProfile";
- LOG();
- if (!_D3D10GetGeometryShaderProfile_ptr) {
- _D3D10GetGeometryShaderProfile_ptr = (PFN_D3D10GETGEOMETRYSHADERPROFILE)_getD3D10ProcAddress(_name);
- if (!_D3D10GetGeometryShaderProfile_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10GetGeometryShaderProfile_ptr(pDevice);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10REFLECTSHADER)(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10ShaderReflection **ppReflector);
-static PFN_D3D10REFLECTSHADER _D3D10ReflectShader_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10ReflectShader(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10ShaderReflection **ppReflector) {
- const char *_name = "D3D10ReflectShader";
- LOG();
- if (!_D3D10ReflectShader_ptr) {
- _D3D10ReflectShader_ptr = (PFN_D3D10REFLECTSHADER)_getD3D10ProcAddress(_name);
- if (!_D3D10ReflectShader_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10ReflectShader_ptr(pShaderBytecode, BytecodeLength, ppReflector);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10PREPROCESSSHADER)(const char *pSrcData, SIZE_T SrcDataSize, const char *pFileName, const D3D10_SHADER_MACRO *pDefines, ID3D10Include *pInclude, ID3D10Blob **ppShaderText, ID3D10Blob **ppErrorMsgs);
-static PFN_D3D10PREPROCESSSHADER _D3D10PreprocessShader_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10PreprocessShader(const char *pSrcData, SIZE_T SrcDataSize, const char *pFileName, const D3D10_SHADER_MACRO *pDefines, ID3D10Include *pInclude, ID3D10Blob **ppShaderText, ID3D10Blob **ppErrorMsgs) {
- const char *_name = "D3D10PreprocessShader";
- LOG();
- if (!_D3D10PreprocessShader_ptr) {
- _D3D10PreprocessShader_ptr = (PFN_D3D10PREPROCESSSHADER)_getD3D10ProcAddress(_name);
- if (!_D3D10PreprocessShader_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10PreprocessShader_ptr(pSrcData, SrcDataSize, pFileName, pDefines, pInclude, ppShaderText, ppErrorMsgs);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10GETINPUTSIGNATUREBLOB)(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10Blob **ppSignatureBlob);
-static PFN_D3D10GETINPUTSIGNATUREBLOB _D3D10GetInputSignatureBlob_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10GetInputSignatureBlob(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10Blob **ppSignatureBlob) {
- const char *_name = "D3D10GetInputSignatureBlob";
- LOG();
- if (!_D3D10GetInputSignatureBlob_ptr) {
- _D3D10GetInputSignatureBlob_ptr = (PFN_D3D10GETINPUTSIGNATUREBLOB)_getD3D10ProcAddress(_name);
- if (!_D3D10GetInputSignatureBlob_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10GetInputSignatureBlob_ptr(pShaderBytecode, BytecodeLength, ppSignatureBlob);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10GETOUTPUTSIGNATUREBLOB)(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10Blob **ppSignatureBlob);
-static PFN_D3D10GETOUTPUTSIGNATUREBLOB _D3D10GetOutputSignatureBlob_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10GetOutputSignatureBlob(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10Blob **ppSignatureBlob) {
- const char *_name = "D3D10GetOutputSignatureBlob";
- LOG();
- if (!_D3D10GetOutputSignatureBlob_ptr) {
- _D3D10GetOutputSignatureBlob_ptr = (PFN_D3D10GETOUTPUTSIGNATUREBLOB)_getD3D10ProcAddress(_name);
- if (!_D3D10GetOutputSignatureBlob_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10GetOutputSignatureBlob_ptr(pShaderBytecode, BytecodeLength, ppSignatureBlob);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10GETINPUTANDOUTPUTSIGNATUREBLOB)(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10Blob **ppSignatureBlob);
-static PFN_D3D10GETINPUTANDOUTPUTSIGNATUREBLOB _D3D10GetInputAndOutputSignatureBlob_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10GetInputAndOutputSignatureBlob(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10Blob **ppSignatureBlob) {
- const char *_name = "D3D10GetInputAndOutputSignatureBlob";
- LOG();
- if (!_D3D10GetInputAndOutputSignatureBlob_ptr) {
- _D3D10GetInputAndOutputSignatureBlob_ptr = (PFN_D3D10GETINPUTANDOUTPUTSIGNATUREBLOB)_getD3D10ProcAddress(_name);
- if (!_D3D10GetInputAndOutputSignatureBlob_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10GetInputAndOutputSignatureBlob_ptr(pShaderBytecode, BytecodeLength, ppSignatureBlob);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10GETSHADERDEBUGINFO)(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10Blob **ppDebugInfo);
-static PFN_D3D10GETSHADERDEBUGINFO _D3D10GetShaderDebugInfo_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10GetShaderDebugInfo(const void *pShaderBytecode, SIZE_T BytecodeLength, ID3D10Blob **ppDebugInfo) {
- const char *_name = "D3D10GetShaderDebugInfo";
- LOG();
- if (!_D3D10GetShaderDebugInfo_ptr) {
- _D3D10GetShaderDebugInfo_ptr = (PFN_D3D10GETSHADERDEBUGINFO)_getD3D10ProcAddress(_name);
- if (!_D3D10GetShaderDebugInfo_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10GetShaderDebugInfo_ptr(pShaderBytecode, BytecodeLength, ppDebugInfo);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10STATEBLOCKMASKUNION)(D3D10_STATE_BLOCK_MASK *pA, D3D10_STATE_BLOCK_MASK *pB, D3D10_STATE_BLOCK_MASK *pResult);
-static PFN_D3D10STATEBLOCKMASKUNION _D3D10StateBlockMaskUnion_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10StateBlockMaskUnion(D3D10_STATE_BLOCK_MASK *pA, D3D10_STATE_BLOCK_MASK *pB, D3D10_STATE_BLOCK_MASK *pResult) {
- const char *_name = "D3D10StateBlockMaskUnion";
- LOG();
- if (!_D3D10StateBlockMaskUnion_ptr) {
- _D3D10StateBlockMaskUnion_ptr = (PFN_D3D10STATEBLOCKMASKUNION)_getD3D10ProcAddress(_name);
- if (!_D3D10StateBlockMaskUnion_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10StateBlockMaskUnion_ptr(pA, pB, pResult);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10STATEBLOCKMASKINTERSECT)(D3D10_STATE_BLOCK_MASK *pA, D3D10_STATE_BLOCK_MASK *pB, D3D10_STATE_BLOCK_MASK *pResult);
-static PFN_D3D10STATEBLOCKMASKINTERSECT _D3D10StateBlockMaskIntersect_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10StateBlockMaskIntersect(D3D10_STATE_BLOCK_MASK *pA, D3D10_STATE_BLOCK_MASK *pB, D3D10_STATE_BLOCK_MASK *pResult) {
- const char *_name = "D3D10StateBlockMaskIntersect";
- LOG();
- if (!_D3D10StateBlockMaskIntersect_ptr) {
- _D3D10StateBlockMaskIntersect_ptr = (PFN_D3D10STATEBLOCKMASKINTERSECT)_getD3D10ProcAddress(_name);
- if (!_D3D10StateBlockMaskIntersect_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10StateBlockMaskIntersect_ptr(pA, pB, pResult);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10STATEBLOCKMASKDIFFERENCE)(D3D10_STATE_BLOCK_MASK *pA, D3D10_STATE_BLOCK_MASK *pB, D3D10_STATE_BLOCK_MASK *pResult);
-static PFN_D3D10STATEBLOCKMASKDIFFERENCE _D3D10StateBlockMaskDifference_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10StateBlockMaskDifference(D3D10_STATE_BLOCK_MASK *pA, D3D10_STATE_BLOCK_MASK *pB, D3D10_STATE_BLOCK_MASK *pResult) {
- const char *_name = "D3D10StateBlockMaskDifference";
- LOG();
- if (!_D3D10StateBlockMaskDifference_ptr) {
- _D3D10StateBlockMaskDifference_ptr = (PFN_D3D10STATEBLOCKMASKDIFFERENCE)_getD3D10ProcAddress(_name);
- if (!_D3D10StateBlockMaskDifference_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10StateBlockMaskDifference_ptr(pA, pB, pResult);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10STATEBLOCKMASKENABLECAPTURE)(D3D10_STATE_BLOCK_MASK *pMask, D3D10_DEVICE_STATE_TYPES StateType, UINT RangeStart, UINT RangeLength);
-static PFN_D3D10STATEBLOCKMASKENABLECAPTURE _D3D10StateBlockMaskEnableCapture_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10StateBlockMaskEnableCapture(D3D10_STATE_BLOCK_MASK *pMask, D3D10_DEVICE_STATE_TYPES StateType, UINT RangeStart, UINT RangeLength) {
- const char *_name = "D3D10StateBlockMaskEnableCapture";
- LOG();
- if (!_D3D10StateBlockMaskEnableCapture_ptr) {
- _D3D10StateBlockMaskEnableCapture_ptr = (PFN_D3D10STATEBLOCKMASKENABLECAPTURE)_getD3D10ProcAddress(_name);
- if (!_D3D10StateBlockMaskEnableCapture_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10StateBlockMaskEnableCapture_ptr(pMask, StateType, RangeStart, RangeLength);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10STATEBLOCKMASKDISABLECAPTURE)(D3D10_STATE_BLOCK_MASK *pMask, D3D10_DEVICE_STATE_TYPES StateType, UINT RangeStart, UINT RangeLength);
-static PFN_D3D10STATEBLOCKMASKDISABLECAPTURE _D3D10StateBlockMaskDisableCapture_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10StateBlockMaskDisableCapture(D3D10_STATE_BLOCK_MASK *pMask, D3D10_DEVICE_STATE_TYPES StateType, UINT RangeStart, UINT RangeLength) {
- const char *_name = "D3D10StateBlockMaskDisableCapture";
- LOG();
- if (!_D3D10StateBlockMaskDisableCapture_ptr) {
- _D3D10StateBlockMaskDisableCapture_ptr = (PFN_D3D10STATEBLOCKMASKDISABLECAPTURE)_getD3D10ProcAddress(_name);
- if (!_D3D10StateBlockMaskDisableCapture_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10StateBlockMaskDisableCapture_ptr(pMask, StateType, RangeStart, RangeLength);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10STATEBLOCKMASKENABLEALL)(D3D10_STATE_BLOCK_MASK *pMask);
-static PFN_D3D10STATEBLOCKMASKENABLEALL _D3D10StateBlockMaskEnableAll_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10StateBlockMaskEnableAll(D3D10_STATE_BLOCK_MASK *pMask) {
- const char *_name = "D3D10StateBlockMaskEnableAll";
- LOG();
- if (!_D3D10StateBlockMaskEnableAll_ptr) {
- _D3D10StateBlockMaskEnableAll_ptr = (PFN_D3D10STATEBLOCKMASKENABLEALL)_getD3D10ProcAddress(_name);
- if (!_D3D10StateBlockMaskEnableAll_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10StateBlockMaskEnableAll_ptr(pMask);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10STATEBLOCKMASKDISABLEALL)(D3D10_STATE_BLOCK_MASK *pMask);
-static PFN_D3D10STATEBLOCKMASKDISABLEALL _D3D10StateBlockMaskDisableAll_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10StateBlockMaskDisableAll(D3D10_STATE_BLOCK_MASK *pMask) {
- const char *_name = "D3D10StateBlockMaskDisableAll";
- LOG();
- if (!_D3D10StateBlockMaskDisableAll_ptr) {
- _D3D10StateBlockMaskDisableAll_ptr = (PFN_D3D10STATEBLOCKMASKDISABLEALL)_getD3D10ProcAddress(_name);
- if (!_D3D10StateBlockMaskDisableAll_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10StateBlockMaskDisableAll_ptr(pMask);
-}
-
-typedef BOOL (WINAPI *PFN_D3D10STATEBLOCKMASKGETSETTING)(D3D10_STATE_BLOCK_MASK *pMask, D3D10_DEVICE_STATE_TYPES StateType, UINT Entry);
-static PFN_D3D10STATEBLOCKMASKGETSETTING _D3D10StateBlockMaskGetSetting_ptr = NULL;
-
-EXTERN_C BOOL WINAPI
-D3D10StateBlockMaskGetSetting(D3D10_STATE_BLOCK_MASK *pMask, D3D10_DEVICE_STATE_TYPES StateType, UINT Entry) {
- const char *_name = "D3D10StateBlockMaskGetSetting";
- LOG();
- if (!_D3D10StateBlockMaskGetSetting_ptr) {
- _D3D10StateBlockMaskGetSetting_ptr = (PFN_D3D10STATEBLOCKMASKGETSETTING)_getD3D10ProcAddress(_name);
- if (!_D3D10StateBlockMaskGetSetting_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10StateBlockMaskGetSetting_ptr(pMask, StateType, Entry);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10CREATESTATEBLOCK)(ID3D10Device *pDevice, D3D10_STATE_BLOCK_MASK *pStateBlockMask, ID3D10StateBlock **ppStateBlock);
-static PFN_D3D10CREATESTATEBLOCK _D3D10CreateStateBlock_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10CreateStateBlock(ID3D10Device *pDevice, D3D10_STATE_BLOCK_MASK *pStateBlockMask, ID3D10StateBlock **ppStateBlock) {
- const char *_name = "D3D10CreateStateBlock";
- LOG();
- if (!_D3D10CreateStateBlock_ptr) {
- _D3D10CreateStateBlock_ptr = (PFN_D3D10CREATESTATEBLOCK)_getD3D10ProcAddress(_name);
- if (!_D3D10CreateStateBlock_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10CreateStateBlock_ptr(pDevice, pStateBlockMask, ppStateBlock);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10COMPILEEFFECTFROMMEMORY)(void *pData, SIZE_T DataLength, const char *pSrcFileName, const D3D10_SHADER_MACRO *pDefines, ID3D10Include *pInclude, UINT HLSLFlags, UINT FXFlags, ID3D10Blob **ppCompiledEffect, ID3D10Blob **ppErrors);
-static PFN_D3D10COMPILEEFFECTFROMMEMORY _D3D10CompileEffectFromMemory_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10CompileEffectFromMemory(void *pData, SIZE_T DataLength, const char *pSrcFileName, const D3D10_SHADER_MACRO *pDefines, ID3D10Include *pInclude, UINT HLSLFlags, UINT FXFlags, ID3D10Blob **ppCompiledEffect, ID3D10Blob **ppErrors) {
- const char *_name = "D3D10CompileEffectFromMemory";
- LOG();
- if (!_D3D10CompileEffectFromMemory_ptr) {
- _D3D10CompileEffectFromMemory_ptr = (PFN_D3D10COMPILEEFFECTFROMMEMORY)_getD3D10ProcAddress(_name);
- if (!_D3D10CompileEffectFromMemory_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10CompileEffectFromMemory_ptr(pData, DataLength, pSrcFileName, pDefines, pInclude, HLSLFlags, FXFlags, ppCompiledEffect, ppErrors);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10CREATEEFFECTFROMMEMORY)(void *pData, SIZE_T DataLength, UINT FXFlags, ID3D10Device *pDevice, ID3D10EffectPool *pEffectPool, ID3D10Effect **ppEffect);
-static PFN_D3D10CREATEEFFECTFROMMEMORY _D3D10CreateEffectFromMemory_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10CreateEffectFromMemory(void *pData, SIZE_T DataLength, UINT FXFlags, ID3D10Device *pDevice, ID3D10EffectPool *pEffectPool, ID3D10Effect **ppEffect) {
- const char *_name = "D3D10CreateEffectFromMemory";
- LOG();
- if (!_D3D10CreateEffectFromMemory_ptr) {
- _D3D10CreateEffectFromMemory_ptr = (PFN_D3D10CREATEEFFECTFROMMEMORY)_getD3D10ProcAddress(_name);
- if (!_D3D10CreateEffectFromMemory_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10CreateEffectFromMemory_ptr(pData, DataLength, FXFlags, pDevice, pEffectPool, ppEffect);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10CREATEEFFECTPOOLFROMMEMORY)(void *pData, SIZE_T DataLength, UINT FXFlags, ID3D10Device *pDevice, ID3D10EffectPool **ppEffectPool);
-static PFN_D3D10CREATEEFFECTPOOLFROMMEMORY _D3D10CreateEffectPoolFromMemory_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10CreateEffectPoolFromMemory(void *pData, SIZE_T DataLength, UINT FXFlags, ID3D10Device *pDevice, ID3D10EffectPool **ppEffectPool) {
- const char *_name = "D3D10CreateEffectPoolFromMemory";
- LOG();
- if (!_D3D10CreateEffectPoolFromMemory_ptr) {
- _D3D10CreateEffectPoolFromMemory_ptr = (PFN_D3D10CREATEEFFECTPOOLFROMMEMORY)_getD3D10ProcAddress(_name);
- if (!_D3D10CreateEffectPoolFromMemory_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10CreateEffectPoolFromMemory_ptr(pData, DataLength, FXFlags, pDevice, ppEffectPool);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10DISASSEMBLEEFFECT)(ID3D10Effect *pEffect, BOOL EnableColorCode, ID3D10Blob **ppDisassembly);
-static PFN_D3D10DISASSEMBLEEFFECT _D3D10DisassembleEffect_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10DisassembleEffect(ID3D10Effect *pEffect, BOOL EnableColorCode, ID3D10Blob **ppDisassembly) {
- const char *_name = "D3D10DisassembleEffect";
- LOG();
- if (!_D3D10DisassembleEffect_ptr) {
- _D3D10DisassembleEffect_ptr = (PFN_D3D10DISASSEMBLEEFFECT)_getD3D10ProcAddress(_name);
- if (!_D3D10DisassembleEffect_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10DisassembleEffect_ptr(pEffect, EnableColorCode, ppDisassembly);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D10CREATEBLOB)(SIZE_T NumBytes, ID3D10Blob **ppBuffer);
-static PFN_D3D10CREATEBLOB _D3D10CreateBlob_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D10CreateBlob(SIZE_T NumBytes, ID3D10Blob **ppBuffer) {
- const char *_name = "D3D10CreateBlob";
- LOG();
- if (!_D3D10CreateBlob_ptr) {
- _D3D10CreateBlob_ptr = (PFN_D3D10CREATEBLOB)_getD3D10ProcAddress(_name);
- if (!_D3D10CreateBlob_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10CreateBlob_ptr(NumBytes, ppBuffer);
-}
-
-typedef DWORD (WINAPI *PFN_D3D10GETVERSION)(void);
-static PFN_D3D10GETVERSION _D3D10GetVersion_ptr = NULL;
-
-EXTERN_C DWORD WINAPI
-D3D10GetVersion(void) {
- const char *_name = "D3D10GetVersion";
- LOG();
- if (!_D3D10GetVersion_ptr) {
- _D3D10GetVersion_ptr = (PFN_D3D10GETVERSION)_getD3D10ProcAddress(_name);
- if (!_D3D10GetVersion_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10GetVersion_ptr();
-}
-
-typedef DWORD (WINAPI *PFN_D3D10REGISTERLAYERS)(void);
-static PFN_D3D10REGISTERLAYERS _D3D10RegisterLayers_ptr = NULL;
-
-EXTERN_C DWORD WINAPI
-D3D10RegisterLayers(void) {
- const char *_name = "D3D10RegisterLayers";
- LOG();
- if (!_D3D10RegisterLayers_ptr) {
- _D3D10RegisterLayers_ptr = (PFN_D3D10REGISTERLAYERS)_getD3D10ProcAddress(_name);
- if (!_D3D10RegisterLayers_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D10RegisterLayers_ptr();
-}
-
diff --git a/wrappers/d3d11.def b/wrappers/d3d11.def
deleted file mode 100644
index af7ea8cf..00000000
--- a/wrappers/d3d11.def
+++ /dev/null
@@ -1,44 +0,0 @@
-LIBRARY "d3d11"
-
-EXPORTS
- D3DKMTDestroyAllocation
- D3DKMTDestroyContext
- D3DKMTDestroyDevice
- D3DKMTDestroySynchronizationObject
- D3DKMTQueryAdapterInfo
- D3DKMTSetDisplayPrivateDriverFormat
- D3DKMTSignalSynchronizationObject
- D3DKMTUnlock
- D3DKMTWaitForSynchronizationObject
- OpenAdapter10
- OpenAdapter10_2
- D3D11CoreCreateDevice
- D3D11CoreCreateLayeredDevice
- D3D11CoreGetLayeredDeviceSize
- D3D11CoreRegisterLayers
- D3D11CreateDevice
- D3D11CreateDeviceAndSwapChain
- D3DKMTCreateAllocation
- D3DKMTCreateContext
- D3DKMTCreateDevice
- D3DKMTCreateSynchronizationObject
- D3DKMTEscape
- D3DKMTGetContextSchedulingPriority
- D3DKMTGetDeviceState
- D3DKMTGetDisplayModeList
- D3DKMTGetMultisampleMethodList
- D3DKMTGetRuntimeData
- D3DKMTGetSharedPrimaryHandle
- D3DKMTLock
- D3DKMTOpenAdapterFromHdc
- D3DKMTOpenResource
- D3DKMTPresent
- D3DKMTQueryAllocationResidency
- D3DKMTQueryResourceInfo
- D3DKMTRender
- D3DKMTSetAllocationPriority
- D3DKMTSetContextSchedulingPriority
- D3DKMTSetDisplayMode
- D3DKMTSetGammaRamp
- D3DKMTSetVidPnSourceOwner
- D3DKMTWaitForVerticalBlankEvent
diff --git a/wrappers/d3d11stubs.cpp b/wrappers/d3d11stubs.cpp
deleted file mode 100644
index 5300fe29..00000000
--- a/wrappers/d3d11stubs.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2012 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-
-/*
- *Stubs for internal D3D11 functions.
- */
-
-
-#include "os.hpp"
-
-#include "d3d11imports.hpp"
-
-
-static HMODULE g_hD3D11Module = NULL;
-
-
-static PROC
-_getD3D11ProcAddress(LPCSTR lpProcName) {
- if (!g_hD3D11Module) {
- char szDll[MAX_PATH] = {0};
- if (!GetSystemDirectoryA(szDll, MAX_PATH)) {
- return NULL;
- }
- strcat(szDll, "\\d3d11.dll");
- g_hD3D11Module = LoadLibraryA(szDll);
- if (!g_hD3D11Module) {
- return NULL;
- }
- }
- return GetProcAddress(g_hD3D11Module, lpProcName);
-}
-
-
-typedef HRESULT (WINAPI *PFN_D3D11COREREGISTERLAYERS)(const void *unknown0, DWORD unknown1);
-static PFN_D3D11COREREGISTERLAYERS _D3D11CoreRegisterLayers_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D11CoreRegisterLayers(const void *unknown0, DWORD unknown1) {
- const char *_name = "D3D11CoreRegisterLayers";
- if (!_D3D11CoreRegisterLayers_ptr) {
- _D3D11CoreRegisterLayers_ptr = (PFN_D3D11COREREGISTERLAYERS)_getD3D11ProcAddress(_name);
- if (!_D3D11CoreRegisterLayers_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D11CoreRegisterLayers_ptr(unknown0, unknown1);
-}
-
-typedef SIZE_T (WINAPI *PFN_D3D11COREGETLAYEREDDEVICESIZE)(const void *unknown0, DWORD unknown1);
-static PFN_D3D11COREGETLAYEREDDEVICESIZE _D3D11CoreGetLayeredDeviceSize_ptr = NULL;
-
-EXTERN_C SIZE_T WINAPI
-D3D11CoreGetLayeredDeviceSize(const void *unknown0, DWORD unknown1) {
- const char *_name = "D3D11CoreGetLayeredDeviceSize";
- if (!_D3D11CoreGetLayeredDeviceSize_ptr) {
- _D3D11CoreGetLayeredDeviceSize_ptr = (PFN_D3D11COREGETLAYEREDDEVICESIZE)_getD3D11ProcAddress(_name);
- if (!_D3D11CoreGetLayeredDeviceSize_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D11CoreGetLayeredDeviceSize_ptr(unknown0, unknown1);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D11CORECREATELAYEREDDEVICE)(const void *unknown0, DWORD unknown1, const void *unknown2, REFIID riid, void **ppvObj);
-static PFN_D3D11CORECREATELAYEREDDEVICE _D3D11CoreCreateLayeredDevice_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D11CoreCreateLayeredDevice(const void *unknown0, DWORD unknown1, const void *unknown2, REFIID riid, void **ppvObj) {
- const char *_name = "D3D11CoreCreateLayeredDevice";
- if (!_D3D11CoreCreateLayeredDevice_ptr) {
- _D3D11CoreCreateLayeredDevice_ptr = (PFN_D3D11CORECREATELAYEREDDEVICE)_getD3D11ProcAddress(_name);
- if (!_D3D11CoreCreateLayeredDevice_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D11CoreCreateLayeredDevice_ptr(unknown0, unknown1, unknown2, riid, ppvObj);
-}
-
-typedef HRESULT (WINAPI *PFN_D3D11CORECREATEDEVICE)(DWORD unknown0, DWORD unknown1, DWORD unknown2, DWORD unknown3, DWORD unknown4, DWORD unknown5, DWORD unknown6, DWORD unknown7, DWORD unknown8);
-static PFN_D3D11CORECREATEDEVICE _D3D11CoreCreateDevice_ptr = NULL;
-
-EXTERN_C HRESULT WINAPI
-D3D11CoreCreateDevice(DWORD unknown0, DWORD unknown1, DWORD unknown2, DWORD unknown3, DWORD unknown4, DWORD unknown5, DWORD unknown6, DWORD unknown7, DWORD unknown8) {
- const char *_name = "D3D11CoreCreateDevice";
- if (!_D3D11CoreCreateDevice_ptr) {
- _D3D11CoreCreateDevice_ptr = (PFN_D3D11CORECREATEDEVICE)_getD3D11ProcAddress(_name);
- if (!_D3D11CoreCreateDevice_ptr) {
- os::log("error: unavailable function %s\n", _name);
- os::abort();
- }
- }
- return _D3D11CoreCreateDevice_ptr(unknown0, unknown1, unknown2, unknown3, unknown4, unknown5, unknown6, unknown7, unknown8);
-}
-
-
diff --git a/wrappers/d3d8trace.py b/wrappers/d3d8trace.py
index 9ce3aad0..2903c48f 100644
--- a/wrappers/d3d8trace.py
+++ b/wrappers/d3d8trace.py
@@ -56,7 +56,7 @@ class D3D8Tracer(DllTracer):
def implementWrapperInterfaceMethodBody(self, interface, base, method):
if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'):
print ' if (_MappedSize && m_pbData) {'
- self.emit_memcpy('(LPBYTE)m_pbData', '(LPBYTE)m_pbData', '_MappedSize')
+ self.emit_memcpy('(LPBYTE)m_pbData', '_MappedSize')
print ' }'
DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method)
diff --git a/wrappers/d3d9.def b/wrappers/d3d9.def
index f52c0c49..8bb86905 100644
--- a/wrappers/d3d9.def
+++ b/wrappers/d3d9.def
@@ -10,3 +10,5 @@ EXPORTS
D3DPERF_QueryRepeatFrame
D3DPERF_SetOptions
D3DPERF_GetStatus
+ DXVA2CreateDirect3DDeviceManager9
+ DXVA2CreateVideoService
diff --git a/wrappers/d3d9shader.hpp b/wrappers/d3d9shader.hpp
index 340f03b3..91b9895a 100644
--- a/wrappers/d3d9shader.hpp
+++ b/wrappers/d3d9shader.hpp
@@ -24,8 +24,7 @@
*
**************************************************************************/
-#ifndef _D3D9SHADER_HPP_
-#define _D3D9SHADER_HPP_
+#pragma once
#include <windows.h>
@@ -35,4 +34,3 @@
void DumpShader(trace::Writer &writer, const DWORD *tokens);
-#endif /* _D3D9SHADER_HPP_ */
diff --git a/wrappers/d3d9trace.py b/wrappers/d3d9trace.py
index df401da5..0850ba3e 100644
--- a/wrappers/d3d9trace.py
+++ b/wrappers/d3d9trace.py
@@ -26,9 +26,8 @@
from dlltrace import DllTracer
from specs.stdapi import API, Pointer, ObjPointer
-from specs.d3d9 import d3d9, D3DSHADER9, IDirect3DSwapChain9Ex
-
-import specs.d3d9dxva2
+from specs.d3d9 import d3d9, D3DSHADER9, IDirect3DSwapChain9Ex, d3dperf
+from specs.dxva2 import dxva2
class D3D9Tracer(DllTracer):
@@ -58,29 +57,51 @@ class D3D9Tracer(DllTracer):
if interface.getMethodByName('Lock') is not None or \
interface.getMethodByName('LockRect') is not None or \
interface.getMethodByName('LockBox') is not None:
- variables += [
- ('size_t', '_MappedSize', '0'),
- ('VOID *', 'm_pbData', '0'),
- ]
+ if interface.name in ['IDirect3DTexture9']:
+ variables += [
+ ('std::map<UINT, std::pair<size_t, VOID *> >', '_MappedData', 'std::map<UINT, std::pair<size_t, VOID *> >()'),
+ ]
+ else:
+ variables += [
+ ('size_t', '_MappedSize', '0'),
+ ('VOID *', 'm_pbData', '0'),
+ ]
return variables
def implementWrapperInterfaceMethodBody(self, interface, base, method):
if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'):
- print ' if (_MappedSize && m_pbData) {'
- self.emit_memcpy('(LPBYTE)m_pbData', '(LPBYTE)m_pbData', '_MappedSize')
- print ' }'
+ if interface.name in ['IDirect3DTexture9']:
+ print ' std::map<UINT, std::pair<size_t, VOID *> >::iterator it = _MappedData.find(Level);'
+ print ' if (it != _MappedData.end()) {'
+ self.emit_memcpy('(LPBYTE)it->second.second', 'it->second.first')
+ print ' _MappedData.erase(it);'
+ print ' }'
+ else:
+ print ' if (_MappedSize && m_pbData) {'
+ self.emit_memcpy('(LPBYTE)m_pbData', '_MappedSize')
+ print ' }'
DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method)
if method.name in ('Lock', 'LockRect', 'LockBox'):
- # FIXME: handle recursive locks
- print ' if (SUCCEEDED(_result) && !(Flags & D3DLOCK_READONLY)) {'
- print ' _getMapInfo(_this, %s, m_pbData, _MappedSize);' % ', '.join(method.argNames()[:-1])
- print ' } else {'
- print ' m_pbData = NULL;'
- print ' _MappedSize = 0;'
- print ' }'
+ if interface.name in ['IDirect3DTexture9']:
+ print ' if (SUCCEEDED(_result) && !(Flags & D3DLOCK_READONLY)) {'
+ print ' size_t mappedSize;'
+ print ' VOID * pbData;'
+ print ' _getMapInfo(_this, %s, pbData, mappedSize);' % ', '.join(method.argNames()[:-1])
+ print ' _MappedData[Level] = std::make_pair(mappedSize, pbData);'
+ print ' } else {'
+ print ' _MappedData.erase(Level);'
+ print ' }'
+ else:
+ # FIXME: handle recursive locks
+ print ' if (SUCCEEDED(_result) && !(Flags & D3DLOCK_READONLY)) {'
+ print ' _getMapInfo(_this, %s, m_pbData, _MappedSize);' % ', '.join(method.argNames()[:-1])
+ print ' } else {'
+ print ' m_pbData = NULL;'
+ print ' _MappedSize = 0;'
+ print ' }'
if __name__ == '__main__':
@@ -92,10 +113,13 @@ if __name__ == '__main__':
print '#include "d3d9imports.hpp"'
print '#include "d3d9size.hpp"'
print '#include "d3d9shader.hpp"'
- print '#include "dxvaint.h"'
+ print '#include "dxva2imports.hpp"'
print
+ d3d9.mergeModule(d3dperf)
+
api = API()
api.addModule(d3d9)
+ api.addModule(dxva2)
tracer = D3D9Tracer()
tracer.traceApi(api)
diff --git a/wrappers/d3dcommonshader.hpp b/wrappers/d3dcommonshader.hpp
index 6d8500b8..1a73ab77 100644
--- a/wrappers/d3dcommonshader.hpp
+++ b/wrappers/d3dcommonshader.hpp
@@ -24,8 +24,7 @@
*
**************************************************************************/
-#ifndef _D3DCOMMONSHADER_HPP_
-#define _D3DCOMMONSHADER_HPP_
+#pragma once
#include <windows.h>
@@ -35,4 +34,3 @@
void DumpShader(trace::Writer &writer, const void *pShaderBytecode, SIZE_T BytecodeLength);
-#endif /* _D3DCOMMONSHADER_HPP_ */
diff --git a/wrappers/d3dkmtstubs.cpp b/wrappers/d3dkmtstubs.cpp
deleted file mode 100644
index 2d125877..00000000
--- a/wrappers/d3dkmtstubs.cpp
+++ /dev/null
@@ -1,713 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2012 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-
-/*
- * Stubs for internal DXGI D3DKMT functions.
- */
-
-
-#include <assert.h>
-#include <windows.h>
-
-
-#ifndef NTSTATUS
-#define NTSTATUS LONG
-#endif
-
-#ifndef STATUS_NOT_IMPLEMENTED
-#define STATUS_NOT_IMPLEMENTED 0xC0000002
-#endif
-
-#define D3DKMT_CREATEALLOCATION void
-#define D3DKMT_CREATEALLOCATION void
-#define D3DKMT_QUERYRESOURCEINFO void
-#define D3DKMT_OPENRESOURCE void
-#define D3DKMT_OPENRESOURCE void
-#define D3DKMT_DESTROYALLOCATION void
-#define D3DKMT_SETALLOCATIONPRIORITY void
-#define D3DKMT_QUERYALLOCATIONRESIDENCY void
-#define D3DKMT_CREATEDEVICE void
-#define D3DKMT_DESTROYDEVICE void
-#define D3DKMT_CREATECONTEXT void
-#define D3DKMT_DESTROYCONTEXT void
-#define D3DKMT_CREATESYNCHRONIZATIONOBJECT void
-#define D3DKMT_CREATESYNCHRONIZATIONOBJECT2 void
-#define D3DKMT_OPENSYNCHRONIZATIONOBJECT void
-#define D3DKMT_DESTROYSYNCHRONIZATIONOBJECT void
-#define D3DKMT_WAITFORSYNCHRONIZATIONOBJECT void
-#define D3DKMT_WAITFORSYNCHRONIZATIONOBJECT2 void
-#define D3DKMT_SIGNALSYNCHRONIZATIONOBJECT void
-#define D3DKMT_SIGNALSYNCHRONIZATIONOBJECT2 void
-#define D3DKMT_LOCK void
-#define D3DKMT_UNLOCK void
-#define D3DKMT_GETDISPLAYMODELIST void
-#define D3DKMT_SETDISPLAYMODE void
-#define D3DKMT_GETMULTISAMPLEMETHODLIST void
-#define D3DKMT_PRESENT void
-#define D3DKMT_RENDER void
-#define D3DKMT_GETRUNTIMEDATA void
-#define D3DKMT_QUERYADAPTERINFO void
-#define D3DKMT_OPENADAPTERFROMHDC void
-#define D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME void
-#define D3DKMT_OPENADAPTERFROMDEVICENAME void
-#define D3DKMT_CLOSEADAPTER void
-#define D3DKMT_GETSHAREDPRIMARYHANDLE void
-#define D3DKMT_ESCAPE void
-#define D3DKMT_SETVIDPNSOURCEOWNER void
-#define D3DKMT_GETPRESENTHISTORY void
-#define D3DKMT_HANDLE LONG
-#define D3DKMT_CREATEOVERLAY void
-#define D3DKMT_UPDATEOVERLAY void
-#define D3DKMT_FLIPOVERLAY void
-#define D3DKMT_DESTROYOVERLAY void
-#define D3DKMT_WAITFORVERTICALBLANKEVENT void
-#define D3DKMT_SETGAMMARAMP void
-#define D3DKMT_GETDEVICESTATE void
-#define D3DKMT_CREATEDCFROMMEMORY void
-#define D3DKMT_DESTROYDCFROMMEMORY void
-#define D3DKMT_SETCONTEXTSCHEDULINGPRIORITY void
-#define D3DKMT_GETCONTEXTSCHEDULINGPRIORITY void
-#define D3DKMT_SCHEDULINGPRIORITYCLASS INT
-#define D3DKMT_GETSCANLINE void
-#define D3DKMT_CHANGESURFACEPOINTER void
-#define D3DKMT_SETQUEUEDLIMIT void
-#define D3DKMT_POLLDISPLAYCHILDREN void
-#define D3DKMT_INVALIDATEACTIVEVIDPN void
-#define D3DKMT_CHECKOCCLUSION void
-#define D3DKMT_WAITFORIDLE void
-#define D3DKMT_CHECKMONITORPOWERSTATE void
-#define D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP void
-#define D3DKMT_SETDISPLAYPRIVATEDRIVERFORMAT void
-#define D3DKMT_SHAREDPRIMARYLOCKNOTIFICATION void
-#define D3DKMT_SHAREDPRIMARYUNLOCKNOTIFICATION void
-#define D3DKMT_CREATEKEYEDMUTEX void
-#define D3DKMT_OPENKEYEDMUTEX void
-#define D3DKMT_DESTROYKEYEDMUTEX void
-#define D3DKMT_ACQUIREKEYEDMUTEX void
-#define D3DKMT_RELEASEKEYEDMUTEX void
-#define D3DKMT_CONFIGURESHAREDRESOURCE void
-#define D3DKMT_GETOVERLAYSTATE void
-#define D3DKMT_CHECKSHAREDRESOURCEACCESS void
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCreateAllocation(D3DKMT_CREATEALLOCATION *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCreateAllocation2(D3DKMT_CREATEALLOCATION *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTQueryResourceInfo(D3DKMT_QUERYRESOURCEINFO *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTOpenResource(D3DKMT_OPENRESOURCE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTOpenResource2(D3DKMT_OPENRESOURCE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTDestroyAllocation(CONST D3DKMT_DESTROYALLOCATION *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSetAllocationPriority(CONST D3DKMT_SETALLOCATIONPRIORITY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTQueryAllocationResidency(CONST D3DKMT_QUERYALLOCATIONRESIDENCY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCreateDevice(D3DKMT_CREATEDEVICE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTDestroyDevice(CONST D3DKMT_DESTROYDEVICE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCreateContext(D3DKMT_CREATECONTEXT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTDestroyContext(CONST D3DKMT_DESTROYCONTEXT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCreateSynchronizationObject(D3DKMT_CREATESYNCHRONIZATIONOBJECT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCreateSynchronizationObject2(D3DKMT_CREATESYNCHRONIZATIONOBJECT2 *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTOpenSynchronizationObject(D3DKMT_OPENSYNCHRONIZATIONOBJECT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTDestroySynchronizationObject(CONST D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTWaitForSynchronizationObject(CONST D3DKMT_WAITFORSYNCHRONIZATIONOBJECT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTWaitForSynchronizationObject2(CONST D3DKMT_WAITFORSYNCHRONIZATIONOBJECT2 *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSignalSynchronizationObject(CONST D3DKMT_SIGNALSYNCHRONIZATIONOBJECT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSignalSynchronizationObject2(CONST D3DKMT_SIGNALSYNCHRONIZATIONOBJECT2 *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTLock(D3DKMT_LOCK *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTUnlock(CONST D3DKMT_UNLOCK *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetDisplayModeList(D3DKMT_GETDISPLAYMODELIST *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSetDisplayMode(CONST D3DKMT_SETDISPLAYMODE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetMultisampleMethodList(D3DKMT_GETMULTISAMPLEMETHODLIST *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTPresent(CONST D3DKMT_PRESENT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTRender(D3DKMT_RENDER *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetRuntimeData(CONST D3DKMT_GETRUNTIMEDATA *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTQueryAdapterInfo(CONST D3DKMT_QUERYADAPTERINFO *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTOpenAdapterFromHdc(D3DKMT_OPENADAPTERFROMHDC *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTOpenAdapterFromGdiDisplayName(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTOpenAdapterFromDeviceName(D3DKMT_OPENADAPTERFROMDEVICENAME *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCloseAdapter(CONST D3DKMT_CLOSEADAPTER *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetSharedPrimaryHandle(D3DKMT_GETSHAREDPRIMARYHANDLE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTEscape(CONST D3DKMT_ESCAPE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSetVidPnSourceOwner(CONST D3DKMT_SETVIDPNSOURCEOWNER *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetPresentHistory(D3DKMT_GETPRESENTHISTORY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetPresentQueueEvent(D3DKMT_HANDLE hAdapter, HANDLE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCreateOverlay(D3DKMT_CREATEOVERLAY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTUpdateOverlay(CONST D3DKMT_UPDATEOVERLAY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTFlipOverlay(CONST D3DKMT_FLIPOVERLAY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTDestroyOverlay(CONST D3DKMT_DESTROYOVERLAY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTWaitForVerticalBlankEvent(CONST D3DKMT_WAITFORVERTICALBLANKEVENT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSetGammaRamp(CONST D3DKMT_SETGAMMARAMP *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetDeviceState(D3DKMT_GETDEVICESTATE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCreateDCFromMemory(D3DKMT_CREATEDCFROMMEMORY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTDestroyDCFromMemory(CONST D3DKMT_DESTROYDCFROMMEMORY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSetContextSchedulingPriority(CONST D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetContextSchedulingPriority(D3DKMT_GETCONTEXTSCHEDULINGPRIORITY *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSetProcessSchedulingPriorityClass(HANDLE hProcess, D3DKMT_SCHEDULINGPRIORITYCLASS Priority)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetProcessSchedulingPriorityClass(HANDLE hProcess, D3DKMT_SCHEDULINGPRIORITYCLASS *pPriority)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTReleaseProcessVidPnSourceOwners(HANDLE hProcess)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetScanLine(D3DKMT_GETSCANLINE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTChangeSurfacePointer(CONST D3DKMT_CHANGESURFACEPOINTER *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSetQueuedLimit(CONST D3DKMT_SETQUEUEDLIMIT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTPollDisplayChildren(CONST D3DKMT_POLLDISPLAYCHILDREN *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTInvalidateActiveVidPn(CONST D3DKMT_INVALIDATEACTIVEVIDPN *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCheckOcclusion(CONST D3DKMT_CHECKOCCLUSION *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTWaitForIdle(CONST D3DKMT_WAITFORIDLE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCheckMonitorPowerState(CONST D3DKMT_CHECKMONITORPOWERSTATE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C BOOLEAN APIENTRY
-D3DKMTCheckExclusiveOwnership(VOID)
-{
- assert(0);
- return FALSE;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCheckVidPnExclusiveOwnership(CONST D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSetDisplayPrivateDriverFormat(CONST D3DKMT_SETDISPLAYPRIVATEDRIVERFORMAT *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSharedPrimaryLockNotification(CONST D3DKMT_SHAREDPRIMARYLOCKNOTIFICATION *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTSharedPrimaryUnLockNotification(CONST D3DKMT_SHAREDPRIMARYUNLOCKNOTIFICATION *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCreateKeyedMutex(D3DKMT_CREATEKEYEDMUTEX *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTOpenKeyedMutex(D3DKMT_OPENKEYEDMUTEX *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTDestroyKeyedMutex(CONST D3DKMT_DESTROYKEYEDMUTEX *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTAcquireKeyedMutex(D3DKMT_ACQUIREKEYEDMUTEX *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTReleaseKeyedMutex(D3DKMT_RELEASEKEYEDMUTEX *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTConfigureSharedResource(CONST D3DKMT_CONFIGURESHAREDRESOURCE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTGetOverlayState(D3DKMT_GETOVERLAYSTATE *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-EXTERN_C NTSTATUS APIENTRY
-D3DKMTCheckSharedResourceAccess(CONST D3DKMT_CHECKSHAREDRESOURCEACCESS *pData)
-{
- assert(0);
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-#define D3D10DDIARG_OPENADAPTER void
-
-EXTERN_C HRESULT APIENTRY
-OpenAdapter10(D3D10DDIARG_OPENADAPTER *pData) {
- assert(0);
- return E_NOTIMPL;
-}
-
-EXTERN_C HRESULT APIENTRY
-OpenAdapter10_2(D3D10DDIARG_OPENADAPTER *pData) {
- assert(0);
- return E_NOTIMPL;
-}
-
diff --git a/wrappers/ddraw.def b/wrappers/ddraw.def
index 6186c602..28fa73d5 100644
--- a/wrappers/ddraw.def
+++ b/wrappers/ddraw.def
@@ -17,7 +17,7 @@ EXPORTS
DSoundHelp
GetDDSurfaceLocal
GetOLEThunkData
- GetSurfaceFromDC
+ ;GetSurfaceFromDC
RegisterSpecialCase
ReleaseDDThreadLock
;SetAppCompatData
diff --git a/wrappers/ddrawtrace.py b/wrappers/ddrawtrace.py
index 94e39e2d..96602d21 100644
--- a/wrappers/ddrawtrace.py
+++ b/wrappers/ddrawtrace.py
@@ -1,6 +1,6 @@
##########################################################################
#
-# Copyright 2008-2009 VMware, Inc.
+# Copyright 2008-2015 VMware, Inc.
# All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -29,36 +29,26 @@ from specs.stdapi import API
from specs.d3d import ddraw, interfaces
-if __name__ == '__main__':
- print '#define INITGUID'
- print '#include <windows.h>'
- print '#include <ddraw.h>'
- print '#include <d3d.h>'
- print
- print '''
+class DDrawTracer(DllTracer):
-#ifndef DDBLT_EXTENDED_FLAGS
-#define DDBLT_EXTENDED_FLAGS 0x40000000l
-#endif
+ pass
-#ifndef DDBLT_EXTENDED_LINEAR_CONTENT
-#define DDBLT_EXTENDED_LINEAR_CONTENT 0x00000004l
-#endif
+ # FIXME: emit fake memcpy calls for IDirectDrawSurface7::EnumAttachedSurfaces
-#ifndef D3DLIGHT_PARALLELPOINT
-#define D3DLIGHT_PARALLELPOINT (D3DLIGHTTYPE)4
-#endif
+ # FIXME: wrap objects passed to IDirectDrawSurface7::EnumAttachedSurfaces
+ # callback -- we don't really care for tracing these calls, but we do want
+ # to trace everything done inside the callback.
-#ifndef D3DLIGHT_GLSPOT
-#define D3DLIGHT_GLSPOT (D3DLIGHTTYPE)5
-#endif
-'''
+if __name__ == '__main__':
+ print '#define INITGUID'
+ print '#include "d3dimports.hpp"'
print '#include "trace_writer_local.hpp"'
+ print '#include "d3d7size.hpp"'
print '#include "os.hpp"'
print
api = API()
api.addModule(ddraw)
- tracer = DllTracer()
+ tracer = DDrawTracer()
tracer.traceApi(api)
diff --git a/wrappers/dlltrace.py b/wrappers/dlltrace.py
index f7ad20fe..26962216 100644
--- a/wrappers/dlltrace.py
+++ b/wrappers/dlltrace.py
@@ -46,7 +46,7 @@ class DllDispatcher(Dispatcher):
print r' if (!GetSystemDirectoryA(szDll, MAX_PATH)) {'
print r' return NULL;'
print r' }'
- print r' strcat(szDll, "\\\\%s.dll");' % module.name
+ print r' strcat(szDll, "\\%s.dll");' % module.name
print r' g_h%sModule = LoadLibraryA(szDll);' % tag
print r' if (!g_h%sModule) {' % tag
print r' return NULL;'
@@ -59,7 +59,6 @@ class DllDispatcher(Dispatcher):
Dispatcher.dispatchModule(self, module)
def getProcAddressName(self, module, function):
- assert self.isFunctionPublic(module, function)
return '_get%sProcAddress' % (module.name.upper())
diff --git a/wrappers/dwrite.def b/wrappers/dwrite.def
deleted file mode 100644
index 4dcdba1d..00000000
--- a/wrappers/dwrite.def
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBRARY "d2d1"
-
-EXPORTS
- DWriteCreateFactory
diff --git a/wrappers/dwritetrace.cpp b/wrappers/dwritetrace.cpp
deleted file mode 100644
index 9ca69d63..00000000
--- a/wrappers/dwritetrace.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <windows.h>
-
-EXTERN_C BOOL WINAPI
-DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
- return TRUE;
-}
diff --git a/wrappers/dxgi.def b/wrappers/dxgi.def
deleted file mode 100644
index db1db156..00000000
--- a/wrappers/dxgi.def
+++ /dev/null
@@ -1,47 +0,0 @@
-LIBRARY "dxgi"
-
-EXPORTS
- D3DKMTCloseAdapter
- D3DKMTDestroyAllocation
- D3DKMTDestroyContext
- D3DKMTDestroyDevice
- D3DKMTDestroySynchronizationObject
- D3DKMTQueryAdapterInfo
- D3DKMTSetDisplayPrivateDriverFormat
- D3DKMTSignalSynchronizationObject
- D3DKMTUnlock
- D3DKMTWaitForSynchronizationObject
- DXGIDumpJournal
- OpenAdapter10
- OpenAdapter10_2
- CreateDXGIFactory1
- CreateDXGIFactory
- D3DKMTCreateAllocation
- D3DKMTCreateContext
- D3DKMTCreateDevice
- D3DKMTCreateSynchronizationObject
- D3DKMTEscape
- D3DKMTGetContextSchedulingPriority
- D3DKMTGetDeviceState
- D3DKMTGetDisplayModeList
- D3DKMTGetMultisampleMethodList
- D3DKMTGetRuntimeData
- D3DKMTGetSharedPrimaryHandle
- D3DKMTLock
- D3DKMTOpenAdapterFromHdc
- D3DKMTOpenResource
- D3DKMTPresent
- D3DKMTQueryAllocationResidency
- D3DKMTQueryResourceInfo
- D3DKMTRender
- D3DKMTSetAllocationPriority
- D3DKMTSetContextSchedulingPriority
- D3DKMTSetDisplayMode
- D3DKMTSetGammaRamp
- D3DKMTSetVidPnSourceOwner
- D3DKMTWaitForVerticalBlankEvent
- DXGID3D10CreateDevice
- DXGID3D10CreateLayeredDevice
- DXGID3D10GetLayeredDeviceSize
- DXGID3D10RegisterLayers
- DXGIReportAdapterConfiguration
diff --git a/wrappers/dxgistubs.cpp b/wrappers/dxgistubs.cpp
deleted file mode 100644
index 1a24f23f..00000000
--- a/wrappers/dxgistubs.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2012 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- **************************************************************************/
-
-
-/*
- * Stubs for internal DXGI functions.
- */
-
-
-#include <assert.h>
-
-#include "d3d10imports.hpp"
-
-#include "os.hpp"
-
-
-static HMODULE g_hDXGIModule = NULL;
-
-
-static PROC
-_getDXGIProcAddress(LPCSTR lpProcName) {
- if (!g_hDXGIModule) {
- char szDll[MAX_PATH] = {0};
- if (!GetSystemDirectoryA(szDll, MAX_PATH)) {
- return NULL;
- }
- strcat(szDll, "\\dxgi.dll");
- g_hDXGIModule = LoadLibraryA(szDll);
- if (!g_hDXGIModule) {
- return NULL;
- }
- }
- return GetProcAddress(g_hDXGIModule, lpProcName);
-}
-
-
-#define STUB(_Ret, _Name, _ArgsDecl, _Args) \
- EXTERN_C _Ret WINAPI \
- _Name _ArgsDecl { \
- typedef _Ret (WINAPI *_PFN) _ArgsDecl; \
- static _PFN _pfn = NULL; \
- if (!_pfn) { \
- static const char *_name = #_Name; \
- _pfn = (_PFN)_getDXGIProcAddress(_name); \
- if (!_pfn) { \
- os::log("error: unavailable function %s\n", _name); \
- os::abort(); \
- } \
- } \
- return _pfn _Args; \
- }
-
-
-STUB(HRESULT, DXGID3D10CreateDevice,
- (HMODULE hModule, IDXGIFactory *pFactory, IDXGIAdapter *pAdapter, UINT Flags, void *unknown, void *ppDevice),
- (hModule, pFactory, pAdapter, Flags, unknown, ppDevice)
-)
-
-struct UNKNOWN {
- BYTE unknown[20];
-};
-
-STUB(HRESULT, DXGID3D10CreateLayeredDevice,
- (UNKNOWN Unknown),
- (Unknown)
-)
-
-STUB(SIZE_T, DXGID3D10GetLayeredDeviceSize,
- (const void *pLayers, UINT NumLayers),
- (pLayers, NumLayers)
-)
-
-STUB(HRESULT, DXGID3D10RegisterLayers,
- (const void *pLayers, UINT NumLayers),
- (pLayers, NumLayers)
-)
-
-EXTERN_C HRESULT WINAPI
-DXGIDumpJournal()
-{
- assert(0);
- return E_NOTIMPL;
-}
-
-EXTERN_C HRESULT WINAPI
-DXGIReportAdapterConfiguration()
-{
- assert(0);
- return E_NOTIMPL;
-}
-
-
diff --git a/wrappers/dxgitrace.def b/wrappers/dxgitrace.def
new file mode 100644
index 00000000..02880c48
--- /dev/null
+++ b/wrappers/dxgitrace.def
@@ -0,0 +1,16 @@
+EXPORTS
+ CreateDXGIFactory
+ CreateDXGIFactory1
+ D3D10CreateDevice
+ D3D10CreateDeviceAndSwapChain
+ D3D10CreateDevice1
+ D3D10CreateDeviceAndSwapChain1
+ D3D11CreateDevice
+ D3D11CreateDeviceAndSwapChain
+ D3DPERF_BeginEvent
+ D3DPERF_EndEvent
+ D3DPERF_SetMarker
+ D3DPERF_SetRegion
+ D3DPERF_QueryRepeatFrame
+ D3DPERF_SetOptions
+ D3DPERF_GetStatus
diff --git a/wrappers/dxgitrace.py b/wrappers/dxgitrace.py
index 45767a0f..3edda2c2 100644
--- a/wrappers/dxgitrace.py
+++ b/wrappers/dxgitrace.py
@@ -31,8 +31,8 @@ from specs import stdapi
from specs.stdapi import API
from specs import dxgi
from specs import d3d10
-from specs import d3d10_1
from specs import d3d11
+from specs import d3d9
class D3DCommonTracer(DllTracer):
@@ -73,13 +73,22 @@ class D3DCommonTracer(DllTracer):
self.serializeValue(arg.type, '_pSwapChainDesc')
return
+ # Serialize object names
+ if function.name == 'SetPrivateData' and arg.name == 'pData':
+ iid = function.args[0].name
+ print r' if (%s == WKPDID_D3DDebugObjectName) {' % iid
+ print r' trace::localWriter.writeString(static_cast<const char *>(pData), DataSize);'
+ print r' } else {'
+ DllTracer.serializeArgValue(self, function, arg)
+ print r' }'
+ return
+
DllTracer.serializeArgValue(self, function, arg)
# Interfaces that need book-keeping for maps
mapInterfaces = (
dxgi.IDXGISurface,
d3d10.ID3D10Resource,
- d3d11.ID3D11Resource,
)
def enumWrapperInterfaceVariables(self, interface):
@@ -88,76 +97,67 @@ class D3DCommonTracer(DllTracer):
# Add additional members to track maps
if interface.hasBase(*self.mapInterfaces):
variables += [
- ('_MAP_DESC', '_MapDesc', None),
+ ('_MAP_DESC', 'm_MapDesc', None),
+ ]
+ if interface.hasBase(d3d11.ID3D11DeviceContext):
+ variables += [
+ ('std::map< std::pair<ID3D11Resource *, UINT>, _MAP_DESC >', 'm_MapDescs', None),
]
return variables
def implementWrapperInterfaceMethodBody(self, interface, base, method):
+ if method.getArgByName('pInitialData'):
+ pDesc1 = method.getArgByName('pDesc1')
+ if pDesc1 is not None:
+ print r' %s pDesc = pDesc1;' % (pDesc1.type,)
+
if method.name in ('Map', 'Unmap'):
# On D3D11 Map/Unmap is not a resource method, but a context method instead.
resourceArg = method.getArgByName('pResource')
if resourceArg is None:
- pResource = 'this'
+ print ' _MAP_DESC & _MapDesc = m_MapDesc;'
else:
- wrapperInterfaceName = getWrapperInterfaceName(resourceArg.type.type)
- print ' %s * _pResource = static_cast<%s*>(%s);' % (wrapperInterfaceName, wrapperInterfaceName, resourceArg.name)
- pResource = '_pResource'
+ print ' _MAP_DESC & _MapDesc = m_MapDescs[std::pair<%s, UINT>(pResource, Subresource)];' % resourceArg.type
if method.name == 'Unmap':
- print ' _MAP_DESC _MapDesc = %s->_MapDesc;' % pResource
- #print r' os::log("%%p -> %%p+%%lu\n", %s,_MapDesc.pData, (unsigned long)_MapDesc.Size);' % pResource
print ' if (_MapDesc.Size && _MapDesc.pData) {'
- self.emit_memcpy('_MapDesc.pData', '_MapDesc.pData', '_MapDesc.Size')
+ self.emit_memcpy('_MapDesc.pData', '_MapDesc.Size')
print ' }'
DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method)
if method.name == 'Map':
# NOTE: recursive locks are explicitely forbidden
- print ' _MAP_DESC _MapDesc;'
print ' if (SUCCEEDED(_result)) {'
print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames())
print ' } else {'
print ' _MapDesc.pData = NULL;'
print ' _MapDesc.Size = 0;'
print ' }'
- #print r' os::log("%%p <- %%p+%%lu\n", %s,_MapDesc.pData, (unsigned long)_MapDesc.Size);' % pResource
- print ' %s->_MapDesc = _MapDesc;' % pResource
if __name__ == '__main__':
- print '#define INITGUID'
+ print r'#define INITGUID'
print
- print '#include "trace_writer_local.hpp"'
- print '#include "os.hpp"'
+ print r'#include "trace_writer_local.hpp"'
+ print r'#include "os.hpp"'
print
- print '#include "d3dcommonshader.hpp"'
+ print r'#include "d3dcommonshader.hpp"'
+ print
+ print r'#include "d3d10imports.hpp"'
+ print r'#include "d3d10size.hpp"'
+ print r'#include "d3d11imports.hpp"'
+ print r'#include "d3d11size.hpp"'
+ print r'#include "d3d9imports.hpp" // D3DPERF_*'
print
-
- moduleNames = sys.argv[1:]
api = API()
-
- if moduleNames:
- api.addModule(dxgi.dxgi)
-
- if 'd3d10' in moduleNames:
- if 'd3d10_1' in moduleNames:
- print r'#include "d3d10_1imports.hpp"'
- api.addModule(d3d10_1.d3d10_1)
- else:
- print r'#include "d3d10imports.hpp"'
- print r'#include "d3d10size.hpp"'
- api.addModule(d3d10.d3d10)
-
- if 'd3d11' in moduleNames:
- print r'#include "d3d11imports.hpp"'
- if 'd3d11_1' in moduleNames:
- print '#include <d3d11_1.h>'
- from specs import d3d11_1
- print r'#include "d3d11size.hpp"'
- api.addModule(d3d11.d3d11)
+ api.addModule(dxgi.dxgi)
+ api.addModule(d3d10.d3d10)
+ api.addModule(d3d10.d3d10_1)
+ api.addModule(d3d11.d3d11)
+ api.addModule(d3d9.d3dperf)
tracer = D3DCommonTracer()
tracer.traceApi(api)
diff --git a/wrappers/egltrace.py b/wrappers/egltrace.py
index 562f060c..abd3bfcc 100644
--- a/wrappers/egltrace.py
+++ b/wrappers/egltrace.py
@@ -36,7 +36,6 @@ from gltrace import GlTracer
from specs.stdapi import Module, API
from specs.glapi import glapi
from specs.eglapi import eglapi
-from specs.glesapi import glesapi
class EglTracer(GlTracer):
@@ -57,24 +56,31 @@ class EglTracer(GlTracer):
print ' gltrace::createContext((uintptr_t)_result);'
if function.name == 'eglMakeCurrent':
- print ' if (_result) {'
- print ' // update the profile'
- print ' if (ctx != EGL_NO_CONTEXT) {'
- print ' EGLint api = EGL_OPENGL_ES_API, version = 1;'
- print ' gltrace::setContext((uintptr_t)ctx);'
- print ' gltrace::Context *tr = gltrace::getContext();'
- print ' _eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_TYPE, &api);'
- print ' _eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &version);'
- print ' if (api == EGL_OPENGL_API)'
- print ' tr->profile = gltrace::PROFILE_COMPAT;'
- print ' else if (version == 1)'
- print ' tr->profile = gltrace::PROFILE_ES1;'
- print ' else'
- print ' tr->profile = gltrace::PROFILE_ES2;'
- print ' } else {'
- print ' gltrace::clearContext();'
- print ' }'
- print ' }'
+ print r' if (_result) {'
+ print r' // update the profile'
+ print r' if (ctx != EGL_NO_CONTEXT) {'
+ print r' gltrace::setContext((uintptr_t)ctx);'
+ print r' gltrace::Context *tr = gltrace::getContext();'
+ print r' EGLint api = EGL_OPENGL_ES_API;'
+ print r' _eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_TYPE, &api);'
+ print r' if (api == EGL_OPENGL_API) {'
+ print r' assert(tr->profile.api == glprofile::API_GL);'
+ print r' } else if (api == EGL_OPENGL_ES_API) {'
+ print r' EGLint client_version = 1;'
+ print r' _eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &client_version);'
+ print r' if (tr->profile.api != glprofile::API_GLES ||'
+ print r' tr->profile.major < client_version) {'
+ print r' std::string version = tr->profile.str();'
+ print r' os::log("apitrace: warning: eglMakeCurrent: expected OpenGL ES %i.x context, but got %s\n",'
+ print r' client_version, version.c_str());'
+ print r' }'
+ print r' } else {'
+ print r' assert(0);'
+ print r' }'
+ print r' } else {'
+ print r' gltrace::clearContext();'
+ print r' }'
+ print r' }'
if function.name == 'eglDestroyContext':
print ' if (_result) {'
@@ -116,7 +122,6 @@ if __name__ == '__main__':
module = Module()
module.mergeModule(eglapi)
module.mergeModule(glapi)
- module.mergeModule(glesapi)
api = API()
api.addModule(module)
tracer = EglTracer()
@@ -173,6 +178,14 @@ void * dlopen(const char *filename, int flag)
} else {
os::log("apitrace: warning: dladdr() failed\n");
}
+
+ // SDL will skip dlopen'ing libEGL.so after it spots EGL symbols on our
+ // wrapper, so force loading it here.
+ // (https://github.com/apitrace/apitrace/issues/291#issuecomment-59734022)
+ if (strcmp(filename, "libEGL.so") != 0 &&
+ strcmp(filename, "libEGL.so.1") != 0) {
+ _dlopen("libEGL.so.1", RTLD_GLOBAL | RTLD_LAZY);
+ }
}
return handle;
@@ -182,11 +195,11 @@ void * dlopen(const char *filename, int flag)
#if defined(ANDROID)
/*
- * Undocumented Android extensions used by Dalvik which have bound information
- * passed to it, but is currently ignored, so probably unreliable.
+ * Undocumented Android extensions used by the wrappers which have bound
+ * information passed to it, but is currently ignored, so probably unreliable.
*
* See:
- * https://github.com/android/platform_frameworks_base/blob/master/opengl/libs/GLES_CM/gl.cpp
+ * https://github.com/android/platform_frameworks_base/search?q=glVertexPointerBounds
*/
extern "C" PUBLIC
diff --git a/wrappers/egltrace.version b/wrappers/egltrace.version
new file mode 100644
index 00000000..0e7e62b9
--- /dev/null
+++ b/wrappers/egltrace.version
@@ -0,0 +1,10 @@
+{
+ global:
+ _init;
+ _fini;
+ egl[A-Z]*;
+ gl[A-Z]*;
+ dlopen;
+ local:
+ *;
+};
diff --git a/wrappers/glcaps.cpp b/wrappers/glcaps.cpp
index f78e29a2..85a76a87 100644
--- a/wrappers/glcaps.cpp
+++ b/wrappers/glcaps.cpp
@@ -35,12 +35,15 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string>
#include <map>
#include "glproc.hpp"
#include "gltrace.hpp"
+#include "os.hpp"
+#include "config.hpp"
namespace gltrace {
@@ -62,10 +65,12 @@ extraExtension_stringsFull[] = {
"GL_KHR_debug",
"GL_EXT_debug_marker",
"GL_EXT_debug_label",
+ "GL_VMWX_map_buffer_debug",
};
static const char *
extraExtension_stringsES[] = {
+ "GL_KHR_debug",
"GL_EXT_debug_marker",
"GL_EXT_debug_label",
};
@@ -93,15 +98,12 @@ extraExtensionsES = {
const struct ExtensionsDesc *
-getExtraExtensions(void)
+getExtraExtensions(const Context *ctx)
{
- Context *ctx = getContext();
-
- switch (ctx->profile) {
- case PROFILE_COMPAT:
+ switch (ctx->profile.api) {
+ case glprofile::API_GL:
return &extraExtensionsFull;
- case PROFILE_ES1:
- case PROFILE_ES2:
+ case glprofile::API_GLES:
return &extraExtensionsES;
default:
assert(0);
@@ -116,7 +118,8 @@ getExtraExtensions(void)
static const char *
overrideExtensionsString(const char *extensions)
{
- const ExtensionsDesc *desc = getExtraExtensions();
+ const Context *ctx = getContext();
+ const ExtensionsDesc *desc = getExtraExtensions(ctx);
size_t i;
ExtensionsMap::const_iterator it = extensionsMap.find(extensions);
@@ -170,7 +173,15 @@ overrideExtensionsString(const char *extensions)
const GLubyte *
_glGetString_override(GLenum name)
{
- const GLubyte *result = _glGetString(name);
+ const configuration *config = getConfig();
+ const GLubyte *result;
+
+ // Try getting the override string value first
+ result = getConfigString(config, name);
+ if (!result) {
+ // Ask the real GL library
+ result = _glGetString(name);
+ }
if (result) {
switch (name) {
@@ -186,16 +197,66 @@ _glGetString_override(GLenum name)
}
+static void
+getInteger(const configuration *config,
+ GLenum pname, GLint *params)
+{
+ // Disable ARB_get_program_binary
+ switch (pname) {
+ case GL_NUM_PROGRAM_BINARY_FORMATS:
+ if (params) {
+ GLint numProgramBinaryFormats = 0;
+ _glGetIntegerv(pname, &numProgramBinaryFormats);
+ if (numProgramBinaryFormats > 0) {
+ os::log("apitrace: warning: hiding program binary formats (https://github.com/apitrace/apitrace/issues/316)\n");
+ }
+ params[0] = 0;
+ }
+ return;
+ case GL_PROGRAM_BINARY_FORMATS:
+ // params might be NULL here, as we returned 0 for
+ // GL_NUM_PROGRAM_BINARY_FORMATS.
+ return;
+ }
+
+ if (params) {
+ *params = getConfigInteger(config, pname);
+ if (*params != 0) {
+ return;
+ }
+ }
+
+ // Ask the real GL library
+ _glGetIntegerv(pname, params);
+}
+
+
+/**
+ * TODO: To be thorough, we should override all glGet*v.
+ */
void
_glGetIntegerv_override(GLenum pname, GLint *params)
{
- _glGetIntegerv(pname, params);
+ const configuration *config = getConfig();
+
+ /*
+ * It's important to handle params==NULL correctly here, which can and does
+ * happen, particularly when pname is GL_COMPRESSED_TEXTURE_FORMATS or
+ * GL_PROGRAM_BINARY_FORMATS and the implementation returns 0 for
+ * GL_NUM_COMPRESSED_TEXTURE_FORMATS or GL_NUM_PROGRAM_BINARY_FORMATS, as
+ * the application ends up calling `params = malloc(0)` or `param = new
+ * GLint[0]` which can yield NULL.
+ */
+
+ getInteger(config, pname, params);
if (params) {
+ const Context *ctx;
switch (pname) {
case GL_NUM_EXTENSIONS:
- {
- const ExtensionsDesc *desc = getExtraExtensions();
+ ctx = getContext();
+ if (ctx->profile.major >= 3) {
+ const ExtensionsDesc *desc = getExtraExtensions(ctx);
*params += desc->numStrings;
}
break;
@@ -207,8 +268,6 @@ _glGetIntegerv_override(GLenum pname, GLint *params)
params[0] = 256;
}
break;
- default:
- break;
}
}
}
@@ -217,21 +276,31 @@ _glGetIntegerv_override(GLenum pname, GLint *params)
const GLubyte *
_glGetStringi_override(GLenum name, GLuint index)
{
- switch (name) {
- case GL_EXTENSIONS:
- {
- const ExtensionsDesc *desc = getExtraExtensions();
- GLint numExtensions = 0;
- _glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
- if ((GLuint)numExtensions <= index && index < (GLuint)numExtensions + desc->numStrings) {
- return (const GLubyte *)desc->strings[index - (GLuint)numExtensions];
+ const configuration *config = getConfig();
+ const Context *ctx = getContext();
+ const GLubyte *retVal;
+
+ if (ctx->profile.major >= 3) {
+ switch (name) {
+ case GL_EXTENSIONS:
+ {
+ const ExtensionsDesc *desc = getExtraExtensions(ctx);
+ GLint numExtensions = 0;
+ getInteger(config, GL_NUM_EXTENSIONS, &numExtensions);
+ if ((GLuint)numExtensions <= index && index < (GLuint)numExtensions + desc->numStrings) {
+ return (const GLubyte *)desc->strings[index - (GLuint)numExtensions];
+ }
}
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
}
+ retVal = getConfigStringi(config, name, index);
+ if (retVal)
+ return retVal;
+
return _glGetStringi(name, index);
}
diff --git a/wrappers/gltrace.hpp b/wrappers/gltrace.hpp
index dd8058ce..5b4a4f44 100644
--- a/wrappers/gltrace.hpp
+++ b/wrappers/gltrace.hpp
@@ -23,8 +23,7 @@
*
**************************************************************************/
-#ifndef _GLTRACE_HPP_
-#define _GLTRACE_HPP_
+#pragma once
#include <string.h>
@@ -33,15 +32,10 @@
#include "glimports.hpp"
-
-namespace gltrace {
+#include "glprofile.hpp"
-enum Profile {
- PROFILE_COMPAT,
- PROFILE_ES1,
- PROFILE_ES2,
-};
+namespace gltrace {
/**
@@ -91,10 +85,10 @@ public:
class Context {
public:
- enum Profile profile;
+ glprofile::Profile profile;
bool user_arrays;
- bool user_arrays_arb;
bool user_arrays_nv;
+ bool userArraysOnBegin;
unsigned retain_count;
// Whether it has been bound before
@@ -104,10 +98,10 @@ public:
std::map <GLuint, Buffer> buffers;
Context(void) :
- profile(PROFILE_COMPAT),
+ profile(glprofile::API_GL, 1, 0),
user_arrays(false),
- user_arrays_arb(false),
user_arrays_nv(false),
+ userArraysOnBegin(false),
retain_count(0),
bound(false)
{ }
@@ -115,7 +109,7 @@ public:
inline bool
needsShadowBuffers(void)
{
- return profile == PROFILE_ES1 || profile == PROFILE_ES2;
+ return profile.es();
}
};
@@ -150,4 +144,3 @@ _glGetStringi_override(GLenum name, GLuint index);
} /* namespace gltrace */
-#endif /* _GLRETRACE_HPP_ */
diff --git a/wrappers/gltrace.py b/wrappers/gltrace.py
index 440e6b3f..9fe679a6 100644
--- a/wrappers/gltrace.py
+++ b/wrappers/gltrace.py
@@ -27,6 +27,9 @@
"""GL tracing generator."""
+import re
+import sys
+
from trace import Tracer
from dispatch import function_pointer_type, function_pointer_value
import specs.stdapi as stdapi
@@ -105,7 +108,7 @@ class GlTracer(Tracer):
]
arrays.reverse()
- # arrays available in PROFILE_ES1
+ # arrays available in ES1
arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord")
def header(self, api):
@@ -119,13 +122,12 @@ class GlTracer(Tracer):
# Which glVertexAttrib* variant to use
print 'enum vertex_attrib {'
print ' VERTEX_ATTRIB,'
- print ' VERTEX_ATTRIB_ARB,'
print ' VERTEX_ATTRIB_NV,'
print '};'
print
print 'static vertex_attrib _get_vertex_attrib(void) {'
print ' gltrace::Context *ctx = gltrace::getContext();'
- print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {'
+ print ' if (ctx->user_arrays_nv) {'
print ' GLboolean _vertex_program = GL_FALSE;'
print ' _glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &_vertex_program);'
print ' if (_vertex_program) {'
@@ -135,7 +137,6 @@ class GlTracer(Tracer):
print ' return VERTEX_ATTRIB_NV;'
print ' }'
print ' }'
- print ' return VERTEX_ATTRIB_ARB;'
print ' }'
print ' }'
print ' return VERTEX_ATTRIB;'
@@ -152,12 +153,15 @@ class GlTracer(Tracer):
print ' return false;'
print ' }'
print
+ print ' glprofile::Profile profile = ctx->profile;'
+ print ' bool es1 = profile.es() && profile.major == 1;'
+ print
for camelcase_name, uppercase_name in self.arrays:
# in which profile is the array available?
- profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
+ profile_check = 'profile.desktop()'
if camelcase_name in self.arrays_es1:
- profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
+ profile_check = '(' + profile_check + ' || es1)';
function_name = 'gl%sPointer' % camelcase_name
enable_name = 'GL_%s_ARRAY' % uppercase_name
@@ -165,19 +169,17 @@ class GlTracer(Tracer):
print ' // %s' % function_name
print ' if (%s) {' % profile_check
self.array_prolog(api, uppercase_name)
- print ' if (_glIsEnabled(%s)) {' % enable_name
- print ' GLint _binding = _glGetInteger(%s);' % binding_name
- print ' if (!_binding) {'
+ print ' if (_glIsEnabled(%s) &&' % enable_name
+ print ' _glGetInteger(%s) == 0) {' % binding_name
self.array_cleanup(api, uppercase_name)
- print ' return true;'
- print ' }'
+ print ' return true;'
print ' }'
self.array_epilog(api, uppercase_name)
print ' }'
print
print ' // ES1 does not support generic vertex attributes'
- print ' if (ctx->profile == gltrace::PROFILE_ES1)'
+ print ' if (es1)'
print ' return false;'
print
print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
@@ -186,30 +188,9 @@ class GlTracer(Tracer):
print ' if (_vertex_attrib == VERTEX_ATTRIB) {'
print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
- print ' GLint _enabled = 0;'
- print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &_enabled);'
- print ' if (_enabled) {'
- print ' GLint _binding = 0;'
- print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &_binding);'
- print ' if (!_binding) {'
- print ' return true;'
- print ' }'
- print ' }'
- print ' }'
- print ' }'
- print
- print ' // glVertexAttribPointerARB'
- print ' if (_vertex_attrib == VERTEX_ATTRIB_ARB) {'
- print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS_ARB);'
- print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
- print ' GLint _enabled = 0;'
- print ' _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &_enabled);'
- print ' if (_enabled) {'
- print ' GLint _binding = 0;'
- print ' _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &_binding);'
- print ' if (!_binding) {'
- print ' return true;'
- print ' }'
+ print ' if (_glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED) &&'
+ print ' _glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) == 0) {'
+ print ' return true;'
print ' }'
print ' }'
print ' }'
@@ -217,8 +198,7 @@ class GlTracer(Tracer):
print ' // glVertexAttribPointerNV'
print ' if (_vertex_attrib == VERTEX_ATTRIB_NV) {'
print ' for (GLint index = 0; index < 16; ++index) {'
- print ' GLboolean _enabled = _glIsEnabled(GL_VERTEX_ATTRIB_ARRAY0_NV);'
- print ' if (_enabled) {'
+ print ' if (_glIsEnabled(GL_VERTEX_ATTRIB_ARRAY0_NV + index)) {'
print ' return true;'
print ' }'
print ' }'
@@ -229,7 +209,15 @@ class GlTracer(Tracer):
print '}'
print
- print 'static void _trace_user_arrays(GLuint count);'
+ print r'static void _trace_user_arrays(GLuint count);'
+ print
+
+ print r'static void _fakeStringMarker(GLsizei len, const GLvoid * string);'
+ print
+ print r'static inline void'
+ print r'_fakeStringMarker(const std::string &s) {'
+ print r' _fakeStringMarker(s.length(), s.data());'
+ print r'}'
print
print '// whether glLockArraysEXT() has ever been called'
@@ -243,30 +231,6 @@ class GlTracer(Tracer):
print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
print 'static bool _checkBufferFlushingUnmapAPPLE = false;'
print
- # Buffer mapping information, necessary for old Mesa 2.1 drivers which
- # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
- print 'struct buffer_mapping {'
- print ' void *map;'
- print ' GLint length;'
- print ' bool write;'
- print ' bool explicit_flush;'
- print '};'
- print
- for target in self.buffer_targets:
- print 'struct buffer_mapping _%s_mapping;' % target.lower();
- print
- print 'static inline struct buffer_mapping *'
- print 'get_buffer_mapping(GLenum target) {'
- print ' switch (target) {'
- for target in self.buffer_targets:
- print ' case GL_%s:' % target
- print ' return & _%s_mapping;' % target.lower()
- print ' default:'
- print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
- print ' return NULL;'
- print ' }'
- print '}'
- print
# Generate a helper function to determine whether a parameter name
# refers to a symbolic value or not
@@ -298,6 +262,8 @@ class GlTracer(Tracer):
print '_gl_param_size(GLenum pname) {'
print ' switch (pname) {'
for function, type, count, name in glparams.parameters:
+ if name == 'GL_PROGRAM_BINARY_FORMATS':
+ count = 0
if type is not None:
print ' case %s: return %s;' % (name, count)
print ' default:'
@@ -311,10 +277,18 @@ class GlTracer(Tracer):
print 'static inline bool'
print 'can_unpack_subimage(void) {'
print ' gltrace::Context *ctx = gltrace::getContext();'
- print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
+ print ' return ctx->profile.desktop();'
print '}'
print
+ # VMWX_map_buffer_debug
+ print r'extern "C" PUBLIC'
+ print r'void APIENTRY'
+ print r'glNotifyMappedBufferRangeVMWX(const void * start, GLsizeiptr length) {'
+ self.emit_memcpy('start', 'length')
+ print r'}'
+ print
+
getProcAddressFunctionNames = []
def traceApi(self, api):
@@ -349,6 +323,7 @@ class GlTracer(Tracer):
ptype = function_pointer_type(function)
pvalue = function_pointer_value(function)
print ' if (strcmp("%s", (const char *)procName) == 0) {' % function.name
+ print ' assert(procPtr != (%s)&%s);' % (retType, function.name)
print ' %s = (%s)procPtr;' % (pvalue, ptype)
print ' return (%s)&%s;' % (retType, function.name,)
print ' }'
@@ -435,39 +410,8 @@ class GlTracer(Tracer):
#"glMatrixIndexPointerARB",
))
- draw_function_names = set((
- 'glDrawArrays',
- 'glDrawElements',
- 'glDrawRangeElements',
- 'glMultiDrawArrays',
- 'glMultiDrawElements',
- 'glDrawArraysInstanced',
- "glDrawArraysInstancedBaseInstance",
- 'glDrawElementsInstanced',
- 'glDrawArraysInstancedARB',
- 'glDrawElementsInstancedARB',
- 'glDrawElementsBaseVertex',
- 'glDrawRangeElementsBaseVertex',
- 'glDrawElementsInstancedBaseVertex',
- "glDrawElementsInstancedBaseInstance",
- "glDrawElementsInstancedBaseVertexBaseInstance",
- 'glMultiDrawElementsBaseVertex',
- 'glDrawArraysIndirect',
- 'glDrawElementsIndirect',
- 'glMultiDrawArraysIndirect',
- 'glMultiDrawArraysIndirectAMD',
- 'glMultiDrawElementsIndirect',
- 'glMultiDrawElementsIndirectAMD',
- 'glDrawArraysEXT',
- 'glDrawRangeElementsEXT',
- 'glDrawRangeElementsEXT_size',
- 'glMultiDrawArraysEXT',
- 'glMultiDrawElementsEXT',
- 'glMultiModeDrawArraysIBM',
- 'glMultiModeDrawElementsIBM',
- 'glDrawArraysInstancedEXT',
- 'glDrawElementsInstancedEXT',
- ))
+ # XXX: We currently ignore the gl*Draw*ElementArray* functions
+ draw_function_regex = re.compile(r'^gl([A-Z][a-z]+)*Draw(Range)?(Arrays|Elements)([A-Z][a-zA-Z]*)?$' )
interleaved_formats = [
'GL_V2F',
@@ -493,11 +437,9 @@ class GlTracer(Tracer):
print ' if (!_array_buffer) {'
print ' gltrace::Context *ctx = gltrace::getContext();'
print ' ctx->user_arrays = true;'
- if function.name == "glVertexAttribPointerARB":
- print ' ctx->user_arrays_arb = true;'
if function.name == "glVertexAttribPointerNV":
print ' ctx->user_arrays_nv = true;'
- print ' trace::localWriter.updateRegion(pointer);'
+ print ' trace::localWriter.updateRegion(pointer);'
# Warn about buggy glGet(GL_*ARRAY_SIZE) not returning GL_BGRA
buggyFunctions = {
@@ -521,21 +463,35 @@ class GlTracer(Tracer):
print ' }'
# And update the regions on the draw calls
- if function.name in self.draw_function_names:
+ if self.draw_function_regex.match(function.name):
print ' if (_need_user_arrays()) {'
- arg_names = ', '.join([arg.name for arg in function.args[1:]])
- print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
- # Some apps, in particular Quake3, can tell the driver to lock more
- # vertices than those actually required for the draw call.
- print ' if (_checkLockArraysEXT) {'
- print ' GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
- print ' + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
- print ' _count = std::max(_count, _locked_count);'
- print ' }'
- print ' _trace_user_arrays(_count);'
+ if 'Indirect' in function.name:
+ print r' os::log("apitrace: warning: %s: indirect user arrays not supported\n");' % (function.name,)
+ else:
+ arg_names = ', '.join([arg.name for arg in function.args[1:]])
+ print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
+ # Some apps, in particular Quake3, can tell the driver to lock more
+ # vertices than those actually required for the draw call.
+ print ' if (_checkLockArraysEXT) {'
+ print ' GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
+ print ' + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
+ print ' _count = std::max(_count, _locked_count);'
+ print ' }'
+ print ' _trace_user_arrays(_count);'
print ' }'
if function.name == 'glLockArraysEXT':
print ' _checkLockArraysEXT = true;'
+
+ # Warn if user arrays are used with glBegin/glArrayElement/glEnd.
+ if function.name == 'glBegin':
+ print r' gltrace::Context *ctx = gltrace::getContext();'
+ print r' ctx->userArraysOnBegin = _need_user_arrays();'
+ if function.name.startswith('glArrayElement'):
+ print r' gltrace::Context *ctx = gltrace::getContext();'
+ print r' if (ctx->userArraysOnBegin) {'
+ print r' os::log("apitrace: warning: user arrays with glArrayElement not supported (https://github.com/apitrace/apitrace/issues/276)\n");'
+ print r' ctx->userArraysOnBegin = false;'
+ print r' }'
# Emit a fake memcpy on buffer uploads
if function.name == 'glBufferParameteriAPPLE':
@@ -547,19 +503,24 @@ class GlTracer(Tracer):
suffix = 'ARB'
else:
suffix = ''
+ print ' GLint access_flags = 0;'
print ' GLint access = 0;'
- print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
- print ' if (access != GL_READ_ONLY) {'
+ print ' bool flush;'
+ print ' // GLES3 does not have GL_BUFFER_ACCESS;'
+ print ' if (_checkBufferMapRange) {'
+ print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);' % suffix
+ print ' flush = (access_flags & GL_MAP_WRITE_BIT) && !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT));'
+ print ' } else {'
+ print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
+ print ' flush = access != GL_READ_ONLY;'
+ print ' }'
+ print ' if (flush) {'
print ' GLvoid *map = NULL;'
print ' _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
print ' if (map) {'
print ' GLint length = -1;'
- print ' bool flush = true;'
print ' if (_checkBufferMapRange) {'
print ' _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
- print ' GLint access_flags = 0;'
- print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
- print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
print ' if (length == -1) {'
print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
print ' // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
@@ -568,14 +529,6 @@ class GlTracer(Tracer):
print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
print ' warned = true;'
print ' }'
- print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
- print ' if (mapping) {'
- print ' length = mapping->length;'
- print ' flush = flush && !mapping->explicit_flush;'
- print ' } else {'
- print ' length = 0;'
- print ' flush = false;'
- print ' }'
print ' }'
print ' } else {'
print ' length = 0;'
@@ -587,65 +540,129 @@ class GlTracer(Tracer):
print ' flush = flush && flushing_unmap;'
print ' }'
print ' if (flush && length > 0) {'
- self.emit_memcpy('map', 'map', 'length')
+ self.emit_memcpy('map', 'length')
print ' }'
print ' }'
print ' }'
if function.name == 'glUnmapBufferOES':
+ print ' GLint access_flags = 0;'
print ' GLint access = 0;'
- print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
- print ' if (access == GL_WRITE_ONLY_OES) {'
+ print ' bool flush;'
+ print ' // GLES3 does not have GL_BUFFER_ACCESS;'
+ print ' if (_checkBufferMapRange) {'
+ print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
+ print ' flush = (access_flags & GL_MAP_WRITE_BIT) && !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT));'
+ print ' } else {'
+ print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS, &access);'
+ print ' flush = access != GL_READ_ONLY;'
+ print ' }'
+ print ' if (flush) {'
print ' GLvoid *map = NULL;'
- print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
- print ' GLint size = 0;'
- print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
- print ' if (map && size > 0) {'
- self.emit_memcpy('map', 'map', 'size')
- self.shadowBufferMethod('bufferSubData(0, size, map)')
+ print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER, &map);'
+ print ' if (map) {'
+ print ' GLint length = 0;'
+ print ' GLint offset = 0;'
+ print ' if (_checkBufferMapRange) {'
+ print ' _glGetBufferParameteriv(target, GL_BUFFER_MAP_LENGTH, &length);'
+ print ' _glGetBufferParameteriv(target, GL_BUFFER_MAP_OFFSET, &offset);'
+ print ' } else {'
+ print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);'
+ print ' }'
+ print ' if (flush && length > 0) {'
+ self.emit_memcpy('map', 'length')
+ self.shadowBufferMethod('bufferSubData(offset, length, map)')
+ print ' }'
+ print ' }'
+ print ' }'
+ if function.name == 'glUnmapNamedBuffer':
+ print ' GLint access_flags = 0;'
+ print ' _glGetNamedBufferParameteriv(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
+ print ' if ((access_flags & GL_MAP_WRITE_BIT) &&'
+ print ' !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT))) {'
+ print ' GLvoid *map = NULL;'
+ print ' _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
+ print ' GLint length = 0;'
+ print ' _glGetNamedBufferParameteriv(buffer, GL_BUFFER_MAP_LENGTH, &length);'
+ print ' if (map && length > 0) {'
+ self.emit_memcpy('map', 'length')
print ' }'
print ' }'
if function.name == 'glUnmapNamedBufferEXT':
print ' GLint access_flags = 0;'
print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
- print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
+ print ' if ((access_flags & GL_MAP_WRITE_BIT) &&'
+ print ' !(access_flags & (GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT))) {'
print ' GLvoid *map = NULL;'
print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
print ' GLint length = 0;'
print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
print ' if (map && length > 0) {'
- self.emit_memcpy('map', 'map', 'length')
+ self.emit_memcpy('map', 'length')
print ' }'
print ' }'
if function.name == 'glFlushMappedBufferRange':
print ' GLvoid *map = NULL;'
print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
print ' if (map && length > 0) {'
- self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
+ self.emit_memcpy('(const char *)map + offset', 'length')
+ print ' }'
+ if function.name == 'glFlushMappedBufferRangeEXT':
+ print ' GLvoid *map = NULL;'
+ print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
+ print ' if (map && length > 0) {'
+ self.emit_memcpy('(const char *)map + offset', 'length')
print ' }'
if function.name == 'glFlushMappedBufferRangeAPPLE':
print ' GLvoid *map = NULL;'
print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
print ' if (map && size > 0) {'
- self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
+ self.emit_memcpy('(const char *)map + offset', 'size')
+ print ' }'
+ if function.name == 'glFlushMappedNamedBufferRange':
+ print ' GLvoid *map = NULL;'
+ print ' _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
+ print ' if (map && length > 0) {'
+ self.emit_memcpy('(const char *)map + offset', 'length')
print ' }'
if function.name == 'glFlushMappedNamedBufferRangeEXT':
print ' GLvoid *map = NULL;'
print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
print ' if (map && length > 0) {'
- self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
+ self.emit_memcpy('(const char *)map + offset', 'length')
print ' }'
# FIXME: We don't support coherent/pinned memory mappings
- # See https://github.com/apitrace/apitrace/issues/232
- if function.name in ('glBufferStorage', 'glNamedBufferStorageEXT'):
- print r' if (flags & GL_MAP_COHERENT_BIT) {'
- print r' os::log("apitrace: warning: coherent mappings not fully supported\n");'
+ if function.name in ('glBufferStorage', 'glNamedBufferStorage', 'glNamedBufferStorageEXT'):
+ print r' if (!(flags & GL_MAP_PERSISTENT_BIT)) {'
+ print r' os::log("apitrace: warning: %s: MAP_NOTIFY_EXPLICIT_BIT_VMWX set w/o MAP_PERSISTENT_BIT\n", __FUNCTION__);'
+ print r' }'
+ print r' flags &= ~GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX;'
+ if function.name in ('glMapBufferRange', 'glMapBufferRangeEXT', 'glMapNamedBufferRange', 'glMapNamedBufferRangeEXT'):
+ print r' if (access & GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX) {'
+ print r' if (!(access & GL_MAP_PERSISTENT_BIT)) {'
+ print r' os::log("apitrace: warning: %s: MAP_NOTIFY_EXPLICIT_BIT_VMWX set w/o MAP_PERSISTENT_BIT\n", __FUNCTION__);'
+ print r' }'
+ print r' if (access & GL_MAP_FLUSH_EXPLICIT_BIT) {'
+ print r' os::log("apitrace: warning: %s: MAP_NOTIFY_EXPLICIT_BIT_VMWX set w/ MAP_FLUSH_EXPLICIT_BIT\n", __FUNCTION__);'
+ print r' }'
+ print r' access &= ~GL_MAP_NOTIFY_EXPLICIT_BIT_VMWX;'
+ print r' } else if (access & GL_MAP_COHERENT_BIT) {'
+ print r' os::log("apitrace: warning: %s: MAP_COHERENT_BIT unsupported (https://github.com/apitrace/apitrace/issues/232)\n", __FUNCTION__);'
+ print r' } else if ((access & GL_MAP_PERSISTENT_BIT) &&'
+ print r' !(access & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
+ print r' os::log("apitrace: warning: %s: MAP_PERSISTENT_BIT w/o FLUSH_EXPLICIT_BIT unsupported (https://github.com/apitrace/apitrace/issues/232)\n", __FUNCTION__);'
print r' }'
if function.name in ('glBufferData', 'glBufferDataARB'):
print r' if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
print r' os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
print r' }'
+ # TODO: We don't track GL_INTEL_map_texture mappings
+ if function.name == 'glMapTexture2DINTEL':
+ print r' if (access & GL_MAP_WRITE_BIT) {'
+ print r' os::log("apitrace: warning: GL_INTEL_map_texture not fully supported\n");'
+ print r' }'
+
# Don't leave vertex attrib locations to chance. Instead emit fake
# glBindAttribLocation calls to ensure that the same locations will be
# used when retracing. Trying to remap locations after the fact would
@@ -699,10 +716,6 @@ class GlTracer(Tracer):
'glStringMarkerGREMEDY',
# GL_GREMEDY_frame_terminator
'glFrameTerminatorGREMEDY',
- # GL_EXT_debug_marker
- 'glInsertEventMarkerEXT',
- 'glPushGroupMarkerEXT',
- 'glPopGroupMarkerEXT',
]
# These entrypoints may be implemented by drivers, but are also very useful
@@ -719,6 +732,17 @@ class GlTracer(Tracer):
'glGetObjectLabel',
'glObjectPtrLabel',
'glGetObjectPtrLabel',
+ # GL_KHR_debug (for OpenGL ES)
+ 'glDebugMessageControlKHR',
+ 'glDebugMessageInsertKHR',
+ 'glDebugMessageCallbackKHR',
+ 'glGetDebugMessageLogKHR',
+ 'glPushDebugGroupKHR',
+ 'glPopDebugGroupKHR',
+ 'glObjectLabelKHR',
+ 'glGetObjectLabelKHR',
+ 'glObjectPtrLabelKHR',
+ 'glGetObjectPtrLabelKHR',
# GL_ARB_debug_output
'glDebugMessageControlARB',
'glDebugMessageInsertARB',
@@ -729,6 +753,13 @@ class GlTracer(Tracer):
'glDebugMessageInsertAMD',
'glDebugMessageCallbackAMD',
'glGetDebugMessageLogAMD',
+ # GL_EXT_debug_label
+ 'glLabelObjectEXT',
+ 'glGetObjectLabelEXT',
+ # GL_EXT_debug_marker
+ 'glInsertEventMarkerEXT',
+ 'glPushGroupMarkerEXT',
+ 'glPopGroupMarkerEXT',
]
def invokeFunction(self, function):
@@ -736,6 +767,13 @@ class GlTracer(Tracer):
# These functions have been dispatched already
return
+ # Force glProgramBinary to fail. Per ARB_get_program_binary this
+ # should signal the app that it needs to recompile.
+ if function.name in ('glProgramBinary', 'glProgramBinaryOES'):
+ print r' binaryFormat = 0xDEADDEAD;'
+ print r' binary = &binaryFormat;'
+ print r' length = sizeof binaryFormat;'
+
Tracer.invokeFunction(self, function)
def doInvokeFunction(self, function):
@@ -748,8 +786,7 @@ class GlTracer(Tracer):
Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
return
- # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
- # driver
+ # We implement GL_GREMEDY_*, etc., and not the driver
if function.name in self.marker_functions:
return
@@ -763,14 +800,14 @@ class GlTracer(Tracer):
print ' }'
if function.name in self.getProcAddressFunctionNames:
- else_ = ''
+ nameArg = function.args[0].name
+ print ' if (strcmp("glNotifyMappedBufferRangeVMWX", (const char *)%s) == 0) {' % (nameArg,)
+ print ' _result = (%s)&glNotifyMappedBufferRangeVMWX;' % (function.type,)
for marker_function in self.marker_functions:
if self.api.getFunctionByName(marker_function):
- print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
+ print ' } else if (strcmp("%s", (const char *)%s) == 0) {' % (marker_function, nameArg)
print ' _result = (%s)&%s;' % (function.type, marker_function)
- print ' }'
- else_ = 'else '
- print ' %s{' % else_
+ print ' } else {'
Tracer.doInvokeFunction(self, function)
# Replace function addresses with ours
@@ -778,13 +815,25 @@ class GlTracer(Tracer):
# contain the addresses of the wrapper functions, and not the real
# functions, but in practice this should make no difference.
if function.name in self.getProcAddressFunctionNames:
- print ' _result = _wrapProcAddress(%s, _result);' % (function.args[0].name,)
+ print ' _result = _wrapProcAddress(%s, _result);' % (nameArg,)
print ' }'
return
+ if function.name in ('glGetProgramBinary', 'glGetProgramBinaryOES'):
+ print r' bufSize = 0;'
+
Tracer.doInvokeFunction(self, function)
+ if function.name == 'glGetProgramiv':
+ print r' if (params && pname == GL_PROGRAM_BINARY_LENGTH) {'
+ print r' *params = 0;'
+ print r' }'
+ if function.name in ('glGetProgramBinary', 'glGetProgramBinaryOES'):
+ print r' if (length) {'
+ print r' *length = 0;'
+ print r' }'
+
buffer_targets = [
'ARRAY_BUFFER',
'ELEMENT_ARRAY_BUFFER',
@@ -803,26 +852,10 @@ class GlTracer(Tracer):
Tracer.wrapRet(self, function, instance)
# Keep track of buffer mappings
- if function.name in ('glMapBuffer', 'glMapBufferARB'):
- print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
- print ' if (mapping) {'
- print ' mapping->map = %s;' % (instance)
- print ' mapping->length = 0;'
- print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
- print ' mapping->write = (access != GL_READ_ONLY);'
- print ' mapping->explicit_flush = false;'
- print ' }'
- if function.name == 'glMapBufferRange':
+ if function.name in ('glMapBufferRange', 'glMapBufferRangeEXT'):
print ' if (access & GL_MAP_WRITE_BIT) {'
print ' _checkBufferMapRange = true;'
print ' }'
- print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
- print ' if (mapping) {'
- print ' mapping->map = %s;' % (instance)
- print ' mapping->length = length;'
- print ' mapping->write = access & GL_MAP_WRITE_BIT;'
- print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
- print ' }'
boolean_names = [
'GL_FALSE',
@@ -832,80 +865,28 @@ class GlTracer(Tracer):
def gl_boolean(self, value):
return self.boolean_names[int(bool(value))]
- # Names of the functions that unpack from a pixel buffer object. See the
- # ARB_pixel_buffer_object specification.
- unpack_function_names = set([
- 'glBitmap',
- 'glColorSubTable',
- 'glColorTable',
- 'glCompressedMultiTexImage1DEXT',
- 'glCompressedMultiTexImage2DEXT',
- 'glCompressedMultiTexImage3DEXT',
- 'glCompressedMultiTexSubImage1DEXT',
- 'glCompressedMultiTexSubImage2DEXT',
- 'glCompressedMultiTexSubImage3DEXT',
- 'glCompressedTexImage1D',
- 'glCompressedTexImage1DARB',
- 'glCompressedTexImage2D',
- 'glCompressedTexImage2DARB',
- 'glCompressedTexImage3D',
- 'glCompressedTexImage3DARB',
- 'glCompressedTexSubImage1D',
- 'glCompressedTexSubImage1DARB',
- 'glCompressedTexSubImage2D',
- 'glCompressedTexSubImage2DARB',
- 'glCompressedTexSubImage3D',
- 'glCompressedTexSubImage3DARB',
- 'glCompressedTextureImage1DEXT',
- 'glCompressedTextureImage2DEXT',
- 'glCompressedTextureImage3DEXT',
- 'glCompressedTextureSubImage1DEXT',
- 'glCompressedTextureSubImage2DEXT',
- 'glCompressedTextureSubImage3DEXT',
- 'glConvolutionFilter1D',
- 'glConvolutionFilter2D',
- 'glDrawPixels',
- 'glMultiTexImage1DEXT',
- 'glMultiTexImage2DEXT',
- 'glMultiTexImage3DEXT',
- 'glMultiTexSubImage1DEXT',
- 'glMultiTexSubImage2DEXT',
- 'glMultiTexSubImage3DEXT',
- 'glPixelMapfv',
- 'glPixelMapuiv',
- 'glPixelMapusv',
- 'glPolygonStipple',
- 'glSeparableFilter2D',
- 'glTexImage1D',
- 'glTexImage1DEXT',
- 'glTexImage2D',
- 'glTexImage2DEXT',
- 'glTexImage3D',
- 'glTexImage3DEXT',
- 'glTexSubImage1D',
- 'glTexSubImage1DEXT',
- 'glTexSubImage2D',
- 'glTexSubImage2DEXT',
- 'glTexSubImage3D',
- 'glTexSubImage3DEXT',
- 'glTextureImage1DEXT',
- 'glTextureImage2DEXT',
- 'glTextureImage3DEXT',
- 'glTextureSubImage1DEXT',
- 'glTextureSubImage2DEXT',
- 'glTextureSubImage3DEXT',
- ])
+ # Regular expression for the names of the functions that unpack from a
+ # pixel buffer object. See the ARB_pixel_buffer_object specification.
+ unpack_function_regex = re.compile(r'^gl(' + r'|'.join([
+ r'Bitmap',
+ r'PolygonStipple',
+ r'PixelMap[a-z]+v',
+ r'DrawPixels',
+ r'Color(Sub)?Table',
+ r'(Convolution|Separable)Filter[12]D',
+ r'(Compressed)?(Multi)?Tex(ture)?(Sub)?Image[1-4]D',
+ ]) + r')[0-9A-Z]*$')
def serializeArgValue(self, function, arg):
# Recognize offsets instead of blobs when a PBO is bound
- if function.name in self.unpack_function_names \
+ if self.unpack_function_regex.match(function.name) \
and (isinstance(arg.type, stdapi.Blob) \
or (isinstance(arg.type, stdapi.Const) \
and isinstance(arg.type.type, stdapi.Blob))):
print ' {'
print ' gltrace::Context *ctx = gltrace::getContext();'
print ' GLint _unpack_buffer = 0;'
- print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
+ print ' if (ctx->profile.desktop())'
print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
print ' if (_unpack_buffer) {'
print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
@@ -941,6 +922,9 @@ class GlTracer(Tracer):
print '{'
print ' gltrace::Context *ctx = gltrace::getContext();'
print
+ print ' glprofile::Profile profile = ctx->profile;'
+ print ' bool es1 = profile.es() && profile.major == 1;'
+ print
# Temporarily unbind the array buffer
print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
@@ -951,9 +935,9 @@ class GlTracer(Tracer):
for camelcase_name, uppercase_name in self.arrays:
# in which profile is the array available?
- profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
+ profile_check = 'profile.desktop()'
if camelcase_name in self.arrays_es1:
- profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
+ profile_check = '(' + profile_check + ' || es1)';
function_name = 'gl%sPointer' % camelcase_name
enable_name = 'GL_%s_ARRAY' % uppercase_name
@@ -996,12 +980,12 @@ class GlTracer(Tracer):
# alias, and they need to be considered independently.
#
print ' // ES1 does not support generic vertex attributes'
- print ' if (ctx->profile == gltrace::PROFILE_ES1)'
+ print ' if (es1)'
print ' return;'
print
print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
print
- for suffix in ['', 'ARB', 'NV']:
+ for suffix in ['', 'NV']:
if suffix:
SUFFIX = '_' + suffix
else:
@@ -1042,7 +1026,7 @@ class GlTracer(Tracer):
print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
# Emit a fake function
- print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
+ print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
for arg in function.args:
assert not arg.output
print ' trace::localWriter.beginArg(%u);' % (arg.index,)
@@ -1070,6 +1054,12 @@ class GlTracer(Tracer):
print '}'
print
+ # Fake glStringMarkerGREMEDY
+ print r'static void _fakeStringMarker(GLsizei len, const GLvoid * string) {'
+ glStringMarkerGREMEDY = api.getFunctionByName('glStringMarkerGREMEDY')
+ self.fake_call(glStringMarkerGREMEDY, ['len', 'string'])
+ print r'}'
+
#
# Hooks for glTexCoordPointer, which is identical to the other array
# pointers except the fact that it is indexed by glClientActiveTexture.
@@ -1077,24 +1067,32 @@ class GlTracer(Tracer):
def array_prolog(self, api, uppercase_name):
if uppercase_name == 'TEXTURE_COORD':
- print ' GLint client_active_texture = _glGetInteger(GL_CLIENT_ACTIVE_TEXTURE);'
- print ' GLint max_texture_coords = 0;'
- print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
- print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
+ print ' GLint max_units = 0;'
+ print ' if (ctx->profile.desktop())'
+ print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_units);'
print ' else'
- print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
- print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
+ print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_units);'
+ print ' GLint client_active_texture = GL_TEXTURE0;'
+ print ' if (max_units > 0) {'
+ print ' _glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
+ print ' }'
+ print ' GLint unit = 0;'
+ print ' do {'
print ' GLint texture = GL_TEXTURE0 + unit;'
- print ' _glClientActiveTexture(texture);'
+ print ' if (max_units > 0) {'
+ print ' _glClientActiveTexture(texture);'
+ print ' }'
def array_epilog(self, api, uppercase_name):
if uppercase_name == 'TEXTURE_COORD':
- print ' }'
+ print ' } while (++unit < max_units);'
self.array_cleanup(api, uppercase_name)
def array_cleanup(self, api, uppercase_name):
if uppercase_name == 'TEXTURE_COORD':
- print ' _glClientActiveTexture(client_active_texture);'
+ print ' if (max_units > 0) {'
+ print ' _glClientActiveTexture(client_active_texture);'
+ print ' }'
def fake_glBindBuffer(self, api, target, buffer):
function = api.getFunctionByName('glBindBuffer')
@@ -1103,7 +1101,7 @@ class GlTracer(Tracer):
def emitFakeTexture2D(self):
function = glapi.glapi.getFunctionByName('glTexImage2D')
instances = function.argNames()
- print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
+ print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
for arg in function.args:
assert not arg.output
self.serializeArg(function, arg)
diff --git a/wrappers/gltrace_state.cpp b/wrappers/gltrace_state.cpp
index f2c4e42a..4ef095bd 100644
--- a/wrappers/gltrace_state.cpp
+++ b/wrappers/gltrace_state.cpp
@@ -28,9 +28,6 @@
#include <assert.h>
#include <map>
-#if defined(HAVE_TR1_MEMORY)
-#include <tr1/memory>
-#endif
#include <memory>
#include <os_thread.hpp>
@@ -39,11 +36,7 @@
namespace gltrace {
-#if !defined(HAVE_TR1_MEMORY)
typedef std::shared_ptr<Context> context_ptr_t;
-#else
-typedef std::tr1::shared_ptr<Context> context_ptr_t;
-#endif
static std::map<uintptr_t, context_ptr_t> context_map;
static os::recursive_mutex context_map_mutex;
@@ -148,6 +141,8 @@ void setContext(uintptr_t context_id)
ts->current_context = ctx;
if (!ctx->bound) {
+ ctx->profile = glprofile::getCurrentContextProfile();
+
/*
* The default viewport and scissor state is set when a context is
* first made current, with values matching the bound drawable. Many
diff --git a/wrappers/glxtrace.py b/wrappers/glxtrace.py
index c61b937d..e9c43a9c 100644
--- a/wrappers/glxtrace.py
+++ b/wrappers/glxtrace.py
@@ -32,7 +32,6 @@ from gltrace import GlTracer
from specs.stdapi import Module, API
from specs.glapi import glapi
from specs.glxapi import glxapi
-from specs.glesapi import glesapi
class GlxTracer(GlTracer):
@@ -175,7 +174,6 @@ if __name__ == '__main__':
module = Module()
module.mergeModule(glxapi)
module.mergeModule(glapi)
- module.mergeModule(glesapi)
api = API()
api.addModule(module)
tracer = GlxTracer()
diff --git a/wrappers/glxtrace.version b/wrappers/glxtrace.version
new file mode 100644
index 00000000..7d7a1624
--- /dev/null
+++ b/wrappers/glxtrace.version
@@ -0,0 +1,9 @@
+{
+ global:
+ _init;
+ _fini;
+ gl[A-Z]*;
+ dlopen;
+ local:
+ *;
+};
diff --git a/wrappers/trace.py b/wrappers/trace.py
index bf11fe37..c1504cd7 100644
--- a/wrappers/trace.py
+++ b/wrappers/trace.py
@@ -31,6 +31,7 @@ import os.path
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
+import itertools
import specs.stdapi as stdapi
@@ -39,6 +40,8 @@ def getWrapperInterfaceName(interface):
return "Wrap" + interface.expr
+debug = False
+
class ComplexValueSerializer(stdapi.OnceVisitor):
'''Type visitors which generates serialization functions for
@@ -64,7 +67,8 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
self.visit(const.type)
def visitStruct(self, struct):
- print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
+ # Ensure member array has nonzero length to avoid MSVC error C2466
+ print 'static const char * _struct%s_members[%u] = {' % (struct.tag, max(len(struct.members), 1))
for type, name, in struct.members:
if name is None:
print ' "",'
@@ -146,7 +150,7 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
for cases, type in polymorphic.iterSwitch():
for case in cases:
print ' %s:' % case
- self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
+ self.serializer.visit(type, '(%s)(value)' % (type,))
print ' break;'
print ' }'
print '}'
@@ -347,7 +351,7 @@ class WrapDecider(stdapi.Traverser):
def visitLinearPointer(self, void):
pass
- def visitInterface(self, interface):
+ def visitObjPointer(self, interface):
self.needsWrapping = True
@@ -382,15 +386,14 @@ class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
self.visitInterfacePointer(elem_type.type, instance)
else:
- self.visitPointer(pointer, instance)
+ # All interfaces should at least implement IUnknown
+ print " WrapIUnknown::_wrap(__FUNCTION__, (IUnknown **) &%s);" % (instance,)
def visitInterface(self, interface, instance):
raise NotImplementedError
def visitInterfacePointer(self, interface, instance):
- print " if (%s) {" % instance
- print " %s = %s::_Create(__FUNCTION__, %s);" % (instance, getWrapperInterfaceName(interface), instance)
- print " }"
+ print " Wrap%s::_wrap(__FUNCTION__, &%s);" % (interface.name, instance)
def visitPolymorphic(self, type, instance):
# XXX: There might be polymorphic values that need wrapping in the future
@@ -435,14 +438,19 @@ class ValueUnwrapper(ValueWrapper):
print " }"
def visitInterfacePointer(self, interface, instance):
- print r' if (%s) {' % instance
- print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
- print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
- print r' %s = pWrapper->m_pInstance;' % (instance,)
- print r' } else {'
- print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
- print r' }'
- print r' }'
+ print r' Wrap%s::_unwrap(__FUNCTION__, &%s);' % (interface.name, instance)
+
+
+def _getInterfaceHierarchy(allIfaces, baseIface, result):
+ for iface in allIfaces:
+ if iface.base is baseIface:
+ _getInterfaceHierarchy(allIfaces, iface, result)
+ result.append(iface)
+
+def getInterfaceHierarchy(allIfaces, baseIface):
+ result = []
+ _getInterfaceHierarchy(allIfaces, baseIface, result)
+ return result
class Tracer:
@@ -488,7 +496,11 @@ class Tracer:
for function in api.getAllFunctions():
self.traceFunctionDecl(function)
for function in api.getAllFunctions():
- self.traceFunctionImpl(function)
+ try:
+ self.traceFunctionImpl(function)
+ except:
+ sys.stderr.write("error: %s: exception\n" % function.name)
+ raise
print
self.footer(api)
@@ -537,9 +549,17 @@ class Tracer:
if function.type is not stdapi.Void:
print ' %s _result;' % function.type
+ for arg in function.args:
+ if not arg.output:
+ self.unwrapArg(function, arg)
+
self.traceFunctionImplBody(function)
+
+ # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
+
if function.type is not stdapi.Void:
print ' return _result;'
+
print '}'
print
@@ -548,9 +568,6 @@ class Tracer:
print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
for arg in function.args:
if not arg.output:
- self.unwrapArg(function, arg)
- for arg in function.args:
- if not arg.output:
self.serializeArg(function, arg)
print ' trace::localWriter.endEnter();'
self.invokeFunction(function)
@@ -604,6 +621,7 @@ class Tracer:
if not other_arg.output and other_arg.type is REFIID:
riid = other_arg
if riid is not None \
+ and riid.name != 'EmulatedInterface' \
and isinstance(arg.type, stdapi.Pointer) \
and isinstance(arg.type.type, stdapi.ObjPointer):
self.wrapIid(function, riid, arg)
@@ -645,31 +663,69 @@ class Tracer:
interfaces = api.getAllInterfaces()
if not interfaces:
return
+
+ print r'#include "guids.hpp"'
+ print
+
map(self.declareWrapperInterface, interfaces)
+
+ # Helper functions to wrap/unwrap interface pointers
+ print r'static inline bool'
+ print r'hasChildInterface(REFIID riid, IUnknown *pUnknown) {'
+ print r' IUnknown *pObj = NULL;'
+ print r' HRESULT hr = pUnknown->QueryInterface(riid, (VOID **)&pObj);'
+ print r' if (FAILED(hr)) {'
+ print r' return false;'
+ print r' }'
+ print r' assert(pObj);'
+ print r' pObj->Release();'
+ print r' return pUnknown == pObj;'
+ print r'}'
+ print
+ print r'static inline const void *'
+ print r'getVtbl(const void *pvObj) {'
+ print r' return pvObj ? *(const void **)pvObj : NULL;'
+ print r'}'
+ print
+
self.implementIidWrapper(api)
+
map(self.implementWrapperInterface, interfaces)
print
def declareWrapperInterface(self, interface):
- print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
+ wrapperInterfaceName = getWrapperInterfaceName(interface)
+ print "class %s : public %s " % (wrapperInterfaceName, interface.name)
print "{"
print "private:"
- print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
- print " virtual ~%s();" % getWrapperInterfaceName(interface)
+ print " %s(%s * pInstance);" % (wrapperInterfaceName, interface.name)
+ print " virtual ~%s();" % wrapperInterfaceName
print "public:"
- print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
+ print " static %s* _create(const char *entryName, %s * pInstance);" % (wrapperInterfaceName, interface.name)
+ print " static void _wrap(const char *entryName, %s ** ppInstance);" % (interface.name,)
+ print " static void _unwrap(const char *entryName, %s ** pInstance);" % (interface.name,)
print
- for method in interface.iterMethods():
+
+ methods = list(interface.iterMethods())
+ for method in methods:
print " " + method.prototype() + ";"
print
- #print "private:"
+
for type, name, value in self.enumWrapperInterfaceVariables(interface):
print ' %s %s;' % (type, name)
- for i in range(64):
- print r' virtual void _dummy%i(void) const {' % i
- print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
- print r' os::abort();'
- print r' }'
+ print
+
+ print r'private:'
+ print r' void _dummy(unsigned i) const {'
+ print r' os::log("error: %%s: unexpected virtual method %%i of instance pWrapper=%%p pvObj=%%p pVtbl=%%p\n", "%s", i, this, m_pInstance, m_pVtbl);' % interface.name
+ print r' trace::localWriter.flush();'
+ print r' os::abort();'
+ print r' }'
+ print
+ for i in range(len(methods), 64):
+ print r' virtual void _dummy%i(void) const { _dummy(%i); }' % (i, i)
+ print
+
print "};"
print
@@ -677,68 +733,122 @@ class Tracer:
return [
("DWORD", "m_dwMagic", "0xd8365d6c"),
("%s *" % interface.name, "m_pInstance", "pInstance"),
- ("void *", "m_pVtbl", "*(void **)pInstance"),
+ ("const void *", "m_pVtbl", "getVtbl(pInstance)"),
("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
]
- def implementWrapperInterface(self, interface):
- self.interface = interface
+ def implementWrapperInterface(self, iface):
+ self.interface = iface
+
+ wrapperInterfaceName = getWrapperInterfaceName(iface)
# Private constructor
- print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
- for type, name, value in self.enumWrapperInterfaceVariables(interface):
+ print '%s::%s(%s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
+ for type, name, value in self.enumWrapperInterfaceVariables(iface):
if value is not None:
print ' %s = %s;' % (name, value)
print '}'
print
# Public constructor
- print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
- print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
- print r' if (it != g_WrappedObjects.end()) {'
- print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
- print r' assert(pWrapper);'
- print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
- print r' assert(pWrapper->m_pInstance == pInstance);'
- print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
- print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
- #print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
- print r' return pWrapper;'
- print r' }'
- print r' }'
- print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
- #print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
+ print '%s *%s::_create(const char *entryName, %s * pInstance) {' % (wrapperInterfaceName, wrapperInterfaceName, iface.name)
+ print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (iface.name, iface.name)
+ if debug:
+ print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", entryName, pInstance, pWrapper, pWrapper->m_pVtbl);' % iface.name
print r' g_WrappedObjects[pInstance] = pWrapper;'
print r' return pWrapper;'
print '}'
print
# Destructor
- print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
- #print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
+ print '%s::~%s() {' % (wrapperInterfaceName, wrapperInterfaceName)
+ if debug:
+ print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % iface.name
print r' g_WrappedObjects.erase(m_pInstance);'
print '}'
print
- for base, method in interface.iterBaseMethods():
+ baseMethods = list(iface.iterBaseMethods())
+ for base, method in baseMethods:
self.base = base
- self.implementWrapperInterfaceMethod(interface, base, method)
+ self.implementWrapperInterfaceMethod(iface, base, method)
print
+ # Wrap pointer
+ ifaces = self.api.getAllInterfaces()
+ print r'void'
+ print r'%s::_wrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
+ print r' if (!ppObj) {'
+ print r' return;'
+ print r' }'
+ print r' %s *pObj = *ppObj;' % (iface.name,)
+ print r' if (!pObj) {'
+ print r' return;'
+ print r' }'
+ print r' assert(hasChildInterface(IID_%s, pObj));' % iface.name
+ print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pObj);'
+ print r' if (it != g_WrappedObjects.end()) {'
+ print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (iface.name, iface.name)
+ print r' assert(pWrapper);'
+ print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
+ print r' assert(pWrapper->m_pInstance == pObj);'
+ print r' if (pWrapper->m_pVtbl == getVtbl(pObj) &&'
+ print r' pWrapper->m_NumMethods >= %s) {' % len(baseMethods)
+ if debug:
+ print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", entryName, pObj, pWrapper, pWrapper->m_pVtbl);'
+ print r' *ppObj = pWrapper;'
+ print r' return;'
+ print r' }'
+ print r' }'
+ for childIface in getInterfaceHierarchy(ifaces, iface):
+ print r' if (hasChildInterface(IID_%s, pObj)) {' % (childIface.name,)
+ print r' *ppObj = Wrap%s::_create(entryName, static_cast<%s *>(pObj));' % (childIface.name, childIface.name)
+ print r' return;'
+ print r' }'
+ print r' *ppObj = Wrap%s::_create(entryName, pObj);' % iface.name
+ print r'}'
+ print
+
+ # Unwrap pointer
+ print r'void'
+ print r'%s::_unwrap(const char *entryName, %s **ppObj) {' % (wrapperInterfaceName, iface.name)
+ print r' if (!ppObj || !*ppObj) {'
+ print r' return;'
+ print r' }'
+ print r' const %s *pWrapper = static_cast<const %s*>(*ppObj);' % (wrapperInterfaceName, getWrapperInterfaceName(iface))
+ print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
+ print r' *ppObj = pWrapper->m_pInstance;'
+ print r' } else {'
+ print r' os::log("apitrace: warning: %%s: unexpected %%s pointer %%p\n", entryName, "%s", *ppObj);' % iface.name
+ print r' trace::localWriter.flush();'
+ print r' }'
+ print r'}'
+ print
+
def implementWrapperInterfaceMethod(self, interface, base, method):
- print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
+ wrapperInterfaceName = getWrapperInterfaceName(interface)
+
+ print method.prototype(wrapperInterfaceName + '::' + method.name) + ' {'
if False:
- print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
+ print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (wrapperInterfaceName + '::' + method.name)
if method.type is not stdapi.Void:
print ' %s _result;' % method.type
+ print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
+ for arg in method.args:
+ if not arg.output:
+ self.unwrapArg(method, arg)
+
self.implementWrapperInterfaceMethodBody(interface, base, method)
-
+
+ # XXX: wrapping should go here, but before we can do that we'll need to protect g_WrappedObjects with its own mutex
+
if method.type is not stdapi.Void:
print ' return _result;'
+
print '}'
print
@@ -748,17 +858,12 @@ class Tracer:
print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1)
- print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
-
print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
print ' trace::localWriter.beginArg(0);'
print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
print ' trace::localWriter.endArg();'
for arg in method.args:
if not arg.output:
- self.unwrapArg(method, arg)
- for arg in method.args:
- if not arg.output:
self.serializeArg(method, arg)
print ' trace::localWriter.endEnter();'
@@ -787,28 +892,42 @@ class Tracer:
print ' trace::localWriter.endLeave();'
def implementIidWrapper(self, api):
+ ifaces = api.getAllInterfaces()
+
print r'static void'
- print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
- print r' os::log("apitrace: warning: %s: %s IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
- print r' functionName, reason,'
- print r' riid.Data1, riid.Data2, riid.Data3,'
- print r' riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);'
+ print r'warnIID(const char *entryName, REFIID riid, void *pvObj, const char *reason) {'
+ print r' os::log("apitrace: warning: %s: %s IID %s\n",'
+ print r' entryName, reason,'
+ print r' getGuidName(riid));'
+ print r' void * pVtbl = *(void **)pvObj;'
+ print r' HMODULE hModule = 0;'
+ print r' BOOL bRet = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |'
+ print r' GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,'
+ print r' (LPCTSTR)pVtbl,'
+ print r' &hModule);'
+ print r' assert(bRet);'
+ print r' if (bRet) {'
+ print r' char szModule[MAX_PATH];'
+ print r' DWORD dwRet = GetModuleFileNameA(hModule, szModule, sizeof szModule);'
+ print r' assert(dwRet);'
+ print r' if (dwRet) {'
+ print r' DWORD dwOffset = (UINT_PTR)pVtbl - (UINT_PTR)hModule;'
+ print r' os::log("apitrace: warning: pVtbl = %p (%s!+0x%0lx)\n", pVtbl, szModule, dwOffset);'
+ print r' }'
+ print r' }'
print r'}'
print
print r'static void'
- print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
+ print r'wrapIID(const char *entryName, REFIID riid, void * * ppvObj) {'
print r' if (!ppvObj || !*ppvObj) {'
print r' return;'
print r' }'
- else_ = ''
- for iface in api.getAllInterfaces():
- print r' %sif (riid == IID_%s) {' % (else_, iface.name)
- print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
+ for iface in ifaces:
+ print r' if (riid == IID_%s) {' % (iface.name,)
+ print r' Wrap%s::_wrap(entryName, (%s **) ppvObj);' % (iface.name, iface.name)
+ print r' return;'
print r' }'
- else_ = 'else '
- print r' %s{' % else_
- print r' warnIID(functionName, riid, "unknown");'
- print r' }'
+ print r' warnIID(entryName, riid, *ppvObj, "unsupported");'
print r'}'
print
@@ -842,23 +961,12 @@ class Tracer:
result = '_result = '
print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
- def emit_memcpy(self, dest, src, length):
- print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig, true);'
- print ' trace::localWriter.beginArg(0);'
- print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
- print ' trace::localWriter.endArg();'
- print ' trace::localWriter.beginArg(1);'
- print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
- print ' trace::localWriter.endArg();'
- print ' trace::localWriter.beginArg(2);'
- print ' trace::localWriter.writeUInt(%s);' % length
- print ' trace::localWriter.endArg();'
- print ' trace::localWriter.endEnter();'
- print ' trace::localWriter.beginLeave(_call);'
- print ' trace::localWriter.endLeave();'
+ def emit_memcpy(self, ptr, size):
+ print ' trace::fakeMemcpy(%s, %s);' % (ptr, size)
def fake_call(self, function, args):
- print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
+ print ' {'
+ print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
for arg, instance in zip(function.args, args):
assert not arg.output
print ' trace::localWriter.beginArg(%u);' % (arg.index,)
@@ -867,4 +975,5 @@ class Tracer:
print ' trace::localWriter.endEnter();'
print ' trace::localWriter.beginLeave(_fake_call);'
print ' trace::localWriter.endLeave();'
+ print ' }'
diff --git a/wrappers/wgltrace.py b/wrappers/wgltrace.py
index bc79d774..29081bde 100644
--- a/wrappers/wgltrace.py
+++ b/wrappers/wgltrace.py
@@ -83,6 +83,149 @@ class WglTracer(GlTracer):
print ' }'
print ' gltrace::releaseContext((uintptr_t)hglrc);'
+ # Emit fake glBitmap calls in the trace on wglUseFontBitmapsA.
+ # This enables to capture the real bitmaps and replay them outside Windows.
+ #
+ # XXX: In spite what
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/dd374392.aspx
+ # implies, GetGlyphOutline(GGO_BITMAP) does not seem to work with
+ # certain fonts. The only solution is to draw the font charactors with
+ # a HBITMAP like the old Mesa fxwgl.c code used to do. That too, seems
+ # to be the way that opengl32.dll implements wglUseFontBitmaps.
+ #
+ if function.name == 'wglUseFontBitmapsA':
+
+ self.invokeFunction(function)
+
+ # Emit a fake string marker with the original call
+ print r' {'
+ print r' std::ostringstream ss;'
+ print r' ss << __FUNCTION__ << "(hdc = " << hdc << ", first = " << first << ", count = " << count << ", listBase = " << listBase << ") = " << (_result ? "TRUE" : "FALSE");'
+ print r' _fakeStringMarker(ss.str());'
+ print r' }'
+ print
+
+ glNewList = glapi.getFunctionByName('glNewList')
+ glBitmap = glapi.getFunctionByName('glBitmap')
+ glEndList = glapi.getFunctionByName('glEndList')
+
+ print r' if (_result) {'
+
+ print r' HFONT hFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);'
+ print r' assert (hFont != nullptr);'
+ print r' LOGFONT lf;'
+ print r' if (GetObject(hFont, sizeof lf, &lf) != 0) {'
+ print r' std::ostringstream ss;'
+ print r' ss << "lfFaceName = " << lf.lfFaceName'
+ print r' << ", lfHeight = " << lf.lfHeight'
+ print r' << ", lfWeight = " << lf.lfWeight;'
+ print r' if (lf.lfItalic) ss << ", lfItalic = 1";'
+ print r' if (lf.lfUnderline) ss << ", lfUnderline = 1";'
+ print r' if (lf.lfStrikeOut) ss << ", lfStrikeOut = 1";'
+ print r' _fakeStringMarker(ss.str());'
+ print r' }'
+ print
+
+ print r' BOOL bRet;'
+ print r' TEXTMETRIC tm;'
+ print r' bRet = GetTextMetricsA(hdc, &tm);'
+ print r' assert(bRet);'
+ print
+ print r' HDC memDC = CreateCompatibleDC(hdc);'
+ print
+ print r' SetMapMode(memDC, MM_TEXT);'
+ print r' SetTextAlign(memDC, TA_BASELINE);'
+ print r' SetBkColor(memDC, RGB(0, 0, 0));'
+ print r' SetBkMode(memDC, OPAQUE);'
+ print r' SetTextColor(memDC, RGB(255,255,255));'
+ print
+ print r' BITMAPINFO * bmi = (BITMAPINFO *)malloc(offsetof(BITMAPINFO, bmiColors[2]));'
+ print r' ZeroMemory(&bmi->bmiHeader, sizeof bmi->bmiHeader);'
+ print r' bmi->bmiHeader.biSize = sizeof bmi->bmiHeader;'
+ print r' bmi->bmiHeader.biPlanes = 1;'
+ print r' bmi->bmiHeader.biBitCount = 1;'
+ print r' bmi->bmiHeader.biCompression = BI_RGB;'
+ print r' bmi->bmiColors[0].rgbBlue = 0;'
+ print r' bmi->bmiColors[0].rgbGreen = 0;'
+ print r' bmi->bmiColors[0].rgbRed = 0;'
+ print r' bmi->bmiColors[0].rgbReserved = 0;'
+ print r' bmi->bmiColors[1].rgbBlue = 255;'
+ print r' bmi->bmiColors[1].rgbGreen = 255;'
+ print r' bmi->bmiColors[1].rgbRed = 255;'
+ print r' bmi->bmiColors[1].rgbReserved = 0;'
+ print
+ print r' for (DWORD i = 0; i < count; ++i) {'
+ self.fake_call(glNewList, ['listBase + i', 'GL_COMPILE'])
+
+ print r' char cChar = first + i;'
+
+ print r' // TODO: Use GetCharABSWidths'
+ print r' // http://www.codeproject.com/Articles/14915/Width-of-text-in-italic-font'
+ print r' // https://support.microsoft.com/en-us/kb/94646'
+ print r' SIZE size;'
+ print r' bRet = GetTextExtentPoint32A(hdc, &cChar, 1, &size);'
+ print r' if (bRet) {'
+ print r' assert(size.cx >= 0);'
+ print r' assert(size.cy >= 0);'
+ print
+ print r' // Round width to 32 pixels'
+ print r' int nWidth = (size.cx + 0x1f) & ~0x1f;'
+ print r' int nHeight = size.cy;'
+ print
+ print r' DWORD dwBytes = nWidth / 8 * nHeight;'
+ print r' LPVOID lpvBits = NULL;'
+ print r' if (dwBytes) {'
+ print r' lpvBits = malloc(dwBytes);'
+ print
+ print r' HBITMAP memBM = CreateCompatibleBitmap(memDC, nWidth, nHeight);'
+ print
+ print r' HGDIOBJ origBM = SelectObject(memDC, memBM);'
+ print
+ print r' PatBlt(memDC, 0, 0, nWidth, nHeight, BLACKNESS);'
+ print r' SelectObject(memDC, hFont);'
+ print
+ print r' bmi->bmiHeader.biWidth = nWidth;'
+ print r' bmi->bmiHeader.biHeight = nHeight;'
+ print
+ print r' bRet = TextOutA(memDC, 0, tm.tmAscent, &cChar, 1);'
+ print r' assert(bRet);'
+ print
+ print r' SelectObject(memDC, origBM);'
+ print
+ print r' int nScanLines = GetDIBits(memDC, memBM, 0, nHeight, lpvBits, bmi, DIB_RGB_COLORS);'
+ print r' assert(nScanLines == nHeight);'
+ print
+ print r' DeleteObject(memBM);'
+ print r' }'
+ print
+ print r' GLsizei width = nWidth;'
+ print r' GLfloat height = nHeight;'
+ print r' GLfloat xorig = 0;'
+ print r' GLfloat yorig = tm.tmDescent;'
+ print r' GLfloat xmove = size.cx;'
+ print r' GLfloat ymove = 0;'
+ print r' const GLubyte *bitmap = (const GLubyte *)lpvBits;'
+ print r' if (bitmap == NULL) {'
+ print r' // We still need to emit an empty glBitmap for empty characters like spaces;'
+ print r' width = height = xorig = yorig = 0;'
+ print r' }'
+
+ # FIXME: glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
+ # FIXME: glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ self.fake_call(glBitmap, ['width', 'height', 'xorig', 'yorig', 'xmove', 'ymove', 'bitmap'])
+
+ print r' free(lpvBits);'
+ print r' }'
+ self.fake_call(glEndList, [])
+ print r' }'
+ print
+ print r' DeleteDC(memDC);'
+ print r' free(bmi);'
+
+ print r' } // _result'
+ return
+
GlTracer.traceFunctionImplBody(self, function)
if function.name in self.createContextFunctionNames:
@@ -105,6 +248,8 @@ if __name__ == '__main__':
print '#include <string.h>'
print '#include <windows.h>'
print
+ print '#include <sstream>'
+ print
print '#include "trace_writer_local.hpp"'
print '#include "os.hpp"'
print